henrythasler / Leaflet.Geodesic

Add-on to draw geodesic lines with leaflet
GNU General Public License v3.0
156 stars 27 forks source link

How to use different color for part of the distance between two points? #88

Closed danechitoaie closed 2 years ago

danechitoaie commented 2 years ago

Hi, Any idea how I could determine, let's say 20% of the path from A to B and use one color for the first segment A to 20% marker and then another color for the 20% to B segment?

I was thinking in having two GeodesicLines but no Idea how to split in these two segments so I cad draw two lines.

henrythasler commented 2 years ago

This can be done but you need to use some internal functions to do that.

Let's consider we have a line between two places like

const Berlin = { lat: 52.5, lng: 13.35 };
const LosAngeles = { lat: 33.82, lng: -118.38 };

Let's create a Geodesic object to do our calculations with:

const line = new L.Geodesic();

We can then calculate some properties for that line:

const lineProperties = line.geom.geodesic.inverse(Berlin, LosAngeles);

We use the bearing and a fraction of the total distance to get the midpoint:

const midPoint = line.geom.geodesic.direct(
  Berlin,
  lineProperties.initialBearing,
  lineProperties.distance * 0.2 // <-- choose the midpoint percentage
);

Now we can draw our two lines with different styles:

const secondPart = new L.Geodesic([midPoint, LosAngeles], {
  weight: 10,
  color: "red"
}).addTo(map);

const firstPart = new L.Geodesic([Berlin, midPoint], {
  weight: 10,
  color: "green"
}).addTo(map);

Full working example: https://codesandbox.io/s/summer-pond-kbetm1?file=/script.js

image

danechitoaie commented 2 years ago

Hi @henrythasler Thank you for taking time to explain this and even provide sample code for this. I wasn't aware that inverse and direct functions are available. Actually I didn't even knew that these are the functions that I need. As my backend was in Python I started searching for something for that as well and eventually found https://geographiclib.sourceforge.io/html/python/code.html and the Inverse and Direct functions from there. So I ended up calculating the three points (start, current distance, end) in the backed:

def get_current_lat_lng(loc1: Location, loc2: Location, distance_done: int, distance_left: int) -> LatLng:
    if distance_left > 0:
        g_inv = Geodesic.WGS84.Inverse(loc1.get("lat"), loc1.get("lng"), loc2.get("lat"), loc2.get("lng"))
        g_dir = Geodesic.WGS84.Direct(g_inv.get("lat1"), g_inv.get("lon1"), g_inv.get("azi1"), distance_done)
        return {"lat": g_dir.get("lat2"), "lng": g_dir.get("lon2")}
    else:
        return {"lat": cast(float, loc2.get("lat")), "lng": cast(float, loc2.get("lng"))}

and in frontend I added three markers and two Polylines with different styling and it looks something like:

Screen Shot 2022-07-04 at 00 11 04

Thank you for the help, and for the awesome library.