I’m wondering if anyone can confirm this…unexpected behavior.
If I have a quadratic that is basically a straight line, and check if it intersects with a vertical line at X, i get 2 intersection points, because the PathFlatteningIterator (for whatever reason), splits the path into linear segments right at the x of my line.
Here’s the coordinates for testing
Line<float> line(28.984375, -5.0, 28.984375, 305.0);
Path path;
path.startNewSubPath(0.0, 215.0);
path.quadraticTo(233.9999847412109375, 134.904998779296875, 400.0, 22.0);
Array<Point<float>> points;
if( intersectsPath(path, line, points) )
{
jassertfalse;
}
where intersectsPath
is:
bool intersectsPath(const Path &p, Line<float> line, Array<Point<float>> &possibleIntersections)
{
//this is taken from Path::intersectsPath and modified
PathFlatteningIterator i (p);
DBG( "checking intersection with line: " << line.getStart().toString() << " " << line.getEnd().toString());
Point<float> intersectionPoint;
while (i.next())
{
if (line.intersects (Line<float> (i.x1, i.y1, i.x2, i.y2), intersectionPoint))
{
DBG( " intersection: " << intersectionPoint.toString() );
if( !possibleIntersections.addIfNotAlreadyThere( intersectionPoint ) )
{
DBG( "**** intersected point found twice! " << intersectionPoint.toString() << " for line: " << line.getStart().toString() << " " << line.getEnd().toString());
}
}
}
if( possibleIntersections.isEmpty() )
return false;
//print our line and path coords so we can replicate it.
if( possibleIntersections.size() > 1 )
{
auto pPrint = [](float x) -> String { return String(x, 20); };
jassertfalse;
for( auto p : possibleIntersections )
{
DBG( "intersection: " << pPrint(p.x) << ", " << pPrint(p.y) );
}
Path::Iterator iter(p);
DBG("");
DBG( "intersectsPath path info" );
DBG( "line: Line<float>(" << pPrint(line.getStartX()) << ", " << pPrint(line.getStartY()) << ", " << pPrint(line.getEndX()) << ", " << pPrint(line.getEndY()) << ");" );
while( iter.next() )
{
switch (iter.elementType)
{
case juce::Path::Iterator::startNewSubPath:
DBG( ".startNewSubPath(" << pPrint(iter.x1) << ", " << pPrint(iter.y1) << ");" );
break;
case juce::Path::Iterator::lineTo:
DBG( ".lineTo(" << pPrint(iter.x1) << ", " << pPrint(iter.x2) << ");" );
break;
case juce::Path::Iterator::quadraticTo:
DBG( ".quadraticTo(" << pPrint(iter.x1) << ", " << pPrint(iter.y1) << ", " << pPrint(iter.x2) << ", " << pPrint(iter.y2) << ");" );
break;
case juce::Path::Iterator::cubicTo:
DBG( ".qubicTo(" << pPrint(iter.x1) << ", " << pPrint(iter.y1) << ", " << pPrint(iter.x2) << ", " << pPrint(iter.y2) << ", " << pPrint(iter.x3) << ", " << pPrint(iter.y3) << ");" );
break;
case juce::Path::Iterator::closePath:
DBG( ".closeSubPath()" );
break;
}
}
}
return true;
}
Maybe changing the tolerance for the PathFlatteningIterator is the solution? Or some other Quadratic/Linear intersection solver?