1

I am trying to connect any 2 points on sphere surface with quartic Bézier curve in such way that every point of a curve are very close to the surface. I saw this solution, but it works only for cubic curves and only in the case when given 2 points have the same latitude or longitude - example A. I have 2 questions:

1) In other cases - example B this solution doesn't work and I feel like control points vectors lack power and I want any curve be spherical like in example A. So what is a right way of calculating control points vectors for cubic Bézier curve to align sphere surface.

2) If question 1 is solvable - how do I randomize middle control point in quartic Bézier curve in order to achieve unique curve every time I generate it like in example C

Thank you!

EDIT: question 2 is solved by the @Kpym solution.

  • I don't think you have read the answers on that post carefully enough - `@Kpym`'s answer states the required control point positions for *any* degree of polynomial. – meowgoesthedog Feb 14 '18 at 18:52
  • You are right, I figured that now. Thank you. –  Feb 14 '18 at 20:09
  • Also if you need to connect points on a sphere, why are you using a bezier curve instead of a circular arc? Those are _way_ easier to compute, and are guaranteed to align with your sphere. Finally, why a 4th order Bezier curve? Many solutions for problems around Beziers can be relatively easily solved for 2nd and 3rd order, but are an unreasonable amount of work for 4th order and higher. – Mike 'Pomax' Kamermans Feb 20 '18 at 23:59
  • I want the connection to be curved. And the curve with 4th order is the best fit for my case. I want to generate each time different curve and for that I randomize middle point in the 4th order curve, so the rest 4 points are left always the same. I don't call connector method often, so the performance isn't an issue for me. I am looking for a proper way to move a 4th order curve from plane to sphere keeping it's shape. –  Feb 25 '18 at 22:06

2 Answers2

0
  1. Transform your problem into a coordinate system where the two points have the same latitude or longitude. This should be a moderately easy exercise on linear algebra. These lecture notes might be a good beginning if this is a completely new topic for you. Note that you look for a coordinate system and not the coordinate system, as there will be more than one solution.
  2. Use the solution that already worked for you in the"standard" case (i.e., when the two points are on the same latitude or longitude).
  3. Take the the Bézier curve from step 2 but express its control points in the original coordinate system. This works thanks to affine invariance of Bézier curves (and thus B-splines in general): affine transformation of the curve (and the change of the coordinates is one) is done by transforming the control points and constructing the curve again. Here you can read more.
Dominik Mokriš
  • 1,118
  • 1
  • 8
  • 29
0

I interpreted this question as "How to calculate a Bézier curve confined to the surface of a sphere?"

The only solution I could find that is guaranteed to stay surface-bound is to use De Casteljau's algorithm with great circle way-points. Basically, the idea is to first plot a great-circle course on the surface of the sphere between all control-points and walk each course by a given percentage. Then use all those waypoints as control-points of a lower degree Bézier-curve. I've scripted this recursively in python:

def _spherical_bezier(*LatLongs, progress=0):
    #DON'T USE IN PRODUCTION! UNTESTED!!!
    """accepts a list of latitude/longitude coordinate-pairs.
    Calculates a point of the bezier-curve characterized by those points.
    Progress is expected between 0 and 1, but DOES accept values outside that range!"""

    #terminate if only one point left or still at start
    if progress == 0 or len(LatLongs) == 1:
        return LatLongs[0]

    #prepare list of points
    next_order = []
    #don't include last point ...
    for i, P1 in enumerate(LatLongs[:-1]):
        #... it will be taken care of here:
        P2 = LatLongs[i+1]
        
        #12-notation as in wikipedia
        lambda12 = P2[1] - P1[1]

        cos1 = cos(P1[0])
        cos2 = cos(P2[0])
        cosL = cos(lambda12)
        sin1 = sin(P1[0])
        sin2 = sin(P2[0])
        sinL = sin(lambda12)
        sigma = atan2(sqrt((cos1*sin2 - sin1*cos2*cosL)**2 + (cos2*sinL)**2), (sin1*sin2 + cos1*cos2*cosL))

        alpha = atan2(cos2*sinL, cos1*sin2 - sin1*cos2*cosL)
        cosa = cos(alpha)
        sina = sin(alpha)

        #1x = from 1 to x
        sigma1x = sigma*progress
        coss = cos(sigma1x)
        sins = sin(sigma1x)
        phix = atan2(sin1*coss + cos1*sins*cosa, sqrt((cos1*coss-sin1*sins*cosa)**2+(sins*sina)**2))
        lambda1x = atan2(sins*sina, cos1*coss - sin1*sins*cosa)

        next_order.append((phix, P1[1]+lambda1x))

    return _spherical_bezier(*next_order, progress=progress)

GammaSQ
  • 361
  • 1
  • 10