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.polygon;
28
29 import java.awt.Graphics2D;
30 import java.util.ArrayList;
31 import java.util.Collection;
32
33 import math.geom2d.AffineTransform2D;
34 import math.geom2d.Point2D;
35 import math.geom2d.Shape2D;
36 import math.geom2d.circulinear.*;
37 import math.geom2d.domain.ContinuousBoundary2D;
38 import math.geom2d.domain.Domain2D;
39 import math.geom2d.domain.GenericDomain2D;
40 import math.geom2d.line.LineSegment2D;
41 import math.geom2d.transform.CircleInversion2D;
42
43
44
45
46
47
48
49
50
51
52
53
54 public class LinearRing2D extends Polyline2D implements CirculinearContour2D {
55
56 public LinearRing2D() {
57 super();
58 }
59
60 public LinearRing2D(Point2D initialPoint) {
61 super(initialPoint);
62 }
63
64 public LinearRing2D(Point2D[] points) {
65 super(points);
66 }
67
68 public LinearRing2D(double[] xcoords, double[] ycoords) {
69 super(xcoords, ycoords);
70 }
71
72 public LinearRing2D(Collection<? extends Point2D> points) {
73 super(points);
74 }
75
76
77
78
79
80
81
82
83
84
85 public static LinearRing2D create(Collection<? extends Point2D> points) {
86 return new LinearRing2D(points);
87 }
88
89
90
91
92
93
94 public static LinearRing2D create(Point2D[] points) {
95 return new LinearRing2D(points);
96 }
97
98
99
100
101
102
103
104
105
106 public double getArea() {
107 return Math.abs(this.getSignedArea());
108 }
109
110
111
112
113
114
115
116
117
118
119 public double getSignedArea() {
120 double area = 0;
121 Point2D prev = this.points.get(this.points.size()-1);
122 Point2D point;
123 for (int i = 0; i<points.size(); i++) {
124 point = this.points.get(i);
125 area += prev.getX()*point.getY()-prev.getY()*point.getX();
126 prev = point;
127 }
128 return area /= 2;
129 }
130
131
132
133
134
135
136
137
138
139
140 @Override
141 public Collection<LineSegment2D> getEdges() {
142 int n = points.size();
143 ArrayList<LineSegment2D> edges = new ArrayList<LineSegment2D>();
144
145 if (n<2)
146 return edges;
147
148 for (int i = 0; i<n-1; i++)
149 edges.add(new LineSegment2D(points.get(i), points.get(i+1)));
150 edges.add(new LineSegment2D(points.get(n-1), points.get(0)));
151 return edges;
152 }
153
154 @Override
155 public LineSegment2D getLastEdge() {
156 int n = points.size();
157 if (n<2)
158 return null;
159 return new LineSegment2D(points.get(n-1), points.get(0));
160 }
161
162
163
164
165 @Override
166 public CirculinearRing2D getParallel(double dist) {
167 return GenericCirculinearRing2D.create(
168 CirculinearCurve2DUtils.createContinuousParallel(this, dist)
169 .getSmoothPieces());
170 }
171
172
173
174
175 @Override
176 public CirculinearContour2D transform(CircleInversion2D inv) {
177
178
179 Collection<LineSegment2D> edges = this.getEdges();
180 ArrayList<CirculinearElement2D> arcs =
181 new ArrayList<CirculinearElement2D>(edges.size());
182
183
184 for(LineSegment2D edge : edges) {
185 arcs.add(edge.transform(inv));
186 }
187
188
189 return new BoundaryPolyCirculinearCurve2D<CirculinearElement2D>(arcs);
190 }
191
192
193
194
195 public Collection<ContinuousBoundary2D> getBoundaryCurves() {
196 ArrayList<ContinuousBoundary2D> list =
197 new ArrayList<ContinuousBoundary2D>(1);
198 list.add(this);
199 return list;
200 }
201
202 public Domain2D getDomain() {
203 return new GenericDomain2D(this);
204 }
205
206 public void fill(Graphics2D g2) {
207 g2.fill(this.getGeneralPath());
208 }
209
210
211
212
213
214
215
216
217
218 @Override
219 public double getSignedDistance(double x, double y) {
220 return (this.isInside(x, y) ? -1 : 1)*this.getDistance(x, y);
221 }
222
223
224
225
226
227
228 @Override
229 public double getSignedDistance(java.awt.geom.Point2D point) {
230 return getSignedDistance(point.getX(), point.getY());
231 }
232
233
234
235
236
237
238 @Override
239 public double getWindingAngle(java.awt.geom.Point2D point) {
240 int wn = Polygon2DUtils.windingNumber(this.points, point);
241 return wn*2*Math.PI;
242 }
243
244 public boolean isInside(double x, double y) {
245 return this.isInside(new Point2D(x, y));
246 }
247
248
249
250
251
252
253 @Override
254 public boolean isInside(java.awt.geom.Point2D point) {
255
256 int wn = Polygon2DUtils.windingNumber(this.points, point);
257 if (wn==1)
258 return true;
259 if (this.contains(point))
260 return true;
261 return false;
262 }
263
264
265
266
267
268
269
270 @Override
271 public boolean isClosed() {
272 return true;
273 }
274
275
276
277
278
279
280
281
282 @Override
283 public math.geom2d.Point2D getPoint(double t) {
284
285 double t0 = this.getT0();
286 double t1 = this.getT1();
287 t = Math.max(Math.min(t, t1), t0);
288
289 int n = points.size();
290
291
292 int ind0 = (int) Math.floor(t+Shape2D.ACCURACY);
293 double tl = t-ind0;
294
295 if (ind0==n)
296 ind0 = 0;
297 Point2D p0 = points.get(ind0);
298
299
300 if (Math.abs(t-ind0)<Shape2D.ACCURACY)
301 return new Point2D(p0);
302
303
304 int ind1 = ind0+1;
305 if (ind1==n)
306 ind1 = 0;
307 Point2D p1 = points.get(ind1);
308
309
310 double x0 = p0.getX();
311 double y0 = p0.getY();
312 double dx = p1.getX()-x0;
313 double dy = p1.getY()-y0;
314
315 return new Point2D(x0+tl*dx, y0+tl*dy);
316 }
317
318
319
320
321 @Override
322 public double getT0() {
323 return 0;
324 }
325
326
327
328
329 @Override
330 public double getT1() {
331 return points.size();
332 }
333
334
335
336
337 @Override
338 public Point2D getFirstPoint() {
339 if (points.size()==0)
340 return null;
341 return points.get(0);
342 }
343
344
345
346
347 @Override
348 public Point2D getLastPoint() {
349 if (points.size()==0)
350 return null;
351 return points.get(0);
352 }
353
354 @Override
355 public Collection<? extends LinearRing2D> getContinuousCurves() {
356 return wrapCurve(this);
357 }
358
359
360
361
362
363
364 @Override
365 public LinearRing2D getReverseCurve() {
366 Point2D[] points2 = new Point2D[points.size()];
367 int n = points.size();
368 if (n>0) {
369 points2[0] = points.get(0);
370 for (int i = 1; i<n; i++)
371 points2[i] = points.get(n-i);
372 }
373 return new LinearRing2D(points2);
374 }
375
376
377
378
379
380 @Override
381 public Polyline2D getSubCurve(double t0, double t1) {
382
383
384 Polyline2D res = new Polyline2D();
385
386
387 int indMax = this.getVertexNumber();
388
389
390 t0 = Math.min(Math.max(t0, 0), indMax);
391 t1 = Math.min(Math.max(t1, 0), indMax);
392
393
394 int ind0 = (int) Math.floor(t0+Shape2D.ACCURACY);
395 int ind1 = (int) Math.floor(t1+Shape2D.ACCURACY);
396
397
398 if (ind0==ind1&&t0<t1) {
399
400 res.addPoint(this.getPoint(t0));
401 res.addPoint(this.getPoint(t1));
402
403 return res;
404 }
405
406
407 res.addPoint(this.getPoint(t0));
408
409 if (ind1>ind0) {
410
411 for (int n = ind0+1; n<=ind1; n++)
412 res.addPoint(points.get(n));
413 } else {
414
415 for (int n = ind0+1; n<indMax; n++)
416 res.addPoint(points.get(n));
417
418
419 for (int n = 0; n<=ind1; n++)
420 res.addPoint(points.get(n));
421 }
422
423
424 res.addPoint(this.getPoint(t1));
425
426
427 return res;
428 }
429
430
431
432
433
434
435
436 @Override
437 public LinearRing2D transform(AffineTransform2D trans) {
438 Point2D[] pts = new Point2D[points.size()];
439 for (int i = 0; i<points.size(); i++)
440 pts[i] = trans.transform(points.get(i));
441 return new LinearRing2D(pts);
442 }
443
444
445
446
447
448
449 @Override
450 public java.awt.geom.GeneralPath appendPath(java.awt.geom.GeneralPath path) {
451
452 if (points.size()<2)
453 return path;
454
455
456
457 Point2D p0 = this.getLastPoint();
458 path.moveTo((float) p0.getX(), (float) p0.getY());
459
460
461 for(Point2D point : points)
462 path.lineTo((float) point.getX(), (float) point.getY());
463
464
465 path.closePath();
466
467 return path;
468 }
469
470
471
472
473 @Override
474 public java.awt.geom.GeneralPath getGeneralPath() {
475 java.awt.geom.GeneralPath path = new java.awt.geom.GeneralPath();
476 if (points.size()<2)
477 return path;
478 return this.appendPath(path);
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496 }
497
498 @Override
499 public boolean equals(Object object) {
500 if (!(object instanceof LinearRing2D))
501 return false;
502 LinearRing2D ring = (LinearRing2D) object;
503
504 if (points.size()!=ring.points.size())
505 return false;
506 for (int i = 0; i<points.size(); i++)
507 if (!(points.get(i)).equals(ring.points.get(i)))
508 return false;
509 return true;
510 }
511
512 @Override
513 public LinearRing2D clone() {
514 ArrayList<Point2D> array = new ArrayList<Point2D>(points.size());
515 for(Point2D point : points)
516 array.add(point.clone());
517 return new LinearRing2D(array);
518 }
519 }