handle wrapX without calculating excess meridians

avoid calculating more meridians or longer parallels than necessary when viewport extent includes a wrapped world
This commit is contained in:
mike-000
2020-03-14 10:37:03 +00:00
committed by Andreas Hocevar
parent 772741cd0e
commit bad0ff38ca

View File

@@ -717,6 +717,22 @@ class Graticule extends VectorLayer {
return; return;
} }
let wrapX = false;
const projectionExtent = this.projection_.getExtent();
const worldWidth = getWidth(projectionExtent);
if (this.getSource().getWrapX() && this.projection_.canWrapX() && !containsExtent(projectionExtent, extent)) {
if (getWidth(extent) >= worldWidth) {
extent[0] = projectionExtent[0];
extent[2] = projectionExtent[2];
} else {
const worldsAway = Math.floor((center[0] - projectionExtent[0]) / worldWidth);
center[0] -= (worldsAway * worldWidth);
extent[0] -= (worldsAway * worldWidth);
extent[2] -= (worldsAway * worldWidth);
wrapX = true;
}
}
// Constrain the center to fit into the extent available to the graticule // Constrain the center to fit into the extent available to the graticule
const validCenterP = [ const validCenterP = [
@@ -740,44 +756,56 @@ class Graticule extends VectorLayer {
// Limit the extent to fit into the extent available to the graticule // Limit the extent to fit into the extent available to the graticule
const validExtentP = [ let validExtentP = extent;
clamp(extent[0], this.minX_, this.maxX_), if (!wrapX) {
clamp(extent[1], this.minY_, this.maxY_), validExtentP = [
clamp(extent[2], this.minX_, this.maxX_), clamp(extent[0], this.minX_, this.maxX_),
clamp(extent[3], this.minY_, this.maxY_) clamp(extent[1], this.minY_, this.maxY_),
]; clamp(extent[2], this.minX_, this.maxX_),
clamp(extent[3], this.minY_, this.maxY_)
];
}
// Transform the extent to get the lon lat ranges for the edges of the extent // Transform the extent to get the lon lat ranges for the edges of the extent
const validExtent = applyTransform(validExtentP, this.toLonLatTransform_, undefined, 8); const validExtent = applyTransform(validExtentP, this.toLonLatTransform_, undefined, 8);
// Check if extremities of the world extent lie inside the extent let maxLat = validExtent[3];
// (for example the pole in a polar projection) let maxLon = validExtent[2];
// and extend the extent as appropriate let minLat = validExtent[1];
let minLon = validExtent[0];
if (containsCoordinate(validExtentP, this.bottomLeft_)) { if (!wrapX) {
validExtent[0] = this.minLon_;
validExtent[1] = this.minLat_;
}
if (containsCoordinate(validExtentP, this.bottomRight_)) {
validExtent[2] = this.maxLon_;
validExtent[1] = this.minLat_;
}
if (containsCoordinate(validExtentP, this.topLeft_)) {
validExtent[0] = this.minLon_;
validExtent[3] = this.maxLat_;
}
if (containsCoordinate(validExtentP, this.topRight_)) {
validExtent[2] = this.maxLon_;
validExtent[3] = this.maxLat_;
}
// The transformed center may also extend the lon lat ranges used for rendering // Check if extremities of the world extent lie inside the extent
// (for example the pole in a polar projection)
// and extend the extent as appropriate
const maxLat = clamp(validExtent[3], centerLat, this.maxLat_); if (containsCoordinate(validExtentP, this.bottomLeft_)) {
const maxLon = clamp(validExtent[2], centerLon, this.maxLon_); minLon = this.minLon_;
const minLat = clamp(validExtent[1], this.minLat_, centerLat); minLat = this.minLat_;
const minLon = clamp(validExtent[0], this.minLon_, centerLon); }
if (containsCoordinate(validExtentP, this.bottomRight_)) {
maxLon = this.maxLon_;
minLat = this.minLat_;
}
if (containsCoordinate(validExtentP, this.topLeft_)) {
minLon = this.minLon_;
maxLat = this.maxLat_;
}
if (containsCoordinate(validExtentP, this.topRight_)) {
maxLon = this.maxLon_;
maxLat = this.maxLat_;
}
// The transformed center may also extend the lon lat ranges used for rendering
maxLat = clamp(maxLat, centerLat, this.maxLat_);
maxLon = clamp(maxLon, centerLon, this.maxLon_);
minLat = clamp(minLat, this.minLat_, centerLat);
minLon = clamp(minLon, this.minLon_, centerLon);
}
// Create meridians // Create meridians
@@ -787,17 +815,29 @@ class Graticule extends VectorLayer {
idx = this.addMeridian_(lon, minLat, maxLat, squaredTolerance, extent, 0); idx = this.addMeridian_(lon, minLat, maxLat, squaredTolerance, extent, 0);
cnt = 0; cnt = 0;
while (lon != this.minLon_ && cnt++ < maxLines) { if (wrapX) {
lon = Math.max(lon - interval, this.minLon_); while ((lon -= interval) >= minLon && cnt++ < maxLines) {
idx = this.addMeridian_(lon, minLat, maxLat, squaredTolerance, extent, idx); idx = this.addMeridian_(lon, minLat, maxLat, squaredTolerance, extent, idx);
}
} else {
while (lon != this.minLon_ && cnt++ < maxLines) {
lon = Math.max(lon - interval, this.minLon_);
idx = this.addMeridian_(lon, minLat, maxLat, squaredTolerance, extent, idx);
}
} }
lon = clamp(centerLon, this.minLon_, this.maxLon_); lon = clamp(centerLon, this.minLon_, this.maxLon_);
cnt = 0; cnt = 0;
while (lon != this.maxLon_ && cnt++ < maxLines) { if (wrapX) {
lon = Math.min(lon + interval, this.maxLon_); while ((lon += interval) <= maxLon && cnt++ < maxLines) {
idx = this.addMeridian_(lon, minLat, maxLat, squaredTolerance, extent, idx); idx = this.addMeridian_(lon, minLat, maxLat, squaredTolerance, extent, idx);
}
} else {
while (lon != this.maxLon_ && cnt++ < maxLines) {
lon = Math.min(lon + interval, this.maxLon_);
idx = this.addMeridian_(lon, minLat, maxLat, squaredTolerance, extent, idx);
}
} }
this.meridians_.length = idx; this.meridians_.length = idx;