1 package com.github.celldynamics.quimp.geom;
2
3 import java.awt.geom.Line2D;
4 import java.util.ArrayList;
5 import java.util.List;
6
7 import org.scijava.vecmath.Tuple2d;
8 import org.scijava.vecmath.Tuple2f;
9 import org.scijava.vecmath.Vector2d;
10 import org.scijava.vecmath.Vector2f;
11
12
13
14
15
16
17
18
19 public class ExtendedVector2d extends Vector2d {
20
21
22
23
24
25
26 public ExtendedVector2d(double[] v) {
27 super(v);
28 }
29
30
31
32
33
34
35 public ExtendedVector2d(Tuple2d t1) {
36 super(t1);
37 }
38
39
40
41
42
43
44 public ExtendedVector2d(Tuple2f t1) {
45 super(t1);
46 }
47
48
49
50
51
52
53 public ExtendedVector2d(Vector2d v1) {
54 super(v1);
55 }
56
57
58
59
60
61
62 public ExtendedVector2d(Vector2f v1) {
63 super(v1);
64 }
65
66
67
68
69 public ExtendedVector2d() {
70 super();
71 }
72
73
74
75
76
77
78
79
80
81 public ExtendedVector2d(double xx, double yy) {
82 super(xx, yy);
83 }
84
85 private static final long serialVersionUID = -7238793665995665600L;
86
87
88
89
90 public void makeUnit() {
91
92 double length = length();
93 if (length != 0) {
94 x = x / length;
95 y = y / length;
96 }
97 }
98
99
100
101
102
103
104
105 public void setXY(double nx, double ny) {
106 y = ny;
107 x = nx;
108
109 }
110
111
112
113
114
115
116 public void addVec(ExtendedVector2d v) {
117 x += v.getX();
118 y += v.getY();
119 }
120
121
122
123
124
125
126 public void multiply(double d) {
127 x *= d;
128 y *= d;
129 }
130
131
132
133
134
135
136 public void power(double p) {
137 x = Math.pow(x, p);
138 y = Math.pow(y, p);
139
140 }
141
142
143
144
145
146
147
148
149 public static ExtendedVector2d../../../../com/github/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d/../com/github/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d unitVector(ExtendedVector2d../../../../com/github/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d a, ExtendedVector2d b) {
150 ExtendedVector2d vec = ExtendedVector2d.vecP2P(a, b);
151
152 double length = vec.length();
153 if (length != 0) {
154 vec.setX(vec.getX() / length);
155 vec.setY(vec.getY() / length);
156 }
157 return vec;
158 }
159
160
161
162
163
164
165
166
167
168 public static List<Double> linspace(double start, double end, int numPoints) {
169 List<Double> result = new ArrayList<Double>();
170 double step = (end - start) / (numPoints - 1);
171 for (int i = 0; i <= numPoints - 2; i++) {
172 result.add(start + (i * step));
173 }
174 result.add(end);
175 return result;
176 }
177
178
179
180
181
182
183
184
185 public static ExtendedVector2d../../../../com/github/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d./../../com/github/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d vecP2P(ExtendedVector2d../../../../com/github/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d a, ExtendedVector2d b) {
186
187 ExtendedVector2dom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d vec = new ExtendedVector2d();
188
189 vec.setX(b.getX() - a.getX());
190 vec.setY(b.getY() - a.getY());
191 return vec;
192 }
193
194
195
196
197
198
199
200
201 public static double lengthP2P(ExtendedVector2d../../../../com/github/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d a, ExtendedVector2d b) {
202 ExtendedVector2d v = vecP2P(a, b);
203 return v.length();
204 }
205
206
207
208
209
210
211
212
213
214
215
216
217 public static ExtendedVector2d/../../../com/github/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2dithub/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d lineIntersectionOLD(ExtendedVector2d/../../../com/github/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d na1, ExtendedVector2d na2,
218 ExtendedVector2d/../../../com/github/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d nb1, ExtendedVector2d nb2) {
219 double aa;
220 double bb;
221 double ab;
222 double ba;
223 double denom;
224 aa = na2.getY() - na1.getY();
225 ba = na1.getX() - na2.getX();
226
227 ab = nb2.getY() - nb1.getY();
228 bb = nb1.getX() - nb2.getX();
229
230 denom = aa * bb - ab * ba;
231
232 if (denom == 0) {
233
234 return null;
235 }
236
237 double ca;
238 double cb;
239
240 ca = na2.getX() * na1.getY() - na1.getX() * na2.getY();
241 cb = nb2.getX() * nb1.getY() - nb1.getX() * nb2.getY();
242
243 ExtendedVector2d cp = null;
244 double da2;
245 double da1;
246 double ea1;
247 double ea2;
248
249
250 cp = new ExtendedVector2d((ba * cb - bb * ca) / denom, (ab * ca - aa * cb) / denom);
251
252
253
254
255
256 da1 = cp.getX() - na1.getX();
257 da2 = cp.getX() - na2.getX();
258 ea1 = cp.getY() - na1.getY();
259 ea2 = cp.getY() - na2.getY();
260
261 double db2;
262 double db1;
263 double eb1;
264 double eb2;
265 db1 = cp.getX() - nb1.getX();
266 db2 = cp.getX() - nb2.getX();
267 eb1 = cp.getY() - nb1.getY();
268 eb2 = cp.getY() - nb2.getY();
269
270 if ((Math.abs(ba) >= (Math.abs(da1) + Math.abs(da2)))
271 && (Math.abs(aa) >= (Math.abs(ea1) + Math.abs(ea2)))) {
272
273 if ((Math.abs(bb) >= (Math.abs(db1) + Math.abs(db2)))
274 && (Math.abs(ab) >= (Math.abs(eb1) + Math.abs(eb2)))) {
275
276
277
278 return cp;
279 }
280 }
281 return null;
282 }
283
284
285
286
287
288
289
290
291
292
293
294 public static ExtendedVector2d/../../../com/github/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2dthub/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d lineIntersectionOLD2(ExtendedVector2d/../../../com/github/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d na1, ExtendedVector2d na2,
295 ExtendedVector2d/../../../com/github/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d nb1, ExtendedVector2d nb2) {
296 if (Line2D.linesIntersect(na1.getX(), na1.getY(), na2.getX(), na2.getY(), nb1.getX(),
297 nb1.getY(), nb2.getX(), nb2.getY())) {
298
299 double aa;
300 double bb;
301 double ab;
302 double ba;
303 double denom;
304 aa = na2.getY() - na1.getY();
305 ba = na1.getX() - na2.getX();
306
307 ab = nb2.getY() - nb1.getY();
308 bb = nb1.getX() - nb2.getX();
309
310 denom = aa * bb - ab * ba;
311
312 if (denom == 0) {
313 System.out.println("parrellel lines");
314 return null;
315 }
316
317 double ca;
318 double cb;
319
320 ca = na2.getX() * na1.getY() - na1.getX() * na2.getY();
321 cb = nb2.getX() * nb1.getY() - nb1.getX() * nb2.getY();
322
323 ExtendedVector2d cp = null;
324
325 cp = new ExtendedVector2d((ba * cb - bb * ca) / denom, (ab * ca - aa * cb) / denom);
326
327
328
329 System.out.println("plot([" + na1.getX() + "," + na2.getX() + "],[" + na1.getY() + ","
330 + na2.getY() + "],'-ob');");
331 System.out.println("hold on; plot([" + nb1.getX() + "," + nb2.getX() + "],[" + nb1.getY()
332 + "," + nb2.getY() + "],'-or');");
333 System.out.println("plot(" + cp.x + "," + cp.y + ", 'og');");
334
335 return cp;
336 } else {
337 return null;
338 }
339 }
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358 public static int segmentIntersection(double x0, double y0, double x1, double y1, double x2,
359 double y2, double x3, double y3, double[] intersection) {
360
361 final double limit = 1e-5;
362 final double infinity = 1e8;
363
364 double x;
365 double y;
366
367
368
369
370
371
372 double a0 = equals(x0, x1, limit) ? infinity : (y0 - y1) / (x0 - x1);
373 double a1 = equals(x2, x3, limit) ? infinity : (y2 - y3) / (x2 - x3);
374
375 double b0 = y0 - a0 * x0;
376 double b1 = y2 - a1 * x2;
377
378
379 if (equals(a0, a1, limit)) {
380 if (!equals(b0, b1, limit)) {
381 return -1;
382
383 } else {
384 if (equals(x0, x1, limit)) {
385 if (Math.min(y0, y1) < Math.max(y2, y3) || Math.max(y0, y1) > Math.min(y2, y3)) {
386 double twoMiddle = y0 + y1 + y2 + y3 - min(y0, y1, y2, y3) - max(y0, y1, y2, y3);
387 y = (twoMiddle) / 2.0;
388 x = (y - b0) / a0;
389 } else {
390 return -1;
391 }
392 } else {
393 if (Math.min(x0, x1) < Math.max(x2, x3) || Math.max(x0, x1) > Math.min(x2, x3)) {
394 double twoMiddle = x0 + x1 + x2 + x3 - min(x0, x1, x2, x3) - max(x0, x1, x2, x3);
395 x = (twoMiddle) / 2.0;
396 y = a0 * x + b0;
397 } else {
398 return -1;
399 }
400 }
401
402 intersection[0] = x;
403 intersection[1] = y;
404 return -2;
405 }
406 }
407
408
409 if (equals(a0, infinity, limit)) {
410 x = x0;
411 y = a1 * x + b1;
412 } else if (equals(a1, infinity, limit)) {
413 x = x2;
414 y = a0 * x + b0;
415 } else {
416 x = -(b0 - b1) / (a0 - a1);
417 y = a0 * x + b0;
418 }
419
420 intersection[0] = x;
421 intersection[1] = y;
422
423
424 double distanceFrom1;
425 if (equals(x0, x1, limit)) {
426 if (y0 < y1) {
427 distanceFrom1 = y < y0 ? lengthP2P(new ExtendedVector2dm/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d(x, y), new ExtendedVector2d(x0, y0))
428 : y > y1 ? lengthP2P(new ExtendedVector2dm/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d(x, y), new ExtendedVector2d(x1, y1))
429 : 0.0;
430 } else {
431 distanceFrom1 = y < y1 ? lengthP2P(new ExtendedVector2dm/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d(x, y), new ExtendedVector2d(x1, y1))
432 : y > y0 ? lengthP2P(new ExtendedVector2dm/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d(x, y), new ExtendedVector2d(x0, y0))
433 : 0.0;
434 }
435 } else {
436 if (x0 < x1) {
437 distanceFrom1 = x < x0 ? lengthP2P(new ExtendedVector2dm/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d(x, y), new ExtendedVector2d(x0, y0))
438 : x > x1 ? lengthP2P(new ExtendedVector2dm/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d(x, y), new ExtendedVector2d(x1, y1))
439 : 0.0;
440 } else {
441 distanceFrom1 = x < x1 ? lengthP2P(new ExtendedVector2dm/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d(x, y), new ExtendedVector2d(x1, y1))
442 : x > x0 ? lengthP2P(new ExtendedVector2dm/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d(x, y), new ExtendedVector2d(x0, y0))
443 : 0.0;
444 }
445 }
446
447 double distanceFrom2;
448 if (equals(x2, x3, limit)) {
449
450 if (y2 < y3) {
451 distanceFrom2 = y < y2 ? lengthP2P(new ExtendedVector2dm/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d(x, y), new ExtendedVector2d(x2, y2))
452 : y > y3 ? lengthP2P(new ExtendedVector2dm/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d(x, y), new ExtendedVector2d(x3, y3))
453 : 0.0;
454 } else {
455 distanceFrom2 = y < y3 ? lengthP2P(new ExtendedVector2dm/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d(x, y), new ExtendedVector2d(x3, y3))
456 : y > y2 ? lengthP2P(new ExtendedVector2dm/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d(x, y), new ExtendedVector2d(x2, y2))
457 : 0.0;
458 }
459 } else {
460 if (x2 < x3) {
461 distanceFrom2 = x < x2 ? lengthP2P(new ExtendedVector2dm/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d(x, y), new ExtendedVector2d(x2, y2))
462 : x > x3 ? lengthP2P(new ExtendedVector2dm/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d(x, y), new ExtendedVector2d(x3, y3))
463 : 0.0;
464 } else {
465 distanceFrom2 = x < x3 ? lengthP2P(new ExtendedVector2dm/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d(x, y), new ExtendedVector2d(x3, y3))
466 : x > x2 ? lengthP2P(new ExtendedVector2dm/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d(x, y), new ExtendedVector2d(x2, y2))
467 : 0.0;
468 }
469 }
470
471 return equals(distanceFrom1, 0.0, limit) && equals(distanceFrom2, 0.0, limit) ? 1 : 0;
472 }
473
474
475
476
477
478
479
480
481
482 public static double triangleArea(ExtendedVector2d../../../../com/github/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d../../../../com/github/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d a, ExtendedVector2d../../../../com/github/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d b, ExtendedVector2d c) {
483
484 return (b.getX() - a.getX()) * (c.getY() - a.getY())
485 - (c.getX() - a.getX()) * (b.getY() - a.getY());
486 }
487
488
489
490
491
492
493
494
495
496 public static ExtendedVector2d../../../../com/github/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2dcom/github/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d pointToSegment(ExtendedVector2d../../../../com/github/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d p, ExtendedVector2d s0,
497 ExtendedVector2d s1) {
498 ExtendedVector2d v = ExtendedVector2d.vecP2P(s0, s1);
499 ExtendedVector2d w = ExtendedVector2d.vecP2P(s0, p);
500
501 double c1 = dot(w, v);
502 if (c1 <= 0) {
503 return s0;
504 }
505
506 double c2 = dot(v, v);
507 if (c2 <= c1) {
508 return s1;
509 }
510
511 double b = c1 / c2;
512
513 v.multiply(b);
514 v.addVec(s0);
515
516 return v;
517 }
518
519
520
521
522
523
524
525
526
527 public static double distPointToSegment(ExtendedVector2d../../../../com/github/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d p, ExtendedVector2d s0,
528 ExtendedVector2d s1) {
529 ExtendedVector2d closest = ExtendedVector2d.pointToSegment(p, s0, s1);
530 return ExtendedVector2d.lengthP2P(p, closest);
531 }
532
533
534
535
536
537
538
539
540 public static double dot(ExtendedVector2d../../../../com/github/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d a, ExtendedVector2d b) {
541 double d = a.getX() * b.getX();
542 d += a.getY() * b.getY();
543 return d;
544 }
545
546
547
548
549
550
551
552
553 public static double angleNonRelative(ExtendedVector2d./../../../com/github/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d aa, ExtendedVector2d bb) {
554 ExtendedVector2d a;
555 ExtendedVector2d b;
556 a = new ExtendedVector2d(aa.getX(), aa.getY());
557 b = new ExtendedVector2d(bb.getX(), bb.getY());
558 a.makeUnit();
559 b.makeUnit();
560
561 return Math.acos(dot(a, b));
562 }
563
564
565
566
567
568
569
570
571 public static double angle(ExtendedVector2d./../../../com/github/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d aa, ExtendedVector2d bb) {
572 ExtendedVector2d a;
573 ExtendedVector2d b;
574 a = new ExtendedVector2d(aa.getX(), aa.getY());
575 b = new ExtendedVector2d(bb.getX(), bb.getY());
576 a.makeUnit();
577 b.makeUnit();
578
579 return Math.atan2(b.getY(), b.getX()) - Math.atan2(a.getY(), a.getX());
580 }
581
582
583
584
585
586
587
588
589
590 public static double distPoinToInfLine(ExtendedVector2d../../../../com/github/celldynamics/quimp/geom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d p, ExtendedVector2d a,
591 ExtendedVector2d b) {
592 return (b.x - a.x) * (p.y - a.y) - (b.y - a.y) * (p.x - a.x);
593 }
594
595
596
597
598
599
600
601
602
603
604 private static boolean equals(double a, double b, double limit) {
605 return Math.abs(a - b) < limit;
606 }
607
608
609
610
611
612
613
614
615
616
617
618 private static double min(double a, double b, double c, double d) {
619 return Math.min(Math.min(a, b), Math.min(c, d));
620 }
621
622
623
624
625
626
627
628
629
630
631
632 private static double max(double a, double b, double c, double d) {
633 return Math.max(Math.max(a, b), Math.max(c, d));
634 }
635
636 }