Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Graticule Drawing for Grid Projections Other than EPSG4326 #15077

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 22 additions & 6 deletions src/ol/geom/flat/geodesic.js
Expand Up @@ -142,10 +142,18 @@ export function greatCircleArc(
* @param {number} lat2 Latitude 2.
* @param {import("../../proj/Projection.js").default} projection Projection.
* @param {number} squaredTolerance Squared tolerance.
* @param {import("../../proj/Projection.js").default|undefined} sourceProjection Source projection.
* @return {Array<number>} Flat coordinates.
*/
export function meridian(lon, lat1, lat2, projection, squaredTolerance) {
const epsg4326Projection = getProjection('EPSG:4326');
export function meridian(
lon,
lat1,
lat2,
projection,
squaredTolerance,
sourceProjection
) {
sourceProjection = sourceProjection || getProjection('EPSG:4326');
return line(
/**
* @param {number} frac Fraction.
Expand All @@ -154,7 +162,7 @@ export function meridian(lon, lat1, lat2, projection, squaredTolerance) {
function (frac) {
return [lon, lat1 + (lat2 - lat1) * frac];
},
getTransform(epsg4326Projection, projection),
getTransform(sourceProjection, projection),
squaredTolerance
);
}
Expand All @@ -166,10 +174,18 @@ export function meridian(lon, lat1, lat2, projection, squaredTolerance) {
* @param {number} lon2 Longitude 2.
* @param {import("../../proj/Projection.js").default} projection Projection.
* @param {number} squaredTolerance Squared tolerance.
* @param {import("../../proj/Projection.js").default|undefined} sourceProjection Source projection.
* @return {Array<number>} Flat coordinates.
*/
export function parallel(lat, lon1, lon2, projection, squaredTolerance) {
const epsg4326Projection = getProjection('EPSG:4326');
export function parallel(
lat,
lon1,
lon2,
projection,
squaredTolerance,
sourceProjection
) {
sourceProjection = sourceProjection || getProjection('EPSG:4326');
return line(
/**
* @param {number} frac Fraction.
Expand All @@ -178,7 +194,7 @@ export function parallel(lat, lon1, lon2, projection, squaredTolerance) {
function (frac) {
return [lon1 + (lon2 - lon1) * frac, lat];
},
getTransform(epsg4326Projection, projection),
getTransform(sourceProjection, projection),
squaredTolerance
);
}
40 changes: 28 additions & 12 deletions src/ol/layer/Graticule.js
Expand Up @@ -169,6 +169,7 @@ const INTERVALS = [
* [30, 10]
* ```
* @property {boolean} [wrapX=true] Whether to repeat the graticule horizontally.
* @property {import("../proj/Projection.js").default|string|undefined} [gridProjection] The Projection used to draw the graticule lines.
* @property {Object<string, *>} [properties] Arbitrary observable properties. Can be accessed with `#get()` and `#set()`.
*/

Expand Down Expand Up @@ -208,13 +209,25 @@ class Graticule extends VectorLayer {
delete baseOptions.lonLabelStyle;
delete baseOptions.latLabelStyle;
delete baseOptions.intervals;
delete baseOptions.gridProjection;
super(baseOptions);

/**
* @type {import("../proj/Projection.js").default}
*/
this.projection_ = null;

/**
* @type {import("../proj/Projection.js").default}
* @private
*/
this.gridProjection_ =
options.gridProjection === undefined
? getProjection('EPSG:4326')
: typeof options.gridProjection === 'string'
? getProjection(options.gridProjection)
: options.gridProjection;

/**
* @type {number}
* @private
Expand Down Expand Up @@ -1017,9 +1030,13 @@ class Graticule extends VectorLayer {
/** @type {Array<number>} **/
const p2 = [];
for (let i = 0, ii = this.intervals_.length; i < ii; ++i) {
const delta = clamp(this.intervals_[i] / 2, 0, 90);
const delta = clamp(this.intervals_[i] / 2, 0, this.maxLat_);
// Don't attempt to transform latitudes beyond the poles!
const clampedLat = clamp(centerLat, -90 + delta, 90 - delta);
const clampedLat = clamp(
centerLat,
this.minLat_ + delta,
this.maxLat_ - delta
);
p1[0] = centerLon - delta;
p1[1] = clampedLat - delta;
p2[0] = centerLon + delta;
Expand Down Expand Up @@ -1050,7 +1067,8 @@ class Graticule extends VectorLayer {
minLat,
maxLat,
this.projection_,
squaredTolerance
squaredTolerance,
this.gridProjection_
);
let lineString = this.meridians_[index];
if (!lineString) {
Expand Down Expand Up @@ -1120,7 +1138,8 @@ class Graticule extends VectorLayer {
minLon,
maxLon,
this.projection_,
squaredTolerance
squaredTolerance,
this.gridProjection_
);
let lineString = this.parallels_[index];
if (!lineString) {
Expand Down Expand Up @@ -1179,9 +1198,7 @@ class Graticule extends VectorLayer {
* @private
*/
updateProjectionInfo_(projection) {
const epsg4326Projection = getProjection('EPSG:4326');

const worldExtent = projection.getWorldExtent();
const worldExtent = this.gridProjection_.getExtent();

this.maxLat_ = worldExtent[3];
this.maxLon_ = worldExtent[2];
Expand All @@ -1191,7 +1208,7 @@ class Graticule extends VectorLayer {
// If the world extent crosses the dateline define a custom transform to
// return longitudes which wrap the dateline

const toLonLatTransform = getTransform(projection, epsg4326Projection);
const toLonLatTransform = getTransform(projection, this.gridProjection_);
if (this.minLon_ < this.maxLon_) {
this.toLonLatTransform_ = toLonLatTransform;
} else {
Expand All @@ -1216,7 +1233,7 @@ class Graticule extends VectorLayer {
// Transform the extent to get the limits of the view projection extent
// which should be available to the graticule

this.fromLonLatTransform_ = getTransform(epsg4326Projection, projection);
this.fromLonLatTransform_ = getTransform(this.gridProjection_, projection);
const worldExtentP = applyTransform(
[this.minLon_, this.minLat_, this.maxLon_, this.maxLat_],
this.fromLonLatTransform_,
Expand All @@ -1241,9 +1258,8 @@ class Graticule extends VectorLayer {
// Some projections may have a void area at the poles
// so replace any NaN latitudes with the min or max value closest to a pole

this.projectionCenterLonLat_ = this.toLonLatTransform_(
getCenter(projection.getExtent())
);
this.projectionCenterLonLat_ = getCenter(this.gridProjection_.getExtent());

if (isNaN(this.projectionCenterLonLat_[1])) {
this.projectionCenterLonLat_[1] =
Math.abs(this.maxLat_) >= Math.abs(this.minLat_)
Expand Down