The Birdfont Source Code


All Repositories / birdfont.git / commitdiff – RSS feed

Find self intersections

These changes was commited to the Birdfont repository Mon, 30 Mar 2015 10:27:36 +0000.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git
[Mon, 30 Mar 2015 10:27:36 +0000]

Updated Files

libbirdfont/EditPoint.vala
libbirdfont/StrokeTool.vala
libbirdfont/SvgParser.vala
--- a/libbirdfont/EditPoint.vala +++ b/libbirdfont/EditPoint.vala @@ -45,6 +45,7 @@ public static uint TIE = 1 << 3; public static uint REFLECTIVE = 1 << 4; public static uint CORNER = 1 << 5; + public static uint INTERSECTION = 1 << 6; public uint flags = NONE;
--- a/libbirdfont/StrokeTool.vala +++ b/libbirdfont/StrokeTool.vala @@ -70,7 +70,6 @@ } else if (!p.is_open () && !p.is_filled ()) { outline = create_stroke (p, thickness); counter = create_stroke (p, -1 * thickness); - paths.add (outline); paths.add (counter); @@ -92,7 +91,7 @@ outline = create_stroke (p, thickness); counter = create_stroke (p, -1 * thickness); merged = merge_strokes (p, outline, counter, thickness); - + if (p.is_clockwise ()) { merged.force_direction (Direction.CLOCKWISE); } else { @@ -154,6 +153,8 @@ warning ("One point."); stroked = new Path (); } + + remove_self_intersections (stroked); return stroked; } @@ -281,9 +282,110 @@ next_handle.angle -= PI; } + static void remove_self_intersections (Path p) { + bool keep = true; + + add_self_intersection_points (p); + + // FIXME: set start on non intersecting point + foreach (EditPoint ep in p.points) { + if ((ep.flags & EditPoint.INTERSECTION) > 0) { + print (@"Inter $(ep)"); + keep = !keep; + } + + if (!keep && (ep.flags & EditPoint.INTERSECTION) == 0) { + ep.deleted = true; + ep.type = PointType.CUBIC; + } + } + + p.remove_deleted_points (); + } + static void add_self_intersection_points (Path path) { + Gee.ArrayList<EditPoint> n = new Gee.ArrayList<EditPoint> (); + + path.all_segments ((ep1, ep2) => { + double ix, iy; + EditPoint nep; + EditPoint nep2; + EditPoint p1; + EditPoint p2; + + if (segment_intersects (path, ep1, ep2, out ix, out iy, out p1, out p2)) { + nep = new EditPoint (); + nep.prev = ep1; + nep.next = ep2; + + nep.x = ix; + nep.y = iy; + + n.add (nep); + + nep2 = new EditPoint (); + nep2.prev = p1; + nep2.next = p2; + + nep2.x = ix; + nep2.y = iy; + + n.add (nep2); + } + + return true; + }); + + foreach (EditPoint np in n) { + path.insert_new_point_on_path (np, -1, true); + np.type = PointType.QUADRATIC; + np.flags |= EditPoint.INTERSECTION; + } + } + + static bool segment_intersects (Path path, EditPoint ep, EditPoint next, + out double ix, out double iy, + out EditPoint ia, out EditPoint ib) { + EditPoint p1, p2; + double cross_x, cross_y; + + ix = 0; + iy = 0; + + ia = new EditPoint (); + ib = new EditPoint (); + + if (path.points.size == 0) { + return false; + } + + // FIXME: last to first + for (int i = 1; i < path.points.size - 2; i++) { + p1 = path.points.get (i - 1); + p2 = path.points.get (i); + + Path.find_intersection_point (ep, next, p1, p2, out cross_x, out cross_y); + + if ((p1.x < cross_x < p2.x || p1.x > cross_x > p2.x) + && (p1.y < cross_y < p2.y || p1.y > cross_y > p2.y) + && (ep.x < cross_x < next.x || ep.x > cross_x > next.x) + && (ep.y < cross_y < next.y || ep.y > cross_y > next.y)) { + + // iterate to find intersection. + ix = cross_x; + iy = cross_y; + + ia = p1; + ib = p2; + + return true; + } + } + + return false; + } } }
--- a/libbirdfont/SvgParser.vala +++ b/libbirdfont/SvgParser.vala @@ -477,7 +477,7 @@ return false; } - prev = path.points.get (path.points.size - 1); + prev = path.get_last_point (); foreach (EditPoint p in path.points) { if ((p.y > point.y) != (prev.y > point.y)