diff --git a/mono/Contours/Circuit.cs b/mono/Contours/Circuit.cs index 487d4d3..1ff1e17 100644 --- a/mono/Contours/Circuit.cs +++ b/mono/Contours/Circuit.cs @@ -129,32 +129,57 @@ namespace Contours { public void swapWith(Entry other) { if (other == this || other == null) return; + + if (this.next == other || other.previous == this) { + this.next = other.next; + other.next.previous = this; + other.previous = this.previous; + this.previous.next = other; + this.previous = other; + other.next = this; + return; + } + + if (other.next == this || this.previous == other) { + other.next = this.next; + this.next.previous = other; + this.previous = other.previous; + other.previous.next = this; + other.previous = this; + this.next = other; + return; + } + + if (other.circuit != null) { + if (other.circuit.first == other) + other.circuit.first = this; + if (other.circuit.last == other) + other.circuit.last = this; + } + + if (this.circuit != null) { + if (this.circuit.first == this) + this.circuit.first = other; + if (this.circuit.last == this) + this.circuit.last = other; + } Circuit otherCircuit = other.circuit; Entry otherPrevious = other.previous; Entry otherNext = other.next; - other.circuit = circuit; - other.previous = previous; - other.next = next; - - if (otherCircuit != null) { - if (otherCircuit.first == other) - otherCircuit.first = this; - if (otherCircuit.last == other) - otherCircuit.last = this; - } + other.circuit = this.circuit; + other.previous = this.previous; + other.next = this.next; - if (circuit != null) { - if (circuit.first == this) - circuit.first = other; - if (circuit.last == this) - circuit.last = other; - } + this.circuit = otherCircuit; + this.previous = otherPrevious; + this.next = otherNext; - circuit = otherCircuit; - previous = otherPrevious; - next = otherNext; + if (other.previous != null) other.previous.next = other; + if (other.next != null) other.next.previous = other; + if (this.previous != null) this.previous.next = this; + if (this.next != null) this.next.previous = this; } public static void swapChains(Circuit a, Circuit b) { diff --git a/mono/Contours/Geometry.cs b/mono/Contours/Geometry.cs index a9a1ce1..c13993a 100644 --- a/mono/Contours/Geometry.cs +++ b/mono/Contours/Geometry.cs @@ -67,16 +67,16 @@ namespace Contours { int b1b0 = -b0b1; // a0a1b0b1 - if (a1b0 == 0 && b0b1 < 0) + if (a1b0 == 0 && b0b1 <= 0) return IntersectionType.Touch_a1_b0; // a0a1b1b0 - if (a1b1 == 0 && b1b0 < 0) + if (a1b1 == 0 && b1b0 <= 0) return IntersectionType.Touch_a1_b1; // b0b1a0a1 - if (b0b1 < 0 && b1a0 == 0) + if (b0b1 <= 0 && b1a0 == 0) return IntersectionType.Touch_a0_b1; // b1b0a0a1 - if (b1b0 < 0 && b0a0 == 0) + if (b1b0 <= 0 && b0a0 == 0) return IntersectionType.Touch_a0_b0; if (a0b0 <= 0 && b0a1 <= 0 && a1b1 <= 0) @@ -113,7 +113,10 @@ namespace Contours { long numeratorY = (long)db.Y*((long)a1.X*(long)a0.Y - (long)a0.X*(long)a1.Y) - (long)da.Y*((long)b1.X*(long)b0.Y - (long)b0.X*(long)b1.Y); Point p = new Point((int)(numeratorX/divider), (int)(numeratorY/divider)); - if (comparePointsAtLine(p, a0, a0, a1) < 0 || comparePointsAtLine(p, a1, a0, a1) > 0) + if ( comparePointsAtLine(p, a0, a0, a1) < 0 + || comparePointsAtLine(p, a1, a0, a1) > 0 + || comparePointsAtLine(p, b0, b0, b1) < 0 + || comparePointsAtLine(p, b1, b0, b1) > 0 ) return IntersectionType.None; if (p.X == a0.X && p.Y == a0.Y) diff --git a/mono/Contours/Shape.cs b/mono/Contours/Shape.cs index 132a42b..8645472 100644 --- a/mono/Contours/Shape.cs +++ b/mono/Contours/Shape.cs @@ -46,6 +46,11 @@ namespace Contours { } public Link split(Shape shape, Position position) { + if (position.point == this.position.getParent().point) return this; + if (position.point == nextPosition.point) return nextPosition.links.getFirst(); + + shape.log.linkSplitted(this, position); + Link link = new Link(); link.position.insertBack(position.links); link.contour.insertAfterOf(contour); @@ -60,13 +65,63 @@ namespace Contours { return split(shape, positionLink.position.getParent()); } } + + class Log { + public bool enabled = true; + public string filename = "log.txt"; + + public void line(string line) { + if (!enabled) return; + System.IO.File.AppendAllLines(filename, new string[] { line }); + } + + public void linkCreated(Link link) { + if (!enabled) return; + line(string.Format( + "Link created {0} {1} {2}", + link.forward ? "->" : "<-", + link.position.getParent().point, + link.nextPosition.point )); + } + + public void linkRemoved(Link link) { + if (!enabled) return; + line(string.Format( + "Link removed {0} {1} {2}", + link.forward ? "->" : "<-", + link.position.getParent().point, + link.nextPosition.point )); + } + + public void linkSplitted(Link link, Position position) { + if (!enabled) return; + line(string.Format( + "Link splitted {0} {1}/{3}/{2}", + link.forward ? "->" : "<-", + link.position.getParent().point, + link.nextPosition.point, + position.point )); + } + + public void linkSwapped(Link a, Link b) { + if (!enabled) return; + line(string.Format( + "Link swapped {0} {1} {2} - {3} {4} {5}", + a.forward ? "->" : "<-", + a.position.getParent().point, + a.nextPosition.point, + b.forward ? "->" : "<-", + b.position.getParent().point, + b.nextPosition.point )); + } + } readonly List positions = new List(); readonly List links = new List(); readonly List contours = new List(); readonly List rootContours = new List(); - + readonly Log log = new Log(); public void clear() { positions.Clear(); @@ -88,6 +143,9 @@ namespace Contours { public void setContours(IEnumerable> contours) { clear(); + + log.line("---- setContours begin ----"); + foreach(IEnumerable contour in contours) { if (contour.Count() >= 3) { Link firstForward = null; @@ -121,8 +179,12 @@ namespace Contours { firstBackward.nextPosition = previousBackward.position.getParent(); } } + foreach(Link link in links) + log.linkCreated(link); calculate(true); + + log.line("---- setContours end ----"); } // returns list of root contour groups @@ -158,6 +220,7 @@ namespace Contours { } void removeLink(Link link) { + log.linkRemoved(link); link.position.unlink(); link.contour.unlink(); link.nextPosition = null; @@ -273,19 +336,17 @@ namespace Contours { Position position = link.position.getParent(); Link nextToRemove = null; - // remove back link + // remove back link if (link.nextPosition != null) { Link backLink = link.nextPosition.links.getFirst(); while (backLink != null) { - Link l = backLink; - backLink = backLink.position.getNextLinear(); - if ( l.forward != link.forward - && l.contour.getNext() != null - && l.contour.getNext().position.getParent() == position ) + if ( backLink.forward != link.forward + && backLink.nextPosition == position ) { - removeLink(l); + removeLink(backLink); break; } + backLink = backLink.position.getNextLinear(); } if (link.nextPosition.links.getCount() == 1) @@ -354,6 +415,7 @@ namespace Contours { b.nextPosition.point, c.nextPosition.point )) { + log.linkSwapped(b, c); b.position.swapWith(c.position); first = a = c; continue; @@ -363,9 +425,8 @@ namespace Contours { }; // remove invisible contours from position - first = position.links.getFirst(); - a = first.position.getNext(); - while(a != first) { + a = first = position.links.getFirst(); + while(true) { bool previous = a.position.getPrevious().forward; bool current = a.forward; bool next = a.position.getNext().forward; @@ -374,8 +435,11 @@ namespace Contours { { // remove link removeLinkFromPosition(a); - first = position.links.getFirst(); - a = first.position.getNext(); + if (position.links.getCount() < 3) break; + a = first = position.links.getFirst(); + } else { + a = a.position.getNext(); + if (a == first) break; } }; } @@ -396,7 +460,7 @@ namespace Contours { throw new Exception(); // find pair - for(Link l = forwardLink.nextPosition.links.getFirst(); l != null; l = l.position.getNext()) + for(Link l = forwardLink.nextPosition.links.getFirst(); l != null; l = l.position.getNextLinear()) if (l.nextPosition == forwardLink.position.getParent()) { backwardLink = l; break; } if (backwardLink == null || backwardLink.forward || backwardLink.contour.getParent() != null) @@ -565,6 +629,9 @@ namespace Contours { static Shape mix(Shape a, bool invertA, Shape b, bool invertB) { Shape sum = new Shape(); + sum.log.enabled = a.log.enabled && b.log.enabled; + + sum.log.line("---- mix begin ----"); // clone a for(int i = 0; i < a.positions.Count; ++i) @@ -591,8 +658,13 @@ namespace Contours { sum.links.Add(l); } } + foreach(Link link in sum.links) + sum.log.linkCreated(link); sum.calculate(false); + + sum.log.line("---- mix end ----"); + return sum; }