1
2 package math.geom2d.conic;
3
4 import java.awt.Graphics2D;
5 import java.util.ArrayList;
6 import java.util.Collection;
7
8 import math.geom2d.AffineTransform2D;
9 import math.geom2d.Box2D;
10 import math.geom2d.Point2D;
11 import math.geom2d.UnboundedShapeException;
12 import math.geom2d.Vector2D;
13 import math.geom2d.curve.AbstractSmoothCurve2D;
14 import math.geom2d.curve.Curve2D;
15 import math.geom2d.curve.Curve2DUtils;
16 import math.geom2d.curve.CurveArray2D;
17 import math.geom2d.curve.CurveSet2D;
18 import math.geom2d.curve.SmoothCurve2D;
19 import math.geom2d.domain.ContinuousBoundary2D;
20 import math.geom2d.domain.Domain2D;
21 import math.geom2d.domain.GenericDomain2D;
22 import math.geom2d.domain.SmoothBoundary2D;
23 import math.geom2d.line.LinearShape2D;
24
25
26
27
28 public class HyperbolaBranch2D extends AbstractSmoothCurve2D
29 implements SmoothBoundary2D, Cloneable {
30
31
32
33
34
35 Hyperbola2D hyperbola = null;
36
37
38
39
40
41 boolean positive = true;
42
43
44
45
46
47
48
49
50
51
52
53 public HyperbolaBranch2D(Hyperbola2D hyperbola, boolean b) {
54 this.hyperbola = hyperbola;
55 this.positive = b;
56 }
57
58
59
60
61
62
63
64 public Hyperbola2D getHyperbola() {
65 return hyperbola;
66 }
67
68
69
70
71
72
73
74 public boolean isPositiveBranch() {
75 return positive;
76 }
77
78
79
80
81
82
83
84
85 public double getCurvature(double t) {
86 double a = hyperbola.a;
87 double b = hyperbola.b;
88 double asih = a*Math.sinh(t);
89 double bcoh = b*Math.cosh(t);
90 return a*b/Math.pow(Math.hypot(bcoh, asih), 3);
91 }
92
93 public Vector2D getTangent(double t) {
94 double a = hyperbola.a;
95 double b = hyperbola.b;
96 double theta = hyperbola.theta;
97 double dx, dy;
98 if (positive) {
99 dx = a*Math.sinh(t);
100 dy = b*Math.cosh(t);
101 } else {
102 dx = -a*Math.sinh(t);
103 dy = -b*Math.cosh(t);
104 }
105 double cot = Math.cos(theta);
106 double sit = Math.sin(theta);
107 return new Vector2D(dx*cot-dy*sit, dx*sit+dy*cot);
108 }
109
110
111
112
113
114
115
116
117 public Collection<ContinuousBoundary2D> getBoundaryCurves() {
118 ArrayList<ContinuousBoundary2D> list = new ArrayList<ContinuousBoundary2D>();
119 list.add(this);
120 return list;
121 }
122
123 public Domain2D getDomain() {
124 return new GenericDomain2D(this);
125 }
126
127
128 public void fill(Graphics2D g2) {
129 throw new UnboundedShapeException(this);
130 }
131
132
133
134
135 public double getSignedDistance(java.awt.geom.Point2D point) {
136 double dist = this.getDistance(point);
137 return this.isInside(point) ? -dist : dist;
138 }
139
140 public double getSignedDistance(double x, double y) {
141 return this.getSignedDistance(new Point2D(x, y));
142 }
143
144 public double getWindingAngle(java.awt.geom.Point2D point) {
145
146 return 0;
147 }
148
149 public boolean isInside(java.awt.geom.Point2D point) {
150 if (hyperbola.isDirect()) {
151 if (hyperbola.isInside(point))
152 return true;
153 double x = hyperbola.toLocal(new Point2D(point)).getX();
154 return positive ? x<0 : x>0;
155 } else {
156 if (!hyperbola.isInside(point))
157 return false;
158 double x = hyperbola.toLocal(new Point2D(point)).getX();
159 return positive ? x>0 : x<0;
160 }
161 }
162
163
164
165
166
167 public boolean isClosed() {
168 return false;
169 }
170
171 public java.awt.geom.GeneralPath appendPath(
172 java.awt.geom.GeneralPath path) {
173 throw new UnboundedShapeException(this);
174 }
175
176
177
178
179
180 public Point2D getPoint(double t) {
181 if (Double.isInfinite(t))
182 throw new UnboundedShapeException(this);
183
184 double x, y;
185 if (positive) {
186 x = Math.cosh(t);
187 if (Double.isInfinite(x))
188 x = Math.abs(t);
189 y = Math.sinh(t);
190 if (Double.isInfinite(y))
191 y = t;
192 } else {
193 x = -Math.cosh(t);
194 if (Double.isInfinite(x))
195 x = -Math.abs(t);
196 y = -Math.sinh(t);
197 if (Double.isInfinite(y))
198 y = -t;
199 }
200 return hyperbola.toGlobal(new Point2D(x, y));
201 }
202
203 public double getPosition(java.awt.geom.Point2D point) {
204 Point2D pt = hyperbola.toLocal(new Point2D(point));
205 double y = this.positive ? pt.getY() : -pt.getY();
206 return Math.log(y+Math.hypot(y, 1));
207 }
208
209 public double project(java.awt.geom.Point2D point) {
210 Point2D pt = hyperbola.toLocal(new Point2D(point));
211 double y = this.positive ? pt.getY() : -pt.getY();
212 return Math.log(y+Math.hypot(y, 1));
213 }
214
215 public HyperbolaBranch2D getReverseCurve() {
216 Hyperbola2D hyper2 = new Hyperbola2D(hyperbola.xc, hyperbola.yc,
217 hyperbola.a, hyperbola.b, hyperbola.theta, !hyperbola.direct);
218 return new HyperbolaBranch2D(hyper2, positive);
219 }
220
221
222
223
224
225 public HyperbolaBranchArc2D getSubCurve(double t0, double t1) {
226 return new HyperbolaBranchArc2D(this, t0, t1);
227 }
228
229
230 public double getT0() {
231 return Double.NEGATIVE_INFINITY;
232 }
233
234
235 public double getT1() {
236 return Double.POSITIVE_INFINITY;
237 }
238
239 public Collection<Point2D> getIntersections(LinearShape2D line) {
240
241 Collection<Point2D> inters = hyperbola.getIntersections(line);
242
243
244 Collection<Point2D> result = new ArrayList<Point2D>();
245 for (Point2D point : inters) {
246 if (!(hyperbola.toLocal(point).getX()>0^positive))
247 result.add(point);
248 }
249
250
251 return result;
252 }
253
254
255
256
257
258
259 public Box2D getBoundingBox() {
260 return new Box2D(
261 Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY,
262 Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
263 }
264
265
266
267
268
269
270
271 public CurveSet2D<? extends HyperbolaBranchArc2D> clip(Box2D box) {
272
273 CurveSet2D<SmoothCurve2D> set = Curve2DUtils.clipSmoothCurve(this, box);
274
275
276 CurveArray2D<HyperbolaBranchArc2D> result =
277 new CurveArray2D<HyperbolaBranchArc2D>(set.getCurveNumber());
278
279
280 for (Curve2D curve : set.getCurves()) {
281 if (curve instanceof HyperbolaBranchArc2D)
282 result.addCurve((HyperbolaBranchArc2D) curve);
283 }
284 return result;
285 }
286
287 public double getDistance(java.awt.geom.Point2D point) {
288 Point2D projected = this.getPoint(this.project(new Point2D(point)));
289 return projected.getDistance(point);
290 }
291
292 public double getDistance(double x, double y) {
293 Point2D projected = this.getPoint(this.project(new Point2D(x, y)));
294 return projected.getDistance(x, y);
295 }
296
297
298 public boolean isBounded() {
299 return false;
300 }
301
302
303
304
305 public boolean isEmpty() {
306 return false;
307 }
308
309 public HyperbolaBranch2D transform(AffineTransform2D trans) {
310
311 Hyperbola2D hyperbola = this.hyperbola.transform(trans);
312 Point2D base = this.getPoint(0).transform(trans);
313
314
315 double d1 = hyperbola.getPositiveBranch().getDistance(base);
316 double d2 = hyperbola.getNegativeBranch().getDistance(base);
317
318
319 return new HyperbolaBranch2D(hyperbola, d1<d2);
320 }
321
322 public boolean contains(java.awt.geom.Point2D point) {
323 return this.contains(point.getX(), point.getY());
324 }
325
326 public boolean contains(double x, double y) {
327 if (!hyperbola.contains(x, y))
328 return false;
329 Point2D point = hyperbola.toLocal(new Point2D(x, y));
330 return point.getX()>0;
331 }
332
333
334
335
336 @Override
337 public boolean equals(Object obj) {
338 if(!(obj instanceof HyperbolaBranch2D))
339 return false;
340 HyperbolaBranch2D branch = (HyperbolaBranch2D) obj;
341
342 if(!hyperbola.equals(branch.hyperbola)) return false;
343 return positive==branch.positive;
344 }
345
346 @Override
347 public HyperbolaBranch2D clone() {
348 return new HyperbolaBranch2D(hyperbola.clone(), positive);
349 }
350 }