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

Commit

Permalink
HARP-10648: Remove usages of ring.contour.
Browse files Browse the repository at this point in the history
Also isolate the code that tries to compute the edges of the
ring that need to be connected with a line when stroking
polygons.

Signed-off-by: Roberto Raggi <roberto.raggi@here.com>
  • Loading branch information
robertoraggi committed Jul 7, 2020
1 parent 02d43fe commit 66a1a93
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 85 deletions.
91 changes: 41 additions & 50 deletions @here/harp-omv-datasource/lib/OmvDecodedTileEmitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,7 @@ export class OmvDecodedTileEmitter implements IOmvEmitter {
? []
: undefined;
rings.forEach(ring => {
const length = ring.contour.length / ring.vertexStride;
const length = ring.points.length;
let line: number[] = [];

// Compute length of whole line and offsets of individual segments.
Expand All @@ -879,17 +879,10 @@ export class OmvDecodedTileEmitter implements IOmvEmitter {
}

const nextIdx = (i + 1) % length;
const currX = ring.contour[i * ring.vertexStride];
const currY = ring.contour[i * ring.vertexStride + 1];
const nextX = ring.contour[nextIdx * ring.vertexStride];
const nextY = ring.contour[nextIdx * ring.vertexStride + 1];

const isOutline = !(
(currX <= 0 && nextX <= 0) ||
(currX >= ring.extents && nextX >= ring.extents) ||
(currY <= 0 && nextY <= 0) ||
(currY >= ring.extents && nextY >= ring.extents)
);
const curr = ring.points[i];
const next = ring.points[nextIdx];

const isOutline = ring.isOutline(i);

if (!isOutline && line.length !== 0) {
lines.push(line);
Expand All @@ -898,7 +891,7 @@ export class OmvDecodedTileEmitter implements IOmvEmitter {
webMercatorTile2TargetTile(
extents,
this.m_decodeInfo,
tmpV2.set(currX, currY),
tmpV2.copy(curr),
tmpV3
);
line.push(tmpV3.x, tmpV3.y, tmpV3.z);
Expand All @@ -908,7 +901,7 @@ export class OmvDecodedTileEmitter implements IOmvEmitter {
webMercatorTile2TargetTile(
extents,
this.m_decodeInfo,
tmpV2.set(nextX, nextY),
tmpV2.copy(next),
tmpV4
);
line.push(tmpV4.x, tmpV4.y, tmpV4.z);
Expand All @@ -926,7 +919,7 @@ export class OmvDecodedTileEmitter implements IOmvEmitter {
webMercatorTile2TargetTile(
extents,
this.m_decodeInfo,
tmpV2.set(nextX, nextY),
tmpV2.copy(next),
tmpV3
);
line.push(tmpV3.x, tmpV3.y, tmpV3.z);
Expand Down Expand Up @@ -1245,6 +1238,10 @@ export class OmvDecodedTileEmitter implements IOmvEmitter {
context: AttrEvaluationContext,
extents: number
): void {
if (polygons.length === 0) {
return;
}

const isExtruded = isExtrudedPolygonTechnique(technique);

const geometryType = isExtruded ? GeometryType.ExtrudedPolygon : GeometryType.Polygon;
Expand Down Expand Up @@ -1311,8 +1308,6 @@ export class OmvDecodedTileEmitter implements IOmvEmitter {
groups
} = meshBuffers;

const featureStride = texCoordType !== undefined ? 4 : 2;
const vertexStride = featureStride + 2;
const isSpherical = this.m_decodeInfo.targetProjection.type === ProjectionType.Spherical;

const edgeWidth = isExtruded
Expand Down Expand Up @@ -1356,30 +1351,31 @@ export class OmvDecodedTileEmitter implements IOmvEmitter {
const vertices: number[] = [];
const polygonBaseVertex = positions.length / 3;

const { contour, winding } = polygon[ringIndex++];
for (let i = 0; i < contour.length / featureStride; ++i) {
const ring = polygon[ringIndex++];

const featureStride = ring.vertexStride;
const vertexStride = featureStride + 2;
const winding = ring.winding;

for (let i = 0; i < ring.points.length; ++i) {
const point = ring.points[i];

// Invert the Y component to preserve the correct winding without transforming
// from webMercator's local to global space.
for (let j = 0; j < featureStride; ++j) {
vertices.push((j === 1 ? -1 : 1) * contour[i * featureStride + j]);
vertices.push(point.x, -point.y);

if (ring.textureCoords !== undefined) {
vertices.push(ring.textureCoords[i].x, ring.textureCoords[i].y);
}

// Calculate nextEdge and nextWall.
const nextIdx = (i + 1) % (contour.length / featureStride);
const currX = contour[i * featureStride];
const currY = contour[i * featureStride + 1];
const nextX = contour[nextIdx * featureStride];
const nextY = contour[nextIdx * featureStride + 1];
const insideExtents = !(
(currX <= 0 && nextX <= 0) ||
(currX >= extents && nextX >= extents) ||
(currY <= 0 && nextY <= 0) ||
(currY >= extents && nextY >= extents)
);
const nextIdx = (i + 1) % ring.points.length;

const isOutline = ring.isOutline(i);

// Calculate nextEdge and nextWall.
vertices.push(
insideExtents ? nextIdx : -1,
boundaryWalls || insideExtents ? nextIdx : -1
isOutline ? nextIdx : -1,
boundaryWalls || isOutline ? nextIdx : -1
);
}

Expand All @@ -1390,26 +1386,21 @@ export class OmvDecodedTileEmitter implements IOmvEmitter {
const vertexOffset = vertices.length / vertexStride;
holes.push(vertexOffset);

const hole = polygon[ringIndex++].contour;
for (let i = 0; i < hole.length / featureStride; ++i) {
const hole = polygon[ringIndex++];
for (let i = 0; i < hole.points.length; ++i) {
const nextIdx = (i + 1) % hole.points.length;
const point = hole.points[i];

// Invert the Y component to preserve the correct winding without
// transforming from webMercator's local to global space.
for (let j = 0; j < featureStride; ++j) {
vertices.push((j === 1 ? -1 : 1) * hole[i * featureStride + j]);
vertices.push(point.x, -point.y);

if (hole.textureCoords !== undefined) {
vertices.push(hole.textureCoords[i].x, hole.textureCoords[i].y);
}

// Calculate nextEdge and nextWall.
const nextIdx = (i + 1) % (hole.length / featureStride);
const currX = hole[i * featureStride];
const currY = hole[i * featureStride + 1];
const nextX = hole[nextIdx * featureStride];
const nextY = hole[nextIdx * featureStride + 1];
const insideExtents = !(
(currX <= 0 && nextX <= 0) ||
(currX >= extents && nextX >= extents) ||
(currY <= 0 && nextY <= 0) ||
(currY >= extents && nextY >= extents)
);
const insideExtents = hole.isOutline(i);

vertices.push(
insideExtents ? vertexOffset + nextIdx : -1,
Expand Down
25 changes: 17 additions & 8 deletions @here/harp-omv-datasource/lib/Ring.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ export class Ring {
*/
readonly vertexStride: number;

private m_contour?: number[];

constructor(
readonly points: Vector2[],
readonly textureCoords?: Vector2[],
Expand Down Expand Up @@ -61,12 +59,23 @@ export class Ring {
}

/**
* Returns a flattened `Array` containing the position and texture coordinates of this `Ring`.
* Tests if the edge connecting the vertex at `index` with
* the vertex at `index+1` should be connected by an outline
* when stroking the polygon.
*
* @param index The index of the first vertex of the outline edge.
*/
get contour(): number[] {
if (this.m_contour === undefined) {
this.m_contour = this.toArray();
}
return this.m_contour;
isOutline(index: number): boolean {
const extents = this.extents;
const nextIdx = (index + 1) % this.points.length;
const curr = this.points[index];
const next = this.points[nextIdx];

return !(
(curr.x <= 0 && next.x <= 0) ||
(curr.x >= extents && next.x >= extents) ||
(curr.y <= 0 && next.y <= 0) ||
(curr.y >= extents && next.y >= extents)
);
}
}
64 changes: 37 additions & 27 deletions @here/harp-omv-datasource/test/RingTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// tslint:disable:only-arrow-functions
// Mocha discourages using arrow functions, see https://mochajs.org/#arrow-functions

import { clipPolygon } from "@here/harp-geometry/lib/ClipPolygon";
import { assert } from "chai";
import { Vector2 } from "three";
import { Ring } from "../lib/Ring";
Expand All @@ -27,7 +28,6 @@ describe("Ring", function() {
assert.strictEqual(ring.winding, false);
assert.strictEqual(ring.extents, DEFAULT_EXTENTS);
assert.deepEqual(ring.toArray(), []);
assert.deepEqual(ring.contour, []);
});

it("with texture coordinates", () => {
Expand All @@ -36,7 +36,6 @@ describe("Ring", function() {
assert.strictEqual(ring.winding, false);
assert.strictEqual(ring.extents, DEFAULT_EXTENTS);
assert.deepEqual(ring.toArray(), []);
assert.deepEqual(ring.contour, []);
});

it("with texture coordinates and extents", () => {
Expand All @@ -46,7 +45,6 @@ describe("Ring", function() {
assert.strictEqual(ring.winding, false);
assert.strictEqual(ring.extents, extent);
assert.deepEqual(ring.toArray(), []);
assert.deepEqual(ring.contour, []);
});

it("throws exception", () => {
Expand Down Expand Up @@ -85,7 +83,6 @@ describe("Ring", function() {
assert.strictEqual(ring.winding, false);
assert.strictEqual(ring.extents, DEFAULT_EXTENTS);
assert.deepEqual(ring.toArray(), [0, 0, 100, 0, 100, 100, 0, 100, 0, 0]);
assert.deepEqual(ring.contour, [0, 0, 100, 0, 100, 100, 0, 100, 0, 0]);
});

it("with texture coordinates", () => {
Expand Down Expand Up @@ -115,28 +112,6 @@ describe("Ring", function() {
0,
0
]);
assert.deepEqual(ring.contour, [
0,
0,
0,
0,
100,
0,
1,
0,
100,
100,
1,
1,
0,
100,
0,
1,
0,
0,
0,
0
]);
});
});

Expand All @@ -157,7 +132,7 @@ describe("Ring", function() {
new Vector2(0, 0)
];

it("no texture coordinates", () => {
it("without texture coordinates", () => {
const ring = new Ring(points, undefined, DEFAULT_EXTENTS);
assert.strictEqual(ring.area, -(100 * 100));
assert.strictEqual(ring.winding, true);
Expand Down Expand Up @@ -243,5 +218,40 @@ describe("Ring", function() {
0
]);
});

it("outlines", () => {
const ring = new Ring(points, texCoords);
assert.strictEqual(ring.isOutline(0), false);
assert.strictEqual(ring.isOutline(1), true);
assert.strictEqual(ring.isOutline(2), true);
assert.strictEqual(ring.isOutline(3), false);
assert.strictEqual(ring.isOutline(4), false);
});
});

describe("Concave polygon resulting into 2 parts after clipping", () => {
const polygon: Vector2[] = [
new Vector2(-100, 0),
new Vector2(4096, 0),
new Vector2(-50, 2048),
new Vector2(4096, 4096),
new Vector2(-100, 4096)
];

const clippedPolygon = clipPolygon(polygon, DEFAULT_EXTENTS);

it("edge outlines", () => {
const ring = new Ring(clippedPolygon, undefined, DEFAULT_EXTENTS);
assert.strictEqual(ring.winding, false);
const outlines = ring.points.map((_, i) => ring.isOutline(i));

assert.deepEqual(
// tslint:disable-next-line: no-bitwise
ring.toArray().map(x => x | 0),
[0, 0, 4096, 0, 0, 2023, 0, 2073, 4096, 4096, 0, 4096]
);

assert.deepEqual(outlines, [false, true, false, true, false, false]);
});
});
});

0 comments on commit 66a1a93

Please sign in to comment.