distance from given point to given ellipse

后端 未结 7 1952
抹茶落季
抹茶落季 2021-02-05 08:07

I have an ellipse, defined by Center Point, radiusX and radiusY, and I have a Point. I want to find the point on the ellipse that is closest to the given point. In the illustrat

相关标签:
7条回答
  • 2021-02-05 08:40

    The following python code implements the equations described at "Distance from a Point to an Ellipse" and uses newton's method to find the roots and from that the closest point on the ellipse to the point.

    Unfortunately, as can be seen from the example, it seems to only be accurate outside the ellipse. Within the ellipse weird things happen.

    from math import sin, cos, atan2, pi, fabs
    
    
    def ellipe_tan_dot(rx, ry, px, py, theta):
        '''Dot product of the equation of the line formed by the point
        with another point on the ellipse's boundary and the tangent of the ellipse
        at that point on the boundary.
        '''
        return ((rx ** 2 - ry ** 2) * cos(theta) * sin(theta) -
                px * rx * sin(theta) + py * ry * cos(theta))
    
    
    def ellipe_tan_dot_derivative(rx, ry, px, py, theta):
        '''The derivative of ellipe_tan_dot.
        '''
        return ((rx ** 2 - ry ** 2) * (cos(theta) ** 2 - sin(theta) ** 2) -
                px * rx * cos(theta) - py * ry * sin(theta))
    
    
    def estimate_distance(x, y, rx, ry, x0=0, y0=0, angle=0, error=1e-5):
        '''Given a point (x, y), and an ellipse with major - minor axis (rx, ry),
        its center at (x0, y0), and with a counter clockwise rotation of
        `angle` degrees, will return the distance between the ellipse and the
        closest point on the ellipses boundary.
        '''
        x -= x0
        y -= y0
        if angle:
            # rotate the points onto an ellipse whose rx, and ry lay on the x, y
            # axis
            angle = -pi / 180. * angle
            x, y = x * cos(angle) - y * sin(angle), x * sin(angle) + y * cos(angle)
    
        theta = atan2(rx * y, ry * x)
        while fabs(ellipe_tan_dot(rx, ry, x, y, theta)) > error:
            theta -= ellipe_tan_dot(
                rx, ry, x, y, theta) / \
                ellipe_tan_dot_derivative(rx, ry, x, y, theta)
    
        px, py = rx * cos(theta), ry * sin(theta)
        return ((x - px) ** 2 + (y - py) ** 2) ** .5
    

    Here's an example:

    rx, ry = 12, 35  # major, minor ellipse axis
    x0 = y0 = 50  # center point of the ellipse
    angle = 45  # ellipse's rotation counter clockwise
    sx, sy = s = 100, 100  # size of the canvas background
    
    dist = np.zeros(s)
    for x in range(sx):
        for y in range(sy):
            dist[x, y] = estimate_distance(x, y, rx, ry, x0, y0, angle)
    
    plt.imshow(dist.T, extent=(0, sx, 0, sy), origin="lower")
    plt.colorbar()
    ax = plt.gca()
    ellipse = Ellipse(xy=(x0, y0), width=2 * rx, height=2 * ry, angle=angle,
                      edgecolor='r', fc='None', linestyle='dashed')
    ax.add_patch(ellipse)
    plt.show()
    

    Which generates an ellipse and the distance from the boundary of the ellipse as a heat map. As can be seen, at the boundary the distance is zero (deep blue).

    0 讨论(0)
提交回复
热议问题