# Minimum distance from point to linestring on earth's surface

**URL:** https://discourse.julialang.org/t/minimum-distance-from-point-to-linestring-on-earths-surface/131964
**Category:** General Usage
**Tags:** question, geospatial
**Created:** [August 30, 2025, 12:46pm UTC](https://discourse.julialang.org/t/minimum-distance-from-point-to-linestring-on-earths-surface/131964 "2025-08-30T12:46:43Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![droodman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/droodman/32/26652_2.png) [@droodman](https://discourse.julialang.org/u/droodman)
#### Post date: [August 30, 2025, 12:46pm UTC](https://discourse.julialang.org/t/minimum-distance-from-point-to-linestring-on-earths-surface/131964/1 "2025-08-30T12:46:43Z")

</div>

Say I have a shapefile representing the highway network in South America and want to find the minimum geographic distance from that network to another point on the continent. Is there no simple way to do this with the available geospatial packages ?

I understand that I can use `nearestPoints()` in LibGEOS.jl to find the point in the network closest to the point of interest under a naive Eucludean interpretation of latitude and longitude, and then use another package to compute the distance between the two points in a coordinate reference system such as WGS 1984. But technically that’s not quite right since the point returned by nearestPoints() might not actually be the nearest point in WGS 1984.

In R, the sf package provides `st_distance()`, which at least computes great circle distances between various kinds of geometry objects.

---

<div class="post-metadata">

### Author: ![technocrat](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/technocrat/32/220947_2.png) [@technocrat](https://discourse.julialang.org/u/technocrat)
#### Post date: [August 30, 2025, 11:26pm UTC](https://discourse.julialang.org/t/minimum-distance-from-point-to-linestring-on-earths-surface/131964/2 "2025-08-30T23:26:58Z")

</div>

```julia-auto
"""
    haversine_distance_km(lon1, lat1, lon2, lat2)

Calculate geodesic distance between two points using the Haversine formula.
"""
function haversine_distance_km(lon1::Float64, lat1::Float64, lon2::Float64, lat2::Float64)
    dlat = deg2rad(lat2 - lat1)
    dlon = deg2rad(lon2 - lon1)
    
    a = sin(dlat/2)^2 + cos(deg2rad(lat1)) * cos(deg2rad(lat2)) * sin(dlon/2)^2
    c = 2 * atan(sqrt(a), sqrt(1-a))
    
    return EARTH_RADIUS_KM * c
end

```

This ought to work given the easternmost, e.g., node on the network.

---

<div class="post-metadata">

### Author: ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)
#### Post date: [August 31, 2025, 12:20am UTC](https://discourse.julialang.org/t/minimum-distance-from-point-to-linestring-on-earths-surface/131964/3 "2025-08-31T00:20:05Z")

</div>

The GMT.jl module [mapproject](https://docs.generic-mapping-tools.org/dev/mapproject.html#g) can do that. Unfortunately, being a such multi-functionality program I have not yet _translated_ the terse GMT syntax to the verbose version of GMT.jl. The work is done by option -G and in GMT.jl it would be something like

```julia-auto
using GMT

D = gmtread("the_shape_file");
mapproject(D, G=(lon,lat)) # Here (lon,lat) is your "point on the continent"

```

---

<div class="post-metadata">

### Author: ![droodman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/droodman/32/26652_2.png) [@droodman](https://discourse.julialang.org/u/droodman)
#### Post date: [August 31, 2025, 1:20am UTC](https://discourse.julialang.org/t/minimum-distance-from-point-to-linestring-on-earths-surface/131964/4 "2025-08-31T01:20:59Z")

</div>

@technocrat, this is the distance between two points, right? Not the minimum distance between a point and a network/MultiLineString.

---

<div class="post-metadata">

### Author: ![technocrat](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/technocrat/32/220947_2.png) [@technocrat](https://discourse.julialang.org/u/technocrat)
#### Post date: [August 31, 2025, 2:18am UTC](https://discourse.julialang.org/t/minimum-distance-from-point-to-linestring-on-earths-surface/131964/5 "2025-08-31T02:18:28Z")

</div>

It is two points. That’s why I suggested that one node on the network would need to be chosen. Am I missing something in what you’re trying to do?

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [August 31, 2025, 5:49am UTC](https://discourse.julialang.org/t/minimum-distance-from-point-to-linestring-on-earths-surface/131964/6 "2025-08-31T05:49:36Z")

</div>

I’m not sure what a MultiLineString is. But in order to find the distance between, e.g., a line segment and a point, pointwise distances are not sufficient. You also need to determine the actual closest point along the segment.

The missing part is that the closest point might not be an endpoint.

---

<div class="post-metadata">

### Author: ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)
#### Post date: [August 31, 2025, 9:03am UTC](https://discourse.julialang.org/t/minimum-distance-from-point-to-linestring-on-earths-surface/131964/7 "2025-08-31T09:03:38Z")

</div>

As I said, GMT does it. Finds the distance and the closest point.

---

<div class="post-metadata">

### Author: ![droodman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/droodman/32/26652_2.png) [@droodman](https://discourse.julialang.org/u/droodman)
#### Post date: [August 31, 2025, 10:44am UTC](https://discourse.julialang.org/t/minimum-distance-from-point-to-linestring-on-earths-surface/131964/8 "2025-08-31T10:44:46Z")

</div>

Yes. There’s a non-trivial algorithmic step in picking the nearest point in the network and doing that properly in spherical/ellipsoidal coordinates.

---

<div class="post-metadata">

### Author: ![droodman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/droodman/32/26652_2.png) [@droodman](https://discourse.julialang.org/u/droodman)
#### Post date: [August 31, 2025, 11:17am UTC](https://discourse.julialang.org/t/minimum-distance-from-point-to-linestring-on-earths-surface/131964/9 "2025-08-31T11:17:21Z")

</div>

> [@joa-quim](#):
>
> `mapproject(D, G=(lon,lat))`

Thank you @joa-quim. I tried this. My actual shapefile has 542 entries, each represented with a vector of coordinate pairs. E.g., the first entry has 94 coordinate pairs. Do I understand right that mapproject() is augmenting this data structure with a 3rd column, which holds the distance to each coordinate pair?

If so, then this is not quite the correct algorithm, right? The minimum of the distances to the vertices is not necessarily the minimum distance to the network.

---

<div class="post-metadata">

### Author: ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)
#### Post date: [August 31, 2025, 12:01pm UTC](https://discourse.julialang.org/t/minimum-distance-from-point-to-linestring-on-earths-surface/131964/10 "2025-08-31T12:01:56Z")

</div>

Sorry, it’s not option G it’s option [L](https://docs.generic-mapping-tools.org/6.6/mapproject.html#l), which in GMT.jl is aliased to `dist2line`. (read the linked description of that option)

I know what you are after (I needed that operation several times before) and I’m sure GMT does it with ellipsoidal accuracy if needed. See this small example that is computing the closest point along the great circle line between [0 0] and [1 1] from point at [0.5 0.5]

```julia-auto
julia> mapproject([0.5 0.5], dist2line=[0.0 0; 1 1])

1×5 GMTdataset{Float64, 2}
 Row │ col.1 col.2 col.3 col.4 col.5
─────┼───────────────────────────────────────────
   1 │ 0.5 0.5 4.46581 0.499972 0.500029

```

The results are in meters and col3=dist, col4=lon\_along\_line; col5=lat\_along\_line

In your real case the command should be

```julia-auto
mapproject([lon lat], dist2line=D)

```

and since you have 542 segments, you’ll have 542 rows. You can test it with a single segment (the first) with

```julia-auto
mapproject([lon lat], dist2line=D[1])

```
