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.polygon;
27
28
29 import java.awt.Graphics2D;
30 import java.util.ArrayList;
31 import java.util.Collection;
32 import java.util.Iterator;
33
34 import math.geom2d.AffineTransform2D;
35 import math.geom2d.Box2D;
36 import math.geom2d.Point2D;
37 import math.geom2d.circulinear.CirculinearBoundarySet2D;
38 import math.geom2d.circulinear.CirculinearCurve2DUtils;
39 import math.geom2d.circulinear.CirculinearDomain2D;
40 import math.geom2d.circulinear.GenericCirculinearDomain2D;
41 import math.geom2d.domain.Boundary2DUtils;
42 import math.geom2d.domain.Domain2D;
43 import math.geom2d.domain.GenericDomain2D;
44 import math.geom2d.line.LineSegment2D;
45 import math.geom2d.line.StraightLine2D;
46 import math.geom2d.transform.CircleInversion2D;
47
48
49
50
51 public class Rectangle2D implements Polygon2D {
52
53
54
55
56
57
58
59 protected double x0;
60 protected double y0;
61 protected double w;
62 protected double h;
63 protected double theta;
64
65
66
67
68
69 public Rectangle2D(double x0, double y0, double w, double h, double theta) {
70 this.x0 = x0;
71 this.y0 = y0;
72 this.w = w;
73 this.h = h;
74 this.theta = theta;
75 }
76
77
78 public Rectangle2D() {
79 this(0, 0, 0, 0, 0);
80 }
81
82
83 public Rectangle2D(java.awt.geom.Rectangle2D rect) {
84 this.x0 = rect.getX();
85 this.y0 = rect.getY();
86 this.w = rect.getWidth();
87 this.h = rect.getHeight();
88 this.theta = 0;
89 }
90
91
92 public Rectangle2D(double x0, double y0, double w, double h) {
93 this.x0 = x0;
94 this.y0 = y0;
95 this.w = w;
96 this.h = h;
97 this.theta = 0;
98 }
99
100
101 public Rectangle2D(Point2D point, double w, double h, double theta) {
102 this.x0 = point.getX();
103 this.y0 = point.getY();
104 this.w = w;
105 this.h = h;
106 this.theta = theta;
107 }
108
109
110 public Rectangle2D(Point2D point, double w, double h) {
111 this.x0 = point.getX();
112 this.y0 = point.getY();
113 this.w = w;
114 this.h = h;
115 this.theta = 0;
116 }
117
118
119
120
121 public double getX() {
122 return x0;
123 }
124
125 public double getY() {
126 return y0;
127 }
128
129 public double getWidth() {
130 return w;
131 }
132
133 public double getHeight() {
134 return h;
135 }
136
137 public double getTheta() {
138 return theta;
139 }
140
141
142
143
144
145
146
147 public void setRectangle(Rectangle2D rect) {
148 this.x0 = rect.x0;
149 this.y0 = rect.y0;
150 this.w = rect.w;
151 this.h = rect.h;
152 this.theta = rect.theta;
153 }
154
155
156
157
158 public void setRectangle(java.awt.geom.Rectangle2D rect) {
159 this.x0 = rect.getX();
160 this.y0 = rect.getY();
161 this.w = rect.getWidth();
162 this.h = rect.getHeight();
163 this.theta = 0;
164 }
165
166
167
168
169 public void setRectangle(double x, double y, double width, double height,
170 double theta) {
171 this.x0 = x;
172 this.y0 = y;
173 this.w = width;
174 this.h = height;
175 this.theta = theta;
176 }
177
178
179
180
181
182
183
184
185
186 public Collection<Point2D> getVertices() {
187 AffineTransform2D rot = AffineTransform2D.createRotation(x0, y0, theta);
188 ArrayList<Point2D> array = new ArrayList<Point2D>(4);
189
190 array.add(new Point2D(x0, y0).transform(rot));
191 array.add(new Point2D(x0+w, y0).transform(rot));
192 array.add(new Point2D(x0+w, y0+h).transform(rot));
193 array.add(new Point2D(x0, y0+h).transform(rot));
194
195 return array;
196 }
197
198
199
200
201
202
203 public Point2D getVertex(int i) {
204 AffineTransform2D rot = AffineTransform2D.createRotation(x0, y0, theta);
205 switch (i) {
206 case 0:
207 return new Point2D(x0, y0).transform(rot);
208 case 1:
209 return new Point2D(x0+w, y0).transform(rot);
210 case 2:
211 return new Point2D(x0+w, y0+h).transform(rot);
212 case 3:
213 return new Point2D(x0, y0+h).transform(rot);
214 default:
215 throw new IndexOutOfBoundsException();
216 }
217 }
218
219
220
221
222
223
224 public int getVertexNumber() {
225 return 4;
226 }
227
228 public Collection<LineSegment2D> getEdges() {
229 ArrayList<LineSegment2D> edges = new ArrayList<LineSegment2D>(4);
230 double cot = Math.cos(theta);
231 double sit = Math.sin(theta);
232
233 double x1 = w*cot+x0;
234 double y1 = w*sit+y0;
235 double x2 = w*cot-h*sit+x0;
236 double y2 = w*sit+h*cot+y0;
237 double x3 = -h*sit+x0;
238 double y3 = h*cot+y0;
239
240 edges.add(new LineSegment2D(x0, y0, x1, y1));
241 edges.add(new LineSegment2D(x1, y1, x2, y2));
242 edges.add(new LineSegment2D(x2, y2, x3, y3));
243 edges.add(new LineSegment2D(x3, y3, x0, y0));
244 return edges;
245 }
246
247 public int getEdgeNumber() {
248 return 4;
249 }
250
251
252
253
254 public Collection<LinearRing2D> getRings() {
255 ArrayList<LinearRing2D> rings = new ArrayList<LinearRing2D>(1);
256 rings.add(new LinearRing2D(this.getVertices()));
257 return rings;
258 }
259
260
261
262
263
264
265
266 public CirculinearDomain2D transform(CircleInversion2D inv) {
267 return new GenericCirculinearDomain2D(
268 this.getBoundary().transform(inv));
269 }
270
271
272
273
274 public CirculinearDomain2D getBuffer(double dist) {
275 return CirculinearCurve2DUtils.computeBuffer(
276 this.getBoundary(), dist);
277 }
278
279
280
281
282
283 public CirculinearBoundarySet2D<LinearRing2D> getBoundary() {
284 double cot = Math.cos(theta);
285 double sit = Math.sin(theta);
286 Point2D pts[] = new Point2D[4];
287 pts[0] = new Point2D(x0, y0);
288 pts[1] = new Point2D(w*cot+x0, w*sit+y0);
289 pts[2] = new Point2D(w*cot-h*sit+x0, w*sit+h*cot+y0);
290 pts[3] = new Point2D(-h*sit+x0, h*cot+y0);
291
292 return new CirculinearBoundarySet2D<LinearRing2D>(
293 new LinearRing2D(pts));
294 }
295
296 public Polygon2D complement() {
297 double cot = Math.cos(theta);
298 double sit = Math.sin(theta);
299 Point2D pts[] = new Point2D[4];
300 pts[0] = new Point2D(x0, y0);
301 pts[1] = new Point2D(-h*sit+x0, h*cot+y0);
302 pts[2] = new Point2D(w*cot-h*sit+x0, w*sit+h*cot+y0);
303 pts[3] = new Point2D(w*cot+x0, w*sit+y0);
304
305 return new SimplePolygon2D(pts);
306 }
307
308
309
310
311
312 public boolean isBounded() {
313 return true;
314 }
315
316 public boolean isEmpty() {
317 return false;
318 }
319
320 public double getDistance(java.awt.geom.Point2D p) {
321 return Math.max(getSignedDistance(p.getX(), p.getY()), 0);
322 }
323
324 public double getDistance(double x, double y) {
325 return Math.max(getSignedDistance(x, y), 0);
326 }
327
328
329
330
331
332
333
334 public double getSignedDistance(java.awt.geom.Point2D p) {
335 return getSignedDistance(p.getX(), p.getY());
336 }
337
338
339
340
341
342
343
344 public double getSignedDistance(double x, double y) {
345 double dist = getBoundary().getDistance(x, y);
346 if (contains(x, y))
347 return -dist;
348 else
349 return dist;
350 }
351
352
353
354
355 public Domain2D clip(Box2D box) {
356 return new GenericDomain2D(Boundary2DUtils.clipBoundary(this
357 .getBoundary(), box));
358 }
359
360
361
362
363 public Box2D getBoundingBox() {
364 double xmin = x0;
365 double xmax = x0;
366 double ymin = y0;
367 double ymax = y0;
368 double x, y;
369 double cot = Math.cos(theta);
370 double sit = Math.sin(theta);
371
372 x = w*cot+x0;
373 y = w*sit+y0;
374 if (xmin>x)
375 xmin = x;
376 if (ymin>y)
377 ymin = y;
378 if (xmax<x)
379 xmax = x;
380 if (ymax<y)
381 ymax = y;
382
383 x = w*cot-h*sit+x0;
384 y = w*sit+h*cot+y0;
385 if (xmin>x)
386 xmin = x;
387 if (ymin>y)
388 ymin = y;
389 if (xmax<x)
390 xmax = x;
391 if (ymax<y)
392 ymax = y;
393
394 x = h*sit+x0;
395 y = h*cot+y0;
396 if (xmin>x)
397 xmin = x;
398 if (ymin>y)
399 ymin = y;
400 if (xmax<x)
401 xmax = x;
402 if (ymax<y)
403 ymax = y;
404
405 return new Box2D(xmin, xmax, ymin, ymax);
406 }
407
408
409
410
411 public SimplePolygon2D transform(AffineTransform2D trans) {
412 int nPoints = 4;
413 Point2D[] array = new Point2D[nPoints];
414 Point2D[] res = new Point2D[nPoints];
415 Iterator<Point2D> iter = this.getVertices().iterator();
416 for (int i = 0; i<nPoints; i++) {
417 array[i] = iter.next();
418 res[i] = new Point2D();
419 }
420
421 trans.transform(array, res);
422 return new SimplePolygon2D(res);
423 }
424
425
426
427
428
429
430
431
432 public boolean contains(java.awt.geom.Point2D point) {
433 return contains(point.getX(), point.getY());
434 }
435
436 public boolean contains(double x, double y) {
437 double cot = Math.cos(theta);
438 double sit = Math.sin(theta);
439
440 double x1 = w*cot+x0;
441 double y1 = w*sit+y0;
442 double x2 = w*cot-h*sit+x0;
443 double y2 = w*sit+h*cot+y0;
444 double x3 = -h*sit+x0;
445 double y3 = h*cot+y0;
446
447 StraightLine2D line = new StraightLine2D(x0, y0, x1-x0, y1-y0);
448 if (line.getSignedDistance(x, y)>0)
449 return false;
450 line = new StraightLine2D(x1, y1, x2-x1, y2-y1);
451 if (line.getSignedDistance(x, y)>0)
452 return false;
453 line = new StraightLine2D(x2, y2, x3-x2, y3-y2);
454
455 if (line.getSignedDistance(x, y)>0)
456 return false;
457 line = new StraightLine2D(x3, y3, x0-x3, y0-y3);
458
459 if (line.getSignedDistance(x, y)>0)
460 return false;
461 return true;
462 }
463
464 public void draw(Graphics2D g2) {
465 g2.draw(this.getBoundary().getGeneralPath());
466 }
467
468 public void fill(Graphics2D g) {
469 g.fill(this.getBoundary().getGeneralPath());
470 }
471
472
473
474
475
476
477
478
479
480 @Override
481 public boolean equals(Object obj) {
482
483 if (!(obj instanceof Rectangle2D))
484 return false;
485 Rectangle2D rect = (Rectangle2D) obj;
486
487
488
489
490
491
492
493
494 boolean ok;
495 for (Point2D point : this.getVertices()) {
496 ok = false;
497
498
499
500
501
502
503 for (Point2D point2 : rect.getVertices())
504 if (point.equals(point2)) {
505 ok = true;
506 break;
507 }
508
509
510
511
512 if (!ok)
513 return false;
514 }
515
516
517 return true;
518 }
519
520 }