Skip to content
This repository has been archived by the owner on Mar 8, 2023. It is now read-only.

HARP-14465: Fix world coordinates precision for screen space techniques #2152

Merged
merged 2 commits into from
Mar 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions @here/harp-datasource-protocol/lib/DecodedTile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,16 +267,11 @@ export interface TextGeometry {
* Structured clone compliant version of a `three.js` geometry object with points of interest (POIs)
* to be rendered. It is composed of buffers with metadata for POI objects.
*/
export interface PoiGeometry {
positions: BufferAttribute;
texts: number[];
export interface PoiGeometry extends TextGeometry {
/**
* Names of the image texture or the name of the POI as indices into the array `stringCatalog`.
*/
imageTextures?: number[];
technique?: number;
stringCatalog: Array<string | undefined>;
objInfos?: AttributeMap[];
// Angle in degrees from north clockwise specifying the directions the icons can be shifted.
offsetDirections?: number[];
}
Expand Down
2 changes: 1 addition & 1 deletion @here/harp-mapview/lib/geometry/TileGeometryCreator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ export class TileGeometryCreator {
}

const positions = new THREE.BufferAttribute(
new Float32Array(text.positions.buffer),
new Float64Array(text.positions.buffer),
text.positions.itemCount
);

Expand Down
2 changes: 1 addition & 1 deletion @here/harp-mapview/lib/poi/PoiManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ export class PoiManager {
}

const positions = new THREE.BufferAttribute(
new Float32Array(poiGeometry.positions.buffer),
new Float64Array(poiGeometry.positions.buffer),
poiGeometry.positions.itemCount
);

Expand Down
41 changes: 16 additions & 25 deletions @here/harp-vectortile-datasource/lib/VectorTileDataEmitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,7 @@ export class VectorTileDataEmitter {
positions: {
name: "position",
type: "float",
buffer: new Float32Array(aLine).buffer,
buffer: new Float64Array(aLine).buffer,
itemCount: 3
},
texts: [0],
Expand Down Expand Up @@ -1706,43 +1706,34 @@ export class VectorTileDataEmitter {
if (technique === undefined) {
return;
}

const positionElements = new Float32Array(meshBuffers.positions);

if (meshBuffers.texts.length > 0 && isTextTechnique(technique)) {
this.m_textGeometries.push({
if (meshBuffers.texts.length > 0) {
const geometry: TextGeometry = {
positions: {
name: "position",
type: "float",
buffer: positionElements.buffer as ArrayBuffer,
buffer: new Float64Array(meshBuffers.positions).buffer,
itemCount: 3
},
texts: meshBuffers.texts,
technique: techniqueIdx,
stringCatalog: meshBuffers.stringCatalog,
objInfos: meshBuffers.objInfos
});
return;
}
};

if (meshBuffers.texts.length > 0 && isPoiTechnique(technique)) {
this.m_poiGeometries.push({
positions: {
name: "position",
type: "float",
buffer: positionElements.buffer as ArrayBuffer,
itemCount: 3
},
texts: meshBuffers.texts,
technique: techniqueIdx,
stringCatalog: meshBuffers.stringCatalog,
imageTextures: meshBuffers.imageTextures,
objInfos: meshBuffers.objInfos,
offsetDirections: meshBuffers.offsetDirections
});
if (isTextTechnique(technique)) {
this.m_textGeometries.push(geometry);
} else {
assert(isPoiTechnique(technique));
const poiGeometry = geometry as PoiGeometry;
poiGeometry.imageTextures = meshBuffers.imageTextures;
poiGeometry.offsetDirections = meshBuffers.offsetDirections;
this.m_poiGeometries.push(poiGeometry);
}
return;
}

const positionElements = new Float32Array(meshBuffers.positions);

if (meshBuffers.groups.length === 0) {
// create a default group containing all the vertices in the position attribute.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,17 @@ describe("OmvDecodedTileEmitter", function () {
const tileKey = TileKey.fromRowColumnLevel(0, 0, level);
const decodeInfo = new DecodeInfo("test", mercatorProjection, tileKey);

function getExpectedHeight(geoAltitude: number, worldCoords: Vector3Like) {
function getExpectedHeight(
geoAltitude: number,
worldCoords: Vector3Like,
toSinglePrecision = true
) {
const scaleFactor = expectScaledHeight
? decodeInfo.targetProjection.getScaleFactor(worldCoords)
: 1.0;
const expectedHeight = geoAltitude * scaleFactor;
// Force conversion to single precision as in decoder so that results match.
return new Float32Array([geoAltitude * scaleFactor])[0];
return toSinglePrecision ? new Float32Array([expectedHeight])[0] : expectedHeight;
}

it(`Point Height at level ${level} with constantHeight ${
Expand Down Expand Up @@ -174,13 +179,13 @@ describe("OmvDecodedTileEmitter", function () {

assert.equal(textGeometries?.length, 1, "only one geometry created");

const buffer = new Float32Array(textGeometries![0].positions.buffer);
const buffer = new Float64Array(textGeometries![0].positions.buffer);
assert.equal(buffer.length, 3, "one position (3 coordinates)");

const actualHeight = buffer[2];
assert.approximately(
actualHeight,
getExpectedHeight(geoCoords.altitude, worldCoords),
getExpectedHeight(geoCoords.altitude, worldCoords, false),
1e-6
);
});
Expand Down
49 changes: 49 additions & 0 deletions test/rendering/ScreenSpaceRenderingTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { Style } from "@here/harp-datasource-protocol";

import { GeoJsonTest } from "./utils/GeoJsonTest";
import { ThemeBuilder } from "./utils/ThemeBuilder";

Expand Down Expand Up @@ -81,6 +83,53 @@ describe("ScreenSpaceRendering Test", function () {
});
});

it("renders icons and text using double precision coordinates", async function () {
this.timeout(5000);

// HARP-14465: Text and cross icon must be centered on green square.
const squaresStyle: Style = {
when: "$geometryType == 'point'",
technique: "squares",
color: "green",
size: 17,
styleSet: "geojson"
};
await geoJsonTest.run({
mochaTest: this,
testImageName: "geojson-precision-icon-text",
theme: new ThemeBuilder()
.withFontCatalog()
.withMarkerStyle()
.withStyle(squaresStyle)
.build(),
geoJson: {
type: "FeatureCollection",
features: [
{
type: "Feature",
properties: {
text: "o",
color: "white",
imageTexture: "plus-icon",
iconYOffset: 0,
size: 18
},
geometry: {
type: "MultiPoint",
coordinates: [
[14.60015, 53.30007],
[14.60015, 53.29993],
[14.59985, 53.29993],
[14.59985, 53.30007]
]
}
}
]
},
lookAt: { tilt: 0, zoomLevel: 20 },
tileGeoJson: false
});
});
it("renders point using marker technique, with theme set to datasource", async function () {
this.timeout(5000);

Expand Down
29 changes: 18 additions & 11 deletions test/rendering/utils/ThemeBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { FlatTheme, ImageTexture, Light, Style, Theme } from "@here/harp-datasource-protocol";
import { FlatTheme, ImageTexture, Light, Style } from "@here/harp-datasource-protocol";

// Mocha discourages using arrow functions, see https://mochajs.org/#arrow-functions

Expand Down Expand Up @@ -53,8 +53,8 @@ export class ThemeBuilder {
technique: "labeled-icon",

// imageTexture: "white-icon",
size: 15,
iconYOffset: 30,
size: ["number", ["get", "size"], 15],
iconYOffset: ["number", ["get", "iconYOffset"], 30],
text: ["get", "text"],
color: ["get", "color"],
imageTexture: ["string", ["get", "imageTexture"], "white-icon"],
Expand Down Expand Up @@ -82,10 +82,15 @@ export class ThemeBuilder {
url:
"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDIyLjEuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiIHZlcnNpb249IjEuMSIgaWQ9Imx1aS1pY29uLWRlc3RpbmF0aW9ucGluLW9uZGFyay1zb2xpZC1sYXJnZSIKCSB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDQ4IDQ4IgoJIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDQ4IDQ4IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPGc+Cgk8ZyBpZD0ibHVpLWljb24tZGVzdGluYXRpb25waW4tb25kYXJrLXNvbGlkLWxhcmdlLWJvdW5kaW5nLWJveCIgb3BhY2l0eT0iMCI+CgkJPHBhdGggZmlsbD0iI2ZmZmZmZiIgZD0iTTQ3LDF2NDZIMVYxSDQ3IE00OCwwSDB2NDhoNDhWMEw0OCwweiIvPgoJPC9nPgoJPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGZpbGw9IiNmZmZmZmYiIGQ9Ik0yNCwyQzEzLjg3MDgsMiw1LjY2NjcsMTAuMTU4NCw1LjY2NjcsMjAuMjIzMwoJCWMwLDUuMDMyNSwyLjA1MzMsOS41ODg0LDUuMzcxNywxMi44ODgzTDI0LDQ2bDEyLjk2MTctMTIuODg4M2MzLjMxODMtMy4zLDUuMzcxNy03Ljg1NTgsNS4zNzE3LTEyLjg4ODMKCQlDNDIuMzMzMywxMC4xNTg0LDM0LjEyOTIsMiwyNCwyeiBNMjQsMjVjLTIuNzY1LDAtNS0yLjIzNS01LTVzMi4yMzUtNSw1LTVzNSwyLjIzNSw1LDVTMjYuNzY1LDI1LDI0LDI1eiIvPgo8L2c+Cjwvc3ZnPgo=",
preload: true
},
"plus-icon": {
url:
"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgo8c3ZnCiAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgeG1sbnM6Y2M9Imh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL25zIyIKICAgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIgogICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIKICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiCiAgIHdpZHRoPSIxMDAiCiAgIGhlaWdodD0iMTIwIgogICBpZD0ic3ZnMjQ1NCIKICAgc29kaXBvZGk6dmVyc2lvbj0iMC4zMiIKICAgaW5rc2NhcGU6dmVyc2lvbj0iMC40NiIKICAgdmVyc2lvbj0iMS4wIgogICBzb2RpcG9kaTpkb2NuYW1lPSJQbHVzIHN5bWJvbC5zdmciCiAgIGlua3NjYXBlOm91dHB1dF9leHRlbnNpb249Im9yZy5pbmtzY2FwZS5vdXRwdXQuc3ZnLmlua3NjYXBlIj4KICA8ZGVmcwogICAgIGlkPSJkZWZzMjQ1NiI+CiAgICA8aW5rc2NhcGU6cGVyc3BlY3RpdmUKICAgICAgIHNvZGlwb2RpOnR5cGU9Imlua3NjYXBlOnBlcnNwM2QiCiAgICAgICBpbmtzY2FwZTp2cF94PSIwIDogNTI2LjE4MTA5IDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3o9Ijc0NC4wOTQ0OCA6IDUyNi4xODEwOSA6IDEiCiAgICAgICBpbmtzY2FwZTpwZXJzcDNkLW9yaWdpbj0iMzcyLjA0NzI0IDogMzUwLjc4NzM5IDogMSIKICAgICAgIGlkPSJwZXJzcGVjdGl2ZTI0NjIiIC8+CiAgPC9kZWZzPgogIDxzb2RpcG9kaTpuYW1lZHZpZXcKICAgICBpZD0iYmFzZSIKICAgICBwYWdlY29sb3I9IiNmZmZmZmYiCiAgICAgYm9yZGVyY29sb3I9IiM2NjY2NjYiCiAgICAgYm9yZGVyb3BhY2l0eT0iMS4wIgogICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwLjAiCiAgICAgaW5rc2NhcGU6cGFnZXNoYWRvdz0iMiIKICAgICBpbmtzY2FwZTp6b29tPSIwLjc5NTQ5NTEzIgogICAgIGlua3NjYXBlOmN4PSIxOTQuNTEzNjEiCiAgICAgaW5rc2NhcGU6Y3k9IjI2Ny43ODMzOSIKICAgICBpbmtzY2FwZTpkb2N1bWVudC11bml0cz0icHgiCiAgICAgaW5rc2NhcGU6Y3VycmVudC1sYXllcj0ibGF5ZXIxIgogICAgIHNob3dncmlkPSJmYWxzZSIKICAgICBpbmtzY2FwZTp3aW5kb3ctd2lkdGg9IjE0NDAiCiAgICAgaW5rc2NhcGU6d2luZG93LWhlaWdodD0iODgxIgogICAgIGlua3NjYXBlOndpbmRvdy14PSItNCIKICAgICBpbmtzY2FwZTp3aW5kb3cteT0iLTQiIC8+CiAgPGcKICAgICBpbmtzY2FwZTpsYWJlbD0iTGl2ZWxsbyAxIgogICAgIGlua3NjYXBlOmdyb3VwbW9kZT0ibGF5ZXIiCiAgICAgaWQ9ImxheWVyMSIKICAgICB0cmFuc2Zvcm09InNjYWxlKDAuMikiPgogICAgPHBhdGgKICAgICAgIHN0eWxlPSJmb250LXNpemU6NDMxLjkyNDIyNDg1cHg7Zm9udC1zdHlsZTpub3JtYWw7Zm9udC13ZWlnaHQ6bm9ybWFsO2ZpbGw6I2ZmMDAwMDtmaWxsLW9wYWNpdHk6MTtzdHJva2U6bm9uZTtzdHJva2Utd2lkdGg6MXB4O3N0cm9rZS1saW5lY2FwOmJ1dHQ7c3Ryb2tlLWxpbmVqb2luOm1pdGVyO3N0cm9rZS1vcGFjaXR5OjE7Zm9udC1mYW1pbHk6Qml0c3RyZWFtIFZlcmEgU2FucyIKICAgICAgIGQ9Ik0gMjQxLjk5MjE5LDQwNy45MTAxNiBMIDI0MS45OTIxOSwzMTAuNDQ5MjIgTCAxNDQuNzI2NTYsMzEwLjQ0OTIyIEwgMTQ0LjcyNjU2LDI5NC40MzM1OSBMIDI0MS45OTIxOSwyOTQuNDMzNTkgTCAyNDEuOTkyMTksMTk3LjM2MzI4IEwgMjU3LjYxNzE5LDE5Ny4zNjMyOCBMIDI1Ny42MTcxOSwyOTQuNDMzNTkgTCAzNTUuMjczNDQsMjk0LjQzMzU5IEwgMzU1LjI3MzQ0LDMxMC40NDkyMiBMIDI1Ny42MTcxOSwzMTAuNDQ5MjIgTCAyNTcuNjE3MTksNDA3LjkxMDE2IEwgMjQxLjk5MjE5LDQwNy45MTAxNiB6IgogICAgICAgaWQ9InRleHQyNDY0IiAvPgogIDwvZz4KPC9zdmc+Cg==",
preload: true
}
};

private readonly m_baseTheme: Theme = {
private readonly m_baseTheme: FlatTheme = {
lights: ThemeBuilder.lights,
sky: {
type: "gradient",
Expand All @@ -95,10 +100,11 @@ export class ThemeBuilder {
},
clearColor: "#4A4D4E",
images: ThemeBuilder.images,
imageTextures: ThemeBuilder.imageTextures
imageTextures: ThemeBuilder.imageTextures,
styles: []
};

private m_theme: Theme | FlatTheme = {};
private m_theme: FlatTheme = { styles: [] };

/**
*
Expand All @@ -111,7 +117,7 @@ export class ThemeBuilder {
}
}

build(): Theme | FlatTheme {
build(): FlatTheme {
return this.m_theme;
}

Expand Down Expand Up @@ -142,10 +148,11 @@ export class ThemeBuilder {
}

withMarkerStyle(): ThemeBuilder {
this.m_theme = {
...this.m_theme,
styles: [ThemeBuilder.markerStyle]
};
return this.withStyle(ThemeBuilder.markerStyle);
}

withStyle(style: Style): ThemeBuilder {
this.m_theme.styles!.push(style);
return this;
}
}