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 package math.geom2d.transform;
27
28 import java.util.*;
29 import math.geom2d.conic.Circle2D;
30 import math.geom2d.conic.CircleArc2D;
31 import math.geom2d.curve.PolyCurve2D;
32 import math.geom2d.domain.BoundaryPolyCurve2D;
33 import math.geom2d.domain.BoundarySet2D;
34 import math.geom2d.line.LineSegment2D;
35 import math.geom2d.line.LinearShape2D;
36 import math.geom2d.line.StraightLine2D;
37 import math.geom2d.polygon.Polygon2D;
38 import math.geom2d.polygon.Polyline2D;
39 import math.geom2d.polygon.LinearRing2D;
40 import math.geom2d.Angle2D;
41 import math.geom2d.Point2D;
42 import math.geom2d.Shape2D;
43
44
45
46
47
48
49
50 public class CircleInversion2D implements Transform2D {
51
52
53
54
55
56
57 protected Circle2D circle = new Circle2D();
58
59
60
61
62
63
64
65
66 public CircleInversion2D() {
67 this.circle = new Circle2D(0, 0, 1);
68 }
69
70 public CircleInversion2D(Circle2D circle) {
71 this.circle = circle;
72 }
73
74
75
76
77 public Point2D getCenter() {
78 return circle.getCenter();
79 }
80
81 public double getRadius() {
82 return circle.getRadius();
83 }
84
85 public void setCircle(double xc, double yc, double r) {
86 this.circle = new Circle2D(xc, yc, r);
87 }
88
89 public void setCircle(Circle2D circle) {
90 this.circle = new Circle2D(circle.getCenter(), circle.getRadius());
91 }
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110 public Shape2D transformShape(Shape2D shape) {
111
112 if (shape instanceof Point2D) {
113 double xc = circle.getCenter().getX();
114 double yc = circle.getCenter().getY();
115 double r = circle.getRadius();
116 Point2D pt = (Point2D) shape;
117
118 double d = r*r/pt.getDistance(xc, yc);
119 double theta = Math.atan2(pt.getY()-yc, pt.getX()-xc);
120 return Point2D.createPolar(circle.getCenter(), d, theta);
121 } else if (shape instanceof LinearShape2D) {
122 Point2D center = circle.getCenter();
123 double r = circle.getRadius();
124 LinearShape2D line = (LinearShape2D) shape;
125
126 Point2D po = line.getSupportingLine().getProjectedPoint(center);
127 double d = center.getDistance(po);
128
129
130
131 if (Math.abs(d)<Shape2D.ACCURACY)
132 return new StraightLine2D(line);
133
134
135 double angle = Angle2D.getHorizontalAngle(center, po);
136
137
138 double r2 = r*r/d/2;
139 Point2D c2 = Point2D.createPolar(center, r2, angle);
140
141
142 if (line instanceof StraightLine2D)
143 return new Circle2D(c2, r2);
144
145
146 if (line instanceof LineSegment2D) {
147 LineSegment2D segment = (LineSegment2D) line;
148
149
150 Point2D p1 = segment.getFirstPoint();
151 Point2D p2 = segment.getLastPoint();
152 p1 = this.transformPoint(p1);
153 p2 = this.transformPoint(p2);
154
155
156 double theta1 = Angle2D.getHorizontalAngle(c2, p1);
157 double theta2 = Angle2D.getHorizontalAngle(c2, p2);
158
159 boolean direct = new StraightLine2D(segment).isInside(center);
160
161 return new CircleArc2D(c2, r2, theta1, theta2, direct);
162 }
163 } else if (shape instanceof Circle2D) {
164 Point2D center = circle.getCenter();
165 Circle2D circle = (Circle2D) shape;
166
167 Point2D c1 = circle.getCenter();
168 StraightLine2D line = new StraightLine2D(center, c1);
169
170
171 Collection<Point2D> points = circle.getIntersections(line);
172 Iterator<Point2D> iter = points.iterator();
173 Point2D p1 = this.transformPoint(iter.next());
174 Point2D p2 = this.transformPoint(iter.next());
175
176
177 double d = p1.getDistance(p2);
178 c1 = Point2D.midPoint(p1, p2);
179
180 return new Circle2D(c1, d/2);
181 } else if (shape instanceof Polyline2D) {
182
183 Collection<LineSegment2D> edges = ((Polyline2D) shape).getEdges();
184
185
186 ArrayList<CircleArc2D> arcs = new ArrayList<CircleArc2D>();
187 for (LineSegment2D edge : edges)
188 arcs.add((CircleArc2D) this.transformShape(edge));
189
190
191 return new PolyCurve2D<CircleArc2D>(arcs);
192 } else if (shape instanceof Polygon2D) {
193
194 Collection<? extends LinearRing2D> rings = ((Polygon2D) shape).getRings();
195
196
197 ArrayList<BoundaryPolyCurve2D<CircleArc2D>> curves =
198 new ArrayList<BoundaryPolyCurve2D<CircleArc2D>>(rings.size());
199 for (LinearRing2D ring : rings)
200 curves.add(this.transformRing(ring));
201
202
203 return new BoundarySet2D<BoundaryPolyCurve2D<CircleArc2D>>(curves);
204 }
205
206 return null;
207 }
208
209
210
211
212
213 @Deprecated
214 public Shape2D transform(Shape2D shape) {
215 return this.transformShape(shape);
216 }
217
218
219 public Point2D transformPoint(java.awt.geom.Point2D pt) {
220 Point2D center = circle.getCenter();
221 double r = circle.getRadius();
222
223 double d = r*r/Point2D.getDistance(pt, center);
224 double theta = Angle2D.getHorizontalAngle(center, pt);
225 return Point2D.createPolar(center, d, theta);
226 }
227
228 public BoundaryPolyCurve2D<CircleArc2D> transformRing(LinearRing2D ring) {
229
230 Collection<LineSegment2D> edges = ring.getEdges();
231
232
233 ArrayList<CircleArc2D> arcs = new ArrayList<CircleArc2D>();
234 for (LineSegment2D edge : edges)
235 arcs.add((CircleArc2D) this.transformShape(edge));
236
237
238 return new BoundaryPolyCurve2D<CircleArc2D>(arcs);
239 }
240
241 public Point2D transform(java.awt.geom.Point2D pt) {
242 Point2D center = circle.getCenter();
243 double r = circle.getRadius();
244
245 double d = r*r/Point2D.getDistance(pt, center);
246 double theta = Angle2D.getHorizontalAngle(center, pt);
247 return Point2D.createPolar(center, d, theta);
248 }
249
250
251 public Point2D[] transform(java.awt.geom.Point2D[] src, Point2D[] dst) {
252
253 double d, theta;
254 double xc, yc, r;
255
256
257 if (dst==null)
258 dst = new Point2D[src.length];
259
260
261 if (dst[0]==null)
262 for (int i = 0; i<dst.length; i++)
263 dst[i] = new Point2D();
264
265 xc = circle.getCenter().getX();
266 yc = circle.getCenter().getY();
267 r = circle.getRadius();
268
269
270 for (int i = 0; i<src.length; i++) {
271 d = java.awt.geom.Point2D.distance(src[i].getX(), src[i].getY(), xc, yc);
272 d = r*r/d;
273 theta = Math.atan2(src[i].getY()-yc, src[i].getX()-xc);
274 dst[i].setLocation(d*Math.cos(theta), d*Math.sin(theta));
275 }
276
277 return dst;
278 }
279
280 }