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 | } |
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] |