1 package com.github.celldynamics.quimp.plugin.ecmm;
2
3 import com.github.celldynamics.quimp.Outline;
4 import com.github.celldynamics.quimp.Vert;
5 import com.github.celldynamics.quimp.geom.ExtendedVector2d;
6
7 import ij.IJ;
8
9
10
11
12
13
14
15 class Mapping {
16
17 Outline o1;
18 Outline o2;
19 Sector[] sectors;
20
21 public Mapping(Outlineef="../../../../../../com/github/celldynamics/quimp/Outline.html#Outline">Outline oo1, Outline oo2) {
22 o1 = oo1;
23 o2 = oo2;
24 ECMp.numINTS = 0;
25
26 if (ECMp.ANA || ECMp.forceNoSectors) {
27 insertFake();
28 o1.updateNormals(true);
29 o2.updateNormals(true);
30 formSectors();
31 return;
32 }
33
34
35 ECMp.numINTS = calcIntersects();
36
37 if (ECMp.numINTS == 0) {
38 System.out.println("No intersects found");
39 insertFake();
40 o1.updateNormals(true);
41 o2.updateNormals(true);
42 formSectors();
43 } else {
44 if (ECMp.inspectSectors) {
45 if (!inspectInts()) {
46 IJ.log(" invalid outline intersections. Intersects corrected");
47 if (ECMp.plot && ECMp.drawFails) {
48 ECMM_Mapping.plot.writeText("Intersects corrected");
49 }
50 rebuildInts();
51
52 }
53 }
54 if (ECMp.plot && ECMp.drawIntersects) {
55 drawIntersects();
56 }
57
58
59 o1.updateNormals(true);
60 o2.updateNormals(true);
61 formSectors();
62 }
63 }
64
65 public void printSector(int i) {
66 sectors[i].print();
67 }
68
69 private int calcIntersects() {
70
71 int ints = 0;
72
73 Vert na;
74 Vert nb;
75 Vert temp;
76 double[] intersect = new double[2];
77 int state;
78
79 na = o1.getHead();
80 do {
81
82 nb = o2.getHead();
83
84 do {
85 state = ExtendedVector2d.segmentIntersection(na.getX(), na.getY(), na.getNext().getX(),
86 na.getNext().getY(), nb.getX(), nb.getY(), nb.getNext().getX(), nb.getNext().getY(),
87 intersect);
88
89 if (state == 1) {
90
91 ints++;
92 temp = o1.insertVert(na);
93 temp.setX(intersect[0]);
94 temp.setY(intersect[1]);
95 temp.setIntPoint(true, ints);
96 na = na.getNext();
97
98 temp = o2.insertVert(nb);
99 temp.setX(intersect[0]);
100 temp.setY(intersect[1]);
101 temp.setIntPoint(true, ints);
102 nb = nb.getNext();
103 }
104 nb = nb.getNext();
105 } while (!nb.isHead());
106 na = na.getNext();
107 } while (!na.isHead());
108
109 return ints;
110 }
111
112 private void insertFake() {
113
114 ExtendedVector2d pos =
115 ExtendedVector2d.vecP2P(o1.getHead().getPoint(), o1.getHead().getNext().getPoint());
116 pos.multiply(0.5);
117 pos.addVec(o1.getHead().getPoint());
118
119 Vert temp = o1.insertVert(o1.getHead());
120 temp.setX(pos.getX());
121 temp.setY(pos.getY());
122 temp.setIntPoint(true, 1);
123
124 pos = ExtendedVector2d.vecP2P(o2.getHead().getPoint(), o2.getHead().getNext().getPoint());
125 pos.multiply(0.5);
126 pos.addVec(o2.getHead().getPoint());
127
128 temp = o2.insertVert(o2.getHead());
129 temp.setX(pos.getX());
130 temp.setY(pos.getY());
131 temp.setIntPoint(true, 1);
132 ECMp.numINTS++;
133 }
134
135 private boolean inspectInts() {
136
137
138
139
140 boolean valid = true;
141
142 Vert v1 = o1.getHead();
143 Vert v2;
144 Vert v1p;
145 Vert v2p;
146 Vert v2m;
147
148 for (int j = 0; j < ECMp.numINTS; j++) {
149 do {
150 v1 = v1.getNext();
151 } while (!v1.isIntPoint());
152
153 v2 = o2.getHead();
154 do {
155 if (v2.isIntPoint()) {
156 if (v2.intsectID == v1.intsectID) {
157 break;
158 }
159 }
160 v2 = v2.getNext();
161 } while (true);
162
163
164
165
166
167 v1p = v1;
168 do {
169 v1p = v1p.getNext();
170 } while (!v1p.isIntPoint());
171
172 v2p = v2;
173 do {
174 v2p = v2p.getNext();
175 } while (!v2p.isIntPoint());
176
177 v2m = v2;
178 do {
179 v2m = v2m.getPrev();
180 } while (!v2m.isIntPoint());
181
182 if (v1p.intsectID == v2p.intsectID) {
183
184 if (v1.intState == 0) {
185 v1.intState = 1;
186 }
187 if (v2.intState == 0) {
188 v2.intState = 1;
189 }
190
191 } else if (v1p.intsectID == v2m.intsectID) {
192 System.out.println("found inverse sector");
193 v1.intState = 3;
194 v2.intState = 3;
195
196
197
198 valid = false;
199 } else {
200
201 valid = false;
202 if (v1.intState == 0) {
203 v1.intState = 2;
204 }
205 if (v2.intState == 0) {
206 v2.intState = 2;
207 }
208 if (v1.intState == 3) {
209 v1.intState = 4;
210 }
211 if (v2.intState == 3) {
212 v2.intState = 4;
213 }
214 }
215 }
216
217 return valid;
218 }
219
220
221
222
223
224
225 private void rebuildInts() {
226
227 System.out.println("Rebuilding intersects");
228
229 Vert v1 = o1.getHead();
230 boolean found = false;
231 do {
232 if (v1.isIntPoint() && v1.intState == 1) {
233 found = true;
234 break;
235 }
236 v1 = v1.getNext();
237 } while (!v1.isHead());
238
239
240
241 if (!found) {
242 v1 = o1.getHead();
243 do {
244 if (v1.isIntPoint() && (v1.intState == 4 || v1.intState == 2)) {
245 found = true;
246 break;
247 }
248 v1 = v1.getNext();
249 } while (!v1.isHead());
250 }
251 if (!found) {
252 System.out.println(" ISSUE! ECMM.01 - NO valid sectors exist! (guessing correct sectors)");
253 v1 = Outline.findIntersect(v1, 4);
254 }
255
256
257 Vert v2 = Outline.findIntersect(o2.getHead(), v1.intsectID);
258
259
260
261
262 int startingInt = v1.intsectID;
263 Vert v1p;
264 Vert v2p;
265 Vert v1pp;
266 Vert v2pp;
267 double ratio1;
268 double ratio2;
269 int d1;
270 int d2;
271 int d3;
272 int d4;
273
274 if (ECMp.plot && ECMp.drawFails) {
275 ECMM_Mapping.plot.setColor(0, 0.8, 0);
276 }
277
278 do {
279
280 v1p = v1;
281 v2p = v2;
282 v1p = Outline.getNextIntersect(v1);
283 v2p = Outline.getNextIntersect(v2);
284 if (v1p.intsectID == v2p.intsectID) {
285 v1 = v1p;
286 v2 = v2p;
287 } else {
288 v1pp = Outline.findIntersect(v1p, v2p.intsectID);
289 v2pp = Outline.findIntersect(v2p, v1p.intsectID);
290
291 ratio1 = Outline.invertsBetween(v1, v1pp);
292 ratio2 = Outline.invertsBetween(v2, v2pp);
293
294 if (ratio1 == ratio2) {
295
296
297 d1 = Outline.distBetweenInts(v1, v1pp);
298 d2 = Outline.distBetweenInts(v2, v2pp);
299 d3 = Outline.distBetweenInts(v1, v1p);
300 d4 = Outline.distBetweenInts(v2, v2p);
301 ratio1 = (d1 > d3) ? d1 / d3 : d3 / d1;
302 ratio2 = (d2 > d4) ? d2 / d4 : d4 / d2;
303 }
304
305 if (ratio1 < ratio2) {
306 do {
307 v1 = v1.getNext();
308 if (v1.intsectID == v2p.intsectID) {
309 break;
310 }
311 if (v1.isIntPoint()) {
312 if (v1.intsectID == startingInt) {
313
314 }
315 o1.removeVert(v1);
316
317 o2.removeVert(Outline.findIntersect(o2.getHead(), v1.intsectID));
318
319 if (ECMp.plot && ECMp.drawFails) {
320 ECMM_Mapping.plot.drawCross(v1.getPoint(), 5);
321 }
322 }
323 } while (true);
324 v2 = v2p;
325 } else {
326 do {
327 v2 = v2.getNext();
328 if (v2.intsectID == v1p.intsectID) {
329 break;
330 }
331 if (v2.isIntPoint()) {
332 if (v2.intsectID == startingInt) {
333
334 }
335 o2.removeVert(v2);
336
337 o1.removeVert(Outline.findIntersect(o1.getHead(), v2.intsectID));
338
339 if (ECMp.plot && ECMp.drawFails) {
340 ECMM_Mapping.plot.drawCross(v2.getPoint(), 5);
341 }
342 }
343 } while (true);
344 v1 = v1p;
345 }
346 }
347 } while (v1.intsectID != startingInt);
348
349
350 v1 = o1.getHead();
351 int intersects = 0;
352 do {
353 if (v1.isIntPoint()) {
354 intersects++;
355 }
356 v1 = v1.getNext();
357 } while (!v1.isHead());
358
359 ECMp.numINTS = intersects;
360 System.out.println("finished rebuilding. INTS:" + ECMp.numINTS);
361 }
362
363 private void drawIntersects() {
364 if (!ECMp.plot) {
365 return;
366 }
367
368 ECMM_Mapping.plot.setColor(0, 0.8, 0);
369 Vert v1 = o1.getHead();
370 do {
371 if (v1.isIntPoint()) {
372 ECMM_Mapping.plot.drawCross(v1.getPoint(), 6);
373 ECMM_Mapping.plot.drawCircle(v1.getPoint(), 12);
374 }
375 v1 = v1.getNext();
376 } while (!v1.isHead());
377
378 }
379
380
381
382
383
384 private void formSectors() {
385
386 if (ECMp.numINTS == 0) {
387
388 System.out.println("No Intersects");
389 }
390 sectors = new Sector[ECMp.numINTS];
391
392 Vert vo1 = o1.getHead();
393 Vert vo2 = o2.getHead();
394
395 for (int i = 0; i < ECMp.numINTS; i++) {
396 do {
397 vo1 = vo1.getNext();
398 } while (!vo1.isIntPoint());
399 do {
400 vo2 = vo2.getNext();
401 if (vo2.isIntPoint()) {
402 if (vo2.intsectID == vo1.intsectID) {
403 break;
404 }
405 }
406 } while (true);
407
408 if (ECMp.numINTS == 1) {
409 sectors[0] = new Sector(0);
410 sectors[0].setStarts(vo1, vo2);
411 break;
412 } else {
413 if (i == 0) {
414 sectors[i] = new Sector(i);
415 sectors[i].setStarts(vo1, vo2);
416 sectors[ECMp.numINTS - 1] = new Sector(ECMp.numINTS - 1);
417
418 } else if (i == ECMp.numINTS - 1) {
419 sectors[i].setStarts(vo1, vo2);
420
421 } else {
422 sectors[i] = new Sector(i);
423 sectors[i].setStarts(vo1, vo2);
424
425 }
426 }
427 }
428
429 if (ECMp.numINTS == 1) {
430 sectors[0].constructWhole(o1.calcArea(), o2.calcArea());
431 } else {
432 for (int i = 0; i < ECMp.numINTS; i++) {
433 sectors[i].construct();
434
435 }
436 }
437 }
438
439
440
441
442
443
444 public Outline migrate() {
445 Vert newVert;
446 ExtendedVector2d newPos;
447 Sector s;
448
449 Vertcs/quimp/Vert.html#Vert">Vert mapHead = new Vert(-1);
450 OutlineOutline.html#Outline">Outline mappedOutline = new Outline(mapHead);
451 Vert currentMapVert = mapHead;
452 for (int i = 0; i < sectors.length; i++) {
453 s = sectors[i];
454 Vert v = s.getMigStart().getNext();
455
456 do {
457
458
459
460
461
462
463 newPos = ODEsolver.euler(v, s);
464 if (!v.snapped) {
465 ECMp.unSnapped++;
466 IJ.log(" node failed to map (" + ECMp.unSnapped + ") - removed");
467 if (!ECMp.ANA && ECMp.plot && ECMp.drawFails) {
468 ECMM_Mapping.plot.writeText("FN(" + ECMp.unSnapped + ")");
469 }
470 v = v.getNext();
471
472
473
474
475
476
477 continue;
478 }
479
480 newVert = mappedOutline.insertVert(currentMapVert);
481 newVert.tarLandingCoord = v.fLandCoord;
482 if (s.expansion) {
483 newVert.distance = -v.distance;
484 } else {
485 newVert.distance = v.distance;
486 }
487
488 if (!s.forwardMap) {
489 newVert.setX(v.getX());
490 newVert.setY(v.getY());
491 newVert.gCoord = v.gLandCoord;
492 newVert.fCoord = v.fLandCoord;
493 } else {
494 newVert.setX(newPos.getX());
495 newVert.setY(newPos.getY());
496 newVert.gCoord = v.gCoord;
497 newVert.fCoord = v.coord;
498 }
499
500 if (ECMp.ANA) {
501
502 newVert.setFluores(v.fluores);
503 newVert.setTrackNum(v.getTrackNum());
504 }
505 currentMapVert = newVert;
506 v = v.getNext();
507 } while (!v.isIntPoint());
508
509 }
510 mappedOutline.removeVert(mapHead);
511
512 return mappedOutline;
513 }
514
515 public Sector getSector(int i) {
516 if (i < 0 || i > ECMp.numINTS) {
517 IJ.error("sectors out of bounds - 250");
518 }
519 return sectors[i];
520 }
521
522 }