srecord noeq G22MeshMapper_v2(G22Mesh mesh1, G22Mesh mesh2) { // import the important classes delegate Anchor, Curve to G22Mesh. G22MeshMapping mm; // index structures MultiMap anchorsByArity2; // EXCEPTIONS (e.g. meshes don't match in signature) // set to the reason why when a mapping is deemed impossible settable O rejectedBecause; bool rejected() { ret rejectedBecause != null; } // INTERNAL VARS bool prechecksDone; S sig1, sig2; G22MeshMapping get() { ret mm; } void search_step1() { prechecks(); if (rejected()) ret; // make empty mapping mapping = new G22MeshMapping(mesh1, mesh2); anchorsByArity2 = multiMapIndex(mesh2.anchors(), a -> a.arity()); Anchor anchor1 = random(mesh1.anchors()); Anchor anchor2 = random(anchorsByArity2.get(anchor1.arity()); mapAnchor(anchor1, anchor2); } bool search_step2() { bool change; for (curve1 : mesh1.curves()) { // skip if curve is already mapped if (mm.isMapped(curve1)) continue; // check if anchors are mapped Anchor start2 = mm.get(curve1.start); Anchor end2 = mm.get(curve1.end); // If neither anchor is mapped, postpone this curve if (start2 == null || end2 == null) continue; // Start at the mapped anchor, choose a viable curve in mesh2 to map to bool startAtEnd = end2 != null; Anchor a1other = curve1.anchor(!startAtEnd); Anchor a2 = mm.get(curve1.anchor(startAtEnd)); new L possibleCurves; for (c2 : a2.curves()) { if (mm.isMapped(c2)) continue; // check for arity match Anchor a3 = c2.anchorOpposite(a2); if (a3.arity() != a1other.arity()) continue; // This curve is viable as a mapping target possibleCurves.add(c2); } if (empty(possibleCurves)) ret with rejectedBecause("Could not map curve " + curve1); // Map the curve mm.mapCurve(curve1, random(possibleCurves); set change; } ret change; } void mapAnchor(Anchor anchor1, Anchor anchor2) { mm.mapAnchor(anchor1, anchor2); } protected void prechecks { set prechecksDone; sig1 = mesh1.signature(); sig2 = mesh1.signature(); if (!eq(sig1, sig2)) ret with rejectedBecause(G22SignatureMismatch(mesh1, mesh2)); } }