漫談可視化Prefuse(六)

  可視化一路走來,體會不少;博客一路寫來,收穫頗豐;代碼一路碼來,思路愈來愈清晰。終究仍是明白了一句古話:紙上得來終覺淺,絕知此事要躬行。html

  跌跌撞撞整合了個可視化小tool,零零碎碎結交了衆多的志同道合之人,迷迷糊糊建立了我"可視化/Prefuse"的QQ羣,詳情可查看左側的公告部分。此羣旨在結實更多的可視化領域的同仁,也但願能夠成爲一個開源項目分享與閱讀的平臺。源於開源,開源爲咱們提供了助咱們快速成長的營養,開源的每一行代碼都是前輩們心血的結晶,開源是智慧的濃縮。web

  在博客園寫博客也是如此,從起初只是一味的平鋪直敘,直抒胸臆,歷來沒有估計到還要格式調整,也沒有想到要佈局美觀,更不用提什麼言簡意賅、一針見血。總之,看看優秀的博客,就如同接觸到一個開源項目,其開篇佈局、文章內容、文本樣式都是學習的教材。最近體會比較深的就是:寫博客也體現出博客的特性,博客,不是論文,過多或者過於複雜的理論闡述(除非必不可少)會讓大部分讀者兩眼昏花、四肢無力;博客,也不是小學造句子,太短或過少缺少總體的連貫性,剛讀起來有點感受,好吧,還沒高潮就結束了,讓人摸不着頭腦。因此,我發現,但凡得到點贊多的文章除了內容含金量高之外,還贏在表述以及篇幅的控制,真正站在Reader的角度去闡述問題、解決問題,Reader就會控制不住要點個贊。In a Word,路很長,要學的東西不少,慢慢體味。微信

 

  上期回顧:《漫談可視化Prefuse(五)---一款屬於我本身的可視化工具》主要介紹了本身開發的一款可視化工具,包含了可視化工具中一些必不可少的功能,有些網友反應期待web版,其實Prefuse是支持applet版本的,這裏沒有走web的緣由可能仍是根據咱們的需求走。要知道在以js爲堅實後盾的各類可視化庫大行其道的狀況下,相似於Gephi、IBM i2等產品仍然具備不可撼動的地位的緣由,在於需求催生產品,不一樣的需求就會對應着不一樣的產品形態。還有些網友反映披露工具相關細節,下面正文將會有所體現。app

 

  本篇主要立足於Prefuse框架講述:1.可視化工具如何根據需求調整邊的粗細;2.try...catch的巧用框架

 

  1.如何經過邊的粗細來反映邊的權重分佈式

  Prefuse框架默認邊的粗細是統一的,都爲1。可是咱們每每面臨的需求是給出數據格式以下函數

Source Target Weight
1   2 0.5

  那麼咱們就能夠經過邊的粗細來體現這個Weight屬性,用來代表節點1和節點2之間的親密程度。工具

  因此,咱們針對Prefuse的源碼作一下改動,在此以前,咱們先了解有關類的繼承關係:佈局

  類LabelRenderer:學習

1
2
3
4
5
6
7
8
9
10
public  class  LabelRenderer  extends  AbstractShapeRenderer {
     ......
     public  void  render(Graphics2D g, VisualItem item) {
         RectangularShape shape = (RectangularShape) getShape(item);
         if  (shape ==  null )
             return ;
                 ......
     }
     ...... 
}

  類EdgeRenderer:

1
2
3
4
5
6
7
8
9
public  class  EdgeRenderer  extends  AbstractShapeRenderer {
     ......
     public  void  render(Graphics2D g, VisualItem item) {
         // render the edge line
         super .render(g, item);
         ......
     }
     ......
}

  抽象類AbstractShapeRenderer:

1
2
3
4
5
6
7
8
public  abstract  class  AbstractShapeRenderer  implements  Renderer {
     ......
     public  void  render(Graphics2D g, VisualItem item) {
     Shape shape = getShape(item);
         ......
     }
     ......
}   

  從以上三個類能夠發現,類LabelRenderer和EdgeRenderer都是繼承自抽象類AbstractShapeRenderer,而且LabelRenderer和EdgeRenderer類都覆寫了父類 render方法。

  兩個類的render方法的最大不一樣之處在於,EdgeRenderer類顯式調用了抽象父類AbstractShapeRenderer的render方法,而且經過在AbstractShapeRenderer類的render方法中加入:

1 System.out.println("該item屬於:" + item.getGroup())

  獲得的打印信息都是"該item屬於:graph.edges",即代表都是對於邊的渲染。

 

  瞭解了類的繼承關係,下面給出修改源碼的步驟以實現經過配置文件實現邊粗細的賦值:

  (1)在PrefuseConfig類中添加:

1 setProperty("data.edge.weight""weight");

  用於xml文件中肯定邊粗細的標示,這裏是weight;

 

  (2)在Graph類中添加:

1 public static final String WEIGHT = PrefuseConfig.get("data.edge.weight");

  用於在GraphMLReader獲取常量;

 

  (3)在GraphMLReader中添加:

1
2
public  static  final  String WEIGHT = Graph.WEIGHT;
public  static  final  String WEIGHTID = WEIGHT +  '_'  + ID;

  方法startDocument()中添加:

1
2
m_esch.addColumn(WEIGHT, String. class ); //邊粗細相關
m_esch.addColumn(WEIGHTID, String. class );

  方法startElement()中添加:

1
2
m_edges.setString(m_row, WEIGHT, atts.getValue(WEIGHT));
m_edges.setString(m_row, WEIGHTID, atts.getValue(WEIGHTID));

  

  (4)在AbstractShapeRenderer中添加:

1
2
3
4
5
6
7
8
9
10
EdgeItem edge = (EdgeItem)item;
VisualItem vi = (VisualItem)edge.getSourceNode();
item.setStrokeColor(vi.getFillColor());
String weight =  null ;
try  {
     weight = item.get(GraphMLHandler.WEIGHT).toString();
      catch  (Exception e) {
        weight =  "1" ;
}
item.setSize(Double.parseDouble(weight)* 10 );   

  

  使用的配置文件爲xml格式,內容爲:

  

  最終的圖形顯示爲:

 

  2.try....catch的巧用

    巧用之處見1(4)中所寫:

1
2
3
4
5
6
7
8
9
10
EdgeItem edge = (EdgeItem)item;
VisualItem vi = (VisualItem)edge.getSourceNode();
item.setStrokeColor(vi.getFillColor());
String weight =  null ;
try  {
     weight = item.get(GraphMLHandler.WEIGHT).toString();
      catch  (Exception e) {
        weight =  "1" ;
}
item.setSize(Double.parseDouble(weight)* 10 ); 

   由於在實際狀況中,會遇到有些xml文件中沒有weight屬性,或者xml部分邊有部分沒有的狀況,這時就會面臨在AbstractShapeRenderer中沒法獲取weight值的情形,即

1 item.get(GraphMLHandler.WEIGHT)

   此值不存在或爲空,起初經過添加語句:

1
2
3
4
5
if (item.get(GraphMLHandler.WEIGHT).toString().equals( "" ) || item.get(GraphMLHandler.WEIGHT).toString() ==  null ){
     weight =  "1" ;
} else {
     weight = item.get(GraphMLHandler.WEIGHT).toString();
}

  等相似手段仍是沒法捕獲item.get()取不到值的全部狀況,後面轉而想到,鑑於要捕獲的是爲空異常,索性使用try...catch直接進行捕獲,捕獲後在進行處理。從而有了上面的處理,即當item.get()函數獲取不到值時就捕獲異常,轉入catch部分執行,在這裏咱們編寫咱們想要實現的功能,也就是獲取爲空時就將weight設置默認值爲1,從而巧妙的解決了考慮全部爲空的狀況。

 

  從該源碼的經歷發現,須要明確本身想要的功能,明確須要觸及哪些類,明確如何保證修改後的源碼運行的完整性,不能由於修改一處而處處報錯;另外,還須要常常思考,靈活運行一些語句的特性爲本身所用。今天就到這吧,若是以爲有用,記得點贊^_^,對可視化(gephi、prefuse、分佈式計算、開源)感興趣的能夠加羣討論。

  本文連接:《漫談可視化Prefuse(六)---改動源碼定製邊粗細》

  

友情贊助

若是你以爲博主的文章對你那麼一點小幫助,恰巧你又有想打賞博主的小衝動,那麼事不宜遲,趕忙掃一掃,小額地贊助下,攢個奶粉錢,也是讓博主有動力繼續努力,寫出更好的文章^^。

    1. 支付寶                          2. 微信

                      

相關文章
相關標籤/搜索