Merge pull request #10795 from mike-000/patch-6

Show graticule labels in wrapped worlds
This commit is contained in:
Andreas Hocevar
2020-03-28 14:46:54 +01:00
committed by GitHub
2 changed files with 100 additions and 39 deletions

View File

@@ -17,6 +17,7 @@ import {
import {
applyTransform,
containsCoordinate,
containsExtent,
equals,
getCenter,
getHeight,
@@ -622,9 +623,9 @@ class Graticule extends VectorLayer {
drawLabels_(event) {
const rotation = event.frameState.viewState.rotation;
const extent = event.frameState.extent;
let rotationCenter, rotationExtent;
const rotationCenter = getCenter(extent);
let rotationExtent = extent;
if (rotation) {
rotationCenter = getCenter(extent);
const width = getWidth(extent);
const height = getHeight(extent);
const cr = Math.abs(Math.cos(rotation));
@@ -637,42 +638,60 @@ class Graticule extends VectorLayer {
];
}
const vectorContext = getVectorContext(event);
let poolIndex = this.meridians_.length + this.parallels_.length;
let feature, index, l, textPoint;
if (this.meridiansLabels_) {
for (index = 0, l = this.meridiansLabels_.length; index < l; ++index) {
const lineString = this.meridians_[index];
if (!rotation) {
textPoint = this.getMeridianPoint_(lineString, extent, index);
} else {
const clone = lineString.clone();
clone.rotate(-rotation, rotationCenter);
textPoint = this.getMeridianPoint_(clone, rotationExtent, index);
textPoint.rotate(rotation, rotationCenter);
}
feature = this.featurePool_[poolIndex++];
feature.setGeometry(textPoint);
feature.set('graticule_label', this.meridiansLabels_[index].text);
vectorContext.drawFeature(feature, this.lonLabelStyle_(feature));
}
let startWorld = 0;
let endWorld = 0;
let labelsAtStart = this.latLabelPosition_ < 0.5;
const projectionExtent = this.projection_.getExtent();
const worldWidth = getWidth(projectionExtent);
if (this.getSource().getWrapX() && this.projection_.canWrapX() && !containsExtent(projectionExtent, extent)) {
startWorld = Math.floor((extent[0] - projectionExtent[0]) / worldWidth);
endWorld = Math.ceil((extent[2] - projectionExtent[2]) / worldWidth);
const inverted = Math.abs(rotation) > Math.PI / 2;
labelsAtStart = labelsAtStart !== inverted;
}
if (this.parallelsLabels_) {
for (index = 0, l = this.parallels_.length; index < l; ++index) {
const lineString = this.parallels_[index];
if (!rotation) {
textPoint = this.getParallelPoint_(lineString, extent, index);
} else {
const clone = lineString.clone();
clone.rotate(-rotation, rotationCenter);
textPoint = this.getParallelPoint_(clone, rotationExtent, index);
textPoint.rotate(rotation, rotationCenter);
const vectorContext = getVectorContext(event);
for (let world = startWorld; world <= endWorld; ++world) {
let poolIndex = this.meridians_.length + this.parallels_.length;
let feature, index, l, textPoint;
if (this.meridiansLabels_) {
for (index = 0, l = this.meridiansLabels_.length; index < l; ++index) {
const lineString = this.meridians_[index];
if (!rotation && world === 0) {
textPoint = this.getMeridianPoint_(lineString, extent, index);
} else {
const clone = lineString.clone();
clone.translate(world * worldWidth, 0);
clone.rotate(-rotation, rotationCenter);
textPoint = this.getMeridianPoint_(clone, rotationExtent, index);
textPoint.rotate(rotation, rotationCenter);
}
feature = this.featurePool_[poolIndex++];
feature.setGeometry(textPoint);
feature.set('graticule_label', this.meridiansLabels_[index].text);
vectorContext.drawFeature(feature, this.lonLabelStyle_(feature));
}
}
if (this.parallelsLabels_) {
if (world === startWorld && labelsAtStart || world === endWorld && !labelsAtStart) {
for (index = 0, l = this.parallels_.length; index < l; ++index) {
const lineString = this.parallels_[index];
if (!rotation && world === 0) {
textPoint = this.getParallelPoint_(lineString, extent, index);
} else {
const clone = lineString.clone();
clone.translate(world * worldWidth, 0);
clone.rotate(-rotation, rotationCenter);
textPoint = this.getParallelPoint_(clone, rotationExtent, index);
textPoint.rotate(rotation, rotationCenter);
}
feature = this.featurePool_[poolIndex++];
feature.setGeometry(textPoint);
feature.set('graticule_label', this.parallelsLabels_[index].text);
vectorContext.drawFeature(feature, this.latLabelStyle_(feature));
}
}
feature = this.featurePool_[poolIndex++];
feature.setGeometry(textPoint);
feature.set('graticule_label', this.parallelsLabels_[index].text);
vectorContext.drawFeature(feature, this.latLabelStyle_(feature));
}
}
}

View File

@@ -1,6 +1,6 @@
import Graticule from '../../../src/ol/layer/Graticule.js';
import Map from '../../../src/ol/Map.js';
import {get as getProjection} from '../../../src/ol/proj.js';
import {fromLonLat, get as getProjection} from '../../../src/ol/proj.js';
import Stroke from '../../../src/ol/style/Stroke.js';
import Text from '../../../src/ol/style/Text.js';
import Feature from '../../../src/ol/Feature.js';
@@ -31,7 +31,48 @@ describe('ol.layer.Graticule', function() {
expect(graticule.parallelsLabels_).to.be(null);
});
it('creates a graticule with labels', function() {
it('creates a graticule with normal world labels', function() {
const feature = new Feature();
graticule = new Graticule({
showLabels: true,
wrapX: false
});
new Map({
layers: [graticule]
});
const extent = [-25614353.926475704, -7827151.696402049,
25614353.926475704, 7827151.696402049];
const projection = getProjection('EPSG:3857');
const resolution = 39135.75848201024;
graticule.loaderFunction(extent, resolution, projection);
const event = {
context: document.createElement('canvas').getContext('2d'),
inversePixelTransform: [1, 0, 0, 1, 0, 0],
frameState: {
coordinateToPixelTransform: [1, 0, 0, 1, 0, 0],
extent: extent,
pixelRatio: 1,
viewState: {
projection: projection,
resolution: resolution,
rotation: 0
}
}
};
graticule.drawLabels_(event);
expect(graticule.meridiansLabels_.length).to.be(13);
expect(graticule.meridiansLabels_[0].text).to.be('0° 00 00″');
expect(graticule.meridiansLabels_[0].geom.getCoordinates()[0]).to.roughlyEqual(0, 1e-9);
expect(graticule.parallelsLabels_.length).to.be(3);
expect(graticule.parallelsLabels_[0].text).to.be('0° 00 00″');
expect(graticule.parallelsLabels_[0].geom.getCoordinates()[1]).to.roughlyEqual(0, 1e-9);
feature.set('graticule_label', graticule.meridiansLabels_[0].text);
expect(graticule.lonLabelStyle_(feature).getText().getText()).to.be('0° 00 00″');
feature.set('graticule_label', graticule.parallelsLabels_[0].text);
expect(graticule.latLabelStyle_(feature).getText().getText()).to.be('0° 00 00″');
});
it('creates a graticule with wrapped world labels', function() {
const feature = new Feature();
graticule = new Graticule({
showLabels: true
@@ -61,7 +102,8 @@ describe('ol.layer.Graticule', function() {
graticule.drawLabels_(event);
expect(graticule.meridiansLabels_.length).to.be(13);
expect(graticule.meridiansLabels_[0].text).to.be('0° 00 00″');
expect(graticule.meridiansLabels_[0].geom.getCoordinates()[0]).to.roughlyEqual(0, 1e-9);
const coordinates = fromLonLat([360, 0]);
expect(graticule.meridiansLabels_[0].geom.getCoordinates()[0]).to.roughlyEqual(coordinates[0], 1e-9);
expect(graticule.parallelsLabels_.length).to.be(3);
expect(graticule.parallelsLabels_[0].text).to.be('0° 00 00″');
expect(graticule.parallelsLabels_[0].geom.getCoordinates()[1]).to.roughlyEqual(0, 1e-9);