1
2
3
4
5 package math.geom2d.polygon;
6
7 import java.util.ArrayList;
8 import java.util.Collection;
9 import java.util.SortedSet;
10 import java.util.TreeSet;
11
12 import math.geom2d.Point2D;
13 import math.geom2d.domain.BoundaryPolyCurve2D;
14 import math.geom2d.domain.BoundarySet2D;
15 import math.geom2d.domain.Domain2D;
16 import math.geom2d.domain.GenericDomain2D;
17 import math.geom2d.domain.SmoothOrientedCurve2D;
18 import math.geom2d.line.LineSegment2D;
19
20
21
22
23 public abstract class Polygon2DUtils {
24
25
26
27
28
29
30
31
32
33 public final static int windingNumber(Collection<Point2D> vertices,
34 java.awt.geom.Point2D point) {
35 int wn = 0;
36
37
38 Point2D previous = null;
39 for (Point2D vertex : vertices)
40 previous = vertex;
41 double x1 = previous.getX();
42 double y1 = previous.getY();
43 double x2, y2;
44
45
46 double y = point.getY();
47 for (Point2D p : vertices) {
48
49 x2 = p.getX();
50 y2 = p.getY();
51
52
53 if (y1<=y) {
54 if (y2>y)
55 if (new LineSegment2D(x1, y1, x2, y2).isInside(point))
56 wn++;
57 } else {
58 if (y2<=y)
59 if (!(new LineSegment2D(x1, y1, x2, y2).isInside(point)))
60 wn--;
61 }
62
63
64 x1 = x2;
65 y1 = y2;
66 }
67
68 return wn;
69 }
70
71 public final static Domain2D createBuffer(Polygon2D polygon, double d) {
72 BoundarySet2D<BoundaryPolyCurve2D<SmoothOrientedCurve2D>> result =
73 new BoundarySet2D<BoundaryPolyCurve2D<SmoothOrientedCurve2D>>();
74
75 for (LinearRing2D ring : polygon.getBoundary())
76 result.addCurve(Polyline2DUtils.createClosedParallel(ring, d));
77
78 return new GenericDomain2D(result);
79 }
80
81 public final static Polygon2D union(Polygon2D polygon1,
82 Polygon2D polygon2) {
83
84
85 ArrayList<LinearRing2D> boundary = new ArrayList<LinearRing2D>();
86
87
88 BoundarySet2D<? extends LinearRing2D> boundary1 = polygon1.getBoundary();
89 BoundarySet2D<? extends LinearRing2D> boundary2 = polygon2.getBoundary();
90
91
92 ArrayList<Point2D> intersections = new ArrayList<Point2D>();
93 for(LinearRing2D ring1 : boundary1.getCurves()){
94 for(LinearRing2D ring2 : boundary2.getCurves()){
95 intersections.addAll(Polyline2DUtils.intersect(ring1, ring2));
96 }
97 }
98
99
100 if(intersections.size()==0) {
101 if(!polygon1.contains(boundary2.getFirstPoint())){
102 boundary.addAll(boundary2.getCurves());
103 }
104 if(!polygon2.contains(boundary1.getFirstPoint())){
105 boundary.addAll(boundary1.getCurves());
106 }
107 return new MultiPolygon2D(boundary);
108 }
109
110
111 SortedSet<Double> positions1 = new TreeSet<Double>();
112 SortedSet<Double> positions2 = new TreeSet<Double>();
113 for (Point2D p : intersections) {
114 positions1.add(new Double(boundary1.getPosition(p)));
115 positions2.add(new Double(boundary2.getPosition(p)));
116 }
117
118
119
120
121
122
123
124 ArrayList<Point2D> points = new ArrayList<Point2D>();
125
126
127 Point2D refPoint = intersections.iterator().next();
128 points.add(refPoint);
129
130
131
132 double pos = boundary1.getPosition(refPoint);
133
134
135 double nextPos = findNext(positions1, pos);
136 double middlePos = chooseBetween(pos, nextPos);
137 Point2D middlePoint = boundary1.getPoint(middlePos);
138
139
140 BoundarySet2D<? extends LinearRing2D> currentBoundary =
141 polygon2.contains(middlePoint) ? boundary2 : boundary1;
142 boolean isOnFirstBoundary = !polygon2.contains(middlePoint);
143
144
145 Point2D point = refPoint;
146 do{
147 if(isOnFirstBoundary){
148 nextPos = findNext(positions1, pos);
149
150 }
151 }while(point!=refPoint);
152
153
154 return null;
155 }
156
157 private final static <T> T findNext(SortedSet<T> set, T element){
158 SortedSet<T> tail = set.tailSet(element);
159 return tail.isEmpty() ? set.first() : tail.first();
160 }
161
162 private final static double chooseBetween(double pos1, double pos2) {
163 if(pos2>pos1) {
164 return pos1 + (pos2-pos1)/2;
165 } else {
166 return pos2/2;
167 }
168 }
169 }