OpenEndedGroup / Field

A development environment for art
201 stars 22 forks source link

another line intersection bug in FLines #36

Open highfellow opened 11 years ago

highfellow commented 11 years ago

Hi,

I've found another bug / feature in the FLine intersection functions. If one line crosses another exactly on one of its own nodes, or the other line's nodes, no points of intersection are returned.

E.g. if you run this code:

line1 = FLine().moveTo(0,300).lineTo(100,200)
line2 = FLine().moveTo(0,200).lineTo(50,250).lineTo(100,300)
_self.lines.clear()
_self.lines.add(line1.append(line2))

print line1.pointsOfIntersection2(line2)
print line2.pointsOfIntersection2(line1)
print line2.doIntersection2(line1)

it returns 3 empty lists:

[]
[]
[]
highfellow commented 11 years ago

Sorry, the test code should look like this:

line1 = FLine().moveTo(0,300).lineTo(100,200)
line2 = FLine().moveTo(0,200).lineTo(50,250).lineTo(100,300)
_self.lines.clear()
_self.lines.add(line1)
_self.lines.add(line2)

print line1.pointsOfIntersection2(line2)
print line2.pointsOfIntersection2(line1)
print line2.doIntersection2(line1)

The output is the same though - no intersections found.

highfellow commented 11 years ago

It looks like doIntersection2 adds the extra node to one line, but the cursor pair isn't returned.

E.g.

line1 = FLine().moveTo(0,300).lineTo(100,200)
line2 = FLine().moveTo(0,200).lineTo(50,250).lineTo(100,300)
_self.lines.clear()
_self.lines.add(line1)
_self.lines.add(line2)

print line1.pointsOfIntersection2(line2)
print line2.pointsOfIntersection2(line1)
print len(line1.events), len(line2.events)
print line2.doIntersection2(line1)
print len(line1.events), len(line2.events)

prints this

[]
[]
2 3
[]
3 3
highfellow commented 11 years ago

I've had a bit of a look at the source. The relevant code is in this java file: core/java/field/core/plugins/drawing/opengl/Intersections.java

I may have a go at fixing the issue at some point. I don't know much java though, so it might take me a while.

One question whether this is code you've written yourselves, or an external library you're distributing as part of Field? Also, as far as you're concerned, is the behaviour I've described definitely a bug, or an intended feature?

highfellow commented 11 years ago

I've found it's possible to work around this issue by running doIntersection2, then calling a custom function I've written which detects any nodes on the two lines that are in the same place.

If you try this, be aware that the extra node added by doIntersection2 isn't necessarily that close to the node on the other line. You need to tune the fuzz factor for the project you are working on. E.g. one of the line pairs in the project I'm working on had nodes about 0.5 units apart.

Here's the workaround code. commonNodes returns cursor pairs, the same as doIntersection2.

def samePosition(pos1, pos2):
    fuzz =  0.7
    if pos1[0] <= pos2[0] + fuzz and pos1[0] >= pos2[0] - fuzz and pos1[1] <= pos2[1] + fuzz and pos1[1] >= pos2[1] - fuzz:
        return True
    else:
        return False

def commonNodes(line1, line2):
    ret = []
    node1No = 0
    for node1 in line1.events:
        pos1 = node1.position()
        node2No = 0
        for node2 in line2.events:
            pos2 = node2.position()
            if samePosition(pos1, pos2):
                print "exact match"
                ret.append((line1.cursor(node1No), line2.cursor(node2No)))
            node2No += 1
        node1No += 1
    return ret
highfellow commented 11 years ago

I've found a work-around for this bug, which is good enough for what I need to do, which is to: