Commit a801bad
Merge self intersections
Changed files (4)
modifiedlibbirdfont/EditPoint.valamodifiedlibbirdfont/Intersection.valamodifiedlibbirdfont/Path.valamodifiedlibbirdfont/StrokeTool.vala
Diff
@@ -56,6 +56,7 @@ public class EditPoint : GLib.Object { public static uint CURVE_KEEP = 1 << 13; public static uint SEGMENT_END = 1 << 14; public static uint SPLIT_POINT = 1 << 15;+ public static uint SELF_INTERSECTION = 1 << 16; public static uint ALL = 0xFFFFFF; @@ -23,6 +23,7 @@ public class Intersection : GLib.Object { public EditPoint other_point; public Path path; public Path other_path;+ public bool self_intersection = false; public Intersection (EditPoint point, Path path, EditPoint other_point, Path other_path) {@@ -1375,8 +1375,11 @@ public class Path : GLib.Object { } } - /** Get a point on the this path closest to x and y coordinates. */- public void get_closest_point_on_path (EditPoint edit_point, double x, double y) {+ /** Get a point on the this path closest to x and y coordinates.+ * Don't look for a point in the segment skip_previous to skip_next.+ */+ public void get_closest_point_on_path (EditPoint edit_point, double x, double y,+ EditPoint? skip_previous = null, EditPoint? skip_next = null) { return_if_fail (points.size >= 1); double min = double.MAX;@@ -1399,7 +1402,7 @@ public class Path : GLib.Object { EditPoint previous; EditPoint next; double step = 0;-+ if (points.size == 0) { warning ("Empty path."); return;@@ -1434,7 +1437,18 @@ public class Path : GLib.Object { } else { break; }- ++ if (skip_previous != null && skip_next != null) {+ EditPoint? si, sp;+ si = i;+ sp = prev;+ + if (skip_previous == sp && skip_next == si) {+ print ("SKIP IN get_closest_point_on_path\n");+ continue;+ }+ }+ all_of (prev, i, (cx, cy, t) => { n = pow (x - cx, 2) + pow (y - cy, 2); @@ -124,22 +124,67 @@ public class StrokeTool : Tool { EditPoint lep = new EditPoint (); pp.get_closest_point_on_path (lep, ep.x, ep.y); - if (Path.distance_to_point (ep, lep) < 1) {- pp.insert_new_point_on_path (lep);- lep.flags |= EditPoint.INTERSECTION;- lep.tie_handles = false;- lep.reflective_point = false;+ if (Path.distance_to_point (ep, lep) < 0.1) {+ // self intersection+ EditPoint lep2 = new EditPoint ();+ pp.get_closest_point_on_path (lep2, ep.x, ep.y, lep.prev, lep.next);+ + if (Path.distance_to_point (ep, lep2) < 0.1) {+ pp.insert_new_point_on_path (lep);+ pp.insert_new_point_on_path (lep2);+ + lep.flags |= EditPoint.SELF_INTERSECTION;+ lep2.flags |= EditPoint.SELF_INTERSECTION;+ + lep.color = Color.pink ();+ lep2.color = Color.pink ();+ + lep.tie_handles = false;+ lep.reflective_point = false;+ lep2.tie_handles = false;+ lep2.reflective_point = false;+ + print (@"SELF INTERSECTION AT $(ep.x) $(ep.y) $(ep.get_prev ().x), $(ep.get_prev ().y)\n");+ } else {+ pp.insert_new_point_on_path (lep);+ lep.flags |= EditPoint.INTERSECTION;+ lep.tie_handles = false;+ lep.reflective_point = false;+ print (@"INTERSECTION AT $(ep.x) $(ep.y)\n");+ } } } } } } + // remove double intersection points + EditPoint prev = new EditPoint ();+ foreach (Path pp in o.paths) {+ foreach (EditPoint ep in pp.points) {+ if ((prev.flags & EditPoint.SELF_INTERSECTION) > 0+ && (ep.flags & EditPoint.SELF_INTERSECTION) > 0+ && fabs (ep.x - prev.x) < 0.01+ && fabs (ep.y - prev.y) < 0.01) {+ + ep.deleted = true;+ }+ + prev = ep;+ }+ }+ + foreach (Path pp in o.paths) {+ pp.remove_deleted_points ();+ }+ //FIXME:DELETE- foreach (Path pp in flat.paths) {- ((!) BirdFont.get_current_font ().get_glyph_by_name ("a")).add_path (pp);+ + foreach (Path pp in o.paths) {+ ((!) BirdFont.get_current_font ().get_glyph_by_name ("a")).add_path (pp.copy ()); } + o = merge_curves (o, flat); // FIXME: remove split points@@ -152,7 +197,11 @@ public class StrokeTool : Tool { foreach (Path p in o.paths) { foreach (EditPoint ep in p.points) {- ep.flags &= uint.MAX ^ (EditPoint.INTERSECTION | EditPoint.COPIED | EditPoint.NEW_CORNER);+ ep.flags &= uint.MAX ^ + (EditPoint.INTERSECTION + | EditPoint.COPIED + | EditPoint.NEW_CORNER + | EditPoint.SELF_INTERSECTION); ep.flags = 0; } p.update_region_boundaries ();@@ -208,6 +257,35 @@ public class StrokeTool : Tool { found = new EditPoint (); min_d = double.MAX; found_intersection = false;++ if ((ep1.flags & EditPoint.SELF_INTERSECTION) > 0+ && (ep1.flags & EditPoint.COPIED) == 0) {+ ep1.flags |= EditPoint.COPIED;+ + for (int j = 0; j < path1.points.size; j++) {+ ep2 = path1.points.get (j);+ d = Path.distance_to_point (ep1, ep2);+ if ((ep2.flags & EditPoint.COPIED) == 0+ && (ep2.flags & EditPoint.SELF_INTERSECTION) > 0) {+ if (d < min_d) {+ min_d = d;+ found_intersection = true;+ found = ep2;+ }+ }+ }++ if (!found_intersection) {+ warning ("No self intersection");+ return r;+ }+ + found.flags |= EditPoint.COPIED;+ Intersection intersection = new Intersection (ep1, path1, found, path1);+ intersection.self_intersection = true;+ intersections.points.add (intersection);+ }+ if ((ep1.flags & EditPoint.INTERSECTION) > 0) { for (int j = 0; j < path2.points.size; j++) { ep2 = path2.points.get (j);@@ -239,6 +317,10 @@ public class StrokeTool : Tool { } // reset copied points+ foreach (EditPoint n in path1.points) {+ n.flags &= uint.MAX ^ EditPoint.COPIED;+ }+ foreach (EditPoint n in path2.points) { n.flags &= uint.MAX ^ EditPoint.COPIED; }@@ -258,6 +340,7 @@ public class StrokeTool : Tool { if (!inter.done && !find_parts) { find_parts = true; new_start = inter;+ current = new_start.path; print (@"new_start: $new_start\n"); break; }@@ -292,8 +375,10 @@ public class StrokeTool : Tool { ep1 = current.points.get (i); current = new_start.get_other_path (current); // swap at first iteration bool first = true;+ Intersection self_intersection_point = new Intersection.empty (); while (true) { if ((ep1.flags & EditPoint.INTERSECTION) > 0) {+ print ("intersection.\n"); bool other; previous = ep1;@@ -353,11 +438,31 @@ public class StrokeTool : Tool { ep1.left_handle = previous.left_handle.copy (); } - if ((ep1.flags & EditPoint.COPIED) > 0) {+ if ((ep1.flags & EditPoint.SELF_INTERSECTION) > 0) {+ print ("self intersection.\n");+ bool other;+ new_start = intersections.get_point (ep1, out other);+ i = index_of (current, other ? new_start.point : new_start.other_point);+ + if (self_intersection_point == new_start) {+ print ("Return to self intersection\n");+ break;+ }+ + self_intersection_point = new_start;+ + if (!(0 <= i < current.points.size)) {+ warning (@"Index out of bounds. ($i)");+ return r;+ }+ + ep1 = current.points.get (i);+ } else if ((ep1.flags & EditPoint.COPIED) > 0) { print ("Copied, part done.\n"); break; } + print ("add\n"); ep1.flags |= EditPoint.COPIED; new_path.add_point (ep1.copy ()); i++;