1 package org.simantics.district.network.ui.nodes;
3 import java.awt.BasicStroke;
5 import java.awt.Graphics2D;
6 import java.awt.geom.Line2D;
7 import java.awt.geom.Path2D;
8 import java.awt.geom.Point2D;
9 import java.awt.geom.Rectangle2D;
11 import org.simantics.district.network.ui.styles.DistrictNetworkStaticInfoStyle;
12 import org.simantics.scenegraph.ParentNode;
13 import org.simantics.scenegraph.g2d.G2DNode;
14 import org.simantics.scenegraph.g2d.nodes.spatial.RTreeNode;
15 import org.simantics.scenegraph.utils.NodeUtil;
16 import org.simantics.utils.datastructures.Pair;
18 public class DistrictNetworkEdgeArrayNode extends G2DNode implements DeferredNode {
20 private static final long serialVersionUID = -8377444630205663419L;
22 public static final String NODE_KEY = "DISTRICT_NETWORK_EDGE_ARRAY";
24 private static final String RENDERER_ID = "edgeArrayDeferredRenderer";
26 private DistrictNetworkEdgeNode edgeNode = null;
27 private Double arrowLength;
28 private Path2D arrowPath;
31 public void render(Graphics2D g2d) {
32 ParentNode<?> root = (ParentNode<?>) NodeUtil.getNearestParentOfType(this, RTreeNode.class);
33 DeferredRenderingNode deferred = root != null ? (DeferredRenderingNode) root.getNode(RENDERER_ID) : null;
35 deferred.deferNode(g2d.getTransform(), this);
41 public void renderDeferred(Graphics2D g2d) {
44 if (arrowLength != null) {
45 double scale = DistrictNetworkEdgeNode.scaleStroke ? (Double) g2d.getRenderingHint(DistrictRenderingHints.KEY_VIEW_SCALE_UNDER_SPATIAL_ROOT) : 1.0;
46 g2d.setColor(Color.BLACK);
47 float lw = DistrictNetworkEdgeNode.STROKE.getLineWidth() / (float)scale;
48 g2d.setStroke(new BasicStroke(lw, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
50 double l = arrowLength;
51 double w = 2 * (double) lw * Math.signum(l);
52 if (Math.abs(w) > Math.abs(l)) w = l;
53 double offset = 2 * (double) lw;
55 int zoomLevel = (Integer) g2d.getRenderingHint(DistrictRenderingHints.KEY_VIEW_ZOOM_LEVEL);
57 Point2D centerPoint = edgeNode.getCenterPoint(zoomLevel);
58 Point2D direction = edgeNode.getDirection(zoomLevel);
59 double centerX = centerPoint.getX(), centerY = centerPoint.getY();
60 double deltaX = direction.getX(), deltaY = direction.getY();
62 // Ensure the line is always rendered on top of the edge
63 // to prevent overlap with static info rendered below it.
64 double odx = offset * deltaY;
65 double ody = offset * deltaX;
71 double x0 = centerX - l/2 * deltaX + ody;
72 double y0 = centerY - l/2 * deltaY - odx;
73 double x1 = centerX + (l/2 - w) * deltaX + ody;
74 double y1 = centerY + (l/2 - w) * deltaY - odx;
76 g2d.draw(new Line2D.Double(x0, y0, x1, y1));
78 arrowPath = new Path2D.Double();
79 arrowPath.moveTo(x1 + w * deltaX, y1 + w * deltaY);
80 arrowPath.lineTo(x1 + w * deltaY, y1 - w * deltaX);
81 arrowPath.lineTo(x1 - w * deltaY, y1 + w * deltaX);
82 arrowPath.closePath();
88 public Rectangle2D getBoundsInLocal() {
92 public void setEdgeNode(DistrictNetworkEdgeNode edgeNode) {
93 this.edgeNode = edgeNode;
96 public void setArrowLength(Double length) {
97 this.arrowLength = length;
100 public static Pair<String, Class<DeferredRenderingNode>> renderer() {
101 return Pair.make(RENDERER_ID, DeferredRenderingNode.class);