0
$\begingroup$

I've preprocessed ~100,000 points in the Vancouver area and am starting to analyze and segment them in different ways. I wanted to start off with a nice finely controllable bounded region since others in the project will have opinions on the viz. I've reduced the code to its basics to reproduce the behaviour. The behaviour is so strange I'm wondering if it's even reproducible by others? I've tried restarting the local Mathematica 12.1 kernal a couple times etc. but the same elongated plot is returned each time.

(* Approx. Lower Mainland *)
b = {{49.0, 53.0}, {-123.3, -122.9}}

GeoGraphics[
 GeoRange -> b,
 GeoRangePadding -> None,
 GeoProjection -> Automatic,
 GeoGridLines -> Automatic,
 Frame -> True
 ] 

Options[%, GeoRange]
(* {GeoRange -> {{49., 53.}, {-123.3, -122.9}}} *)

A couple things of note. Firstly, we can confirm the GeoRange was applied correctly; and secondly, looking at the image, the longitude was correctly applied but the latitude way overshoots northward. I had a pretty through look at the GeoRange doc, but nothing in the relationship section seemed to apply.

Can someone more familiar with GeoGraphics could suggest how they would control the geoplotting region? Or explain the behaviour we're seeing here?

$\endgroup$
3
  • 1
    $\begingroup$ To cut plot we can use PlotRange -> {{-123.3, -122.9}, {49.0, 53.0}}. $\endgroup$ Nov 16, 2020 at 21:15
  • $\begingroup$ Options[GeoGraphics, AspectRatio] evaluates to {AspectRatio -> Automatic}. Since you do not prefer this default, add whatever value you want, e.g., AspectRatio->1 $\endgroup$
    – Bob Hanlon
    Nov 16, 2020 at 21:17
  • $\begingroup$ having gone through the GeoRange docs so recently, the Properties & Relations section mentions another approach using PlotRange. $\endgroup$
    – BBirdsell
    Nov 17, 2020 at 0:01

2 Answers 2

3
$\begingroup$
Clear["Global`*"]

If you want the region around Vancouver you can use that entity for the plot with a selectable GeoRangePadding

EDIT: Added control for GeoProjection

Clear["Global`*"]

Manipulate[
 GeoGraphics[
  Entity["City", {"Vancouver", "BritishColumbia", "Canada"}],
  GeoRangePadding -> padding,
  GeoProjection -> projection,
  GeoGridLines -> Automatic,
  Frame -> True],
 Row[{
   Control[
    {{padding, Quantity[50, "km"], "GeoRangePadding"},
     Range[Quantity[0, "km"], Quantity[200, "km"], 
      Quantity[25, "km"]]}],
   Spacer[50],
   Control[
    {{projection, "Equirectangular", 
      "GeoProjection"}, {"Equirectangular", "Mercator"}}]}]]

enter image description here

$\endgroup$
0
1
$\begingroup$

The reason the map is elongated is because the boundaries are tall (latitude) and narrow (longitude). To demonstrate the problem, I'll use a function that computes the dimensions of a map from its GeoRange.

Here's a function to find map dimensions computed from GeoRange. mapDimensions returns:
• latitude distance at west, center, and east of map
• longitude distance at north, center, and south of map

mapDimensions[geoRange_?MatrixQ] := Module[{}, {{
    GeoDistance[{#1, {#2[[1]], #1[[2]]}} & @@ Transpose[geoRange]],
    With[{centerLongitude = Mean@Last[geoRange]},
     GeoDistance[{{#1[[1]], centerLongitude}, {#2[[1]], 
          centerLongitude}} & @@
       Transpose[geoRange]]],
    GeoDistance[{{#1[[1]], #2[[2]]}, #2} & @@ 
      Transpose[geoRange]]}, {
    GeoDistance[{{#2[[1]], #1[[2]]}, #2} & @@ Transpose[geoRange]],
    With[{centerLatitude = Mean@First[geoRange]},
     GeoDistance[{{centerLatitude, #1[[2]]}, {centerLatitude, #2[[
           2]]}} & @@
       Transpose[geoRange]]],
    GeoDistance[{#1, {#1[[1]], #2[[2]]}} & @@ Transpose[geoRange]]}}
  ]

Original map

The boundary, b, is why the map is elongated. Let's draw a map and get its GeoRange from Options. The map boundary is 4° latitude by 0.4° longitude, or 277 miles by 17 miles, so the map is tall and narrow.

b = {{49.0, 53.0}, {-123.3, -122.9}};(*values from question*)
g = GeoGraphics[
   GeoRange -> b,
   GeoRangePadding -> None,
   GeoProjection -> Automatic,
   GeoGridLines -> Automatic
];
(*GeoRange from map*)
geoRange = GeoRange /. Options[g, "GeoRange"]
(*latitude and longitude differences*)
Differences@Transpose@geoRange
(*map dimensions*)
mapDimensions[geoRange]
{{49., 53.}, {-123.3, -122.9}}
{{4., 0.4}}
{{276.506mi, 276.506mi, 276.506mi}, {16.6868mi, 17.4475mi, 18.1867mi}}

Map with increased range of longitude

Fix the problem by increasing the range of longitude. Let's keep the same center, but replace the boundary longitudes with 2° west and east of the midpoint. Add a marker at the center of the map.

b[[2, All]] = {-2, 2} + Mean@b[[2]];
g = GeoGraphics[GeoMarker[GeoPosition[Mean /@ b]],
  GeoRange -> b,
  GeoRangePadding -> None,
  GeoProjection -> Automatic,
  GeoGridLines -> Automatic
]

4-by-4 degree map

Now the map is 4° square, or 277 miles by 174 miles.

geoRange = GeoRange /. Options[g, "GeoRange"]
Differences@Transpose@geoRange
mapDimensions[geoRange]
{{49., 53.}, {-125.1, -121.1}}
{{4., 4.}}
{{276.506mi, 276.506mi, 276.506mi}, {166.847mi, 174.454mi, 181.846mi}}

Map using GeoRange distance

Another way to set map boundaries is to use a distance with GeoRange instead of latitude and longitude boundaries. Let's keep the same center, but use a GeoRange distance. GeoGraphics computes ranges for latitude and longitude.

g = GeoGraphics[GeoMarker[GeoPosition[Mean /@ b]],
  GeoCenter -> Mean /@ b,
  GeoRange -> 
   Quantity[89, "Miles"],(*approximately 4° longitude*)
  GeoRangePadding -> None,
  GeoProjection -> Automatic,
  GeoGridLines -> Automatic
]

map using GeoRange with distance

The map is 178 miles by 178 miles. Notice that the latitude distance is twice the GeoRange setting.

geoRange = GeoRange /. Options[g, "GeoRange"]
Differences@Transpose@geoRange
mapDimensions[geoRange]
{{49.7124, 52.2874}, {-125.141, -121.059}}
{{2.57499, 4.08122}}
{{178.mi, 178.mi, 178.mi}, {173.024mi, 177.996mi, 182.877mi}}
$\endgroup$

Not the answer you're looking for? Browse other questions tagged or ask your own question.