Clone in a terminal:
Commit a801bad
Johan Mattsson - 2015-07-03T13:22:18+00:00
a801bad092c39cd3ed60f8be25395d6a7c9e3718johan.mattsson.m@gmail.com

Merge self intersections

Changed files (4)

Diff

diff --git a/libbirdfont/EditPoint.vala b/libbirdfont/EditPoint.valaindex 6efe750..ec913c3 100644--- a/libbirdfont/EditPoint.vala+++ b/libbirdfont/EditPoint.vala@@ -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; 	diff --git a/libbirdfont/Intersection.vala b/libbirdfont/Intersection.valaindex 9808f2f..3fd2aa8 100644--- a/libbirdfont/Intersection.vala+++ b/libbirdfont/Intersection.vala@@ -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)  {diff --git a/libbirdfont/Path.vala b/libbirdfont/Path.valaindex eb5a728..b264a4f 100644--- a/libbirdfont/Path.vala+++ b/libbirdfont/Path.vala@@ -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); 				diff --git a/libbirdfont/StrokeTool.vala b/libbirdfont/StrokeTool.valaindex dc5aa34..c6aa4dc 100644--- a/libbirdfont/StrokeTool.vala+++ b/libbirdfont/StrokeTool.vala@@ -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++;

Contact

Email: johan.mattsson.m@gmail.com
Mastodon: typo.social/@birdfont
GitHub: johanmattssonm
LinkedIn: johan-mattsson-2ab324112