question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

contour functionality using different projections

See original GitHub issue

I tried to use the contour transform for other projections than identity for an array that covers the whole world. My source file is a GeoTiff containing the global annual precipitation (for year 2016 based on CFSv2 data): map_tif_precip The geographic coordinate system is WGS:84 (epsg:4326), origin (top-left corner) is (-180.02,87.58), pixel size is (1.0,-1.0) for x and y respectively and the file has a width of 360 pixels and a height of 168 pixels. I managed to visualise this file using the identity projection, but once I try to use the mercator projection, I start to see certain issues: gif_identity_basemap_mercator While I see that it applies a certain projection transformation, it gets wrongly projected.

I then did some trial and error with the data transformation and prepared 6 datafiles. 3 files had a longitude from -180 to 180, one normal, one upside down, and one upside down and vertically rolled 84 pixels (array height divide by 2`) and 3 files where longitude goes from 0 to 360.

Eventually found out that the version that goes from 0 to 360 in longitude, which is placed upside down and vertically rolled by half the height of the array is positioned correctly on the mercator projection: gif_identity_basemap_mercator_contour_data But somehow everything below 0 degrees latitude is cut-off and there is a stiching issue at the geographical prime meridian. That are two problems, but quite glad I got this far.

Then I tried to change the rotate parmeters. I see that the geographical lines (equator, international date line, arctic- and antartic circle) are reprojecting nicely, but the contours are giving some strange results: gif_identity_basemap_mercator_contour_data Where mercator still has some stable rotations (rotate0), other projections (eg. robinson) have not any rotation which show the contours somehow right.

The following specification were used (vega-editor link):

Click to expand

{
  "$schema": "https://vega.github.io/schema/vega/v4.json",
  "width": 500,
  "height": 500,
  "autosize": "none",
  "signals": [  
    {
      "name": "contour_data",
      "value": "-180:180",
      "bind": {"input": "select", "options": [
        "-180:180", "-180:180 flipud", "-180:180 flipud roll vert",
        "0:360", "0:360 flipud", "0:360 flipud roll vert"]}
    },     
    {
      "name": "contour_proj",
      "value": "identity",
      "bind": {"input": "select", "options": ["identity", "basemap"]}      
    },       
    {
      "name": "basemap_proj",
      "value": "mercator",
      "bind": {"input": "select", "options": ["mercator", "robinson"]}      
    },
    {
      "name": "contour_fill", "value": true,
      "bind": {"input": "radio", "options": [true, false]}
    },    
    {
      "name": "scale",
      "value": 78,
      "bind": {"input": "range", "min": 54, "max": 202, "step": 8}
    },
    {
      "name": "rotate0",
      "value": 0,
      "bind": {"input": "select", "options": [-360, -270,-180, -90, 0, 90, 180, 270, 360]}
    },
    {
      "name": "rotate1",
      "value": 0,
      "bind": {"input": "select", "options": [-360, -270,-180, -90, 0, 90, 180, 270, 360]}
    },
    {
      "name": "rotate2",
      "value": 0,
      "bind": {"input": "select", "options": [-180, -135, -90,-45, 0, 45, 90, 135, 180]}
    },
    {
      "name": "center0",
      "value": 0,
      "bind": {"input": "select", "options": [-180, -135, -90,-45, 0, 45, 90, 135, 180]}
    },
    {
      "name": "center1",
      "value": 0,
      "bind": {"input": "select", "options": [-89,-45, 0, 45, 89]}
    },
    {
      "name": "precipitation",
      "update": "if(contour_data === '-180:180', data('p-180:180')[0], if(contour_data === '-180:180 flipud', data('p-180:180-flipud')[0], if(contour_data === '-180:180 flipud roll vert', data('p-180:180-flipud-roll-vert')[0], if(contour_data === '0:360', data('p0:360')[0], if(contour_data === '0:360 flipud', data('p0:360-flipud')[0], data('p0:360-flipud-roll-vert')[0])))))"
    }
  ],
  "data": [
    {
      "name": "sphere",
      "values": [{"type": "Sphere"} ],
      "transform": [{"type": "geopath", "projection": "proj_basemap" } ]
    },
    {
      "name": "graticule",
      "transform": [{"type": "graticule"}, {"type": "geopath", "projection": "proj_basemap"}]
    },
    {
      "name": "geographic_lines",
      "url": "https://raw.githubusercontent.com/martynafford/natural-earth-geojson/master/110m/physical/ne_110m_geographic_lines.json",
      "format": {"type": "json", "property": "features"},      
      "transform": [{"type": "geopath", "projection": "proj_basemap"}]
    },
    {
      "name": "world",
      "url": "https://raw.githubusercontent.com/vega/datalib/master/test/data/world-110m.json",
      "format": {"type": "topojson", "feature": "countries"},
      "transform": [{"type": "geopath", "projection": "proj_basemap"}]
    },
    {
      "name": "p-180:180",
      "url": "https://raw.githubusercontent.com/mattijn/datasets/master/annual-precip_-180-180.json"
    },
    {
      "name": "p-180:180-flipud",
      "url": "https://raw.githubusercontent.com/mattijn/datasets/master/annual-precip_-180-180_flip-ud.json"
    },
    {
      "name": "p-180:180-flipud-roll-vert",
      "url": "https://raw.githubusercontent.com/mattijn/datasets/master/annual-precip_-180-180_flip-ud_roll-vert.json"
    },  
    {
      "name": "p0:360",
      "url": "https://raw.githubusercontent.com/mattijn/datasets/master/annual-precip_0-360.json"
    },
    {
      "name": "p0:360-flipud",
      "url": "https://raw.githubusercontent.com/mattijn/datasets/master/annual-precip_0-360_flip-ud.json"
    },
    {
      "name": "p0:360-flipud-roll-vert",
      "url": "https://raw.githubusercontent.com/mattijn/datasets/master/annual-precip_0-360_flip-ud_roll-vert.json"
    },            
    {
      "name": "contours",
      "transform": [
        {
          "type": "contour",
          "values": {"signal": "precipitation.values"},
          "size": [{"signal": "precipitation.width"}, {"signal": "precipitation.height"}],
          "smooth": true,
          "thresholds": {"signal": "sequence(0, 3000, 500)"}
        }
      ]
    }
  ],  
  "projections": [
    {
      "name": "proj_basemap",
      "type": {"signal": "basemap_proj"},
      "scale": {"signal": "scale"},
      "rotate": [{"signal": "rotate0"}, {"signal": "rotate1"}, {"signal": "rotate2"}],
      "center": [{"signal": "center0"}, {"signal": "center1"}],
      "translate": [{"signal": "width/2"}, {"signal": "height/2"}]
    },
    {
      "name": "proj_identity",
      "type": "identity",
      "scale": {"signal": "width / precipitation.width"},
      "translate": [0, {"signal": "height/4"}]
    }    
  ],
  "scales": [
    {
      "name": "color",
      "type": "sequential",
      "domain": [0, 3000],
      "range": {"scheme": "bluepurple"}
      
    }
  ],
  "marks": [
    {
      "type": "path",
      "from": {"data": "sphere"},
      "encode": {
        "update": {
          "fill": {"value": "#fefef6"},
          "stroke": {"value": null},
          "path": {"field": {"signal": "if(contour_proj === 'basemap', 'path', 'null')"}}
        }
      }
    },  
    {
      "type": "path",
      "from": {"data": "graticule"},
      "clip": {"sphere": "proj_basemap"},
      "interactive": false,
      "encode": {
        "update": {
          "strokeWidth": {"value": 0.5},
          "stroke": {"value": "#ddd"},
          "fill": {"value": null},
          "path": {"field": {"signal": "if(contour_proj === 'basemap', 'path', 'null')"}}
        }
      }
    },
    {
      "type": "path",
      "from": {"data": "world"},
      "clip": {"sphere": "proj_basemap"},
      "interactive": false,
      "encode": {
        "update": {
          "strokeWidth": {"value": 1},
          "stroke": {"value": "#dadada"},
          "fill": {"value": "#ccc"},
          "zindex": {"value": 0},
          "path": {"field": {"signal": "if(contour_proj === 'basemap', 'path', 'null')"}}
        }
      }
    },
    {
      "type": "path",
      "from": {"data": "contours"},
      "clip": {"sphere": "proj_basemap"},      
      "encode": {
        "update": {
          "strokeWidth": {"value": 0.5},
          "stroke": {"signal": "if(contour_proj === 'identity', null, 'firebrick')"},
          "fill": {"signal": "if(contour_proj === 'identity', null, if(contour_fill === false, null, scale('color', datum.value)))"},
          "fillOpacity": {"value": 0.5} 
        }
      },
      "transform": [{"type": "geopath",  "field": "datum", "projection": "proj_basemap"}]
    },
    {
      "type": "path",
      "from": { "data": "contours"},      
      "encode": {
        "update": {
          "strokeWidth": {"value": 0.5},
          "stroke": {"signal": "if(contour_proj === 'identity', 'firebrick', null)"},
          "fill": {"signal": "if(contour_proj === 'identity', if(contour_fill === false, null, scale('color', datum.value)), null)"},          
          "fillOpacity": {"value": 0.5}
        }
      },
      "transform": [{"type": "geopath", "field": "datum", "projection": "proj_identity"}]
    },  
    {
      "type": "path",
      "from": {"data": "geographic_lines"},
      "clip": {"sphere": "proj_basemap"},
      "interactive": false,
      "encode": {
        "update": {
          "strokeWidth": {"value": 2},
          "stroke": {"value": "green"},
          "fill": {"value": null},
          "path": {"field": {"signal": "if(contour_proj === 'basemap', 'path', 'null')"}}
        }
      }
    },        
    {
      "type": "path",
      "from": {"data": "sphere"},
      "encode": {
        "update": {
          "fill": {"value": null},
          "stroke": {"value": "black"},
          "strokeWidth": {"value": 0.5},
          "strokeDash": {"value": [8, 3]},
          "path": {"field": {"signal": "if(contour_proj === 'basemap', 'path', 'null')"}}
        }
      }
    }
  ],
  "legends": [
    {
      "title": "Annual Precipitation (mm)",
      "orient": "top-left",
      "type": "symbol",
      "fill": "color",
      "format": ".0f",
      "clipHeight": 16,
      "direction":"horizontal",
      "fillColor": "#fefef6"
    }
  ]
}

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:8 (8 by maintainers)

github_iconTop GitHub Comments

1reaction
jheercommented, Jun 21, 2018

A new version of d3-contour with a weight parameter for density estimation has been released, as well as an update version of vega-geo. So this functionality will be included in the Vega release.

0reactions
mattijncommented, Jul 4, 2018

Using the new vega release (congrats!), I tried the weight functionality within contours transform. The behaviour of the contours seems different to the behaviour of the contours in the notebook of @Fil (pretty awesome notebook btw!)

Using a drag rotate event (specs). mercator_mousemove

The contours in the North Atlantic (between US and EU) seems to indicate that the weight is increasing while doing a mousemove event. That seems not right. As far as I can see, this doesn’t happen in @Fil 's notebook.

I also tried to use the timer eventstream to make the earth auto rotate (specs). orthographic_timmerv2 This is an animated gif, but it also auto rotates in the editor. But here seems another issue that I maybe understand. Since it calculates the x and y coordinates located on screen, also the coordinates on the dark side of the earth are incorporated in the contours transform as these x and y are next to the visible coordinates. (edit: no, I don’t think this happens)

Besides that, the timer event worked out reasonably well, two things:

  • I would like to be able to stop the timer
  • My browser is eaten alive. Quickly the memory increase and the page eventually crash.

Regarding scale of the contour colors, I now use "domain": [0,16] since I checked the values of the contours using

VEGA_DEBUG.view._runtime.subcontext[0].data.contours.values.value

Giving:

(10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
0 : {type: "MultiPolygon", value: 1.6611, coordinates: Array(1), Symbol(vega_id): 2807}
1: {type: "MultiPolygon", value: 3.284, coordinates: Array(1), Symbol(vega_id): 2808}
2: {type: "MultiPolygon", value: 4.907, coordinates: Array(3), Symbol(vega_id): 2809}
3: {type: "MultiPolygon", value: 6.530, coordinates: Array(2), Symbol(vega_id): 2810}
4: {type: "MultiPolygon", value: 8.153, coordinates: Array(3), Symbol(vega_id): 2811}
5: {type: "MultiPolygon", value: 9.777, coordinates: Array(4), Symbol(vega_id): 2812}
6: {type: "MultiPolygon", value: 11.400, coordinates: Array(3), Symbol(vega_id): 2813}
7: {type: "MultiPolygon", value: 13.023, coordinates: Array(2), Symbol(vega_id): 2814}
8: {type: "MultiPolygon", value: 14.6468, coordinates: Array(3), Symbol(vega_id): 2815}
9: {type: "MultiPolygon", value: 16.270, coordinates: Array(1), Symbol(vega_id): 2816}
length: 10

I’ve now idea where these numbers relates to, as the original values goes from 0 to > 3000

Read more comments on GitHub >

github_iconTop Results From Across the Web

How are different map projections used? - USGS.gov
Different projections have different uses. Some projections are used for navigation, while other projections show better representations of the true relative ...
Read more >
How to choose a projection
You should use a conformal projection when the map's main purpose involves measuring angles, ... or representing the shapes of features or contour...
Read more >
Types of Maps and Projection » Geologyscience.com
Contour lines Elevation on a topographic map is represented by a contour line. · Contour intervals, topographic maps use contour lines to show...
Read more >
Contour (Spatial Analyst)—ArcGIS Pro | Documentation
ArcGIS Spatial Analyst geoprocessing tool that creates a feature class of contours from a raster surface.
Read more >
4. Using map projections
Plot the eastern North Atlantic using an Albers Equal-Area Conic projection. 4 Adding to map plots. Several functions are provided by oce to ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found