简体   繁体   中英

Find the point on a curve a given distance along the curve from another point

I am trying to find a point 'p2' on a curve, and it is 'd' away from point 'p1'.

  • The curve is quadratic formula a x^2 + b x + c = y
  • point p1 is on the curve, let us say (p1x, p1y)
  • point p2 is on the curve, but we only know its distance 'along the curve' from p1, which is 'd'. A distance on a curve can be calculated by integrating'(1+(2*a*x+b)^2)^(1/2) dx'. Here, integrating'(1+(2*a*x+b)^2)^(1/2) dx' from p1x to p2x is expectd to have a given number k. p2x is unknown.

I have been using a loop to find the point.

from scipy import integrate

def integral(a, b, c, p1x, distance_between_p1_and_p2):
        x = lambda x:(1+(2*a*x+b)**2)**(1/2)
        best_i=0
        p2x=0
        for points_on_curve in range(int(p1x*1000),int((p1x+0.15)*1000),1):
                i,j  = integrate.quad(x,p1x,points_on_curve/1000)
                if abs(i-distance_between_p1_and_p2)<abs(best_i-distance_between_p1_and_p2):
                        best_i=i
                        p2x=points_on_curve/1000
        return p1x+p2x

The problem here is it takes so long becuase it begins from p1x and slightly increase the value, calculate the length from p1 to potential p2 and see if it is closer to the target distance_between_p1_and_p2 than the previous one.

Would it be there a better way of programming it?

I have been working on it and i found two solutions to this.

First, I used sympy.geometry.curve

from sympy.geometry.curve import Curve
x = sp. Symbol('x')
a = sp. Symbol('a')
b = sp. Symbol('b')
c = sp. Symbol('c')
start = sp. Symbol('start')
end = sp. Symbol('end')
print('length')
print(Curve((a*x**2+b*x+c, x), (x, start, end)).length)

I get this as an output.

(end + b/(2*a))*sqrt(4*a**2*(end + b/(2*a))**2 + 1)/2 - (start + b/(2*a))*sqrt(4*a**2*(start + b/(2*a))**2 + 1)/2 + asinh(2*a*(end + b/(2*a)))/(4*a) - asinh(2*a*(start + b/(2*a)))/(4*a)

Here, I can use the equation.

from sympy import solve, sqrt, asinh, nsolve
end = sp.S('end')
a = -1
b = 0
c = 4
w3 = 1
length = 2

eq = sp.Eq((end + b/(2*a))*sqrt(4*a**2*(end + b/(2*a))**2 + 1)/2 - (w3 + b/(2*a))*sqrt(4*a**2*(w3 + b/(2*a))**2 + 1)/2 + asinh(2*a*(end + b/(2*a)))/(4*a) - asinh(2*a*(w3 + b/(2*a)))/(4*a),length)

I found two ways to solve the equation.

  1. Use nsolve. This gives only one answer even if I have two. For example, if there are two answers (a+sqrt(b), a-sqrt(b)), I guess this gives only one answer closer to expected_value_to_start_search_answer.

    print(sp.nsolve(eq, expected_value_to_start_search_answer))

  2. Use solve. This gives all possible answers, but it is slower than the first option.

    sol = solve(eq,end) print(sol)

Your target points x, y sit on the parabolic curve as well as on a circle around p1, in other words, all fulfill the equations

a x^2 + b x + c = y
(x - p1x)^2 + (y - p1y)^2 = r^2

You can simply eliminate y by inserting the lhs from the first equation into the second, and solve the resulting quadratic equation for x .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM