1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package math.geom2d.domain;
28
29
30 import java.util.Collection;
31
32 import math.geom2d.AffineTransform2D;
33 import math.geom2d.Angle2D;
34 import math.geom2d.Box2D;
35 import math.geom2d.Point2D;
36 import math.geom2d.Vector2D;
37 import math.geom2d.curve.ContinuousCurve2D;
38 import math.geom2d.curve.Curve2D;
39 import math.geom2d.curve.Curve2DUtils;
40 import math.geom2d.curve.CurveArray2D;
41 import math.geom2d.curve.CurveSet2D;
42 import math.geom2d.curve.PolyCurve2D;
43 import math.geom2d.curve.SmoothCurve2D;
44 import math.geom2d.line.StraightLine2D;
45
46
47
48
49
50
51
52
53
54 public class PolyOrientedCurve2D<T extends ContinuousOrientedCurve2D> extends
55 PolyCurve2D<T> implements ContinuousOrientedCurve2D {
56
57
58
59
60 public PolyOrientedCurve2D() {
61 super();
62 }
63
64 public PolyOrientedCurve2D(int size) {
65 super(size);
66 }
67
68 public PolyOrientedCurve2D(T[] curves) {
69 super(curves);
70 }
71
72 public PolyOrientedCurve2D(T[] curves, boolean closed) {
73 super(curves, closed);
74 }
75
76 public PolyOrientedCurve2D(Collection<? extends T> curves) {
77 super(curves);
78 }
79
80 public PolyOrientedCurve2D(Collection<? extends T> curves, boolean closed) {
81 super(curves, closed);
82 }
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112 public double getWindingAngle(java.awt.geom.Point2D point) {
113 double angle = 0;
114 for (OrientedCurve2D curve : this.curves)
115 angle += curve.getWindingAngle(point);
116 return angle;
117 }
118
119 public double getSignedDistance(java.awt.geom.Point2D p) {
120 return getSignedDistance(p.getX(), p.getY());
121 }
122
123
124
125
126
127
128 public double getSignedDistance(double x, double y) {
129 double dist = this.getDistance(x, y);
130
131 if (this.isInside(new Point2D(x, y)))
132 dist = -dist;
133
134 return dist;
135 }
136
137 private static Vector2D getTangent(ContinuousCurve2D curve, double pos) {
138
139 if (curve instanceof SmoothCurve2D)
140 return ((SmoothCurve2D) curve).getTangent(pos);
141
142
143 if (curve instanceof CurveSet2D) {
144 CurveSet2D<?> curveSet = (CurveSet2D<?>) curve;
145 double pos2 = curveSet.getLocalPosition(pos);
146 Curve2D subCurve = curveSet.getChildCurve(pos);
147 return getTangent((ContinuousCurve2D) subCurve, pos2);
148 }
149
150 System.err
151 .println("Unknown type of curve: should be either continuous or curveset");
152 return null;
153 }
154
155 public boolean isInside(java.awt.geom.Point2D point) {
156 double pos = this.project(point);
157
158 if (this.isSingular(pos)) {
159
160
161 int n = this.getCurveNumber();
162
163
164 int i = this.getCurveIndex(pos);
165 if (pos/2-i>.25)
166 i++;
167
168
169 if (Math.round(pos)==2*n-1) {
170 pos = 0;
171 i = 0;
172 }
173
174
175 Point2D vertex = this.getPoint(2*pos);
176
177
178 int iPrev = i>0 ? i-1 : n-1;
179
180 int iNext = i;
181
182
183 T prev = this.curves.get(iPrev);
184 T next = this.curves.get(iNext);
185
186
187 Vector2D v1 = getTangent(prev, prev.getT1());
188 Vector2D v2 = getTangent(next, next.getT0());
189
190
191 boolean in1 = new StraightLine2D(vertex, v1).isInside(point);
192 boolean in2 = new StraightLine2D(vertex, v2).isInside(point);
193
194
195 if (Angle2D.getAngle(v1, v2)<Math.PI) {
196 return in1&&in2;
197 } else {
198 return in1||in2;
199 }
200 } else {
201
202 return this.getChildCurve(pos).isInside(point);
203 }
204 }
205
206 @Override
207 public PolyOrientedCurve2D<? extends ContinuousOrientedCurve2D> getReverseCurve() {
208 ContinuousOrientedCurve2D[] curves2 = new ContinuousOrientedCurve2D[curves
209 .size()];
210 int n = curves.size();
211 for (int i = 0; i<n; i++)
212 curves2[i] = (ContinuousOrientedCurve2D)curves.get(n-1-i).getReverseCurve();
213 return new PolyOrientedCurve2D<ContinuousOrientedCurve2D>(curves2);
214 }
215
216
217
218
219 @Override
220 public PolyOrientedCurve2D<? extends ContinuousOrientedCurve2D> getSubCurve(
221 double t0, double t1) {
222 PolyCurve2D<?> set = super.getSubCurve(t0, t1);
223 PolyOrientedCurve2D<ContinuousOrientedCurve2D> subCurve = new PolyOrientedCurve2D<ContinuousOrientedCurve2D>();
224 subCurve.setClosed(false);
225
226
227 for (Curve2D curve : set.getCurves())
228 subCurve.addCurve((ContinuousOrientedCurve2D) curve);
229
230 return subCurve;
231 }
232
233
234
235
236
237
238
239 @Override
240 public CurveSet2D<? extends ContinuousOrientedCurve2D> clip(Box2D box) {
241
242 CurveSet2D<? extends Curve2D> set = Curve2DUtils.clipCurve(this, box);
243
244
245 int n = set.getCurveNumber();
246 CurveArray2D<ContinuousOrientedCurve2D> result =
247 new CurveArray2D<ContinuousOrientedCurve2D>(n);
248
249
250 for (Curve2D curve : set.getCurves()) {
251 if (curve instanceof ContinuousOrientedCurve2D)
252 result.addCurve((ContinuousOrientedCurve2D) curve);
253 }
254 return result;
255 }
256
257 @Override
258 public PolyOrientedCurve2D<?> transform(AffineTransform2D trans) {
259 PolyOrientedCurve2D<ContinuousOrientedCurve2D> result =
260 new PolyOrientedCurve2D<ContinuousOrientedCurve2D>();
261 for (ContinuousOrientedCurve2D curve : curves)
262 result.addCurve((ContinuousOrientedCurve2D)curve.transform(trans));
263 return result;
264 }
265 }