diff --git a/src/ol/layer/Graticule.js b/src/ol/layer/Graticule.js index 6bc7360dfa..0e3f073eb1 100644 --- a/src/ol/layer/Graticule.js +++ b/src/ol/layer/Graticule.js @@ -717,6 +717,22 @@ class Graticule extends VectorLayer { 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 const validCenterP = [ @@ -740,44 +756,56 @@ class Graticule extends VectorLayer { // Limit the extent to fit into the extent available to the graticule - const validExtentP = [ - clamp(extent[0], this.minX_, this.maxX_), - clamp(extent[1], this.minY_, this.maxY_), - clamp(extent[2], this.minX_, this.maxX_), - clamp(extent[3], this.minY_, this.maxY_) - ]; + let validExtentP = extent; + if (!wrapX) { + validExtentP = [ + clamp(extent[0], this.minX_, this.maxX_), + 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 const validExtent = applyTransform(validExtentP, this.toLonLatTransform_, undefined, 8); - // 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 + let maxLat = validExtent[3]; + let maxLon = validExtent[2]; + let minLat = validExtent[1]; + let minLon = validExtent[0]; - if (containsCoordinate(validExtentP, this.bottomLeft_)) { - 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_; - } + if (!wrapX) { - // 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_); - const maxLon = clamp(validExtent[2], centerLon, this.maxLon_); - const minLat = clamp(validExtent[1], this.minLat_, centerLat); - const minLon = clamp(validExtent[0], this.minLon_, centerLon); + if (containsCoordinate(validExtentP, this.bottomLeft_)) { + minLon = this.minLon_; + minLat = this.minLat_; + } + 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 @@ -787,17 +815,29 @@ class Graticule extends VectorLayer { idx = this.addMeridian_(lon, minLat, maxLat, squaredTolerance, extent, 0); cnt = 0; - while (lon != this.minLon_ && cnt++ < maxLines) { - lon = Math.max(lon - interval, this.minLon_); - idx = this.addMeridian_(lon, minLat, maxLat, squaredTolerance, extent, idx); + if (wrapX) { + while ((lon -= interval) >= minLon && cnt++ < maxLines) { + 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_); cnt = 0; - while (lon != this.maxLon_ && cnt++ < maxLines) { - lon = Math.min(lon + interval, this.maxLon_); - idx = this.addMeridian_(lon, minLat, maxLat, squaredTolerance, extent, idx); + if (wrapX) { + while ((lon += interval) <= maxLon && cnt++ < maxLines) { + 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;