Handle view projections crossing dateline
Use custom toLonLat transform to return wrapped longitudes for extents if view projection crosses the dateline. Enhance the validation for center and extents to avoid proj4 errors.
This commit is contained in:
+53
-18
@@ -12,10 +12,18 @@ import VectorSource from '../source/Vector.js';
|
|||||||
import {
|
import {
|
||||||
equivalent as equivalentProjection,
|
equivalent as equivalentProjection,
|
||||||
get as getProjection,
|
get as getProjection,
|
||||||
getTransform,
|
getTransform
|
||||||
transformExtent
|
|
||||||
} from '../proj.js';
|
} from '../proj.js';
|
||||||
import {getCenter, getHeight, getWidth, intersects, equals, getIntersection, isEmpty} from '../extent.js';
|
import {
|
||||||
|
applyTransform,
|
||||||
|
equals,
|
||||||
|
getCenter,
|
||||||
|
getHeight,
|
||||||
|
getIntersection,
|
||||||
|
getWidth,
|
||||||
|
intersects,
|
||||||
|
isEmpty
|
||||||
|
} from '../extent.js';
|
||||||
import {clamp} from '../math.js';
|
import {clamp} from '../math.js';
|
||||||
import Style from '../style/Style.js';
|
import Style from '../style/Style.js';
|
||||||
import Feature from '../Feature.js';
|
import Feature from '../Feature.js';
|
||||||
@@ -665,24 +673,30 @@ class Graticule extends VectorLayer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const centerLonLat = this.toLonLatTransform_(center);
|
const validCenter = [
|
||||||
|
clamp(center[0], this.minLonP_, this.maxLonP_),
|
||||||
|
clamp(center[1], this.minLatP_, this.maxLatP_)
|
||||||
|
];
|
||||||
|
|
||||||
|
const centerLonLat = this.toLonLatTransform_(validCenter);
|
||||||
let centerLon = centerLonLat[0];
|
let centerLon = centerLonLat[0];
|
||||||
let centerLat = centerLonLat[1];
|
let centerLat = centerLonLat[1];
|
||||||
const maxLines = this.maxLines_;
|
const maxLines = this.maxLines_;
|
||||||
let cnt, idx, lat, lon;
|
let cnt, idx, lat, lon;
|
||||||
|
|
||||||
let validExtent = [
|
let validExtent = [
|
||||||
Math.max(extent[0], this.minLonP_),
|
clamp(extent[0], this.minLonP_, this.maxLonP_),
|
||||||
Math.max(extent[1], this.minLatP_),
|
clamp(extent[1], this.minLatP_, this.maxLatP_),
|
||||||
Math.min(extent[2], this.maxLonP_),
|
clamp(extent[2], this.minLonP_, this.maxLonP_),
|
||||||
Math.min(extent[3], this.maxLatP_)
|
clamp(extent[3], this.minLatP_, this.maxLatP_)
|
||||||
];
|
];
|
||||||
|
|
||||||
validExtent = transformExtent(validExtent, this.projection_, 'EPSG:4326', 8);
|
validExtent = applyTransform(validExtent, this.toLonLatTransform_, undefined, 8);
|
||||||
const maxLat = validExtent[3];
|
|
||||||
const maxLon = validExtent[2];
|
const maxLat = Math.min(validExtent[3], this.maxLat_);
|
||||||
const minLat = validExtent[1];
|
const maxLon = Math.min(validExtent[2], this.maxLon_);
|
||||||
const minLon = validExtent[0];
|
const minLat = Math.max(validExtent[1], this.minLat_);
|
||||||
|
const minLon = Math.max(validExtent[0], this.minLon_);
|
||||||
|
|
||||||
// Create meridians
|
// Create meridians
|
||||||
|
|
||||||
@@ -897,22 +911,43 @@ class Graticule extends VectorLayer {
|
|||||||
const epsg4326Projection = getProjection('EPSG:4326');
|
const epsg4326Projection = getProjection('EPSG:4326');
|
||||||
|
|
||||||
const worldExtent = projection.getWorldExtent();
|
const worldExtent = projection.getWorldExtent();
|
||||||
const worldExtentP = transformExtent(worldExtent, epsg4326Projection, projection, 8);
|
|
||||||
|
|
||||||
this.maxLat_ = worldExtent[3];
|
this.maxLat_ = worldExtent[3];
|
||||||
this.maxLon_ = worldExtent[2];
|
this.maxLon_ = worldExtent[2];
|
||||||
this.minLat_ = worldExtent[1];
|
this.minLat_ = worldExtent[1];
|
||||||
this.minLon_ = worldExtent[0];
|
this.minLon_ = worldExtent[0];
|
||||||
|
|
||||||
|
const toLonLatTransform = getTransform(projection, epsg4326Projection);
|
||||||
|
if (this.minLon_ < this.maxLon_) {
|
||||||
|
this.toLonLatTransform_ = toLonLatTransform;
|
||||||
|
} else {
|
||||||
|
const split = this.minLon_ + this.maxLon_ / 2;
|
||||||
|
this.maxLon_ += 360;
|
||||||
|
this.toLonLatTransform_ = function(coordinates, opt_output, opt_dimension) {
|
||||||
|
const dimension = opt_dimension || 2;
|
||||||
|
const lonLatCoordinates = toLonLatTransform(coordinates, opt_output, dimension);
|
||||||
|
for (let i = 0, l = lonLatCoordinates.length; i < l; i += dimension) {
|
||||||
|
if (lonLatCoordinates[i] < split) {
|
||||||
|
lonLatCoordinates[i] += 360;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lonLatCoordinates;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.fromLonLatTransform_ = getTransform(epsg4326Projection, projection);
|
||||||
|
const worldExtentP = applyTransform(
|
||||||
|
[this.minLon_, this.minLat_, this.maxLon_, this.maxLat_],
|
||||||
|
this.fromLonLatTransform_,
|
||||||
|
undefined,
|
||||||
|
8
|
||||||
|
);
|
||||||
|
|
||||||
this.maxLatP_ = worldExtentP[3];
|
this.maxLatP_ = worldExtentP[3];
|
||||||
this.maxLonP_ = worldExtentP[2];
|
this.maxLonP_ = worldExtentP[2];
|
||||||
this.minLatP_ = worldExtentP[1];
|
this.minLatP_ = worldExtentP[1];
|
||||||
this.minLonP_ = worldExtentP[0];
|
this.minLonP_ = worldExtentP[0];
|
||||||
|
|
||||||
this.fromLonLatTransform_ = getTransform(epsg4326Projection, projection);
|
|
||||||
|
|
||||||
this.toLonLatTransform_ = getTransform(projection, epsg4326Projection);
|
|
||||||
|
|
||||||
this.projectionCenterLonLat_ = this.toLonLatTransform_(getCenter(projection.getExtent()));
|
this.projectionCenterLonLat_ = this.toLonLatTransform_(getCenter(projection.getExtent()));
|
||||||
|
|
||||||
this.projection_ = projection;
|
this.projection_ = projection;
|
||||||
|
|||||||
Reference in New Issue
Block a user