6

I've read related posts, including:

How to tell if a line segment intersects with a circle? where the suggestions are probably relevant, but above my level, and the final solution is actually not what I need, and

Circle and Line segment intersection Which may be what I need, but assumes more math knowledge than is in my brain.

Context: I have two circles in powerpoint, each of which have 8 points (anchors) on the perimeter. I am cycling through all 64 combinations in VBA to identify which two lines provide the longest point-to-point connectors that do not go through either circle. For convenience, I can check each line against each circle separately.

Basically, I am trying to create code that will allow me to automatically create something like this http://www.harrisgolfonline.com/userfiles/image/wlcc%201932%20bylaws%20callout.jpg except I'll also have a small circle around the enlarged part of the original image. I'm trying to get the math to figure out which circle anchors will give me those two outer lines.

So for example, if I draw the shortest possible line segment between the two closest connectors, I should not intersect with either circle. A line between the furthest away connectors would have to travel through both circles, and therefore fail either circle test.

Anyway, I'm hoping someone can help me with the equation setup, since the two pages I reference put in multiple equations and then say "then just solve it". I'm not exactly sure how to combine those formulas to solve. What I'm hoping for is something more like this equation, except this evaluates based on the whole line and not just a line segment:

Private Function LineCrossesCircle(x1, y1, x2, y2, cx, cy, cr) As Boolean

x1 = x1 - cx

y1 = y1 - cy

x2 = x2 - cx

y2 = y2 - cy

LineCrossesCircle = 0 <= cr ^ 2 * ((x2 - x1) ^ 2 + (y2 - y1) ^ 2) - (x1 * y2 - x2 * y1) ^ 2

End Function

Reading the answers, I do understand that there may be multiple conditions, e.g. it may be something similar to the above AND some other equation or two.

My connector points will always be on the circumference of the circle, so I was adjusting my calculated radius value to be [r*.95] otherwise they might all intersect at the endpoints. That means that my endpoints will never fall within the circles, but part of the line will fall in one or both circles probably 80% of the time. Once I find the lines that don't, I can check their lengths and add them as connectors.

Any help translating the previous solutions into one or more equations that just take the two endpoints (x1, y1, x2, y2) and circle info (cx, cy, cr) and return a boolean for whether there is an intersect would be greatly appreciated!!

===================================================================================

Sample code based on OAO's helpful post. I think I got something wrong, because it is no connectors with intersects, when I know about 80% should have an intersect.

EDIT: updated the formulas for MA and MB (I had some of the elements reversed I think) but still showing no intersects

Private Function IntersectCheck(ByVal Cx As Single, _
                            ByVal Cy As Single, _
                            ByVal Radius As Single, _
                            ByVal Ax As Single, _
                            ByVal Ay As Single, _
                            ByVal Bx As Single, _
                            ByVal By As Single) As Boolean

'distance between endpoints

d = (((Bx - Ax) ^ 2) + ((By - Ay) ^ 2)) ^ 0.5

'not totally sure what this is

alpha = (1 / (d ^ 2)) * ((Bx - Ax) * (Cx - Ax) + (Bx - Ax) * (Cx - Ax))

'point nearest circle center

mx = Ax + ((Bx - Ax) * alpha)

my = Ay + ((By - Ay) * alpha)

MC = ((Cx - mx) ^ 2 + (Cy - my) ^ 2) ^ 0.5

MA = ((Ax - mx) ^ 2 + (Ay - my) ^ 2) ^ 0.5

MB = ((Bx - mx) ^ 2 + (By - my) ^ 2) ^ 0.5

AC = ((Cx - Ax) ^ 2 + (Cy - Ay) ^ 2) ^ 0.5

BC = ((Cx - Bx) ^ 2 + (Cy - By) ^ 2) ^ 0.5

IntersectCheck = False

If MC > Radius Then

'there is no intersect

Else

If (MA < d) And (MB < d) Then

    'there is an intersect

    IntersectCheck = True

Else

    If AC <= Radius Or BC <= Radius Then

        'there is an intersect

        IntersectCheck = True

    End If

End If

End If

End Function

K ATL
  • 111
  • 2
  • 6
  • 2
    Is there any reason you're not simply calculating the tangent lines from the one circle to the other? – Mark Ping May 31 '13 at 21:10
  • It seems to me that your sample code just tests whether either of the endpoints of the line segment are inside the circle. But both endpoints could be outside, and the line segment might enter and then exit the circle, no? – Jyrki Lahtonen May 31 '13 at 21:14
  • @Mark Ping- The powerpoint shapes have anchors that I want to connect to, even if they aren't the perfect tangents. That allows me to move the shapes manually and the lines will adjust automagically. If I used tangents then I'd need to manually adjust those as well. The key is to find anchor-to-anchor connectors that are just shorter than the tangent on each side :) – K ATL May 31 '13 at 21:17
  • @Jurki Lahtonen That may be true, it was a sample I picked up that someone else created in VBA. Both endpoints will definitely be outside, and the question is whether (each) enters and exits, you are correct – K ATL May 31 '13 at 21:18
  • 1
    off topic comment: I thought you were calling me. – newbie May 31 '13 at 22:38
  • The image link in the question seems to be broken, but this image seems to match the description (and the file name): https://www.wilsonlakecountryclub.com/wp-content/uploads/sites/5219/2015/08/wlcc-1932-bylaws-callout.jpg – David K May 07 '22 at 18:10

4 Answers4

2

Given the coordinates of two distinct points, represented by vectors of coordinates $v_p$ and $v_q$, the coordinate vectors of points on the line between them can be parameterized by $v(t) = tv_p + (1-t)v_q$, in which the $x$ and $y$ coordinates of $v(t)$ are linear functions of $t$. The squared distance from $v(t)$ to center of the circle is a quadratic function of $t$ with coefficients calculable from the given information, $At^2 + Bt + C$ with $A > 0$, and you want to know whether its minimum (which is the value when $t = -\frac{B}{2A}$) is less than or equal to $R^2$.

zyx
  • 36,077
0

@Mooncat39: I have loaded the working powerpoint file here (link below)- I haven't touched the code in a while, and it is entirely possible that I left fragments of other code attempts in there that I didn't delete when I got this one working... but this one does work, instructions included. You are welcome to adapt it as you see fit. I'll leave this link live for a few days (or until I see a reply post from you confirming you downloaded a copy) so that you can access the VBA code that drives the callout maker.

https://drive.google.com/file/d/0B1a_NxK2EF77ckR4WWFKclVoOE0/view?usp=sharing

K ATL
  • 111
  • 2
  • 6
0

Let's name your segment $[A,B]$, $C$ the center of your circle and $R$ it radius. $d=\sqrt{(Bx-Ax)^2 + (By-Ay)^2}$ is the distance between the two points.

First you get the point that is the nearest of C, in $(A,B)$. This point, M, has coordinates $Ax + (Bx-Ax)\ \alpha$ and $Ay + (By-Ay)\ \alpha$ , where $\alpha=\frac{1}{d^2}\left((Bx-Ax)\ (Cx-Ax) + (By-Ay)\ (Cy-Ay) \right)$ is the distance between A and B. This is just $\overrightarrow{AM}=\left( \frac{\overrightarrow{AB}}{AB} \cdot\overrightarrow{AC}\right) \frac{\overrightarrow{AB}}{AB}$

Then you check if this point is in the circle. If $|MC|=\sqrt{((Cx-Mx)^2+(Cy-My)^2)}>R$, the circle and the line doesn't intersect, so the circle and the segment doesn't intersect.

If $|MC| \leq R$, you have to check if M is in the segment, ie if $|MA| \leq d$ and $|MB| \leq d$. If it is true, the circle and the line intersect.

If $|MC| \leq R$ but M is not in the segment, you just have to check if $|AC| \leq R$ or $|BC| \leq R$. If it is true, the segment and the circle intersect. If is is false, they do not intersect.

oao
  • 161
  • 5
  • This is almost down to my low level of understanding- thank you for spelling out all of the equations. |MC| signifies the distance between M and C? If so then I understand what MA and MB stands for, but I need to work out the math to understand what it is doing. I don't know what Ror or R$ stand for? This is the closest yet to my level of understanding, I appreciate any further help! – K ATL May 31 '13 at 21:47
  • Yes $|MC|$ is the distance between M and C. It is also commonly writen just $MC$. R is the radius of the circle. R$ is a mispelling ;) – oao May 31 '13 at 21:59
  • I've converted the formulas to the following code, but I'm getting 100% of the results indicating that there is an intersect (even though I know there should be a handful without). I know this is a less familiar format, but if you notice any errors on my part, please let me know. – K ATL May 31 '13 at 22:19
  • I will append to original post, the comments are too small to accept the code – K ATL May 31 '13 at 22:21
  • Oops, error on my part- it is 100% returned without intersect (I thought it was the reverse) – K ATL May 31 '13 at 22:39
  • My mistake, there were a typo in the formula for alpha. By the way, you should use a pastebin or gist.github.com and keep you question clean. – oao May 31 '13 at 22:46
  • @ oao I'm not familiar with those programs, but I'll take a look. If they require a local installation I won't be able to use them due to our IT rules. – K ATL Jun 03 '13 at 14:58
  • I can't post a picture from this PC, but my current calculations are still not giving expected results; of the 64 possible combinations, only 8 are returning as non-intersecting, and those are all to one point on the first circle- so 5 of those actually do intersect. Looks like I have more troubleshooting to do... – K ATL Jun 03 '13 at 17:00
  • should alpha always be a positive number? I'm going through detailed review of each line, and I'm seeing negative alpha values. I'm not sure if that means I got the equation wrong, or if I need to take an absolute value of whatever comes out of that equation. Thanks! – K ATL Jun 03 '13 at 21:25
  • Got it! oao thank you again for your help! – K ATL Jun 03 '13 at 22:16
  • Good ! Mark this answer as solution. You can also add your final code, if you want to help someone with the same issue. And try to learn basic vectorial math ;) – oao Jun 03 '13 at 22:41
0

Alternatively, you can also skip the 2nd order polynomial calculation entirely.

Let's start with line-circle intersection. If you project the center of the circle on the line, you get by definition the closest point to the circle center $C$ on that line. Now, if this point isn't inside the circle, that is less than one radius $R$ away from the center, you directly know the line won't intersect.

To get the projection point you can do $\vec{P} = \vec{A} + (\vec{AC}.\vec{u}_{AB}) \times \vec{u}_{AB}$ where $\vec{u}_{AB} = \frac{\vec{AB}}{|AB|}$

And then we check $\vec{PC}.\vec{PC} \leq R^2$

Now that we know whether the line intersects, there are 3 cases:

  • The 2 end points of your segment are on each side of the intersected area. In this case the distance from $A$ to $P$ should be less than the distance from $A$ to $B$, i.e. $\vec{AP}.\vec{AP} <= \vec{AB}.\vec{AB}$
  • One end point is inside the circle. In this case, the projection point could very well be outside the segment. So we check whether the end points of the segment are within one radius of the center. $\vec{AC}.\vec{AC} <= R^2$ or $\vec{BC}.\vec{BC} <= R^2$
  • Finally both end points are outside the circle, which we already tested above.

And voilà! No equation to solve. Just dot products.

Niels
  • 1