Commit b09d1af
fix path is clockwise
Changed files (5)
modifiedsrc/EditPoint.valamodifiedsrc/Glyph.valamodifiedsrc/Path.valamodifiedsrc/PenTool.valamodifiedsrc/Toolbox.vala
Diff
@@ -32,6 +32,7 @@ enum PointType { } class EditPoint {+ public double x; public double y; public PointType type;@@ -161,10 +162,67 @@ class EditPoint { tie_handles = t; } + public void process_tied_handle () {+ double a, b, c, length, angle;+ EditPointHandle eh;+ + eh = right_handle;+ + a = left_handle.x () - right_handle.x ();+ b = left_handle.y () - right_handle.y ();+ c = a * a + b * b;+ + if (c == 0) {+ return;+ }+ + length = sqrt (fabs (c));+ + if (right_handle.y () < left_handle.y ()) {+ angle = acos (a / length) + PI;+ } else {+ angle = -acos (a / length) + PI;+ }+ + left_handle.type = PointType.CURVE;+ right_handle.type = PointType.CURVE;+ + right_handle.angle = angle;+ left_handle.angle = angle;++ set_tie_handle (true);+ eh.move_to_coordinate (right_handle.x (), right_handle.y ());+ }+ public void set_point_type (PointType point_type) { type = point_type; } + public double get_average_angle () {+ double a, b, c, length, angle;++ recalculate_linear_handles ();+ + a = left_handle.x () - right_handle.x ();+ b = left_handle.y () - right_handle.y ();+ c = a * a + b * b;+ + if (c == 0) {+ warning ("Can't calculate average length");+ return 0;+ }+ + length = sqrt (fabs (c));+ + if (right_handle.y () < left_handle.y ()) {+ angle = acos (a / length) + PI; + } else {+ angle = -acos (a / length) + PI;+ } + + return angle;+ }+ public EditPoint copy () { EditPoint new_point = new EditPoint (); @@ -769,7 +769,8 @@ class Glyph : FontDisplay { } if (unlikely (min_distance == double.MAX)) {- warning (@"No path found in path_list. Length: $(path_list.length ())");+ // put back important warning:+ // warning (@"No path found in path_list. Length: $(path_list.length ())"); if (path_list.length () > 0) { stderr.printf (@"p.points.length () $(path_list.first ().data.points.length ()) \n");@@ -604,31 +604,77 @@ class Path { } } - private bool is_clockwise_top () {- EditPoint top_point = new EditPoint (1000, 1000);+ private bool validate_list () {+ unowned List<EditPoint> ep = points.first (); - return_if_fail (points.length () >= 3);- - create_list ();+ if (points.length () < 3) {+ warning ("points.length () < 3");+ } - foreach (EditPoint ep in points) {- if (ep.y < top_point.y) {- top_point = ep;+ if (!is_open ()) {+ for (int i = 0; i < points.length (); i++) {+ if (ep.data.next == null) {+ return false;+ }++ if (ep.data.prev == null) {+ return false;+ }+ + ep = (!) ep.data.next;+ }+ }++ if (is_open ()) {+ for (int i = 1; i < points.length () - 1; i++) {+ if (ep.data.next == null) {+ return false;+ }++ if (ep.data.prev == null) {+ return false;+ }+ + ep = (!) ep.data.next;+ }+ + if (ep.data.next != null) {+ return false; } } - return_if_fail (top_point.next != null && top_point.prev != null);+ return true;+ }+ + private double clockwise_sum () {+ return_if_fail (points.length () >= 3);+ + double sum = 0;+ EditPoint prev = points.last ().data;+ foreach (EditPoint e in points) {+ sum += (e.x - prev.x) * (e.y + prev.y);+ prev = e;+ } - return (top_point.get_prev ().data.x < top_point.get_next ().data.x);+ return sum; } public bool is_clockwise () {+ double s;+ if (unlikely (points.length () <= 2)) { no_derived_direction = true; return clockwise_direction; } - return is_clockwise_top ();+ s = clockwise_sum ();+ + if (s == 0) {+ no_derived_direction = true;+ return clockwise_direction; + }+ + return s > 0; } public bool is_editable () {@@ -853,14 +899,6 @@ class Path { return np; }- - /*// FIXA: DELETE- public void add_point_on_path (double x, double y) {- EditPoint e = new EditPoint (0, 0);- get_closest_point_on_path (e, x, y);- add_after (x, y, e.prev);- }- */ public void close () { open = false;@@ -1228,7 +1266,8 @@ class Path { } public void create_list () {- unowned List<EditPoint> ep = points;+ unowned List<EditPoint> ep = points.first ();+ unowned List<EditPoint> prev = ep; if (points.length () == 0) { return;@@ -1241,21 +1280,32 @@ class Path { } ep.data.next = ep.next;- ep.data.prev = ep.last ();+ ep.data.prev = points.last ();+ prev = ep;+ + assert (ep.data.next != null);+ assert (ep.data.prev != null); while (ep != ep.last ()) { ep.data.next = ep.next;- ep.data.prev = ep.prev;+ ep.data.prev = prev;+ prev = ep;+ + assert (ep.data.next != null);+ assert (ep.data.prev != null);+ ep = ep.next; } if (is_open ()) {- ep.data.next = null;+ ep.data.next = points.first (); } else {- ep.data.next = ep.first ();+ ep.data.next = points.first ();+ assert (ep.data.next != null); } - ep.data.prev = ep.prev;+ ep.data.prev = prev;+ assert (ep.data.prev != null); } public void delete_edit_point (EditPoint ep) @@ -840,8 +840,7 @@ class PenTool : Tool { test_open_next_glyph (); pen = select_pen (); - int skip = 0;- for (int i = 0; i < 10; i++) {+ for (int i = 0; i < 30; i++) { this.yield (); ax = Random.int_range (0, 300);@@ -869,10 +868,7 @@ class PenTool : Tool { return false; } - if (++skip == 5) {- test_open_next_glyph ();- skip = 0;- }+ test_open_next_glyph (); } if (r) test_open_next_glyph ();@@ -152,8 +152,6 @@ class Toolbox : DrawingArea { Tool tie_editpoint_tool = new Tool ("tie_point", "Tie curve handles for selected edit point", 'w'); tie_editpoint_tool.select_action.connect((self) => { EditPoint ep;- EditPointHandle eh;- double a, b, c, length, angle; bool tie; select_draw_tool ();@@ -161,33 +159,8 @@ class Toolbox : DrawingArea { ep = pen_tool.selected_corner; tie = !ep.tie_handles; - eh = ep.right_handle;- if (tie) {- a = ep.left_handle.x () - ep.right_handle.x ();- b = ep.left_handle.y () - ep.right_handle.y ();- c = a * a + b * b;- - if (c == 0) {- return;- }- - length = sqrt (fabs (c));- - if (ep.right_handle.y () < ep.left_handle.y ()) {- angle = acos (a / length) + PI;- } else {- angle = -acos (a / length) + PI;- }- - ep.left_handle.type = PointType.CURVE;- ep.right_handle.type = PointType.CURVE;- - ep.right_handle.angle = angle;- ep.left_handle.angle = angle;-- ep.set_tie_handle (true);- eh.move_to_coordinate (ep.right_handle.x (), ep.right_handle.y ());+ ep.process_tied_handle (); } ep.set_tie_handle (tie);