View Javadoc
1   package com.github.celldynamics.quimp.plugin.ecmm;
2   
3   import java.util.ArrayList;
4   
5   import com.github.celldynamics.quimp.Outline;
6   import com.github.celldynamics.quimp.Vert;
7   import com.github.celldynamics.quimp.geom.ExtendedVector2d;
8   
9   import ij.IJ;
10  import ij.process.FloatPolygon;
11  
12  /**
13   * A mapping between nodes?.
14   * 
15   * @author rtyson
16   *
17   */
18  class Sector {
19  
20    private int id;
21    private Vert startO1;
22    private Vert startO2;
23    public Outline migCharges;
24    public Outline tarCharges;
25    FloatPolygon chargesPoly;
26    FloatPolygon innerPoly;
27    FloatPolygon outerPoly; // if no intersects have to use these
28    public double lengthO1;
29    public double lengthO2;
30    public int vertSo1;
31    public int vertSo2; // num verts in 01 and o2
32    public boolean forwardMap; // mapping forward or reverse?
33    /**
34     * the cell expanding here. is segment T to the left or right of segment T+1.
35     */
36    public boolean expansion;
37    /**
38     * the other direction of the normals of migration charges.
39     */
40    public double outerNormal;
41  
42    /**
43     * Constructor of sector.
44     * 
45     * @param i id
46     */
47    public Sector(int i) {
48      id = i;
49    }
50  
51    /**
52     * Print Sector.
53     */
54    public void print() {
55      IJ.log("Sector " + id + "\nMig charges: ");
56      migCharges.print();
57      IJ.log("");
58  
59      IJ.log("tar charges: ");
60      tarCharges.print();
61    }
62  
63    /**
64     * Construct.
65     */
66    public void construct() {
67      // calc lengths, determin expansion, set charges
68      calcLengths();
69      // left or right? Use the "left" algorithm (sign of triangle area)
70      double sectorTriArea = ExtendedVector2d.triangleArea(startO1.getPoint(),
71              startO1.getNext().getPoint(), startO2.getNext().getPoint());
72  
73      if ((lengthO1 > lengthO2) || ECMp.forceForwardMapping) {
74        forwardMap = true;
75        migCharges = formCharges(startO1);
76        tarCharges = formCharges(startO2);
77        if (sectorTriArea > 0) {
78          expansion = true; //
79          outerNormal = -1.;
80        } else {
81          expansion = false; //
82          outerNormal = 1.;
83        }
84      } else {
85        forwardMap = false; // backward in time
86        migCharges = formCharges(startO2);//
87        tarCharges = formCharges(startO1);
88        if (sectorTriArea > 0) {
89          expansion = true; //
90          outerNormal = 1.;
91  
92        } else {
93          expansion = false; //
94          outerNormal = -1.;
95        }
96      }
97  
98      Vert v = migCharges.getHead();
99      ExtendedVector2d normal;
100     do {
101       normal = new ExtendedVector2d(v.getNormal().getX(), v.getNormal().getY());
102       normal.multiply(outerNormal * ECMp.w);
103       v.getPoint().addVec(normal);
104       v = v.getNext();
105     } while (!v.isHead());
106 
107     if (ECMp.chargeDensity != -1) {
108       migCharges.setResolution(ECMp.chargeDensity);
109       tarCharges.setResolution(ECMp.chargeDensity);
110     }
111 
112     // create polygon off all charges for cal point inside/outside sector
113     chargesPolygon();
114 
115   }
116 
117   /**
118    * constructWhole.
119    * 
120    * @param area1 area1
121    * @param area2 area2
122    */
123   public void constructWhole(double area1, double area2) {
124     Outline innerCharges;
125     Outline outerCharges;
126 
127     calcLengths();
128 
129     if (((lengthO1 > lengthO2) || ECMp.forceForwardMapping || ECMp.ANA)
130             && !ECMp.forceBackwardMapping) {
131       forwardMap = true;
132       migCharges = formCharges(startO1);
133       tarCharges = formCharges(startO2);
134       if (area1 > area2) {
135         expansion = false; // n is migrating from outside in
136         outerNormal = 1.;
137         innerCharges = tarCharges;
138         outerCharges = migCharges;
139       } else {
140         expansion = true; // n is migrating from inside out
141         outerNormal = -1.;
142         innerCharges = migCharges;
143         outerCharges = tarCharges;
144       }
145     } else {
146       forwardMap = false; // backward in time
147       migCharges = formCharges(startO2);//
148       tarCharges = formCharges(startO1);
149       if (area1 > area2) {
150         expansion = true; // n+1 is migrating from inside out, expansion
151         outerNormal = -1.;
152         innerCharges = migCharges;
153         outerCharges = tarCharges;
154       } else {
155         expansion = false; // n+1 is migrating from outside in, contraction
156         outerNormal = 1.;
157         innerCharges = tarCharges;
158         outerCharges = migCharges;
159       }
160     }
161 
162     Vert v = migCharges.getHead();
163     ExtendedVector2d normal;
164     do {
165       normal = new ExtendedVector2d(v.getNormal().getX(), v.getNormal().getY());
166       normal.multiply(outerNormal * ECMp.w);
167       v.getPoint().addVec(normal);
168       v = v.getNext();
169     } while (!v.isHead());
170 
171     if (ECMp.chargeDensity != -1) {
172       migCharges.setResolution(ECMp.chargeDensity);
173       tarCharges.setResolution(ECMp.chargeDensity);
174     }
175 
176     outerPoly = ioPolygons(outerCharges);
177     innerPoly = ioPolygons(innerCharges);
178 
179   }
180 
181   public void setStarts(Vertt" href="../../../../../../com/github/celldynamics/quimp/Vert.html#Vert">Vert a, Vert b) {
182     startO1 = a;
183     startO2 = b;
184   }
185 
186   private void calcLengths() {
187     lengthO1 = 0.;
188     vertSo1 = 0;
189     Vert v = startO1;
190     do {
191       lengthO1 += ExtendedVector2d.lengthP2P(v.getPoint(), v.getNext().getPoint());
192       vertSo1++;
193       v = v.getNext();
194     } while (!v.isIntPoint());
195 
196     lengthO2 = 0.;
197     vertSo2 = 0;
198     v = startO2;
199     do {
200       lengthO2 += ExtendedVector2d.lengthP2P(v.getPoint(), v.getNext().getPoint());
201       vertSo2++;
202       v = v.getNext();
203     } while (!v.isIntPoint());
204 
205     // double t = lengthO1;
206     // lengthO1 = lengthO2;
207     // lengthO2 = t;
208   }
209 
210   private Outline formCharges(Vert s) {
211     // create a new outline from the sector starting at s
212     Vertamics/quimp/Vert.html#Vert">Vert newV = new Vert(s.getX(), s.getY(), 1);
213     newV.setNormal(s.getNormal().getX(), s.getNormal().getY());
214     newV.setIntPoint(true, -1);
215     Outlineamics/quimp/Outline.html#Outline">Outline o = new Outline(newV);
216 
217     s = s.getNext();
218     do {
219       newV = o.insertVert(newV);
220       newV.setX(s.getX());
221       newV.setY(s.getY());
222       newV.setNormal(s.getNormal().getX(), s.getNormal().getY());
223 
224       if (s.isIntPoint()) {
225         newV.setIntPoint(true, -1);
226       }
227 
228       s = s.getNext();
229     } while (!s.getPrev().isIntPoint()); // copy the int point too
230 
231     return o;
232   }
233 
234   public Vert getMigStart() { // NOT CHARGES!
235     if (forwardMap) {
236       return startO1;
237     } else {
238       return startO2;
239     }
240   }
241 
242   public Vert getTarStart() { // NOT CHARGES
243     if (forwardMap) {
244       return startO2;
245     } else {
246       return startO1;
247     }
248   }
249 
250   public Vert/../../../../../com/github/celldynamics/quimp/Vert.html#Vert">Vert addTempCharge(Vert tv) {
251     // inserts a temporary charge into the charged nodes to ensure a
252     // migrating node
253     // remains within the boubdary of the outline. Have to find where to
254     // insert it though.
255     Vert v = migCharges.getHead();
256     double dis = 99999.;
257     double cdis;
258     Vert closest = v;
259     do {
260       cdis = ExtendedVector2d.distPointToSegment(tv.getPoint(), v.getPoint(),
261               v.getNext().getPoint());
262       if (cdis < dis) {
263         closest = v;
264         dis = cdis;
265       }
266       v = v.getNext();
267     } while (!v.isHead());
268 
269     Vert newVert = migCharges.insertVert(closest);
270     newVert.setTrackNum(-35);
271     newVert.setX(tv.getX());
272     newVert.setY(tv.getY());
273     ExtendedVector2dom/ExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d normal = new ExtendedVector2d(tv.getNormal().getX(), tv.getNormal().getY());
274     normal.multiply(outerNormal * ECMp.w);
275     newVert.getPoint().addVec(normal);
276     newVert.updateNormale(true);
277     return newVert;
278   }
279 
280   public void removeTempCharge(Vert v) {
281     migCharges.removeVert(v);
282   }
283 
284   private void chargesPolygon() {
285     ArrayList<ExtendedVector2d> points = new ArrayList<ExtendedVector2d>();
286 
287     Vert v = migCharges.getHead(); // get charges from head to int point, forward
288     do {
289 
290       points.add(v.getPoint());
291       if (v.isIntPoint() && !v.isHead()) {
292         break;
293       }
294       v = v.getNext();
295     } while (!v.isHead());
296 
297     // find int point in tar
298     v = tarCharges.getHead();
299     do {
300       v = v.getNext();
301     } while (!v.isIntPoint());
302 
303     // get tar charges in reverse
304     do {
305       points.add(v.getPoint());
306       v = v.getPrev();
307     } while (!v.getNext().isHead());
308 
309     // create floats
310     float[] x = new float[points.size()];
311     float[] y = new float[points.size()];
312 
313     ExtendedVector2d p;
314     for (int i = 0; i < points.size(); i++) {
315       p = (ExtendedVector2d) points.get(i);
316       x[i] = (float) p.getX();
317       y[i] = (float) p.getY();
318     }
319 
320     chargesPoly = new FloatPolygon(x, y, x.length);
321   }
322 
323   private FloatPolygon ioPolygons(Outline charges) { // in and out polygons
324     float[] x = new float[charges.getNumPoints()];
325     float[] y = new float[charges.getNumPoints()];
326 
327     int i = 0;
328     Vert v = charges.getHead();
329     do {
330       x[i] = (float) v.getX();
331       y[i] = (float) v.getY();
332       i++;
333       v = v.getNext();
334     } while (!v.isHead());
335 
336     return new FloatPolygon(x, y, x.length); // was this
337   }
338 
339   public boolean insideCharges(ExtendedVector2d p) {
340     if (ECMp.numINTS > 1) {
341       return chargesPoly.contains(p.getX(), p.getY());
342     } else {
343       if (outerPoly.contains(p.getX(), p.getY())) {
344         if (innerPoly.contains(p.getX(), p.getY())) {
345           return false;
346         } else {
347           return true;
348         }
349       } else {
350         return false;
351       }
352     }
353 
354   }
355 
356   public void switchMigDirection() {
357     Outline tempO = tarCharges; // swtich charges
358     tarCharges = migCharges;
359     migCharges = tempO;
360     forwardMap = !forwardMap;
361   }
362 }