diff --git a/mono/Contours/Circuit.cs b/mono/Contours/Circuit.cs index 5e885d0..487d4d3 100644 --- a/mono/Contours/Circuit.cs +++ b/mono/Contours/Circuit.cs @@ -156,6 +156,13 @@ namespace Contours { previous = otherPrevious; next = otherNext; } + + public static void swapChains(Circuit a, Circuit b) { + for(Entry e = a.getFirstEntry(); e != null; e = e.getNextEntryLinear()) + e.circuit = b; + for(Entry e = b.getFirstEntry(); e != null; e = e.getNextEntryLinear()) + e.circuit = a; + } } readonly Parent owner; @@ -185,6 +192,10 @@ namespace Contours { public void clear() { while(!empty()) getFirstEntry().unlink(); } + + public void swapWith(Circuit other) { + Entry.swapChains(this, other); + } } } diff --git a/mono/Contours/Shape.cs b/mono/Contours/Shape.cs index 809b0a1..2f2a209 100644 --- a/mono/Contours/Shape.cs +++ b/mono/Contours/Shape.cs @@ -114,33 +114,27 @@ namespace Contours { calculate(true); } - - /* TODO: - public bool removeEmptyContours() { - bool removed = false; - bool retry = true; - while(retry) { - retry = false; - for(Contour contour = contours.getFirst(); !retry && contour != null; contour = contour.shape.getNextLinear()) { - if (contour.forward.getCount() < 3 || contour.backward.getCount() < 3) { - while(contour.forward.getFirst() != null) - contour.forward.getFirst().unlink(); - while(contour.backward.getFirst() != null) - contour.backward.getFirst().unlink(); - contour.shape.unlink(); - retry = true; - removed = true; - break; - } - } - if (retry) continue; + // returns list of root contour groups + // first contour in group is outer contour, others - inner + public List>> getContours() { + List>> groups = new List>>(); + foreach(Contour root in rootContours) { + List> list = new List>(); + list.Add(contourToList(root)); + foreach(Contour c in root.childs) + list.Add(contourToList(c)); } - - return removed; + return groups; } - */ - + + List contourToList(Contour contour) { + List list = new List(); + for(Link link = contour.forward.getFirst(); link != null; link = link.contour.getNext()) + list.Add(link.position.getParent().point); + return list; + } + void resetTraceInformation() { for(int i = 0; i < contours.Count; ++i) { contours[i].forward.clear(); @@ -541,6 +535,61 @@ namespace Contours { buildContoursHierarhy(simple); removeEmptyPositions(); } + + public void invert() { + foreach(Link link in links) + link.forward = !link.forward; + foreach(Contour contour in contours) + contour.forward.swapWith(contour.backward); + } + + static Shape mix(Shape a, bool invertA, Shape b, bool invertB) { + Shape sum = new Shape(); + + // clone a + for(int i = 0; i < a.positions.Count; ++i) + sum.positions.Add(new Position(a.positions[i].point)); + for(int i = 0; i < a.positions.Count; ++i) { + for(Link link = a.positions[i].links.getFirst(); link != null; link = link.position.getNext()) { + Link l = new Link(); + l.forward = invertA != link.forward; + l.nextPosition = sum.positions[a.positions.IndexOf(link.nextPosition)]; + l.position.insertBack(sum.positions[a.positions.IndexOf(a.positions[i])].links); + sum.links.Add(l); + } + } + + // clone b + for(int i = 0; i < b.positions.Count; ++i) + sum.positions.Add(new Position(b.positions[i].point)); + for(int i = 0; i < b.positions.Count; ++i) { + for(Link link = b.positions[i].links.getFirst(); link != null; link = link.position.getNext()) { + Link l = new Link(); + l.forward = invertB != link.forward; + l.nextPosition = sum.positions[a.positions.Count + b.positions.IndexOf(link.nextPosition)]; + l.position.insertBack(sum.positions[a.positions.Count + b.positions.IndexOf(a.positions[i])].links); + } + } + + sum.calculate(false); + return sum; + } + + public static Shape add(Shape a, Shape b) { + return mix(a, false, b, false); + } + + public static Shape subtract(Shape a, Shape b) { + return mix(a, false, b, true); + } + + public static Shape xor(Shape a, Shape b) { + return add(subtract(a, b), subtract(b, a)); + } + + public static Shape intersection(Shape a, Shape b) { + return subtract(add(a, b), xor(a, b)); + } } }