Search code examples
pythonarraysnumpyopen3d

finding arc length in a curve created by numpy array


I have a NumPy array that can be used to create a curve the array looks like this.

curve=np.asarray([0,0,0], [0.5,0,0], [0.8,0.2,0], [1,0.5,0], [1.2,0.7,0])

If I connect them up it will look like the following figureenter image description here

The points are the vertices on the curve.

Is there any way to find the arc length between any two given points on this curve for example the two blue points?


Solution

  • To get the curve length between any two points of the curve you need to define these points as vertices of this curve.

    In the following example I insert the two blue points at the needed position and then sum up the Euclidean distances of all the vertices between these two points:

    import numpy as np
    
    curve = np.asarray([[0,0,0], [0.5,0,0], [0.8,0.2,0], [1,0.5,0], [1.2,0.7,0]])
    points = np.array([[.65,.1,0],[.9,.35,0]])
    
    #insert points in curve 
    start = np.searchsorted(curve[:,0], points[0,0])
    curve = np.insert(curve, start, points[0], axis=0)
    end = np.searchsorted(curve[:,0], points[1,0])
    curve = np.insert(curve, end, points[1], axis=0)
    print(curve)
    #[[0.   0.   0.  ]
    # [0.5  0.   0.  ]
    # [0.65 0.1  0.  ]
    # [0.8  0.2  0.  ]
    # [0.9  0.35 0.  ]
    # [1.   0.5  0.  ]
    # [1.2  0.7  0.  ]]
    
    def curve_length(curve):
        """ sum of Euclidean distances between points """
        return np.sum(np.sqrt(np.sum((curve[:-1] - curve[1:])**2,axis=1)))
    
    print(curve_length(curve[start:end+1]))
    #0.3605551275463989
    

    UPDATE

    as per comment: in order to find the coordinates of the point point on the curve that is len units away from the origin (curve[0]) we first cumulatively sum up the curve segments' lengths to find the segment on which our point lies. Let this segment be the line between curve[i] and curve[i+1]. We then find the portion lambda (l) of this segment according to the following sketch: enter image description here
    With this lambda we can then calculate the searched for point:

    import numpy as np
    import matplotlib.pyplot as plt
    
    curve = np.asarray([[0,0,0], [0.5,0,0], [0.8,0.2,0], [1,0.5,0], [1.2,0.7,0]])
    len = 1
    
    #len is reached between curve[i] and curve[i+1]
    cs = np.cumsum(np.sqrt(np.sum((curve[:-1] - curve[1:])**2, axis=1)))
    i = np.argmin(cs < len)
    dist = len - cs[i-1]
    
    l = dist / np.sqrt(np.sum((curve[i+1] - curve[i])**2))
    point = l * (curve[i+1] - curve[i]) + curve[i]
    print(point)
    #[0.8773501  0.31602515 0.        ]
    

    Visualization:

    plt.plot(curve[:,0], curve[:,1])
    plt.plot(point[0], point[1], 'o')
    

    enter image description here

    Verification:

    end = np.searchsorted(curve[:,0], point[0])
    curve = np.insert(curve, end, point, axis=0)
    print(curve_length(curve[:end+1]))
    #1.0