# Converting Longitude & Latitude to X Y on a map using Julia

**URL:** <https://discourse.julialang.org/t/converting-longitude-latitude-to-x-y-on-a-map-using-julia/20611>\
**Category:** General Usage\
**Tags:** geo, gmt, geodesy\
**Created:** [February 9, 2019, 6:08pm UTC](https://discourse.julialang.org/t/converting-longitude-latitude-to-x-y-on-a-map-using-julia/20611 "2019-02-09T18:08:37Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![bsnyh](https://avatars.discourse-cdn.com/v4/letter/b/ce7236/32.png) [@bsnyh](https://discourse.julialang.org/u/bsnyh)\
**Post date:** [February 9, 2019, 6:08pm UTC](https://discourse.julialang.org/t/converting-longitude-latitude-to-x-y-on-a-map-using-julia/20611/1 "2019-02-09T18:08:37Z")

</div>

Hey. I searched for this question and I found this link: [gps - Converting Longitude & Latitude to X Y on a map with Calibration points - Stack Overflow](https://stackoverflow.com/questions/1369512/converting-longitude-latitude-to-x-y-on-a-map-with-calibration-points)  
My question is not exactly the same as the above link, because I do not have any calibration points at all. All I have is a bunch of locations in the latitudes and longitudes, and I need to project them to a self-designed planar map. In fact, I think if the concerned area is not big enough, then maybe I can use the latitude and longtitude directly as the x axis and y axis of the points in the planar map.  
Any ideas or comments about this simple task?

---

<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:** [February 9, 2019, 6:46pm UTC](https://discourse.julialang.org/t/converting-longitude-latitude-to-x-y-on-a-map-using-julia/20611/2 "2019-02-09T18:46:25Z")

</div>

There are other options (like using proj4.jl) but the one I know is with [GMT.jl](https://github.com/GenericMappingTools/GMT.jl). With its `mapproject` module you would do it like this (the [0 0;10 10;20 20;30 30] is an invented lon lat array). Here I’m projecting from geographic to mercator. The syntax after the `-J` is that of the proj4 lib (ah, and need GMT6dev here, otherwise the GMT projection syntax must be used).

```julia
julia> gmt("mapproject -J+proj=merc", [0 0;10 10;20 20;30 30])
1-element Array{GMT.GMTdataset,1}:
 GMT.GMTdataset([0.0 7.08115e-10; 1.11319e6 1.11148e6; 2.22639e6 2.25842e6; 3.33958e6 3.48219e6], Any[], "", Any[], "", "")

```

---

<div class="post-metadata">

**Author:** ![bsnyh](https://avatars.discourse-cdn.com/v4/letter/b/ce7236/32.png) [@bsnyh](https://discourse.julialang.org/u/bsnyh)\
**Post date:** [February 9, 2019, 7:20pm UTC](https://discourse.julialang.org/t/converting-longitude-latitude-to-x-y-on-a-map-using-julia/20611/3 "2019-02-09T19:20:29Z")

</div>

So, you are projecting four locations with lon lat pair `(0,0), (10,10), (20,20), (30,30)` to four points `(0.0, 7.08115e-10), (1.11319e6, 1.11148e6), (2.22639e6, 2.25842e6), (3.33958e6, 3.48219e6)`?

---

<div class="post-metadata">

**Author:** ![bsnyh](https://avatars.discourse-cdn.com/v4/letter/b/ce7236/32.png) [@bsnyh](https://discourse.julialang.org/u/bsnyh)\
**Post date:** [February 9, 2019, 7:21pm UTC](https://discourse.julialang.org/t/converting-longitude-latitude-to-x-y-on-a-map-using-julia/20611/4 "2019-02-09T19:21:29Z")

</div>

@joa-quim, is there any advantage to do this? What are the map size and scale?

---

<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:** [February 9, 2019, 7:30pm UTC](https://discourse.julialang.org/t/converting-longitude-latitude-to-x-y-on-a-map-using-julia/20611/5 "2019-02-09T19:30:05Z")

</div>

I don’t know exactly what you want/need to do. My example just converted a couple of invented points to Mercator meters. There is no scale it nor map size. The converted xx mean meters east of Greenwich and yy meters north of equator. For a more realistic case maybe an UTM projection would be better, but as I said I don’t know what for you need the projected coordinates.

---

<div class="post-metadata">

**Author:** ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)\
**Post date:** [February 9, 2019, 8:19pm UTC](https://discourse.julialang.org/t/converting-longitude-latitude-to-x-y-on-a-map-using-julia/20611/6 "2019-02-09T20:19:08Z")

</div>

If the area is not too large (thousands of kilometers), a simple way is to convert to UTM coordinates within the same zone. UTM consists of an x coordinate (easting) and y coordinate (northing), and a change in 1 in easting or northing is roughly equivalent to a distance of 1 meter. This makes the coordinates conceptually easy to understand, and it becomes trivial to calculate approximate distances. You can use the `Geodesy` package for this. An example:

```julia
using Geodesy

# latitude and longitude for two cities in Sweden
stockholm_lla = LLA(59.3293, 18.0686)
uppsala_lla = LLA(59.8586, 17.6389)

# all of Sweden uses UTM zone 33 north
utm_sweden = UTMfromLLA(33, true, wgs84)

```

Now to calculate the UTM coordinates:

```julia
julia> stockholm_utm = utm_sweden(stockholm_lla)
UTM(674571.8664470176, 6.580743008454201e6, 0.0)

julia> uppsala_utm = utm_sweden(uppsala_lla)
UTM(647793.4861253307, 6.638608056491923e6, 0.0)

julia> diff = stockholm_utm.x - uppsala_utm.x, stockholm_utm.y - uppsala_utm.y
(26778.38032168697, -57865.048037721775)

```

So Uppsala is roughly 27 km west and 58 km north of Stockholm, for a total distance of

```julia
julia> √sum(diff.^2)
63760.84564261018

```

approximately 64 km. Let’s compare that with a more accurate distance calculation to see how bad the approximation is:

```julia
julia> distance(stockholm_utm, uppsala_utm, 33, true)
63765.736076373265

julia> distance(stockholm_lla, uppsala_lla)
63765.73607637202

```

Off by ~5 meters, which is good enough for many applications (and several orders of magnitude faster to calculate).

---

<div class="post-metadata">

**Author:** ![bsnyh](https://avatars.discourse-cdn.com/v4/letter/b/ce7236/32.png) [@bsnyh](https://discourse.julialang.org/u/bsnyh)\
**Post date:** [February 10, 2019, 9:21am UTC](https://discourse.julialang.org/t/converting-longitude-latitude-to-x-y-on-a-map-using-julia/20611/7 "2019-02-10T09:21:14Z")

</div>

Very good. Thank you so much. Was just curious for the following two questions.  
(1): Why all of Sweden use UTM zone 33 north, does this have something to do with the time zone of Sweden?  
(2): The last two distance function calls, what are the algorithm do they use to calculate the more accurate distance?

---

<div class="post-metadata">

**Author:** ![bsnyh](https://avatars.discourse-cdn.com/v4/letter/b/ce7236/32.png) [@bsnyh](https://discourse.julialang.org/u/bsnyh)\
**Post date:** [February 10, 2019, 9:29am UTC](https://discourse.julialang.org/t/converting-longitude-latitude-to-x-y-on-a-map-using-julia/20611/8 "2019-02-10T09:29:08Z")

</div>

One more question which is more revenant. If I plan to visualise it in a map, it’s probably good to have the size of the map, something like `xMin, xMax, yMin, yMax`. So, I think the boundary of all my points would roughly correspond to the approximated boundary of the map.

---

<div class="post-metadata">

**Author:** ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)\
**Post date:** [February 10, 2019, 12:18pm UTC](https://discourse.julialang.org/t/converting-longitude-latitude-to-x-y-on-a-map-using-julia/20611/9 "2019-02-10T12:18:06Z")

</div>

> [@bsnyh](#):
>
> Why all of Sweden use UTM zone 33 north, does this have something to do with the time zone of Sweden?

No, time zone has nothing to do with this. Geographically, Sweden extend over zones 32 - 35, but the main part is in zone 33, so the national projection uses that zone. It leads to some distorsions towards the edges, but it’s much easier to have a single zone.

> [@bsnyh](#):
>
> The last two distance function calls, what are the algorithm do they use to calculate the more accurate distance?

To figure that out, you can either [read the docs](https://github.com/JuliaGeo/Geodesy.jl#quick-start), or use the `@less` macro to check the source:

```julia
julia> @less distance(stockholm_lla, uppsala_lla)
distance(a::LLA, b, datum = wgs84) = distance(ECEFfromLLA(datum)(a), b, datum)
...
julia> @less distance(ECEFfromLLA(wgs84)(stockholm_lla), ECEFfromLLA(wgs84)(uppsala_lla))
distance(a::T, b::T) where {T <: AbstractVector} = norm(a-b)

```

So it’s cartesian distance in Earth-Centered-Earth-Fixed (ECEF) coordinates (not great circle distance).

> [@bsnyh](#):
>
> One more question which is more revenant. /…/ I think the boundary of all my points would roughly correspond to the approximated boundary of the map.

What’s the question here? 🙂

---

<div class="post-metadata">

**Author:** ![scelles](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scelles/32/220408_2.png) [@scelles](https://discourse.julialang.org/u/scelles)\
**Post date:** [February 2, 2021, 8:42pm UTC](https://discourse.julialang.org/t/converting-longitude-latitude-to-x-y-on-a-map-using-julia/20611/10 "2021-02-02T20:42:44Z")

</div>

Hello,

I was looking for an answer to a similar question and found [python - Converting x, y, zoom for Calculating tile bounds - Geographic Information Systems Stack Exchange](https://gis.stackexchange.com/questions/20128/converting-x-y-zoom-for-calculating-tile-bounds/20141) where it was suggested to read up on [web mercator projection](https://en.wikipedia.org/wiki/Web_Mercator_projection). I’m not a specialist of this field but I’m wondering if there is any (pure) Julia library which implements this.  
Does Geodesy.jl provides that ? Ping @garborg @c42f

Kind regards

---

<div class="post-metadata">

**Author:** ![Jeff\_Emanuel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff_emanuel/32/15440_2.png) [@Jeff\_Emanuel](https://discourse.julialang.org/u/Jeff_Emanuel)\
**Post date:** [February 2, 2021, 10:25pm UTC](https://discourse.julialang.org/t/converting-longitude-latitude-to-x-y-on-a-map-using-julia/20611/11 "2021-02-02T22:25:11Z")

</div>

I don’t know about a Julia library, but webmercator projections are straightforward. This code is in a non-Julia language, but should be obvious to translate. Latitude and longitude in WGS84

```julia
// WGS84 earth semi-minor axis in meters.
R = 6378137.0
easting, northing = R*longRads, R*math.Log(math.Tan(math.Pi*0.25+0.5*latRads))

longRads = easting/R
latRads = 2.0*(math.Atan(math.Exp(northing/R)) - math.Pi*0.25)

```

Reference:  
[http://earth-info.nga.mil/GandG/wgs84/web\_mercator/(U)%20NGA\_SIG\_0011\_1.0.0\_WEBMERC.pdf](http://earth-info.nga.mil/GandG/wgs84/web_mercator/(U)%20NGA_SIG_0011_1.0.0_WEBMERC.pdf)  
equations (4) & (5.a), p. A-2.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [February 2, 2021, 11:24pm UTC](https://discourse.julialang.org/t/converting-longitude-latitude-to-x-y-on-a-map-using-julia/20611/12 "2021-02-02T23:24:28Z")

</div>

Not a pure Julia library but just in case: [Proj4.jl](https://github.com/JuliaGeo/Proj4.jl) wraps the [PROJ](https://proj.org/) cartographic projections library, which includes [Web Mercator EPSG:3857](https://proj.org/operations/projections/webmerc.html) among many others.

---

<div class="post-metadata">

**Author:** ![Nosferican](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nosferican/32/9275_2.png) [@Nosferican](https://discourse.julialang.org/u/Nosferican)\
**Post date:** [February 3, 2021, 12:33am UTC](https://discourse.julialang.org/t/converting-longitude-latitude-to-x-y-on-a-map-using-julia/20611/13 "2021-02-03T00:33:49Z")

</div>

I think a nice projection package would be great. These days I would probably just use LibPQ.jl for a PostGIS database and make most of the work in the PostgreSQL server and get it back to Julia.

---

<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:** [February 3, 2021, 12:45am UTC](https://discourse.julialang.org/t/converting-longitude-latitude-to-x-y-on-a-map-using-julia/20611/14 "2021-02-03T00:45:07Z")

</div>

Which, under the hood, would be using the same `PROJ4` external lib that `Proj.jl` wraps.

---

<div class="post-metadata">

**Author:** ![Nosferican](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nosferican/32/9275_2.png) [@Nosferican](https://discourse.julialang.org/u/Nosferican)\
**Post date:** [February 3, 2021, 12:55am UTC](https://discourse.julialang.org/t/converting-longitude-latitude-to-x-y-on-a-map-using-julia/20611/15 "2021-02-03T00:55:27Z")

</div>

Aye. I like the database component especially within a larger project (e.g., GUI like pgAdmin/Compass are nice for quick interactive rendering of maps and such). For simple projections and transformations I think Proj4.jl does the job really conveniently.

---

<div class="post-metadata">

**Author:** ![Wedg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wedg/32/7673_2.png) [@Wedg](https://discourse.julialang.org/u/Wedg)\
**Post date:** [February 6, 2021, 10:35am UTC](https://discourse.julialang.org/t/converting-longitude-latitude-to-x-y-on-a-map-using-julia/20611/16 "2021-02-06T10:35:32Z")

</div>

The PlotShapefiles package has a number of functions to help drawing in web mercator projection and overlaying plots onto a map:

[See here for these coordinate conversions:](https://github.com/Wedg/PlotShapefiles.jl/blob/master/src/coordinate_conversions.jl)

- WGS84 longitude & latitude to Web Mercator (which is used by Google maps and most web map apps)
- Web Mercator back to longitude and latitude
- Longitude, latitude and zoom level to pixel numbers (specifically for the Google API)

[And here are some helper functions to overlay onto a Google map](https://github.com/Wedg/PlotShapefiles.jl/blob/master/src/google_overlay.jl)  
E.g.

- Given a bounding box and zoom, generating the right Google API info (centre coords, width and height)
- Building the Google API string

---

<div class="post-metadata">

**Author:** ![scelles](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scelles/32/220408_2.png) [@scelles](https://discourse.julialang.org/u/scelles)\
**Post date:** [February 6, 2021, 7:02pm UTC](https://discourse.julialang.org/t/converting-longitude-latitude-to-x-y-on-a-map-using-julia/20611/17 "2021-02-06T19:02:40Z")

</div>

Thanks @Wedg . Your project is interesting.

I had a look at [your code](https://github.com/Wedg/PlotShapefiles.jl/blob/master/src/coordinate_conversions.jl)… maybe you should define some constants and also use some functions (such as `deg2rad`) to avoid to repeat code, constants.

```julia
const POLAR_RADIUS = 6378137.0
const MAX_LAT = rad2deg(2*atan(ℯ^pi)-pi/2) # 85.051129...

```

---

<div class="post-metadata">

**Author:** ![Wedg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wedg/32/7673_2.png) [@Wedg](https://discourse.julialang.org/u/Wedg)\
**Post date:** [February 7, 2021, 12:41pm UTC](https://discourse.julialang.org/t/converting-longitude-latitude-to-x-y-on-a-map-using-julia/20611/18 "2021-02-07T12:41:02Z")

</div>

Thanks Sébastien (@scelles )  
Yes agreed - that would help readability and avoiding repetition. Do you know if there is any performance loss to defining constants outside function definitions (vs defining them inside the function)?

---

<div class="post-metadata">

**Author:** ![scelles](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scelles/32/220408_2.png) [@scelles](https://discourse.julialang.org/u/scelles)\
**Post date:** [February 7, 2021, 12:45pm UTC](https://discourse.julialang.org/t/converting-longitude-latitude-to-x-y-on-a-map-using-julia/20611/19 "2021-02-07T12:45:38Z")

</div>

If you define them (globally) as `const` I think it doesn’t hurt. But I’m not a specialist of Julia code optimization… but I ever noticed a performance loss with global variable which wasn’t defined as `const`.

---

<div class="post-metadata">

**Author:** ![c42f](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/c42f/32/52842_2.png) [@c42f](https://discourse.julialang.org/u/c42f)\
**Post date:** [February 9, 2021, 5:48am UTC](https://discourse.julialang.org/t/converting-longitude-latitude-to-x-y-on-a-map-using-julia/20611/20 "2021-02-09T05:48:53Z")

</div>

> [@Wedg](#):
>
> Do you know if there is any performance loss to defining constants outside function definitions

Declare them `const` there will be no performance hit. If you forget this there will be a big performance cost because the compiler won’t be able to know the type or value of the global variable and will need to generate dynamic non-optimized code for every calculation involving the global variable.

Just a small note @scelles - if you could start a new discussion for new questions that would be better than tacking it onto an old thread like this one.

Regarding your question, Web Mercator is very simple so you could just implement it as already suggested in this thread. TBH we should probably have Web Mercator support in Geodesy.jl because it’s ubiquitous (due to its extreme simplicity — in other mathematical technical aspects it’s quite bad 😆 )

[Next page](https://discourse.julialang.org/t/converting-longitude-latitude-to-x-y-on-a-map-using-julia/20611.md?page=2)
