# Scattermapbox plot curved lines like Scattergeo

Hi,

In this tutorial (https://plotly.com/python/lines-on-maps/), the lines connecting the points are curved. However I can’t seem to recreate this behavior when using mapbox, i.e. go.Scattermapbox. With Scattermapbox the lines created are straight as shown on this page https://plotly.com/python/lines-on-mapbox/. Are there any options or workarounds to join points using curved lines when using mapbox?

Hi @dee214 did you find any solution for this?

Those curved lines on maps are shortest paths on the shere, representing the Earth, projected on a flat map.
Here is defined the function `slerp` which returns such a path, and must work on mapbox, too::
https://community.plotly.com/t/prevent-lines-in-scattergeo-plot-to-be-drawn-over-pacific/59196/2

Thanks for your response @empet, I’ll try out the function.

Curved lines representing shortest path between two locations on a mapbox, can be plotted using spherical liniar interpolation, `slerp`:

``````import numpy as np
from numpy import pi, sin, cos
import plotly.graph_objects as go
def point_sphere(lon, lat):
#associate the cartesian coords (x, y, z) to a point on the  globe of given lon and lat
#lon longitude
#lat latitude
lon = lon*pi/180
lat = lat*pi/180
x = cos(lon) * cos(lat)
y = sin(lon) * cos(lat)
z = sin(lat)
return np.array([x, y, z])

def slerp(A=[100, 45], B=[-50, -25], dir=-1, n=100):
#Spherical "linear" interpolation
"""
A=[lonA, latA] lon lat given in degrees; lon in  (-180, 180], lat in ([-90, 90])
B=[lonB, latB]
returns n points on the great circle of the globe that passes through the  points A, B
#represented by lon and lat
#if dir=1 it returns the shortest path; for dir=-1 the complement of the shortest path
"""
As = point_sphere(A, A)
Bs = point_sphere(B, B)
alpha = np.arccos(np.dot(As,Bs)) if dir==1 else  2*pi-np.arccos(np.dot(As,Bs))
if abs(alpha) < 1e-6 or abs(alpha-2*pi)<1e-6:
return A
else:
t = np.linspace(0, 1, n)
P = sin((1 - t)*alpha)
Q = sin(t*alpha)
#pts records the cartesian coordinates of the points on the chosen path
pts =  np.array([a*As + b*Bs for (a, b) in zip(P,Q)])/sin(alpha)
#convert cartesian coords to lons and lats to be recognized by go.Scattergeo
lons = 180*np.arctan2(pts[:, 1], pts[:, 0])/pi
lats = 180*np.arctan(pts[:, 2]/np.sqrt(pts[:, 0]**2+pts[:,1]**2))/pi
return lons, lats

lons, lats = slerp(A=[-111.5, 25], B=[-56, 49], dir=1)
fig = go.Figure(go.Scattermapbox(lon=lons, lat=lats, mode="lines", line_color="red"))