1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.vectomatic.client.rep.view;
19
20 import static org.vectomatic.common.model.geometry.Ellipse.K;
21
22 import java.util.Iterator;
23 import java.util.List;
24
25 import org.vectomatic.common.model.IShapeVisitor;
26 import org.vectomatic.common.model.Shape;
27 import org.vectomatic.common.model.geometry.BezierSegment;
28 import org.vectomatic.common.model.geometry.BoundingBox;
29 import org.vectomatic.common.model.geometry.Ellipse;
30 import org.vectomatic.common.model.geometry.LineSegment;
31 import org.vectomatic.common.model.geometry.Path;
32 import org.vectomatic.common.model.geometry.Point;
33 import org.vectomatic.common.model.geometry.Polyline;
34 import org.vectomatic.common.model.geometry.Rect;
35 import org.vectomatic.common.model.geometry.Segment;
36 import org.vectomatic.common.model.geometry.ShapeGroup;
37 import org.vectomatic.common.model.geometry.TransformMatrix;
38
39
40
41
42
43 public class PickVisitor implements IShapeVisitor {
44 private DrawingView _view;
45 private Point _p, _p0, _p1, _p2, _p3;
46 private TransformMatrix _m;
47 private TransformMatrix[] _stack;
48 private int _index;
49 private boolean _picked;
50
51 public PickVisitor(DrawingView view) {
52 _view = view;
53 _m = new TransformMatrix();
54 _stack = new TransformMatrix[8];
55 _p0 = new Point();
56 _p1 = new Point();
57 _p2 = new Point();
58 _p3 = new Point();
59 }
60
61
62
63
64
65
66
67
68
69
70 public Shape pick(Point p, Iterator<Shape> shapes) {
71 _p = p;
72 _picked = false;
73 while(shapes.hasNext()) {
74 Shape shape = shapes.next();
75 shape.acceptVisitor(this);
76 if (_picked) {
77 return shape;
78 }
79 }
80 return null;
81 }
82
83
84 private TransformMatrix pushTransform(TransformMatrix m) {
85 TransformMatrix currentTransform;
86 if (_index == 0) {
87 _stack[_index] = m;
88 currentTransform = m;
89 } else {
90
91 if (_index >= _stack.length) {
92 TransformMatrix[] stack = new TransformMatrix[2 * _stack.length];
93 for (int i = 0; i < _stack.length; i++) {
94 stack[i] = _stack[i];
95 }
96 _stack = stack;
97 }
98
99 if (_stack[_index] == null) {
100 _stack[_index] = new TransformMatrix();
101 }
102 currentTransform = m.preMultiply(_stack[_index - 1], _stack[_index]);
103 }
104 _index++;
105 return currentTransform;
106 }
107
108 private void popTransform() {
109 _index--;
110 }
111
112 public void visitEllipse(Ellipse ellipse) {
113 BoundingBox bbox = ellipse.getBoundingBox();
114 TransformMatrix m = pushTransform(ellipse.getTransform());
115 _view.beginPath();
116 _p0.x = -1f;
117 _p0.y = 0f;
118 _p0.transform(m, _p1);
119 _view.moveTo(_p1.x, _p1.y);
120
121 _p0.x = -1f;
122 _p0.y = -K;
123 _p0.transform(m, _p1);
124 _p0.x = -K;
125 _p0.y = -1f;
126 _p0.transform(m, _p2);
127 _p0.x = 0f;
128 _p0.y = -1f;
129 _p0.transform(m, _p3);
130 _view.bezierCurveTo(_p1.x, _p1.y, _p2.x, _p2.y, _p3.x, _p3.y);
131
132 _p0.x = K;
133 _p0.y = -1f;
134 _p0.transform(m, _p1);
135 _p0.x = 1f;
136 _p0.y = -K;
137 _p0.transform(m, _p2);
138 _p0.x = 1f;
139 _p0.y = 0f;
140 _p0.transform(m, _p3);
141 _view.bezierCurveTo(_p1.x, _p1.y, _p2.x, _p2.y, _p3.x, _p3.y);
142
143 _p0.x = 1f;
144 _p0.y = K;
145 _p0.transform(m, _p1);
146 _p0.x = K;
147 _p0.y = 1f;
148 _p0.transform(m, _p2);
149 _p0.x = 0f;
150 _p0.y = 1f;
151 _p0.transform(m, _p3);
152 _view.bezierCurveTo(_p1.x, _p1.y, _p2.x, _p2.y, _p3.x, _p3.y);
153
154 _p0.x = -K;
155 _p0.y = bbox.ymax;
156 _p0.transform(m, _p1);
157 _p0.x = -1f;
158 _p0.y = K;
159 _p0.transform(m, _p2);
160 _p0.x = -1f;
161 _p0.y = 0f;
162 _p0.transform(m, _p3);
163 _view.bezierCurveTo(_p1.x, _p1.y, _p2.x, _p2.y, _p3.x, _p3.y);
164
165 _view.closePath();
166 _picked = _view.isPointInPath(_p.x, _p.y);
167 popTransform();
168 }
169
170 public void visitPolyline(Polyline polyline) {
171 TransformMatrix m = pushTransform(polyline.getTransform());
172 Point[] pts = polyline.getVertices();
173
174 _view.beginPath();
175 pts[0].transform(m, _p0);
176 _view.moveTo(_p0.x, _p0.y);
177 for (int i = 1; i < pts.length; i++) {
178 pts[i].transform(m, _p0);
179 _view.lineTo(_p0.x, _p0.y);
180 }
181 if (!polyline.isClosed()) {
182 float d = _view.convertToReferenceLength(3);
183 _m.translation(d, d);
184 m.preMultiply(_m, _m);
185 for (int i = pts.length - 1; i >= 0; i--) {
186 pts[i].transform(_m, _p0);
187 _view.lineTo(_p0.x, _p0.y);
188 }
189 pts[0].transform(_m, _p0);
190 _view.lineTo(_p0.x, _p0.y);
191 }
192 _view.closePath();
193 _picked = _view.isPointInPath(_p.x, _p.y);
194
195 popTransform();
196 }
197
198 public void visitRect(Rect rect) {
199 TransformMatrix m = pushTransform(rect.getTransform());
200
201 _view.beginPath();
202 _p0.x = -1f;
203 _p0.y = -1f;
204 _p0.transform(m, _p1);
205 _view.moveTo(_p1.x, _p1.y);
206
207 _p0.x = 1f;
208 _p0.y = -1f;
209 _p0.transform(m, _p2);
210 _view.lineTo(_p2.x, _p2.y);
211
212 _p0.x = 1f;
213 _p0.y = 1f;
214 _p0.transform(m, _p2);
215 _view.lineTo(_p2.x, _p2.y);
216
217 _p0.x = -1f;
218 _p0.y = 1f;
219 _p0.transform(m, _p2);
220 _view.lineTo(_p2.x, _p2.y);
221
222 _view.lineTo(_p1.x, _p1.y);
223
224 _view.closePath();
225 _picked = _view.isPointInPath(_p.x, _p.y);
226 popTransform();
227 }
228
229 public void visitShapeGroup(ShapeGroup group) {
230 pushTransform(group.getTransform());
231 List<Shape> shapes = group.getShapes();
232 for (int i = 0, size = shapes.size(); i < size && !_picked; i++) {
233 Shape shape = shapes.get(i);
234 shape.acceptVisitor(this);
235 }
236 popTransform();
237 }
238
239 public void visitPath(Path path) {
240 List<Segment> segments = path.getSegments();
241 if (path.isClosed()) {
242 TransformMatrix m = pushTransform(path.getTransform());
243 _view.beginPath();
244 for (int i = 0, size = segments.size(); i < size; i++) {
245 Segment segment = segments.get(i);
246 if (i == 0) {
247 _view.beginPath();
248 segment.getStartPoint().transform(m, _p0);
249 _view.moveTo(_p0.x, _p0.y);
250 }
251 if (segment instanceof LineSegment) {
252 segment.getEndPoint().transform(m, _p0);
253 _view.lineTo(_p0.x, _p0.y);
254 } else {
255 BezierSegment bezierSegment = (BezierSegment)segment;
256 bezierSegment.getStartControlPoint().transform(m, _p0);
257 bezierSegment.getEndControlPoint().transform(m, _p1);
258 bezierSegment.getEndPoint().transform(m, _p2);
259 _view.bezierCurveTo(_p0.x, _p0.y, _p1.x, _p1.y, _p2.x, _p2.y);
260 }
261 }
262 _view.closePath();
263 _picked = _view.isPointInPath(_p.x, _p.y);
264 popTransform();
265
266 } else {
267 TransformMatrix m = pushTransform(path.getTransform().invert(new TransformMatrix()));
268 float dmax = _view.convertToReferenceLength(3);
269 dmax *= dmax;
270 _p.transform(m, _p0);
271 for (int i = 0, size = segments.size(); i < size; i++) {
272 Segment segment = segments.get(i);
273 if (segment.squaredDistanceToPoint(_p0) < dmax) {
274 _picked = true;
275 break;
276 }
277 }
278 popTransform();
279 }
280 }
281 }