-2

I'm using Three.js and am trying to figure out how to get the closest line segment of a circle from a random point on an X and Y grid. Basically which line is the center of the red disc closest too. the invisible grid is x = 400 and y = 400. z = 0. I am looking for an algorithm in any language. I know it Trigonometry but I'm sorry to say I'm not as fresh as I thought I was. If anyone can answer in javascript or python that would be great but any coding language would be great!

If I start with the red disc here at the origin (0,0) then move it enter image description here

ok to clarify, say the green line is Y, and the red line is X, Now I want to know the mathematical formula that will tell me which axis the middle of the red circle closest to. Now the red circle will be randomly placed anywhere with in the bounds of X and Y axis. I think it's a triganomic function but I'm rusty at math. If you can convert your answer to javascript that will be really helpful

Justin Meskan
  • 618
  • 1
  • 9
  • 32
  • 1
    This is not so much a JavaScript question. More of a math question. This post should help you get started: https://stackoverflow.com/questions/10957689/collision-detection-between-a-line-and-a-circle-in-javascript – Dan Mullin Sep 05 '20 at 00:08
  • 1
    This one too. It has javascript code examples for line circle collision detection: https://stackoverflow.com/questions/37224912/circle-line-segment-collision/37225895 You'll need to be able to "detect collisions" in the sense that you have to use the same distance calculation which would lead you to being able to find the line segment that is the closest distance. – Dan Mullin Sep 05 '20 at 00:11
  • 1
    This is a math question. Go to math.stackexchange.com to ask. PS:Take a point on the line calculate de equation between the point and the center of the circle and change the point until you minimize the distance. – Dominique Fortin Sep 05 '20 at 00:53
  • 1
    I don't understand the question. Could you reformulate it and show more clear picture explaining what you want? – MBo Sep 05 '20 at 02:55
  • 1
    The phrase `the invisible grid is x = 10 and y = 10. z = 0` is hard to understand. How is the grid related to the red point and/or the circle? Would `z` be zero for all elements involved, or are there elements in 3D involved? You write about a circle but show and octagon. So, do you mean a circle subdivided in `N` segments? How do you represent the circle and the start of the first segment? Are the radial segments drawn just as illustration, or are they part of the "circle segments" – JohanC Sep 05 '20 at 11:28
  • A Cartesian coordinate system is a coordinate system that specifies each point uniquely in a plane by a set of numerical coordinates, which are the signed distances to the point from two fixed perpendicular oriented lines, measured in the same unit of length – Justin Meskan Sep 06 '20 at 23:57
  • Thanks for all the help guys It was answered perfectly here. Sorry I had so much trouble explaining myself. – Justin Meskan Sep 06 '20 at 23:58

1 Answers1

1

The first step is to find the angle of the line between the chosen point and the circle center with the x-axis. This angle is theta = atan2(y0-yc, x0-xc). Subtracting the starting angle and finding the fraction relative to the 2*pi of a complete circle gives the index: floor(theta * num_segments / (2 * pi)). This number has to be taken modulo the number of segments to obtain an index between 0 <= ind < num_segments.

To find the distance between the point and the circle, first calculate the distance to the center and subtract it from the radius. So, radius - sqrt((x0-xc)*(x0-xc)+(y0-yc)*(y0-yc)).

Here is some python code to illustrate the concept (avoiding numpy which would make things easier to implement, but harder to convert to other programming languages).

from matplotlib import pyplot as plt
from math import sin, cos, pi, atan2, floor

def draw_segmented_circle(xc, yc, radius, num_segments=8, theta0=0, selected_segment=None, **kwargs):
    xpos = [xc + radius * cos(theta0 + 2 * pi * i / num_segments) for i in range(num_segments + 1)]
    ypos = [xc + radius * sin(theta0 + 2 * pi * i / num_segments) for i in range(num_segments + 1)]
    if selected_segment is not None:
        i = selected_segment
        plt.plot([xpos[i], xpos[i + 1]], [ypos[i], ypos[i + 1]], **kwargs)
    else:
        for i in range(num_segments):
            plt.plot([xpos[i], xpos[i + 1]], [ypos[i], ypos[i + 1]], **kwargs)
            plt.plot([xc, xpos[i]], [yc, ypos[i]], ls=':', **kwargs)

def find_closest_segment(x0, y0, xc, yc, radius, num_segments=8, theta0=0):
    theta = (atan2(y0 - yc, x0 - xc) - theta0)
    return (floor(theta * num_segments / (2 * pi)) + num_segments) % num_segments

xc, yc, radius, num_segments, theta0 = 0, 0, 5, 8, 0
circle = (xc, yc, radius, num_segments, theta0)
draw_segmented_circle(*circle, color='blue')

x0, y0 = 1, 3
ind = find_closest_segment(x0, y0, *circle)
draw_segmented_circle(*circle, selected_segment=ind, color='red')
plt.plot(x0, y0, 'o', color='red')

plt.gca().set_aspect('equal')
plt.show()

example plot

JohanC
  • 71,591
  • 8
  • 33
  • 66