The Birdfont Source Code


All Repositories / birdfont.git / commit – RSS feed

Merge self intersections

These changes was commited to the Birdfont repository Fri, 03 Jul 2015 13:22:18 +0000.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git
author Johan Mattsson <johan.mattsson.m@gmail.com>
Fri, 03 Jul 2015 13:22:18 +0000 (15:22 +0200)
committer Johan Mattsson <johan.mattsson.m@gmail.com>
Fri, 03 Jul 2015 13:22:18 +0000 (15:22 +0200)
commit a801bad092c39cd3ed60f8be25395d6a7c9e3718
tree 0dccc152b7ef55f138aa20ec99d008ba46e2ea70
parent f1fb0cc0f4daa1006e7a89433411b90d0c874e4b
Merge self intersections

libbirdfont/EditPoint.vala
libbirdfont/Intersection.vala
libbirdfont/Path.vala
libbirdfont/StrokeTool.vala
--- a/libbirdfont/EditPoint.vala +++ b/libbirdfont/EditPoint.vala @@ -56,6 +56,7 @@ 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;
--- a/libbirdfont/Intersection.vala +++ b/libbirdfont/Intersection.vala @@ -23,6 +23,7 @@ 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) {
--- a/libbirdfont/Path.vala +++ b/libbirdfont/Path.vala @@ -1375,8 +1375,11 @@ } } - /** 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 @@ EditPoint previous; EditPoint next; double step = 0; - + if (points.size == 0) { warning ("Empty path."); return; @@ -1434,7 +1437,18 @@ } 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);
--- a/libbirdfont/StrokeTool.vala +++ b/libbirdfont/StrokeTool.vala @@ -124,21 +124,66 @@ 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); @@ -152,7 +197,11 @@ 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 @@ 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 @@ } // 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 @@ 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 @@ 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 @@ 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++;