Clone in a terminal:
Commit 2064000
Johan Mattsson - 2012-08-19T22:02:33+00:00
20640001f82081894f4a326425ef8314e5e0d985johan.mattsson.m@gmail.com

merge more paths

Changed files (5)

Diff

diff --git a/src/CutTool.vala b/src/CutTool.valaindex b965887..590a6a1 100644--- a/src/CutTool.vala+++ b/src/CutTool.vala@@ -22,7 +22,7 @@ class CutTool : Tool { 	PenTool pen; 	 	public CutTool (string n) {-		base (n, "Cut", 'u', CTRL);+		base (n, "Create counter path", 'u', CTRL); 		 		select_action.connect((self) => { 			pen = (PenTool) MainWindow.get_tool ("pen_tool");diff --git a/src/EditPointHandle.vala b/src/EditPointHandle.valaindex 8112ac8..ce776ad 100644--- a/src/EditPointHandle.vala+++ b/src/EditPointHandle.vala@@ -88,10 +88,12 @@ class EditPointHandle  { 	} 	 	double px () {+		assert ((EditPoint?) parent != null); 		return cos (angle) * length + parent.x; 	}  	double py () {+		assert ((EditPoint?) parent != null); 		return sin (angle) * length + parent.y; 	} 		diff --git a/src/Glyph.vala b/src/Glyph.valaindex 27b710b..664447b 100644--- a/src/Glyph.vala+++ b/src/Glyph.vala@@ -1697,7 +1697,7 @@ class Glyph : FontDisplay { 		} 		 		open_path ();-		close_path ();+		// close_path (); 		 		redraw_area (0, 0, allocation.width, allocation.height); 	}@@ -1705,6 +1705,7 @@ class Glyph : FontDisplay { 	public bool merge_path (Path p0) { 		Path? m; 		Path mp;+		PathList path_list; 		int i = 0; 		 		foreach (Path p1 in active_paths) {@@ -1713,20 +1714,24 @@ class Glyph : FontDisplay { 				continue; 			} 			-			m = p0.merge (p1);+			//path_list = Path.merge (p0.copy(), p1.copy());+			path_list = Path.merge (p1, p0); -			if (m == null) {+			if (path_list.paths.length () == 0) { 				p0 = p1; 				continue; 			} 			-			mp = (!) m;+			mp = path_list.paths.first ().data;  			delete_path (p0); 			delete_path (p1); 			-			mp.close ();			-			add_path (mp.copy ());+			// add new path + it's counter paths+			foreach (Path p in path_list.paths) {+				p.close ();			+				add_path (p.copy ());+			} 			 			add_active_path (mp); diff --git a/src/IntersectionList.vala b/src/IntersectionList.valaindex 9070455..2d15631 100644--- a/src/IntersectionList.vala+++ b/src/IntersectionList.vala@@ -51,6 +51,14 @@ class IntersectionList { 		points.append (i); 	} 	+	public void remove_point (EditPoint e) {+		foreach (Intersection n in points) {+			if (n.editpoint_a == e || n.editpoint_b == e) {+				points.remove_all (n);+			}+		}	+	}+	 	public bool has_edit_point (EditPoint e) { 		foreach (Intersection n in points) { 			if (n.editpoint_a == e || n.editpoint_b == e) {diff --git a/src/Path.vala b/src/Path.valaindex e7ceab9..cdcece7 100644--- a/src/Path.vala+++ b/src/Path.vala@@ -738,11 +738,51 @@ class Path {  		y *= -1; 		+		return is_over_coordinate (x, y);+	}+	+	public bool is_over_coordinate (double x, double y) {+		List<EditPoint> ycoordinates = new List<EditPoint> ();+		double last = 0;+				 		if (!is_over_boundry (x, y)) { 			return false; 		} -		return true;+		all_of_path ((cx, cy, ct) => {+			if (Math.fabs (cx - x) < 0.2 && Math.fabs (last - cy) > 1) {+				ycoordinates.append (new EditPoint (cx, cy));+				last = cy;+			}+			return true;+		});++		ycoordinates.sort ((a, b) => {+			return (a.y < b.y) ? 1 : -1;+		});++		return_val_if_fail (ycoordinates.length () >= 2, true);+		+		if (unlikely (ycoordinates.length () % 2 != 0)) {+			warning (@"not an even number of coordinates ($(ycoordinates.length ()))");+		}++		for (unowned List<EditPoint> e = ycoordinates.first (); true; e = e.next) {+			if (y < e.data.y) {+				return_if_fail ((void*) e.next != null);+				e = e.next;++				if (y > e.data.y) {+					return true;+				}+			}+			+			if (e == ycoordinates.last ()) {+				break;+			}+		}++		return false; 	} 	 	public bool is_over_boundry (double x, double y) {@@ -1159,9 +1199,11 @@ class Path {  		ep.get_left_handle ().set_point_type (PointType.CURVE); 		ep.get_left_handle ().move_to_coordinate (x0, y0);+		ep.get_left_handle ().parent = ep; 		 		ep.get_right_handle ().set_point_type (PointType.CURVE); 		ep.get_right_handle ().move_to_coordinate (x1, y1);+		ep.get_right_handle ().parent = ep;  		stop.get_left_handle ().length *= 1 - position; 		start.get_right_handle ().length *= position;@@ -1474,9 +1516,11 @@ class Path { 		uint len = points.length (); 		unowned List<EditPoint> iter = points.first (); 		unowned List<EditPoint>? ni = null;+		bool found = false; 		 		foreach (EditPoint it in points) { 			if (it == ep) {+				found = true; 				break; 			} 			@@ -1484,6 +1528,10 @@ class Path { 			ni = (!) iter; 		} 		+		if (unlikely (!found)) {+			warning ("Could not find edit point.");+		}+		 		if (ni == null) { 			return;			 		}@@ -1510,11 +1558,27 @@ class Path { 		 	} 	-	public Path? merge (Path p) {+	public static PathList merge (Path p0, Path p1) {+		bool err;+		PathList path_list;+		+		err = try_merge (p1.copy(), p0.copy(), out path_list);+		+		if (err) {+			err = try_merge (p0.copy(), p1.copy(), out path_list);+		}+		+		if (err) {+			warning ("failed to merge paths");+		}+		+		return path_list;+	}+	+	private static bool try_merge (Path p0, Path p1, out PathList path_list) { 		EditPoint e;-		IntersectionList il = IntersectionList.create_intersection_list (this, p);-		Path np = new Path ();-		Intersection s = new Intersection (0, 0, 1);+		IntersectionList il = IntersectionList.create_intersection_list (p0, p1);+		 		EditPoint ex; 		EditPoint ix; 		uint offset_i = 0;@@ -1523,74 +1587,119 @@ class Path { 		int i, j; 		uint len_j; 		bool over;+		Path np;+		Path np_counter;+				+		path_list = new PathList (); 		-		if (p == this) {-			return null;+		if (p0 == p1) {+			return true; 		} 		 		// add editpoints points on intersections  		foreach (Intersection inter in il.points) { 			e = new EditPoint ();-			get_closest_point_on_path (e, inter.x, inter.y);+			p0.get_closest_point_on_path (e, inter.x, inter.y); 			inter.editpoint_a = e; 			 			e = inter.editpoint_a;-			if (!has_edit_point (e)) {-				insert_new_point_on_path (e);+			if (!p0.has_edit_point (e)) {+				p0.insert_new_point_on_path (e); 			}  			e = new EditPoint ();-			p.get_closest_point_on_path (e, inter.x, inter.y);+			p1.get_closest_point_on_path (e, inter.x, inter.y); 			inter.editpoint_b = e; 			 			e = inter.editpoint_b;-			if (!p.has_edit_point (e)) {-				p.insert_new_point_on_path (e);+			if (!p1.has_edit_point (e)) {+				p1.insert_new_point_on_path (e); 			}  		} 		 		if (il.points.length () == 0) {-			return null;+			return true; 		} 		 		// begin outside intersection-		ex = points.first ().data;-		for (i = 0; i < points.length (); i++) {+		ex = p0.points.first ().data;+		for (i = 0; i < p0.points.length (); i++) { 			ex = ex.get_next ().data; 			-			if (!p.is_over_boundry (ex.x, ex.y)) {-				set_new_start (ex);-				break;				+			if (!p1.is_over_coordinate (ex.x, ex.y) && !il.has_edit_point (ex)) {+				p0.set_new_start (ex);			 			} 		} -		if (i == points.length ()) {-			warning ("No point outside path.");-			return null;+		if (i == p0.points.length ()) {+			warning ("no point outside path."); 		} -		// p.set_new_start (il.points.first ().data.editpoint_b);-	 		// create a new path -		ex = points.last ().data;-		ix = points.last ().data;-		len_i = points.length ();+		np = create_merged_path (il, p0, p1);+		+		path_list.paths.append (np);+		+		if (!np.is_clockwise ()) {+			warning ("Outline is counter clockwise after merge");+			return true;+		}++		// find counter path if we have more intersections+		if (il.points.length () > 0) { +			ex = p0.points.first ().data;+			p0.set_new_start (il.points.first ().data.editpoint_a);++			np_counter = create_merged_path (il, p0, p1);+			+			path_list.paths.append (np_counter);+			+			if (np_counter.is_clockwise ()) {+				warning ("Counter is clockwise after merge");+				return true;+			}+			+		}+		+		return false;+	}+	+	private static Path create_merged_path (IntersectionList il, Path p0, Path p1) {+		EditPoint ex;+		EditPoint ix;+		uint offset_i = 0;+		uint offset_j;+		uint len_i;+		int i, j;+		uint len_j;+		bool over;+		Path np = new Path ();+		Intersection s = new Intersection (0, 0, 1); 		-		for (i = 0; i < points.length (); i++) {-			ex = points.nth ((i + offset_i) % len_i).data;+		ex = p0.points.last ().data;+		ix = p0.points.last ().data;+		len_i = p0.points.length ();+		+		for (i = 0; i < p0.points.length (); i++) {+			ex = p0.points.nth ((i + offset_i) % len_i).data; -			if (ex == points.first ().data && i != 0) {+			if (ex == p0.points.first ().data && i != 0) {	 				break; 			}  			// add new point for path a 			np.add_point (ex);-			ex.recalculate_linear_handles ();+			if (np.has_edit_point (ix)) {+				// SPLIT+			} else {+				ex.recalculate_linear_handles ();+			} 			 			// swap paths 			if (il.has_edit_point (ex)) { 				s = (!) il.get_intersection (ex);+				il.remove_point (ex); 				 				ex.type = PointType.CURVE; 				ex.right_handle.type = PointType.CURVE;@@ -1600,8 +1709,8 @@ class Path { 				ex.left_handle.type = PointType.CURVE;  				// read until we find ex-				for (j = 0; j < p.points.length (); j++) {-					ix = p.points.nth (j).data;+				for (j = 0; j < p1.points.length (); j++) {+					ix = p1.points.nth (j).data; 					 					if (ix == s.editpoint_b) { 						break;@@ -1609,17 +1718,22 @@ class Path { 				} 				 				offset_j = j + 1;-				len_j = p.points.length ();-				for (j = 0; j < p.points.length (); j++) {+				len_j = p1.points.length ();+				for (j = 0; j < p1.points.length (); j++) { 					-					ix = p.points.nth ((j + offset_j) % len_j).data;+					ix = p1.points.nth ((j + offset_j) % len_j).data; 					 					// add+					if (np.has_edit_point (ix)) {+						// SPLIT+					} else {+						ix.recalculate_linear_handles ();+					} 					np.add_point (ix);-					ix.recalculate_linear_handles (); 					 					if (il.has_edit_point (ix)) { 						s = (!) il.get_intersection (ix);+						il.remove_point (ix); 						break; 					} 				}@@ -1631,22 +1745,22 @@ class Path { 				 				ix.left_handle.type = PointType.CURVE; 				-				if (j == points.length ()) {+				if (j == p0.points.length ()) { 					np.close (); 					return np; 				}  				// skip to next intersection 				int k;-				for (k = 0; k < points.length (); k++) {-					ix = points.nth (k).data; +				for (k = 0; k < p0.points.length (); k++) {+					ix = p0.points.nth (k).data;   					if (ix == s.editpoint_a) { 						break; 					} 				} 				-				if (k == points.length ()) {+				if (k == p0.points.length ()) { 					return np; 				} 				@@ -1655,9 +1769,21 @@ class Path { 			} 		} 		-		return np;+		return np;		 	}+} +class PathList : GLib.Object {+	public List<Path> paths = new List<Path> ();+	+	public PathList () {+	}+	+	public void clear () {+		while (paths.length () > 0) {+			paths.remove_link (paths.first ());+		}+	} }  }

Contact

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