用prefuse对owl本体可视化

时间:2022-12-25 19:50:56

 

 

在上一篇随笔中介绍了用Jena对owl本体片断进行解析存储到mysql数据库中,本文将接上次的内容对存入到mysql中本体片断进行抽取然后可视化化显示。

把owl本体片断导入protage后的可视化的效果:

用prefuse对owl本体可视化

鼠标移到结点或边对象时,显示语义信息:

 用prefuse对owl本体可视化

用prefuse对owl本体可视化

我所做的工作就是实现像protage一样用图形交互。我用的图形交互式可视化组件包是prefuse(到官网上下载http://prefuse.org/  beta版或mater版),导入到JAVA工程中即可调用。

由于prefuse从db中读取数据->添充到自已的数据结构->着色、布置位置->渲染->呈现,这个过程是稳定,而且必须一次性完成,而且它的数据结构是稳定。

用prefuse对owl本体可视化

所以我的思路是,首先,建产稳定的Graph数据表,其有三个字段:url,name,type(用于标记是类还是实体),然后把所有类和对象属性实例从db中提取出来,填入到Graph数据表中,

然后,根据类之间,类与实例,实例与实例之间的语义关系添加边。

最后,可视化后鼠标移到结点或边上显示的语义信息是根据选中结点url(如果是边就是两个端点的url),从数据库中提取相应的语义信息,然后用tooltip(关于tooltip换行显示的方法可在我的随笔中找到)显示出来。

Java代码:

用prefuse对owl本体可视化用prefuse对owl本体可视化View Code
  1 import javax.swing.JFrame;
  2 import javax.swing.JPanel;
  3 import javax.swing.SwingUtilities;
  4 import java.awt.BasicStroke;
  5 import java.awt.Shape;
  6 import java.awt.Graphics2D;
  7 import java.awt.BorderLayout;
  8 import java.awt.event.MouseEvent;
  9 import java.util.Iterator;
 10 import java.lang.String;
 11 import prefuse.Constants;
 12 import prefuse.Display;
 13 import prefuse.Visualization;
 14 import prefuse.action.ActionList;
 15 import prefuse.action.GroupAction;
 16 import prefuse.action.RepaintAction;
 17 import prefuse.action.animate.ColorAnimator;
 18 import prefuse.action.animate.PolarLocationAnimator;
 19 import prefuse.action.animate.QualityControlAnimator;
 20 import prefuse.action.animate.VisibilityAnimator;
 21 import prefuse.action.assignment.ColorAction;
 22 import prefuse.action.assignment.DataColorAction;
 23 import prefuse.action.assignment.FontAction;
 24 import prefuse.action.assignment.StrokeAction;
 25 import prefuse.action.layout.CollapsedSubtreeLayout;
 26 import prefuse.action.layout.graph.RadialTreeLayout;
 27 import prefuse.activity.SlowInSlowOutPacer;
 28 import prefuse.controls.ControlAdapter;
 29 import prefuse.controls.DragControl;
 30 import prefuse.controls.FocusControl;
 31 import prefuse.controls.HoverActionControl;
 32 import prefuse.controls.PanControl;
 33 import prefuse.controls.WheelZoomControl;
 34 import prefuse.data.Graph;
 35 import prefuse.data.Node;
 36 import prefuse.data.Table;
 37 import prefuse.data.io.sql.*;
 38 import prefuse.data.tuple.TupleSet;
 39 import prefuse.render.DefaultRendererFactory;
 40 import prefuse.render.LabelRenderer;
 41 import prefuse.render.EdgeRenderer;
 42 import prefuse.util.ColorLib;
 43 import prefuse.util.FontLib;
 44 import prefuse.visual.EdgeItem;
 45 import prefuse.visual.VisualItem;
 46 import prefuse.visual.expression.InGroupPredicate;
 47 
 48 public class Buyer extends Display {
 49      
 50       //jdbc driver name
 51     public static final String driverName= "com.mysql.jdbc.Driver";    
 52     // path for database
 53     public static final String dbURL= "jdbc:mysql://localhost:3306/ontology?useUnicode=true&characterEncoding=utf8";    
 54     //username 
 55     public static final String userName= "root";    
 56     //password
 57     public static final String userPwd= "sql123";    
 58     
 59     
 60     private final String graph= "graph";
 61     private final String graphNodes = "graph.nodes";
 62     private final String graphEdges = "graph.edges";
 63     private final String linear = "linear";
 64     private static String label="name";
 65     private static Graph graphdata=null;
 66     private static BasicStroke bsfocus=null,bslosefocus=null;
 67     
 68     //public static Table classnodes=null;
 69     //public static Table individualnodes=null;
 70     public Buyer()
 71     {
 72         super(new Visualization());
 73         
 74         //第二步,创建Visualization把数据映射到abstraction中
 75         graphdata=new Graph(true);    //true表明有向图
 76         bsfocus=new BasicStroke(4);
 77         bslosefocus=new BasicStroke(1);
 78     }
 79     
 80     public void InitComponent()
 81     {    
 82         m_vis.add(graph,graphdata);
 83         //第三步,进行渲染根据abstraction中的数据
 84         LabelRenderer labelrender=new LabelRenderer(label);
 85         labelrender.setRoundedCorner(5,5);
 86         labelrender.setMaxTextWidth(100);
 87         EdgeRenderer edgesrender=new MyEdgeRenderer(Constants.EDGE_TYPE_CURVE,Constants.EDGE_ARROW_FORWARD);
 88         //设置箭头大小
 89         DefaultRendererFactory drf=new DefaultRendererFactory();
 90         drf.add(new InGroupPredicate(graphNodes),labelrender);
 91         drf.add(new InGroupPredicate(graphEdges),edgesrender);
 92         m_vis.setRendererFactory(drf);
 93         int[] palette = new int[]{ColorLib.rgb(10,190,255),ColorLib.rgb(255,10,180)};
 94         
 95          DataColorAction fill = new DataColorAction(graphNodes, "type",Constants.NOMINAL, VisualItem.FILLCOLOR, palette); 
 96          ColorAction textColor = new ColorAction(graphNodes,VisualItem.TEXTCOLOR, ColorLib.gray(0));    
 97          ColorAction edgesColor = new MyColorAction(graphEdges,VisualItem.STROKECOLOR); 
 98          FontAction fonts = new FontAction(graph, FontLib.getFont("宋体&新宋体",1,15)); 
 99          //着色动作
100          ActionList color=new ActionList();
101          color.add(fill);    
102          color.add(textColor);    
103          color.add(edgesColor); 
104          color.add(fonts);
105          m_vis.putAction("color",color);
106          
107          //更新动作序列
108          ActionList update = new ActionList();
109          update.add(new MyStrokeAction());
110          update.add(new RepaintAction());  
111          m_vis.putAction("update", update);
112          
113          RadialTreeLayout treeLayout = new RadialTreeLayout(graph);
114          //treeLayout.setAngularBounds(-Math.PI/2, Math.PI);
115          m_vis.putAction("treeLayout", treeLayout);
116          
117          CollapsedSubtreeLayout subLayout = new CollapsedSubtreeLayout(graph);
118          m_vis.putAction("subLayout", subLayout);
119          
120          // create the filtering and layout
121          ActionList filter = new ActionList();
122          filter.add(new TreeRootAction(graph));
123          filter.add(color);
124          filter.add(treeLayout);
125          filter.add(subLayout);
126          m_vis.putAction("filter", filter);
127          
128          // animated transition
129          ActionList animate = new ActionList(1250);
130          animate.setPacingFunction(new SlowInSlowOutPacer());
131          
132          animate.add(new QualityControlAnimator());
133          animate.add(new VisibilityAnimator(graph)); //是否显示变动的动画过程
134          animate.add(new PolarLocationAnimator(graph, linear));
135          animate.add(new ColorAnimator(graphNodes));
136          animate.add(new RepaintAction());
137          m_vis.putAction("animate", animate);
138          m_vis.alwaysRunAfter("filter", "animate");
139          
140          
141          setSize(1000,700);
142           addControlListener(new DragControl()); // drag items around
143           addControlListener(new PanControl());  // pan with background left-drag
144           addControlListener(new WheelZoomControl()); // zoom with vertical Wheel
145          addControlListener(new FocusControl(1, "filter"));
146          addControlListener(new HoverActionControl("repaint"));
147          addControlListener(new DataMouseControl());
148          // filter graph and perform layout
149          m_vis.run("filter");
150     }
151     /**
152      * @param args
153      */
154     public static void main(String[] args) {
155         // TODO Auto-generated method stub
156         DatabaseDataSource datasrc=null;
157         try
158         {    
159             //create and load node of class    
160             Table nodes= GetData("SELECT C_Uri,C_Name  From ontologyclass");    
161             Table edges = GetData("SELECT x.C_Uri,y.curi FROM ontologyclass as x,tmpclass as y where x.C_Name=y.cvalue");  
162            
163             
164             Buyer buy=new Buyer();
165             graphdata.addColumn("uri",java.lang.String.class);
166             graphdata.addColumn("name", java.lang.String.class);
167             graphdata.addColumn("type",java.lang.Character.class);
168             
169              //添加类结点
170             buy.AddClassNode(nodes);
171             //添加类之间的父子关系
172             buy.AddEdges(edges,"C_Uri","curi","uri");
173             
174             //添加类之间的对象属性关系
175             edges=GetData("SELECT * FROM property where Proty_Type=\'OP\'");
176             buy.AddEdges(edges,"Proty_Domain","Proty_Range","name");
177             
178             //添加实例结点
179             nodes=GetData("SELECT * from individual as x,property as y where x.Indiv_PURI=y.Proty_URI and y.Proty_Type='OP'");       
180             buy.AddIndividualNode(nodes);
181             //添加实例和类之间的边
182             edges=GetData("SELECT z.Indiv_ClaURI,z.Indiv_URI from property as y,individual as z where y.Proty_URI=z.Indiv_PURI and y.Proty_Type='OP'");
183             buy.AddEdges(edges,"Indiv_ClaURI","Indiv_URI","uri");
184             //添加实例间的关系
185             edges=GetData("SELECT x.Indiv_URI,x.Indiv_PURI,y.iuri from individual as x,tmpindividual as y,property as z where x.Indiv_PVal=y.iname and y.ipuri=z.Proty_URI and z.Proty_Type='OP'");
186             buy.AddEdges(edges,"Indiv_URI","iuri","uri");
187             //初始化显示
188            
189             buy.InitComponent();
190             //定制界面
191             JPanel  panel= new JPanel(new BorderLayout());
192             panel.add(buy, BorderLayout.CENTER);
193             JFrame frame = new JFrame("本体展示");
194             frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
195             frame.getContentPane().add(panel);
196             frame.pack();
197             frame.setVisible(true);
198         }
199         catch(Exception e)
200         {
201              e.printStackTrace();
202                System.exit(1);
203         }
204     }
205     
206     public static Table GetData(String sql)
207     {
208         DatabaseDataSource datasrc =null; 
209         Table table=null;
210         try 
211         {   
212             // declare a datasource
213              datasrc = ConnectionFactory.getDatabaseConnection(driverName, dbURL, userName, userPwd);      
214              //create a table of data    
215              table= datasrc.getData(sql); 
216         } 
217         catch (Exception e) 
218         {
219             e.printStackTrace();
220             System.exit(1);
221         }
222         return table;
223     }//end of static function GetData
224     
225       public static class TreeRootAction extends GroupAction 
226       {    
227             public TreeRootAction(String graphGroup) {
228                 super(graphGroup);
229                 
230             }
231             public void run(double frac) {
232                 TupleSet focus = m_vis.getGroup(Visualization.FOCUS_ITEMS);
233                 if ( focus==null || focus.getTupleCount() == 0 ) return;
234                 
235                 Graph g = (Graph)m_vis.getGroup(m_group);
236                 Node f = null;
237                 Iterator tuples = focus.tuples();
238                 while (tuples.hasNext() && !g.containsTuple(f=(Node)tuples.next()))
239                 {
240                     f = null;
241                 }
242                 if ( f == null ) return;
243                 g.getSpanningTree(f);
244             }
245         }//end of class TreeRootAction
246 
247     public class DataMouseControl extends ControlAdapter
248     {
249            private String uri=null; 
250            String sql=null;
251            private Graph g=null;
252            Node startnode,targetnode;
253            public String GetShowInformation()
254            {   
255                String relation=null;
256                
257                char sourcetype=(Character) startnode.get("type");
258                char targettype=(Character) targetnode.get("type");
259                switch(sourcetype)
260                {
261                  case 'c':
262                  {
263                   if(targettype=='c')
264                   //处理都是类
265                   relation=GetRelationInfo(1);//表示类间关系
266                   else
267                     //处理一个类一个实例(肯定是类与实例关系)
268                       relation=startnode.getString("name")+"--has Individual-->"+targetnode.get("name");
269                   break;
270                  }
271                 
272                 case 's':
273                  {   
274                      //实例间的关系
275                      relation=GetRelationInfo(2);//表示实例间关系
276                      break;
277                  }
278                  
279                }
280                return relation;
281            }
282            
283            public String GetRelationInfo(int type)
284            {  
285                String relation="";
286               
287               Table Relationtable;
288               if (type==1)
289               {   //处理类间关系
290                   sql="SELECT C_Descript  from ontologyclass  where C_Name=\'"+
291                           targetnode.getString("name")+"\' and C_DescriptVal=\'"+startnode.getString("name")+"\'";
292                           Relationtable=GetData(sql);
293                           if(Relationtable.getRowCount()>0)
294                             relation=targetnode.getString("name")+"---"+Relationtable.getString(0,"C_Descript")+"--->"+startnode.getString("name");
295                           else
296                           {     //说明这两个类之间不是父子关系,接下来尝试其它关系 
297                               sql="SELECT * FROM property where Proty_Type=\'OP\' and  Proty_Domain=\'"+startnode.getString("name")+"\' and Proty_Range=\'"+targetnode.getString("name")+"\'";
298                               Relationtable=GetData(sql);
299                               for(int i=0;i<Relationtable.getRowCount();++i)
300                               {
301                                   relation+=Relationtable.getString(i,"Proty_Domain")+"---"+Relationtable.getString(i,"Proty_Name")+"(定义域>值域)--->"+Relationtable.getString(i,"Proty_Range");
302                               }
303                               
304                           }
305               }
306               else
307               {
308                   //处理实例间关系
309                  sql="SELECT x.Indiv_Name,x.Indiv_PURI,y.iname  from individual as x,tmpindividual as y,property as z"+ 
310                     "    where x.Indiv_PVal=y.iname and y.ipuri=z.Proty_URI and z.Proty_Type='OP' and x.Indiv_URI=\'"+startnode.getString("uri")+"\'  and y.iuri=\'"+targetnode.getString("uri")+"\'";
311                  Relationtable=GetData(sql);
312                  if(Relationtable.getRowCount()>0)
313                  {   
314                      relation=Relationtable.getString(0,"Indiv_PURI").substring(Relationtable.getString(0,"Indiv_PURI").lastIndexOf("#")+1);
315                      relation=Relationtable.getString(0,"Indiv_Name")+"---"+relation+"--->"+Relationtable.getString(0,"iname");
316                      //System.out.print(relation);
317                  }
318                  
319               }
320               
321               return relation;
322            }
323            public void itemEntered(VisualItem item, MouseEvent e)
324            {   
325                Display d = (Display)e.getSource();
326                item.setHighlighted(true);
327                //说明选中的是边
328                if(item.getGroup().equals(graphEdges))
329                 {   
330                    //起始结点在图中结点号
331                     int startid=Integer.parseInt(item.getSourceTuple().getString(0));
332                     startnode=graphdata.getNode(startid);
333                     //目标结点在图中结点号
334                     int targetid=Integer.parseInt(item.getSourceTuple().getString(1));
335                     targetnode=graphdata.getNode(targetid);
336                     //System.out.print(relation);
337                     d.setToolTipText(GetShowInformation());
338                     m_vis.run("update");
339                     
340                 }
341                else
342                {    
343                    uri=item.getString("uri");
344                    String msg="";
345                    if((Character)item.get("type")=='c')
346                    {   
347                        //类结点处理
348                        msg="<html>类名:"+item.getString("name")+"<br>资源URI:"+uri;
349                        sql="SELECT x.C_Name,z.Proty_Name,y.R_Type,y.R_Val,z.Proty_Range"
350                        +" FROM ontologyclass as x,propertyrestriction as y,property as z"+
351                        "  WHERE x.C_Uri=y.R_Curi and y.R_Puri=z.Proty_URI and x.C_Uri=\'"+item.getString("uri")+"\'";
352                        Table restrictioninfo=GetData(sql);
353                        for(int i=0;i<restrictioninfo.getRowCount();++i)
354                        {
355                           msg+="<br>约束条件:"+restrictioninfo.getString(i,"C_Name")+" "+restrictioninfo.getString(i,"Proty_Name")+" "+restrictioninfo.getString(i,"R_Type")
356                                +"--"+restrictioninfo.getString(i,"R_Val")+" "+restrictioninfo.getString(i,"Proty_Range");
357                        }
358                        msg+="</html>";
359                    }  
360                    else
361                    {
362                        msg="<html>实例名:"+item.getString("name")+"<br>资源URI:"+uri;
363                        //对象属性定义
364                        sql="SELECT x.Proty_Name,y.Indiv_Name,y.Indiv_PVal"
365                                +" FROM property as x,individual as y WHERE x.Proty_URI=y.Indiv_PURI "
366                                +"and x.Proty_Type='OP' and y.Indiv_URI=\'"+item.getString("uri")+"\'";
367                        Table restrictioninfo=GetData(sql);
368                        for(int i=0;i<restrictioninfo.getRowCount();++i)
369                        {
370                           msg+="<br>对象属性定义:"+restrictioninfo.getString(i,"Indiv_Name")+" "+restrictioninfo.getString(i,"Proty_Name")+" "
371                           +restrictioninfo.getString(i,"Indiv_PVal");
372                        }
373                     
374                        sql="SELECT x.Proty_Name,y.Indiv_Name,y.Indiv_PVal,x.Proty_Range"
375                        +" FROM property as x,individual as y WHERE x.Proty_URI=y.Indiv_PURI "
376                        +"and x.Proty_Type='DP' and y.Indiv_URI=\'"+item.getString("uri")+"\'";
377                        restrictioninfo=GetData(sql);
378                        for(int i=0;i<restrictioninfo.getRowCount();++i)
379                        {
380                           msg+="<br>数据类型属性定义:"+restrictioninfo.getString(i,"Indiv_Name")+" "+restrictioninfo.getString(i,"Proty_Name")+" "
381                           +restrictioninfo.getString(i,"Indiv_PVal")+"--"+restrictioninfo.getString(i,"Proty_Range");
382                        }
383                        msg+="</html>";
384                    }
385                     d.setToolTipText(msg);
386                }
387           
388             
389            
390            }
391            
392            public void itemExited(VisualItem item, MouseEvent e)
393            {
394                Display d = (Display)e.getSource();
395                d.setToolTipText("");
396                m_vis.run("update");
397            }
398            
399            public void itemClicked(VisualItem item, MouseEvent e)
400            {
401                if (!SwingUtilities.isLeftMouseButton(e)) return;
402                if ( e.getClickCount()==2)
403                {
404                    
405                }
406            }
407            
408            
409            public void itemPressed(VisualItem item, MouseEvent e)
410            {
411            
412            }
413         
414            public void itemReleased(VisualItem item, MouseEvent e)
415            {
416            
417            }
418     }//end of class DataMouseControl
419     
420     
421       //添加当前类的边
422     public void AddEdges(Table edges,String startkey,String endkey,String according)
423     {
424         Node  source=null,target=null;
425         
426        for(int j=0;j<edges.getRowCount();++j)
427        { 
428            String startname=edges.getString(j,startkey);
429            String endname=edges.getString(j, endkey);
430            //System.out.print(startname+"---");
431            //System.out.println(endname);
432            //找到起始端点
433            for(int i=0;i<graphdata.getNodeCount();++i)
434            {
435                String name=graphdata.getNode(i).getString(according);
436                if(name.equalsIgnoreCase(startname))
437                {
438                   source=graphdata.getNode(i);
439                   break;
440                }
441            }
442            
443           //找到末端点
444            for(int k=0;k<graphdata.getNodeCount();++k)
445            {
446                String name=graphdata.getNode(k).getString(according);
447                if(name.equalsIgnoreCase(endname))
448                {
449                   target=graphdata.getNode(k);
450                   break;
451                }
452            }
453            
454            //两结点间加条线
455          //System.out.print(source.get(according)+"--");
456          //System.out.println(target.get(according)); 
457          graphdata.addEdge(source, target);
458          
459        }
460     }//end of function AddEdges
461     
462     public void AddClassNode(Table nodes)
463     {
464         for(int i=0;i<nodes.getRowCount();++i)
465         {
466             Node node=graphdata.addNode();
467             //System.out.print(nodes.getString(i,key2));
468             node.setString("uri", nodes.getString(i,"C_Uri"));
469             node.setString("name", nodes.getString(i,"C_Name"));
470             node.set("type",'c');
471         }
472         //System.out.print(graphdata.getNode(2).get("name"));
473     }
474     
475     public void AddIndividualNode(Table nodes)
476     {
477         for(int i=0;i<nodes.getRowCount();++i)
478         {
479              Node node = graphdata.addNode();
480              node.set("uri",nodes.getString(i, "Indiv_URI"));
481                node.setString("name",nodes.getString(i, "Indiv_Name"));
482                node.set("type",'s');
483                
484         }
485         System.out.print(nodes.getRowCount());
486     }//end of function  AddIndividualNode
487     
488     public class MyColorAction extends ColorAction
489     {   
490         private Node startnode,targetnode;
491         public MyColorAction(String group,String field)
492         {
493             super(group,field);
494         }
495         
496         public int getColor(VisualItem item)
497         {
498               
499             //起始结点在图中结点号
500             int startid=Integer.parseInt(item.getSourceTuple().getString(0));
501             startnode=graphdata.getNode(startid);
502             //目标结点在图中结点号
503             int targetid=Integer.parseInt(item.getSourceTuple().getString(1));
504             targetnode=graphdata.getNode(targetid);
505              int color=0;
506                 switch((Character)startnode.get("type"))
507                 {
508                 
509                 case 'c':
510                     if((Character)targetnode.get("type")=='c')
511                         color=ColorLib.rgb(246,129,4);
512                     else
513                         color=ColorLib.rgb(0,0,0);
514                     break;
515                 case 's':
516                     color=ColorLib.rgb(0,140,0);
517                     break;
518                 }    
519             
520                 return color;
521         }
522         
523     }
524     public class MyStrokeAction extends StrokeAction
525     {
526         public BasicStroke getStroke(VisualItem item) 
527         {   
528             return item.isHover()?(bsfocus):(bslosefocus);
529         }
530     }
531     
532     public class MyEdgeRenderer extends EdgeRenderer
533     {
534         public MyEdgeRenderer(int edgeType, int arrowType)
535         {
536             super(edgeType,arrowType);
537         }
538         public void render(Graphics2D g, VisualItem item)
539         {
540             /* 
541             //虚线
542             float[] dash1 = {5.0f};
543             BasicStroke s = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, dash1, 0.0f);
544             item.setStroke( s );
545             // render the edge line
546              */
547             super.render(g, item);
548             
549             // render the edge arrow head, if appropriate
550             if ( m_curArrow != null )
551             {
552                 g.setPaint(ColorLib.getColor(item.getStrokeColor()));
553                 super.setArrowHeadSize(10,10);
554                 g.fill(m_curArrow);
555             }
556 
557         }
558      
559     }
560 }

最后的可视化效果:

蓝色结点是类,紫色结点是实例,类与类之间,类与实例,实例与实例之间用不同的线条颜色表示,鼠标移到边或结点对象时,显示相应的语义信息。

用prefuse对owl本体可视化

用prefuse对owl本体可视化

这样就完成owl本体片断的可视化,不过效果和protage的比差了些。

转载本文请标明出处。