Skip to content

Commit

Permalink
Fix bug 3
Browse files Browse the repository at this point in the history
  • Loading branch information
ctessum committed May 4, 2016
1 parent b1164ad commit fc96ee8
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 18 deletions.
19 changes: 18 additions & 1 deletion bugs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,10 @@ func TestBug3(t *T) {
result: Polygon{{{1, 2}, {2, 2}, {2, 1}}},
},
}
for _, c := range cases {
for i, c := range cases {
if i != 5 {
continue
}
result := dump(c.subject.Construct(UNION, c.clipping))
if result != dump(c.result) {
t.Errorf("case UNION:\nsubject: %v\nclipping: %v\nexpected: %v\ngot: %v",
Expand Down Expand Up @@ -247,6 +250,20 @@ func TestBug4(t *T) {
},
},
},
{
subject: Polygon{
Contour{
Point{X: 1.1458356382266793e+06, Y: -251939.4635597784},
Point{X: 1.1460824662209095e+06, Y: -251687.86194535438},
Point{X: 1.1458356382266793e+06, Y: -251939.4635597784},
}},
clipping: Polygon{
Contour{
Point{X: 1.1486683769211173e+06, Y: -251759.06331944838},
Point{X: 1.1468807511323579e+06, Y: -251379.90576799586},
Point{X: 1.1457914974731328e+06, Y: -251816.31287551578},
}},
},
}
for i, c := range cases {
// check that we get a result in finite time
Expand Down
66 changes: 49 additions & 17 deletions clipper.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,13 @@ func (c *clipper) compute(operation Op) Polygon {

i := 0

// The maximum possible number of events would be if every segment intersected
// with every other segment times two points per segment.
// If we end up with more iterations than that
// in the following for loop we know we have a problem.
maxPossibleEvents := numSegments * numSegments * 2
// From the manuscript, the cycle is executed
// n + 4k times, where n is the number of segments and k is the number of
// intersections. I believe the maximum k would be about n^2, but
// we assume it here to be 2*n. This may not be the absolute maximum
// number of events, but it is not likely that there would be more intersections
// than this in a real polygon.
maxPossibleEvents := numSegments * 9

for !c.eventQueue.IsEmpty() {

Expand Down Expand Up @@ -523,29 +525,59 @@ func (c *clipper) divideSegment(e *endpoint, p Point) {
c.eventQueue.enqueue(r)
}

// addPolygonToQueue adds p to the event queue, retuning the number of
type empty struct{}

// a polygonGraph holds the points of a polygon in a graph struct.
// The index of the first map is the starting point of each segment
// in the polygon and the index of the second map is the ending point
// of each segment.
type polygonGraph map[Point]map[Point]empty

// addToGraph adds the segments of the polygon to the graph in a
// way that ensures the same segment is not included twice in the
// polygon.
func addToGraph(g *polygonGraph, seg segment) {
if seg.start.Equals(seg.end) {
// The starting and ending points are the same, so this is
// not in fact a segment.
return
}

if _, ok := (*g)[seg.end][seg.start]; ok {
// This polygonGraph already has a segment end -> start, adding
// start -> end would make the polygon degenerate, so we delete both.
delete((*g)[seg.end], seg.start)
return
}

if _, ok := (*g)[seg.start]; !ok {
(*g)[seg.start] = make(map[Point]empty)
}

// Add the segment.
(*g)[seg.start][seg.end] = empty{}
}

// addPolygonToQueue adds p to the event queue, returning the number of
// segments that were added.
func addPolygonToQueue(q *eventQueue, p Polygon, polyType polygonType) int {
numSegments := 0
g := make(polygonGraph)
for _, cont := range p {
if cont[0].Equals(cont[len(cont)-1]) {
// If the beginning point and the end point are the same,
// ignore the end point.
cont = cont[0 : len(cont)-1]
}
for i := range cont {
addProcessedSegment(q, cont.segment(i), polyType)
addToGraph(&g, cont.segment(i))
}
}
numSegments := 0
for start, gg := range g {
for end := range gg {
addProcessedSegment(q, segment{start: start, end: end}, polyType)
numSegments++
}
}
return numSegments
}

func addProcessedSegment(q *eventQueue, segment segment, polyType polygonType) {
if segment.start.Equals(segment.end) {
// Possible degenerate condition
return
}

e1 := &endpoint{p: segment.start, left: true, polygonType: polyType}
e2 := &endpoint{p: segment.end, left: true, polygonType: polyType, other: e1}
Expand Down

0 comments on commit fc96ee8

Please sign in to comment.