contour functionality using different projections
See original GitHub issueI 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):
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:
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:
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:
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:
- Created 5 years ago
- Comments:8 (8 by maintainers)
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.
Using the new vega release (congrats!), I tried the
weight
functionality withincontours
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](https://user-images.githubusercontent.com/5186265/42294385-ad111442-7fe0-11e8-87f8-d3211a00409d.gif)
The contours in the North Atlantic (between US and EU) seems to indicate that the
weight
is increasing while doing amousemove
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
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
timer
eventstream
to make the earth auto rotate (specs).x
andy
coordinates located on screen, also the coordinates on the dark side of the earth are incorporated in thecontours
transform as thesex
andy
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:timer
Regarding
scale
of thecontour
colors, I now use"domain": [0,16]
since I checked the values of thecontours
usingGiving:
I’ve now idea where these numbers relates to, as the original values goes from 0 to > 3000