]> gerrit.simantics Code Review - simantics/sysdyn.git/blob
1b2bf60d2b78a383626edfe08da8af8200a4844e
[simantics/sysdyn.git] /
1 package org.simantics.sysdyn.ui.editor.routing;\r
2 \r
3 import java.awt.geom.Arc2D;\r
4 import java.awt.geom.Path2D;\r
5 import java.awt.geom.Point2D;\r
6 import java.awt.geom.Rectangle2D;\r
7 \r
8 import org.simantics.g2d.routing.IConnection;\r
9 import org.simantics.g2d.routing.IConnection.Connector;\r
10 import org.simantics.g2d.routing.IRouter2;\r
11 import org.simantics.sysdyn.ui.elements.connections.Arcs;\r
12 import org.simantics.utils.datastructures.Pair;\r
13 \r
14 public class DependencyRouter implements IRouter2 {\r
15     \r
16     public static DependencyRouter INSTANCE = new DependencyRouter();\r
17 \r
18         @Override\r
19         public void route(IConnection connection) {\r
20                 if(connection.getSegments().isEmpty())\r
21                         return;\r
22                 Object seg = connection.getSegments().iterator().next();\r
23         Connector begin = connection.getBegin(seg);\r
24         Connector end = connection.getEnd(seg);\r
25         \r
26         Pair<Arc2D, Path2D> shapes = new Pair<Arc2D, Path2D>(new Arc2D.Double(), new Path2D.Double());\r
27         createArrowShape(shapes,\r
28                         begin.parentObstacle,\r
29                         end.parentObstacle,\r
30                         0.1);\r
31         \r
32         Path2D path = new Path2D.Double();\r
33         path.append(shapes.first, false);\r
34         path.append(shapes.second, false);\r
35         connection.setPath(seg, path);\r
36         }\r
37 \r
38         \r
39         /*\r
40          * Total length of the arrow is ARROW_LENGTH1 + ARROW_LENGTH2\r
41          */\r
42     public static double ARROW_LENGTH1 = 0.2;\r
43     public static double ARROW_LENGTH2 = 1.0;\r
44     public static double ARROW_WIDTH = 0.5;\r
45     \r
46 \r
47         private static Path2D createArrow(Path2D shape, double x, double y, double dx, double dy) {\r
48                 if(shape == null)\r
49                         shape = new Path2D.Double();\r
50                 else\r
51                         shape.reset();\r
52                 \r
53         shape.moveTo(x+ARROW_LENGTH1*dx, y+ARROW_LENGTH1*dy);\r
54         x -= ARROW_LENGTH2*dx;\r
55         y -= ARROW_LENGTH2*dy;\r
56         shape.lineTo(x-ARROW_WIDTH*dy, y+ARROW_WIDTH*dx);\r
57         shape.lineTo(x+ARROW_WIDTH*dy, y-ARROW_WIDTH*dx);\r
58         shape.closePath();\r
59         return shape;\r
60     }\r
61         \r
62         public static Arc2D createArc(Arc2D arc, Rectangle2D tail, Rectangle2D head, double angle) {\r
63                 double x0 = tail.getCenterX();\r
64         double y0 = tail.getCenterY();\r
65         double x1 = head.getCenterX();\r
66         double y1 = head.getCenterY();\r
67         \r
68 //        System.out.println("createArrowShape " + x0 + " " + y0 + " " + x1 + " " + y1);\r
69         \r
70         double offset = \r
71             Math.abs(angle) < 1.0e-6\r
72             ? 1e3 * Math.signum(angle)\r
73             : Math.tan(Math.PI*0.5-angle)*0.5;\r
74             \r
75         double cx = 0.5*(x0+x1) + offset * (y1-y0);\r
76         double cy = 0.5*(y0+y1) + offset * (x0-x1);\r
77         double dx0 = x0 - cx;\r
78         double dy0 = y0 - cy;\r
79         double dx1 = x1 - cx;\r
80         double dy1 = y1 - cy;\r
81         \r
82         double r = Math.sqrt(dx0*dx0 + dy0*dy0);\r
83         \r
84 //        Rectangle2D bounds = new Rectangle2D.Double();\r
85 //        tail.getBounds(bounds);\r
86         double angle0 = Arcs.nextIntersectingAngle(cx, cy, r, \r
87             Math.atan2(-dy0, dx0), tail, angle < 0.0);\r
88 //        head.getBounds(bounds);\r
89         double angle1 = Arcs.nextIntersectingAngle(cx, cy, r, \r
90             Math.atan2(-dy1, dx1), head, angle > 0.0);\r
91         double extent = angle1-angle0;\r
92         //double arcAngle = angle0;\r
93         if(angle < 0.0) {\r
94             double temp = angle0;            \r
95             angle0 = angle1;\r
96             angle1 = temp;\r
97             extent = -extent;\r
98         }                \r
99         if(extent < 0)\r
100             extent += Math.PI*2.0;\r
101         else if(extent >= 360.0)\r
102             extent -= Math.PI*2.0;\r
103         if(arc == null)\r
104                 arc = new Arc2D.Double();\r
105         arc.setArc(cx-r, cy-r, 2*r, 2*r, \r
106             Math.toDegrees(angle0), \r
107             Math.toDegrees(extent), \r
108             Arc2D.OPEN);\r
109 //        \r
110                 return arc;\r
111         }\r
112         \r
113         public static Point2D computeCenter(Rectangle2D tail, Rectangle2D head, double angle) {\r
114 \r
115                 double x0 = tail.getCenterX();\r
116         double y0 = tail.getCenterY();\r
117         double x1 = head.getCenterX();\r
118         double y1 = head.getCenterY();\r
119         \r
120 //        System.out.println("createArrowShape " + x0 + " " + y0 + " " + x1 + " " + y1);\r
121         \r
122         double offset = \r
123             Math.abs(angle) < 1.0e-6\r
124             ? 1e3 * Math.signum(angle)\r
125             : Math.tan(Math.PI*0.5-angle)*0.5;\r
126             \r
127         double cx = 0.5*(x0+x1) + offset * (y1-y0);\r
128         double cy = 0.5*(y0+y1) + offset * (x0-x1);\r
129         \r
130         return new Point2D.Double(cx, cy);\r
131                 \r
132         }\r
133         \r
134         public static Pair<Arc2D, Path2D> createArrowShape(Pair<Arc2D, Path2D> shapes, Rectangle2D tail, Rectangle2D head, double angle) {\r
135                 if(shapes == null || shapes.first == null || shapes.second == null) {\r
136                         shapes = new Pair<Arc2D, Path2D>(new Arc2D.Double(), new Path2D.Double());\r
137                 }\r
138 \r
139                 createArc(shapes.first, tail, head, angle);\r
140                 \r
141         double angle0 =  Math.toRadians(shapes.first.getAngleStart());\r
142         double angle1 = Math.toRadians(shapes.first.getAngleStart() + shapes.first.getAngleExtent());\r
143         double x = Math.cos(angle > 0.0 ? angle1 : angle0);\r
144         double y = -Math.sin(angle > 0.0 ? angle1 : angle0);\r
145         double r = shapes.first.getHeight() / 2;\r
146         \r
147         createArrow(shapes.second, shapes.first.getCenterX() + r*x, shapes.first.getCenterY() + r*y, \r
148             angle < 0.0 ? -y : y, \r
149             angle > 0.0 ? -x : x);\r
150 \r
151         return shapes;\r
152         \r
153         }\r
154 }\r