Line::clipToPath


#1

am i right in assuming that this only works if the line starts inside the path?

i’m making a concept mapping program (the one i like most is pretty buggy and slow), and so i have blocks that are joined by arrows.

say i have two rectangular components. the centres are joined with a line, but i wish for the line to actually start at the edges rather than the centre (but point to the centres). the easiest way i found to do this is…

[saying A is the start block and B is the end block]

  1. create a line from centreA to centreB
  2. create a path with the rectangular bounds of A
  3. clip the line to the path
  4. clear the path, and add the rectangular bounds of B
  5. clip the line to the path

the second clipping doesn’t do anything, and i imagine it’s because the line doesn’t start within the path. i tried them the other way round and it always leaves the end of the line unaltered.

is there an easier way to do this? the first thing i was going to do was use the withShortenedEnd/Start functions, but that appears to involve trig functions plus lots of conditionals (determining the amount to reduce by probably depends on which side the other box is on).


#2

Sounds like you’re doing it right, and I don’t see why it would make a difference which end is inside the path. The stuff at line 364 of juce_Line.cpp seems to be the bit that handles which end is which, so maybe try stepping into it?


#3

okay, so i’ve stepped through the Line::clipToPath function, and have encountered the point at which something happens incorrectly. but it’s during a bunch of maths that i haven’t figured out yet!

the actual error occurs during the juce_lineIntersection() function. i’ve drawn a diagram to show the state of all the variables in play…

you can see that the line is clearly intersecting the second interation of the path being clipped to. stepping thru the juce_lineIntersection function shows it correctly work out the point of intersection, but then it returns false from this:

const float along2 = ((y1 - y3) * dx1 - (x1 - x3) * dy1);
return along2 >= 0 && along2 <= divisor;

i have no idea what that code does, but in this example the ‘divisor’ is -9100.

any ideas why it thinks this isn’t an intersection?


#4

further investigation shows that the problem is indeed due to an intersection not being detected.

here’s some sample code as evidence (if you want to test it yourself, just paste it into something like MainComponent constructor in a template project). The diagram of course just shows the lines being used…

Line diagonal1 (0.0f,0.0f,10.0f,10.0f);
Line diagonal2 (10.0f,10.0f,0.0f,0.0f);
Line horizontal (0.0f,5.0f,10.0f,5.0f);
float x,y;
if (diagonal1.intersects (horizontal,x,y))
{
	DBG (T("diagonal1 intersects horizontal."));
}
else
{
	DBG (T("diagonal1 doesn't intersect horizontal."));
}
if (diagonal2.intersects (horizontal,x,y))
{
	DBG (T("diagonal2 intersects horizontal."));
}
else
{
	DBG (T("diagonal2 doesn't intersect horizontal."));
}

Here, clearly the two diagonal lines are the same, just travelling in opposite directions. The debugging output from this is…

diagonal1 doesn't intersect horizontal.
diagonal2 intersects horizontal.

I guess it’s got to be something to do with how the end point of ‘this’ line in juce_lineIntersection is analysed. But i’ve got to say i don’t really get the maths involved here, and have slightly more important things to be getting on with than deciphering uncommented code :hihi: maybe if you can remember how it works you can figure out what the problem is?


#5

well, i’ve changed line 110 of juce_Line.cpp to this:

            const float along2 = ((y1 - y3) * dx1 - (x1 - x3) * dy1) / divisor;

            if (along2 < 0 || along2 > 1.0f) return false;
			else return true;

and it now appears to work properly. it’s weird that it was written the way it was, because every single other calculation/test in this function is written in this way!


#6

What lovely diagrams! Thanks for going to so much trouble to illustrate my coding misdemeanours!

So many years have passed since I wrote that bit, that I’ve really no more idea than you about what’s going on, but it looks to me like I tried to be clever by optimising-out the division, but forgot that “divisor” could be negative, which would mess up the comparisons. Your fix looks right to me, and I apologise for being a doofus!


#7