1 package prefuse.render; 2 3 import java.awt.BasicStroke ; 4 import java.awt.Graphics2D ; 5 import java.awt.Polygon ; 6 import java.awt.Shape ; 7 import java.awt.geom.AffineTransform ; 8 import java.awt.geom.CubicCurve2D ; 9 import java.awt.geom.Line2D ; 10 import java.awt.geom.Point2D ; 11 import java.awt.geom.Rectangle2D ; 12 13 import prefuse.Constants; 14 import prefuse.util.ColorLib; 15 import prefuse.util.GraphicsLib; 16 import prefuse.util.StrokeLib; 17 import prefuse.visual.EdgeItem; 18 import prefuse.visual.VisualItem; 19 20 21 34 public class EdgeRenderer extends AbstractShapeRenderer { 35 36 public static final String EDGE_TYPE = "edgeType"; 37 38 protected static final double HALF_PI = Math.PI / 2; 39 40 protected Line2D m_line = new Line2D.Float (); 41 protected CubicCurve2D m_cubic = new CubicCurve2D.Float (); 42 43 protected int m_edgeType = Constants.EDGE_TYPE_LINE; 44 protected int m_xAlign1 = Constants.CENTER; 45 protected int m_yAlign1 = Constants.CENTER; 46 protected int m_xAlign2 = Constants.CENTER; 47 protected int m_yAlign2 = Constants.CENTER; 48 protected double m_width = 1; 49 protected float m_curWidth = 1; 50 protected Point2D m_tmpPoints[] = new Point2D [2]; 51 protected Point2D m_ctrlPoints[] = new Point2D [2]; 52 protected Point2D m_isctPoints[] = new Point2D [2]; 53 54 protected int m_edgeArrow = Constants.EDGE_ARROW_FORWARD; 56 protected int m_arrowWidth = 8; 57 protected int m_arrowHeight = 12; 58 protected Polygon m_arrowHead = updateArrowHead( 59 m_arrowWidth, m_arrowHeight); 60 protected AffineTransform m_arrowTrans = new AffineTransform (); 61 protected Shape m_curArrow; 62 63 66 public EdgeRenderer() { 67 m_tmpPoints[0] = new Point2D.Float (); 68 m_tmpPoints[1] = new Point2D.Float (); 69 m_ctrlPoints[0] = new Point2D.Float (); 70 m_ctrlPoints[1] = new Point2D.Float (); 71 m_isctPoints[0] = new Point2D.Float (); 72 m_isctPoints[1] = new Point2D.Float (); 73 } 74 75 81 public EdgeRenderer(int edgeType) { 82 this(edgeType, Constants.EDGE_ARROW_FORWARD); 83 } 84 85 96 public EdgeRenderer(int edgeType, int arrowType) { 97 this(); 98 setEdgeType(edgeType); 99 setArrowType(arrowType); 100 } 101 102 105 public int getRenderType(VisualItem item) { 106 return RENDER_TYPE_DRAW; 107 } 108 109 112 protected Shape getRawShape(VisualItem item) { 113 EdgeItem edge = (EdgeItem)item; 114 VisualItem item1 = edge.getSourceItem(); 115 VisualItem item2 = edge.getTargetItem(); 116 117 int type = m_edgeType; 118 119 getAlignedPoint(m_tmpPoints[0], item1.getBounds(), 120 m_xAlign1, m_yAlign1); 121 getAlignedPoint(m_tmpPoints[1], item2.getBounds(), 122 m_xAlign2, m_yAlign2); 123 m_curWidth = (float)(m_width * getLineWidth(item)); 124 125 EdgeItem e = (EdgeItem)item; 127 if ( e.isDirected() && m_edgeArrow != Constants.EDGE_ARROW_NONE ) { 128 boolean forward = (m_edgeArrow == Constants.EDGE_ARROW_FORWARD); 130 Point2D start = null, end = null; 131 start = m_tmpPoints[forward?0:1]; 132 end = m_tmpPoints[forward?1:0]; 133 134 VisualItem dest = forward ? e.getTargetItem() : e.getSourceItem(); 136 int i = GraphicsLib.intersectLineRectangle(start, end, 137 dest.getBounds(), m_isctPoints); 138 if ( i > 0 ) end = m_isctPoints[0]; 139 140 AffineTransform at = getArrowTrans(start, end, m_curWidth); 142 m_curArrow = at.createTransformedShape(m_arrowHead); 143 144 Point2D lineEnd = m_tmpPoints[forward?1:0]; 147 lineEnd.setLocation(0, -m_arrowHeight); 148 at.transform(lineEnd, lineEnd); 149 } else { 150 m_curArrow = null; 151 } 152 153 Shape shape = null; 155 double n1x = m_tmpPoints[0].getX(); 156 double n1y = m_tmpPoints[0].getY(); 157 double n2x = m_tmpPoints[1].getX(); 158 double n2y = m_tmpPoints[1].getY(); 159 switch ( type ) { 160 case Constants.EDGE_TYPE_LINE: 161 m_line.setLine(n1x, n1y, n2x, n2y); 162 shape = m_line; 163 break; 164 case Constants.EDGE_TYPE_CURVE: 165 getCurveControlPoints(edge, m_ctrlPoints,n1x,n1y,n2x,n2y); 166 m_cubic.setCurve(n1x, n1y, 167 m_ctrlPoints[0].getX(), m_ctrlPoints[0].getY(), 168 m_ctrlPoints[1].getX(), m_ctrlPoints[1].getY(), 169 n2x, n2y); 170 shape = m_cubic; 171 break; 172 default: 173 throw new IllegalStateException ("Unknown edge type"); 174 } 175 176 return shape; 178 } 179 180 183 public void render(Graphics2D g, VisualItem item) { 184 super.render(g, item); 186 if ( m_curArrow != null ) { 188 g.setPaint(ColorLib.getColor(item.getFillColor())); 189 g.fill(m_curArrow); 190 } 191 } 192 193 198 protected AffineTransform getArrowTrans(Point2D p1, Point2D p2, 199 double width) 200 { 201 m_arrowTrans.setToTranslation(p2.getX(), p2.getY()); 202 m_arrowTrans.rotate(-HALF_PI + 203 Math.atan2(p2.getY()-p1.getY(), p2.getX()-p1.getX())); 204 if ( width > 1 ) { 205 double scalar = width/4; 206 m_arrowTrans.scale(scalar, scalar); 207 } 208 return m_arrowTrans; 209 } 210 211 219 protected Polygon updateArrowHead(int w, int h) { 220 if ( m_arrowHead == null ) { 221 m_arrowHead = new Polygon (); 222 } else { 223 m_arrowHead.reset(); 224 } 225 m_arrowHead.addPoint(0, 0); 226 m_arrowHead.addPoint(-w/2, -h); 227 m_arrowHead.addPoint( w/2, -h); 228 m_arrowHead.addPoint(0, 0); 229 return m_arrowHead; 230 } 231 232 233 234 237 protected AffineTransform getTransform(VisualItem item) { 238 return null; 239 } 240 241 244 public boolean locatePoint(Point2D p, VisualItem item) { 245 Shape s = getShape(item); 246 if ( s == null ) { 247 return false; 248 } else { 249 double width = Math.max(2, getLineWidth(item)); 250 double halfWidth = width/2.0; 251 return s.intersects(p.getX()-halfWidth, 252 p.getY()-halfWidth, 253 width,width); 254 } 255 } 256 257 260 public void setBounds(VisualItem item) { 261 if ( !m_manageBounds ) return; 262 Shape shape = getShape(item); 263 if ( shape == null ) { 264 item.setBounds(item.getX(), item.getY(), 0, 0); 265 return; 266 } 267 GraphicsLib.setBounds(item, shape, getStroke(item)); 268 if ( m_curArrow != null ) { 269 Rectangle2D bbox = (Rectangle2D )item.get(VisualItem.BOUNDS); 270 Rectangle2D.union(bbox, m_curArrow.getBounds2D(), bbox); 271 } 272 } 273 274 284 protected double getLineWidth(VisualItem item) { 285 return item.getSize(); 286 } 287 288 297 protected BasicStroke getStroke(VisualItem item) { 298 return StrokeLib.getDerivedStroke(item.getStroke(), m_curWidth); 299 } 300 301 314 protected void getCurveControlPoints(EdgeItem eitem, Point2D [] cp, 315 double x1, double y1, double x2, double y2) 316 { 317 double dx = x2-x1, dy = y2-y1; 318 cp[0].setLocation(x1+2*dx/3,y1); 319 cp[1].setLocation(x2-dx/8,y2-dy/8); 320 } 321 322 326 protected static void getAlignedPoint(Point2D p, Rectangle2D r, int xAlign, int yAlign) { 327 double x = r.getX(), y = r.getY(), w = r.getWidth(), h = r.getHeight(); 328 if ( xAlign == Constants.CENTER ) { 329 x = x+(w/2); 330 } else if ( xAlign == Constants.RIGHT ) { 331 x = x+w; 332 } 333 if ( yAlign == Constants.CENTER ) { 334 y = y+(h/2); 335 } else if ( yAlign == Constants.BOTTOM ) { 336 y = y+h; 337 } 338 p.setLocation(x,y); 339 } 340 341 347 public int getEdgeType() { 348 return m_edgeType; 349 } 350 351 357 public void setEdgeType(int type) { 358 if ( type < 0 || type >= Constants.EDGE_TYPE_COUNT ) 359 throw new IllegalArgumentException ( 360 "Unrecognized edge curve type: "+type); 361 m_edgeType = type; 362 } 363 364 371 public int getArrowType() { 372 return m_edgeArrow; 373 } 374 375 384 public void setArrowType(int type) { 385 if ( type < 0 || type >= Constants.EDGE_ARROW_COUNT ) 386 throw new IllegalArgumentException ( 387 "Unrecognized edge arrow type: "+type); 388 m_edgeArrow = type; 389 } 390 391 400 public void setArrowHeadSize(int width, int height) { 401 m_arrowWidth = width; 402 m_arrowHeight = height; 403 m_arrowHead = updateArrowHead(width, height); 404 } 405 406 411 public int getArrowHeadHeight() { 412 return m_arrowHeight; 413 } 414 415 420 public int getArrowHeadWidth() { 421 return m_arrowWidth; 422 } 423 424 429 public int getHorizontalAlignment1() { 430 return m_xAlign1; 431 } 432 433 438 public int getVerticalAlignment1() { 439 return m_yAlign1; 440 } 441 442 448 public int getHorizontalAlignment2() { 449 return m_xAlign2; 450 } 451 452 457 public int getVerticalAlignment2() { 458 return m_yAlign2; 459 } 460 461 467 public void setHorizontalAlignment1(int align) { 468 m_xAlign1 = align; 469 } 470 471 477 public void setVerticalAlignment1(int align) { 478 m_yAlign1 = align; 479 } 480 481 488 public void setHorizontalAlignment2(int align) { 489 m_xAlign2 = align; 490 } 491 492 498 public void setVerticalAlignment2(int align) { 499 m_yAlign2 = align; 500 } 501 502 508 public void setDefaultLineWidth(double w) { 509 m_width = w; 510 } 511 512 518 public double getDefaultLineWidth() { 519 return m_width; 520 } 521 522 } | Popular Tags |