1 package com.github.celldynamics.quimp;
2
3 import org.slf4j.Logger;
4 import org.slf4j.LoggerFactory;
5
6 import com.github.celldynamics.quimp.geom.ExtendedVector2d;
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 public abstract class PointsList<T extends PointsList<T>> {
22
23
24
25
26 static final Logger LOGGER = LoggerFactory.getLogger(PointsList.class.getName());
27
28
29
30
31 protected transient T prev;
32
33
34
35
36 protected transient T next;
37
38
39
40 protected ExtendedVector2d point;
41
42
43
44
45
46
47 protected ExtendedVector2d normal;
48
49
50
51
52 protected ExtendedVector2d tan;
53
54
55
56
57 protected boolean head = false;
58
59
60
61
62 private static boolean clockwise = true;
63
64
65
66
67 protected int tracknumber = 1;
68
69
70
71
72
73
74
75 protected double position = -1;
76
77
78
79 private boolean frozen = false;
80
81
82
83
84 public PointsList() {
85 point = new ExtendedVector2d();
86 normal = new ExtendedVector2d();
87 tan = new ExtendedVector2d();
88 }
89
90
91
92
93
94
95
96
97 public PointsList(int t) {
98 this();
99 setTrackNum(t);
100 }
101
102
103
104
105
106
107
108
109 public PointsList(final PointsList<?> src) {
110 this.point = new ExtendedVector2d(src.point);
111 this.normal = new ExtendedVector2d(src.normal);
112 this.tan = new ExtendedVector2d(src.tan);
113 this.head = src.head;
114 this.tracknumber = src.tracknumber;
115 this.position = src.position;
116 this.frozen = src.frozen;
117 }
118
119
120
121
122
123
124
125
126
127
128 public PointsList(double xx, double yy, int t) {
129 this(t);
130 point = new ExtendedVector2d(xx, yy);
131 }
132
133
134
135
136
137
138 @Override
139 public int hashCode() {
140 final int prime = 31;
141 int result = 1;
142 result = prime * result + (frozen ? 1231 : 1237);
143 result = prime * result + (head ? 1231 : 1237);
144 result = prime * result + ((normal == null) ? 0 : normal.hashCode());
145 result = prime * result + ((point == null) ? 0 : point.hashCode());
146 long temp;
147 temp = Double.doubleToLongBits(position);
148 result = prime * result + (int) (temp ^ (temp >>> 32));
149 result = prime * result + ((tan == null) ? 0 : tan.hashCode());
150 result = prime * result + tracknumber;
151 return result;
152 }
153
154
155
156
157
158
159 @Override
160 public boolean equals(Object obj) {
161 if (this == obj) {
162 return true;
163 }
164 if (obj == null) {
165 return false;
166 }
167 if (!(obj instanceof PointsList)) {
168 return false;
169 }
170 PointsList<?> other = (PointsList<?>) obj;
171 if (frozen != other.frozen) {
172 return false;
173 }
174 if (head != other.head) {
175 return false;
176 }
177 if (normal == null) {
178 if (other.normal != null) {
179 return false;
180 }
181 } else if (!normal.equals(other.normal)) {
182 return false;
183 }
184 if (point == null) {
185 if (other.point != null) {
186 return false;
187 }
188 } else if (!point.equals(other.point)) {
189 return false;
190 }
191 if (Double.doubleToLongBits(position) != Double.doubleToLongBits(other.position)) {
192 return false;
193 }
194 if (tan == null) {
195 if (other.tan != null) {
196 return false;
197 }
198 } else if (!tan.equals(other.tan)) {
199 return false;
200 }
201 if (tracknumber != other.tracknumber) {
202 return false;
203 }
204 return true;
205 }
206
207
208
209
210
211
212 public double getX() {
213 return point.getX();
214 }
215
216
217
218
219
220
221 public double getY() {
222 return point.getY();
223 }
224
225
226
227
228
229
230 public void setX(double x) {
231 point.setX(x);
232 }
233
234
235
236
237
238
239 public void setY(double y) {
240 point.setY(y);
241 }
242
243
244
245
246
247
248 public static void setClockwise(boolean b) {
249 PointsList.clockwise = b;
250 }
251
252
253
254
255
256
257 public ExtendedVector2d getPoint() {
258 return point;
259 }
260
261
262
263
264
265
266 public int getTrackNum() {
267 return tracknumber;
268 }
269
270
271
272
273
274
275 public ExtendedVector2d getNormal() {
276 return normal;
277 }
278
279
280
281
282
283
284 public ExtendedVector2d getTangent() {
285 return tan;
286 }
287
288
289
290
291
292
293 public double getPosition() {
294 return position;
295 }
296
297
298
299
300
301
302 public void setPosition(double position) {
303 this.position = position;
304 }
305
306
307
308
309
310
311 public boolean isHead() {
312 return head;
313 }
314
315
316
317
318
319
320
321 public void setNormal(double x, double y) {
322 normal.setX(x);
323 normal.setY(y);
324 }
325
326
327
328
329
330
331 public void setTrackNum(int b) {
332 tracknumber = b;
333 }
334
335
336
337
338
339
340
341
342
343
344
345
346 public void setHead(boolean t) {
347 head = t;
348 }
349
350
351
352
353
354
355 public T getPrev() {
356 if (clockwise) {
357 return prev;
358 } else {
359 return next;
360 }
361 }
362
363
364
365
366
367
368 public T getNext() {
369 if (clockwise) {
370 return next;
371 } else {
372 return prev;
373 }
374 }
375
376
377
378
379
380
381 public void setPrev(T n) {
382 if (clockwise) {
383 prev = n;
384 } else {
385 next = n;
386 }
387 }
388
389
390
391
392
393
394 public void setNext(T n) {
395 if (clockwise) {
396 next = n;
397 } else {
398 prev = n;
399 }
400 }
401
402
403
404
405
406
407 public void updateNormale(boolean inner) {
408 boolean c = clockwise;
409 clockwise = true;
410 tan = calcTan();
411
412 if (!inner) {
413 normal.setX(-tan.getY());
414 normal.setY(tan.getX());
415 } else {
416 normal.setX(tan.getY());
417 normal.setY(-tan.getX());
418 }
419 clockwise = c;
420
421 }
422
423
424
425
426
427
428
429
430
431
432 private ExtendedVector2d calcTan() {
433
434 ExtendedVector2d unitVecLeft = ExtendedVector2d.unitVector(point, prev.getPoint());
435 ExtendedVector2dedVector2d.html#ExtendedVector2d">ExtendedVector2d pointLeft = new ExtendedVector2d();
436 pointLeft.setX(getX());
437 pointLeft.setY(getY());
438 pointLeft.addVec(unitVecLeft);
439
440 ExtendedVector2d unitVecRight = ExtendedVector2d.unitVector(point, next.getPoint());
441 ExtendedVector2ddVector2d.html#ExtendedVector2d">ExtendedVector2d pointRight = new ExtendedVector2d();
442 pointRight.setX(getX());
443 pointRight.setY(getY());
444 pointRight.addVec(unitVecRight);
445
446 return ExtendedVector2d.unitVector(pointLeft, pointRight);
447 }
448
449
450
451
452 public static void randDirection() {
453 if (Math.random() < 0.5) {
454 clockwise = true;
455 } else {
456 clockwise = false;
457 }
458 }
459
460
461
462
463
464
465 @Override
466 public String toString() {
467 return "PointsList [point=" + point + ", normal=" + normal + ", tan=" + tan + ", head=" + head
468 + ", tracknumber=" + tracknumber + ", position=" + position + ", frozen=" + frozen
469 + "]";
470 }
471
472
473
474
475 public void freeze() {
476 frozen = true;
477 }
478
479
480
481
482 public void unfreeze() {
483 frozen = false;
484 }
485
486
487
488
489
490
491 public boolean isFrozen() {
492 return frozen;
493 }
494
495
496
497
498
499
500 public double getCurvatureLocal() {
501 ExtendedVector2d edge1 = ExtendedVector2d.vecP2P(this.getPoint(), this.getPrev().getPoint());
502 ExtendedVector2d edge2 = ExtendedVector2d.vecP2P(this.getPoint(), this.getNext().getPoint());
503
504 double angle = ExtendedVector2d.angle(edge1, edge2) * (180 / Math.PI);
505
506 if (angle > 360 || angle < -360) {
507 LOGGER.warn("Warning-angle out of range (Vert l:320)");
508 }
509
510 if (angle < 0) {
511 angle = 360 + angle;
512 }
513
514 double curvatureLocal = 0;
515 if (angle == 180) {
516 curvatureLocal = 0;
517 } else if (angle < 180) {
518 curvatureLocal = -1 * (1 - (angle / 180));
519 } else {
520 curvatureLocal = (angle - 180) / 180;
521 }
522 return curvatureLocal;
523 }
524
525 }