Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

261
LINES

< > BotCompany Repo | #1035369 // G22MeshMapper_v2 - tries to map mesh1 to mesh2 [dev.]

JavaX fragment (include) [tags: use-pretranspiled]

Transpiled version (25187L) is out of date.

1  
srecord noeq G22MeshMapper_v2(G22Mesh mesh1, G22Mesh mesh2) {
2  
  // import the important classes
3  
  delegate Anchor, Curve to G22Mesh.
4  
  delegate mapAnchor, unmapAnchor, tempMapAnchor to mm.
5  
  delegate MappedCurve to G22MeshMapping.
6  
  
7  
  // params
8  
  
9  
  settable bool chooseAnchor1AtRandom;
10  
  
11  
  // output
12  
  
13  
  G22MeshMapping mm;
14  
  settable L debugOutput;
15  
  
16  
  // for visualization
17  
  settable float contrast = 0.25f;
18  
  settable int brightness = 128;
19  
  
20  
  // index structures
21  
  
22  
  MultiMap<Int, Anchor> anchorsByArity2;
23  
    
24  
  // EXCEPTIONS (e.g. meshes don't match in signature)
25  
  
26  
  // set to the reason why when a mapping is deemed impossible
27  
  settable O rejectedBecause;
28  
  
29  
  bool rejected() { ret rejectedBecause != null; }
30  
  
31  
  // INTERNAL VARS
32  
  
33  
  bool prechecksDone;
34  
  S sig1, sig2;
35  
  Anchor anchor1; // first anchor to map
36  
  
37  
  G22MeshMapping get() { ret mm; }
38  
  
39  
  Search newSearch() {
40  
    ret new Search;
41  
  }
42  
  
43  
  // backtracking version
44  
  class Search extends VStackComputableWithStep<Void> is IMakeEmptyClone {
45  
    Anchor anchor2;
46  
    
47  
    public selfType makeEmptyClone() { ret new selfType; }
48  
    
49  
    void step(VStack stack) {
50  
      cast stack to BStack<?>;
51  
      
52  
      if (step == 0) {
53  
        prechecks();
54  
        if (rejected()) stack.ret();
55  
        step = 1;
56  
      } else if (step == 1) {
57  
        // make empty mapping
58  
        mm = new G22MeshMapping(mesh1, mesh2);
59  
        
60  
        anchorsByArity2 = multiMapIndex(mesh2.anchors(), a -> a.arity());
61  
        
62  
        // Choose first anchor to map - this is arbitrary
63  
        // (not a backtracking point)
64  
        anchor1 = chooseAnchor1AtRandom ? random(mesh1.anchors()) : first(mesh1.anchors());
65  
      
66  
        // Choose which anchor to map it to (first backtracking point).
67  
        // List should never be empty because we checked the signatures first.
68  
        L<Anchor> anchor2options = anchorsByArity2.get(anchor1.arity());
69  
        
70  
        step = 2;
71  
        stack.options(this, map(anchor2options, anchor2
72  
          -> instance -> instance.anchor2 = anchor2));
73  
      } else if (step == 2) {
74  
        print("G22MeshMapper_v2 step1: Connecting " + anchor1 + " to " + anchor2);
75  
        add(debugOutput, "Mapping anchor");
76  
        stack.temp(tempMapAnchor(anchor1, anchor2));
77  
        stack.temp(-> add(debugOutput, print("Unmapping anchor")));
78  
        
79  
        addMappingToDebugOutput();
80  
        step = 3;
81  
      } else if (step == 3) {
82  
        stack.call(new Step2);
83  
        step = 4;
84  
      } else {
85  
        if (isTrue(stack.subResult()))
86  
          step = 3;
87  
        else
88  
          stack.return();
89  
      }
90  
    }
91  
  }
92  
  
93  
  class Step2 extends VStackComputableWithStep<Bool> is IMakeEmptyClone {
94  
    bool change;
95  
    Iterator<Curve> curve1iterator;
96  
    Curve curve1;
97  
    MappedCurve c2;
98  
    Anchor a2;
99  
    
100  
    public selfType makeEmptyClone() { ret new selfType; }
101  
    
102  
    void step(VStack stack) {
103  
      cast stack to BStack<?>;
104  
      
105  
      if (step == 0) {
106  
        print(n2(mesh1.curves(), "curve") + " in mesh1, mapped: " + l(mm.curveMap));
107  
        print("mesh1.curves: " + map identityHashCode(mesh1.curves()));
108  
        print("mapped: " + map identityHashCode(keys(mm.curveMap)));
109  
        print("mapped (backward map): " + map identityHashCode(keys(mm.curveBackwardMap)));
110  
        curve1iterator = iterator(mesh1.curves());
111  
        step++;
112  
      } else if (step == 1) {
113  
        if (!curve1iterator.hasNext())
114  
          ret with stack.return(change);
115  
116  
        curve1 = curve1iterator.next();
117  
        
118  
        print("Looking to match " + curve1);
119  
      
120  
        // skip if curve is already mapped
121  
        MappedCurve curve1mapping = mm.get(curve1);
122  
        if (curve1mapping != null) {
123  
          print("Curve is mapped: " + curve1);
124  
          assertTrue("mesh2 contains curve1mapping", mesh2.containsCurve(curve1mapping!));
125  
          ret; // continue loop
126  
        }
127  
        
128  
        // check if anchors are mapped
129  
        Anchor start2 = mm.get(curve1.start);
130  
        Anchor end2 = mm.get(curve1.end);
131  
      
132  
        // If neither anchor is mapped, postpone this curve
133  
        if (start2 == null && end2 == null) {
134  
          //print("Curve is not discovered yet: " + curve1);
135  
          ret; // continue loop;
136  
        }
137  
        
138  
        new L<MappedCurve> possibleCurves;
139  
        
140  
        if (start2 != null && end2 != null) {
141  
          // Both anchors are mapped already, choose
142  
          // one the curves connecting them in mesh2.
143  
          
144  
          for (curve2 : start2.curves())
145  
            if (curve2.connectedTo(end2)) {
146  
              bool flipped = curve2.end == start2;
147  
              possibleCurves.add(new MappedCurve(curve2, flipped));
148  
            }
149  
        } else {
150  
          // Only one anchor is mapped.
151  
          // Start at the mapped anchor, choose a viable curve in mesh2 to map to
152  
          bool startAtEnd = end2 != null;
153  
          Anchor a1 = curve1.anchor(startAtEnd);
154  
          Anchor a1other = curve1.anchor(!startAtEnd);
155  
          a2 = mm.get(curve1.anchor(startAtEnd));
156  
        
157  
          print(+a1);
158  
          print(+a2);
159  
          print(+a1other);
160  
        
161  
          for (c2 : a2.curves()) {
162  
            if (mm.isMapped(c2)) {
163  
              //print("Curve already mapped: " + c2);
164  
              continue; // continue loop
165  
            }
166  
            
167  
            // check for arity match
168  
            Anchor a3 = c2.anchorOpposite(a2);
169  
            print(+a3);
170  
            int arity1 = a3.arity(), arity2 = a1other.arity();
171  
            if (arity1 != arity2) {
172  
              print("Arity mismatch (" + arity1 + "/" + arity2 + ") for curve " + c2);
173  
              continue; // continue loop
174  
            }
175  
              
176  
            // This curve is viable as a mapping target
177  
            bool flipped = c2.start() != a2;
178  
            possibleCurves.add(new MappedCurve(c2, flipped));
179  
            print("Possible curve!");
180  
          }
181  
        }
182  
      
183  
        addPossibleCurvesToDebugOutput(curve1, possibleCurves);
184  
        print(l(possibleCurves)
185  
          + " possible curve(s) to map " + curve1 + " to: ");
186  
        pnl(possibleCurves);
187  
        if (empty(possibleCurves)) {
188  
          stack.temp(tempRejectedBecause("Could not map curve " + curve1));
189  
          ret with stack.ret(false);
190  
        }
191  
        
192  
        // Go through all curve mappings
193  
        step = 2;
194  
        stack.options(this, map(possibleCurves,
195  
          c2 -> instance -> instance.c2 = c2));
196  
        ret;
197  
      } else {
198  
        print("Mapping curve " + curve1 + " to " + c2);
199  
        add(debugOutput, print("Mapping curve"));
200  
        stack.temp(mm.tempMapCurve(curve1, c2!, c2.flipped));
201  
        stack.temp(-> add(debugOutput, "Unmapping curve"));
202  
        addMappingToDebugOutput();
203  
        set change;
204  
        
205  
        // continue loop
206  
        step = 1;
207  
      }
208  
    }
209  
  }
210  
  
211  
  protected void prechecks {
212  
    set prechecksDone;
213  
    sig1 = mesh1.signature();
214  
    sig2 = mesh1.signature();
215  
    if (!eq(sig1, sig2))
216  
      ret with rejectedBecause(G22SignatureMismatch(mesh1, mesh2));
217  
  }
218  
  
219  
  AutoCloseable tempRejectedBecause(O reason) {
220  
    rejectedBecause(reason);
221  
    ret -> rejectedBecause(null);
222  
  }
223  
  
224  
  void addMappingToDebugOutput() {
225  
    if (debugOutput == null) ret;
226  
    
227  
    O error = mm.validityError();
228  
    addIfNotNull(debugOutput, error);
229  
    
230  
    // use full meshes as background
231  
    var img1 = mesh1.getBufferedImage();
232  
    var img2 = mesh2.getBufferedImage();
233  
    for (img : ll(img1, img2))
234  
      bufferedImageContrastAndBrightness(img, contrast, brightness);
235  
      
236  
    mm.drawMappedPartOfMesh1(createGraphics(img1));
237  
    mm.drawMappedPartOfMesh2(createGraphics(img2));
238  
    addPair(debugOutput, img1, img2);
239  
  }
240  
  
241  
  void addPossibleCurvesToDebugOutput(Curve c1, Cl<MappedCurve> possibleCurves) {
242  
    if (debugOutput == null) ret;
243  
    
244  
    // use full meshes as background
245  
    var img1 = mesh1.getBufferedImage();
246  
    var img2 = mesh2.getBufferedImage();
247  
    for (img : ll(img1, img2))
248  
      bufferedImageContrastAndBrightness(img, contrast, brightness);
249  
    
250  
    new G22VisualizeMeshes().drawCurve(createGraphics(img1), c1);  
251  
    for (curve : possibleCurves) {
252  
      new G22VisualizeMeshes vm;
253  
      if (curve.flipped)
254  
        vm.curveColor(Color.green);
255  
      vm.drawCurve(createGraphics(img2), curve!);
256  
    }
257  
      
258  
    add(debugOutput, n2(possibleCurves, "possible curve"));
259  
    addPair(debugOutput, img1, img2);
260  
  }
261  
}

Author comment

Began life as a copy of #1035358

download  show line numbers  debug dex  old transpilations   

Travelled to 3 computer(s): ekrmjmnbrukm, mowyntqkapby, mqqgnosmbjvj

No comments. add comment

Snippet ID: #1035369
Snippet name: G22MeshMapper_v2 - tries to map mesh1 to mesh2 [dev.]
Eternal ID of this version: #1035369/62
Text MD5: 636e2740d06ed46e3dee923d159620b9
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2022-05-06 19:54:18
Source code size: 8561 bytes / 261 lines
Pitched / IR pitched: No / No
Views / Downloads: 224 / 504
Version history: 61 change(s)
Referenced in: [show references]