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

Commit

Permalink
HARP-10648: Clean up the Ring API.
Browse files Browse the repository at this point in the history
This change simplifies the support for working with rings
and texture coordinates. The Ring now maintains distinct
arrays of position and texture coordinates and has APIs
to flatten the Ring into an Array of numbers.

Signed-off-by: Roberto Raggi <roberto.raggi@here.com>
  • Loading branch information
robertoraggi committed Jul 7, 2020
1 parent 702d21a commit 02d43fe
Show file tree
Hide file tree
Showing 4 changed files with 342 additions and 68 deletions.
56 changes: 23 additions & 33 deletions @here/harp-omv-datasource/lib/OmvDecodedTileEmitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,14 @@ import {

import { ILineGeometry, IPolygonGeometry } from "./IGeometryProcessor";
import { LinesGeometry } from "./OmvDataSource";
import { IOmvEmitter, Ring } from "./OmvDecoder";
import { IOmvEmitter } from "./OmvDecoder";
import {
tile2world,
webMercatorTile2TargetTile,
webMercatorTile2TargetWorld,
world2tile
} from "./OmvUtils";
import { Ring } from "./Ring";

import {
AttrEvaluationContext,
Expand Down Expand Up @@ -207,7 +208,7 @@ export enum LineType {
Complex
}

type TexCoordsFunction = (tilePos: THREE.Vector2, tileExtents: number) => { u: number; v: number };
type TexCoordsFunction = (tilePos: THREE.Vector2, tileExtents: number) => THREE.Vector2;
const tmpColor = new THREE.Color();

export class OmvDecodedTileEmitter implements IOmvEmitter {
Expand Down Expand Up @@ -460,14 +461,8 @@ export class OmvDecodedTileEmitter implements IOmvEmitter {
worldLine.push(tmpV4.x, tmpV4.y, tmpV4.z);

if (computeTexCoords) {
{
const { u, v } = computeTexCoords(pos1, extents);
lineUvs.push(u, v);
}
{
const { u, v } = computeTexCoords(pos2, extents);
lineUvs.push(u, v);
}
computeTexCoords(pos1, extents).toArray(lineUvs, lineUvs.length);
computeTexCoords(pos2, extents).toArray(lineUvs, lineUvs.length);
}
if (hasUntiledLines) {
// Find where in the [0...1] range relative to the line our current
Expand Down Expand Up @@ -520,8 +515,7 @@ export class OmvDecodedTileEmitter implements IOmvEmitter {
worldLine.push(tmpV3.x, tmpV3.y, tmpV3.z);

if (computeTexCoords) {
const { u, v } = computeTexCoords(pos, extents);
lineUvs.push(u, v);
computeTexCoords(pos, extents).toArray(lineUvs, lineUvs.length);
}
if (hasUntiledLines) {
// Find where in the [0...1] range relative to the line our current vertex
Expand Down Expand Up @@ -799,14 +793,11 @@ export class OmvDecodedTileEmitter implements IOmvEmitter {
isStandard ||
(isShaderTechnique(technique) && technique.primitive === "mesh");
const computeTexCoords = this.getComputeTexCoordsFunc(technique, objectBounds);
const vertexStride = computeTexCoords !== undefined ? 4 : 2;

for (const polygon of geometry) {
const rings: Ring[] = [];

for (const outline of polygon.rings) {
const ringContour: number[] = [];

let coords = outline;

// disable clipping for the polygon geometries
Expand All @@ -828,15 +819,13 @@ export class OmvDecodedTileEmitter implements IOmvEmitter {
continue;
}

for (const coord of coords) {
ringContour.push(coord.x, coord.y);
if (computeTexCoords !== undefined) {
const { u, v } = computeTexCoords(coord, extents);
ringContour.push(u, v);
}
let textureCoords: THREE.Vector2[] | undefined;

if (computeTexCoords !== undefined) {
textureCoords = coords.map(coord => computeTexCoords(coord, extents));
}

rings.push(new Ring(extents, vertexStride, ringContour));
rings.push(new Ring(coords, textureCoords, extents));
}

if (rings.length === 0) {
Expand Down Expand Up @@ -1149,36 +1138,37 @@ export class OmvDecodedTileEmitter implements IOmvEmitter {

switch (texCoordType) {
case TextureCoordinateType.TileSpace:
return (tilePos: THREE.Vector2, tileExtents: number) => {
const { x: u, y: v } = new THREE.Vector2()
.copy(tilePos)
.divideScalar(tileExtents);
return { u, v: 1 - v };
return (tilePos: THREE.Vector2, tileExtents: number): THREE.Vector2 => {
const uv = tilePos.clone().divideScalar(tileExtents);
uv.y = 1 - uv.y;
return uv;
};

case TextureCoordinateType.EquirectangularSpace:
return (tilePos: THREE.Vector2, extents: number) => {
return (tilePos: THREE.Vector2, extents: number): THREE.Vector2 => {
const worldPos = tile2world(extents, this.m_decodeInfo, tilePos, false, tmpV2r);
const { x: u, y: v } = normalizedEquirectangularProjection.reprojectPoint(
const uv = normalizedEquirectangularProjection.reprojectPoint(
webMercatorProjection,
new THREE.Vector3(worldPos.x, worldPos.y, 0)
);
return { u, v };
return new THREE.Vector2(uv.x, uv.y);
};

case TextureCoordinateType.FeatureSpace:
if (!objectBounds) {
return undefined;
}
return (tilePos: THREE.Vector2, extents: number) => {
const uv = tile2world(extents, this.m_decodeInfo, tilePos, false, tmpV2r);
return (tilePos: THREE.Vector2, extents: number): THREE.Vector2 => {
const uv = new THREE.Vector2();
tile2world(extents, this.m_decodeInfo, tilePos, false, uv);
if (objectBounds) {
uv.x -= objectBounds.min.x;
uv.y -= objectBounds.min.y;
uv.x /= objectBounds.max.x - objectBounds.min.x;
uv.y /= objectBounds.max.y - objectBounds.min.y;
}
return { u: uv.x, v: 1 - uv.y };
uv.y = 1 - uv.y;
return uv;
};

default:
Expand Down
35 changes: 0 additions & 35 deletions @here/harp-omv-datasource/lib/OmvDecoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,41 +49,6 @@ import { VTJsonDataAdapter } from "./VTJsonDataAdapter";

const logger = LoggerManager.instance.create("OmvDecoder", { enabled: false });

export class Ring {
readonly winding: boolean;

/**
* Constructs a new [[Ring]].
*
* @param extents - The extents of the enclosing layer.
* @param vertexStride - The stride of this elements stored in 'contour'.
* @param contour - The [[Array]] containing the projected world coordinates.
*/
constructor(
readonly extents: number,
readonly vertexStride: number,
readonly contour: number[]
) {
this.winding = this.area() < 0;
}

area(): number {
const points = this.contour;
const stride = this.vertexStride;
const n = points.length / stride;

let area = 0.0;

for (let p = n - 1, q = 0; q < n; p = q++) {
area +=
points[p * stride] * points[q * stride + 1] -
points[q * stride] * points[p * stride + 1];
}

return area / 2;
}
}

export interface IOmvEmitter {
processPointFeature(
layer: string,
Expand Down
72 changes: 72 additions & 0 deletions @here/harp-omv-datasource/lib/Ring.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright (C) 2017-2020 HERE Europe B.V.
* Licensed under Apache 2.0, see full license in LICENSE
* SPDX-License-Identifier: Apache-2.0
*/

import { ShapeUtils, Vector2 } from "three";

/**
* A class representing a ring of a polygon geometry.
*/
export class Ring {
/**
* The area of this `Ring`.
*/
readonly area: number;

/**
* The winding of this `Ring`.
*/
readonly winding: boolean;

/**
* The vertex stride.
*/
readonly vertexStride: number;

private m_contour?: number[];

constructor(
readonly points: Vector2[],
readonly textureCoords?: Vector2[],
readonly extents: number = 4 * 1024
) {
if (textureCoords !== undefined && textureCoords.length !== points.length) {
throw new Error(
`the array of texture coordinates must have the same number of elements of the array of points`
);
}

this.vertexStride = 2;

if (textureCoords !== undefined) {
this.vertexStride = this.vertexStride + 2;
}

this.area = ShapeUtils.area(this.points);
this.winding = this.area < 0;
}

/**
* Returns a flattened `Array` containing the position and texture coordinates of this `Ring`.
*
* @param array The target `Array`.
* @param offset Optional offset into the array.
*/
toArray(array: number[] = [], offset: number = 0): number[] {
this.points.forEach((p, i) => p.toArray(array, offset + this.vertexStride * i));
this.textureCoords?.forEach((p, i) => p.toArray(array, offset + this.vertexStride * i + 2));
return array;
}

/**
* Returns a flattened `Array` containing the position and texture coordinates of this `Ring`.
*/
get contour(): number[] {
if (this.m_contour === undefined) {
this.m_contour = this.toArray();
}
return this.m_contour;
}
}
Loading

0 comments on commit 02d43fe

Please sign in to comment.