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

Commit

Permalink
HARP-13235: Set constantHeight as common parameter for all techniques.
Browse files Browse the repository at this point in the history
If datasource geometry is 3D and technique's constantHeight is
set to true or defaults to true (for store levels lower than 12), then
projected geometry height is scaled by target projection's scale factor.
  • Loading branch information
atomicsulfate committed Jan 22, 2021
1 parent c4740df commit 8416574
Show file tree
Hide file tree
Showing 6 changed files with 245 additions and 71 deletions.
24 changes: 24 additions & 0 deletions @here/harp-datasource-protocol/lib/DecodedTile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -442,3 +442,27 @@ export function getFeatureText(

return getFeatureName(env, propName, useAbbreviation, useIsoCode, languages);
}

/**
* Determine whether to scale heights by the projection scale factor for geometry
* using the given technique.
* @remarks Unless explicitly defined, the scale factor to convert meters to world space units
* won't be applied if the tile's level is less than a fixed storage level.
* @param context - Context for evaluation of technique attributes.
* @param technique - Technique to be evaluated.
* @param tileLevel - The level of the tile where the geometry is stored.
* @returns `true` if height must be scaled, `false` otherwise.
*/
export function scaleHeight(
context: Env | AttrEvaluationContext,
technique: Technique,
tileLevel: number
): boolean {
const SCALED_HEIGHT_MIN_STORAGE_LEVEL = 12;
const useConstantHeight = evaluateTechniqueAttr(
context,
technique.constantHeight,
tileLevel < SCALED_HEIGHT_MIN_STORAGE_LEVEL
);
return !useConstantHeight;
}
2 changes: 1 addition & 1 deletion @here/harp-datasource-protocol/lib/TechniqueDescriptors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ const baseTechniqueParamsDescriptor: TechniqueDescriptor<BaseTechniqueParams> =
// For now we chosen all, but it maybe not suitable for text or line marker techniques.
attrTransparencyColor: "color",
attrDescriptors: {
constantHeight: AttrScope.FeatureGeometry,
enabled: AttrScope.FeatureGeometry,
fadeFar: AttrScope.TechniqueRendering,
fadeNear: AttrScope.TechniqueRendering,
Expand Down Expand Up @@ -270,7 +271,6 @@ const extrudedPolygonTechniqueDescriptor = mergeTechniqueDescriptor<ExtrudedPoly
color: AttrScope.FeatureGeometry,
defaultColor: AttrScope.FeatureGeometry,
defaultHeight: AttrScope.FeatureGeometry,
constantHeight: AttrScope.FeatureGeometry,
boundaryWalls: AttrScope.FeatureGeometry,
footprint: AttrScope.FeatureGeometry,
maxSlope: AttrScope.FeatureGeometry,
Expand Down
18 changes: 10 additions & 8 deletions @here/harp-datasource-protocol/lib/TechniqueParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,16 @@ export interface BaseTechniqueParams {
* Maximum zoom level. If the current zoom level is equal to or greater, the technique will not be used.
*/
maxZoomLevel?: DynamicProperty<number>;

/**
* If `true`, geometry height won't be scaled on projection. Enable it for projections with
* variable scale factor (e.g. mercator) to avoid distortions in geometry with great heights and
* latitude spans. E.g. a large object with even height would look oblique to the ground plane
* on mercator unless this property is set to `true`.
*
* @defaultValue `true` for geometries stored at level less than `12`.
*/
constantHeight?: boolean;
}

export enum TextureCoordinateType {
Expand Down Expand Up @@ -1212,14 +1222,6 @@ export interface ExtrudedPolygonTechniqueParams extends StandardTechniqueParams
*/
defaultColor?: DynamicProperty<StyleColor>;

/**
* If `true`, the height of the extruded buildings will not be modified by the mercator
* projection distortion that happens around the poles.
*
* @defaultValue `true` for geometries stored at level less than `12`.
*/
constantHeight?: boolean;

/**
* If `true`, wall geometry will is added along the tile boundaries.
*
Expand Down
7 changes: 6 additions & 1 deletion @here/harp-vectortile-datasource/lib/OmvUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,19 +130,24 @@ export function webMercatorTile2TargetWorld(
decodeInfo: DecodeInfo,
position: THREE.Vector2 | THREE.Vector3,
target: THREE.Vector3,
scaleHeight: boolean,
flipY: boolean = false
) {
tile2world(extents, decodeInfo, position, flipY, target);
decodeInfo.targetProjection.reprojectPoint(webMercatorProjection, target, target);
if (position instanceof THREE.Vector3 && scaleHeight) {
target.z *= decodeInfo.targetProjection.getScaleFactor(target);
}
}

export function webMercatorTile2TargetTile(
extents: number,
decodeInfo: DecodeInfo,
position: THREE.Vector2 | THREE.Vector3,
target: THREE.Vector3,
scaleHeight: boolean,
flipY: boolean = false
) {
webMercatorTile2TargetWorld(extents, decodeInfo, position, target, flipY);
webMercatorTile2TargetWorld(extents, decodeInfo, position, target, scaleHeight, flipY);
target.sub(decodeInfo.center);
}
90 changes: 55 additions & 35 deletions @here/harp-vectortile-datasource/lib/VectorTileDataEmitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {
PathGeometry,
PoiGeometry,
PoiTechnique,
scaleHeight,
StyleColor,
Technique,
TextGeometry,
Expand Down Expand Up @@ -85,7 +86,6 @@ import { Ring } from "./Ring";
const logger = LoggerManager.instance.create("OmvDecodedTileEmitter");

const tempTileOrigin = new THREE.Vector3();
const tempVertOrigin = new THREE.Vector3();
const tempVertNormal = new THREE.Vector3();
const tempFootDisp = new THREE.Vector3();
const tempRoofDisp = new THREE.Vector3();
Expand Down Expand Up @@ -331,6 +331,7 @@ export class VectorTileDataEmitter {
}
}

const scaleHeights = scaleHeight(context, technique, this.m_decodeInfo.tileKey.level);
const featureId = getFeatureId(env.entries);
for (const pos of tilePositions) {
if (shouldCreateTextGeometries) {
Expand All @@ -347,9 +348,21 @@ export class VectorTileDataEmitter {
// Always store the position, otherwise the following POIs will be
// misplaced.
if (shouldCreateTextGeometries) {
webMercatorTile2TargetWorld(extents, this.m_decodeInfo, pos, tmpV3);
webMercatorTile2TargetWorld(
extents,
this.m_decodeInfo,
pos,
tmpV3,
scaleHeights
);
} else {
webMercatorTile2TargetTile(extents, this.m_decodeInfo, pos, tmpV3);
webMercatorTile2TargetTile(
extents,
this.m_decodeInfo,
pos,
tmpV3,
scaleHeights
);
}
positions.push(tmpV3.x, tmpV3.y, tmpV3.z);
objInfos.push(this.m_gatherFeatureAttributes ? env.entries : featureId);
Expand Down Expand Up @@ -404,6 +417,7 @@ export class VectorTileDataEmitter {
let texCoordinateType: TextureCoordinateType | undefined;

const hasUntiledLines = geometry[0].untiledPositions !== undefined;
const scaleHeights = false; // No need to scale height, source data is 2D.

// If true, special handling for dashes is required (round and diamond shaped dashes).
let hasIndividualLineSegments = false;
Expand Down Expand Up @@ -471,9 +485,21 @@ export class VectorTileDataEmitter {

const pos1 = polyline.positions[i];
const pos2 = polyline.positions[i + 1];
webMercatorTile2TargetWorld(extents, this.m_decodeInfo, pos1, tmpV3);
webMercatorTile2TargetWorld(
extents,
this.m_decodeInfo,
pos1,
tmpV3,
scaleHeights
);
worldLine.push(tmpV3.x, tmpV3.y, tmpV3.z);
webMercatorTile2TargetWorld(extents, this.m_decodeInfo, pos2, tmpV4);
webMercatorTile2TargetWorld(
extents,
this.m_decodeInfo,
pos2,
tmpV4,
scaleHeights
);
worldLine.push(tmpV4.x, tmpV4.y, tmpV4.z);

if (computeTexCoords) {
Expand Down Expand Up @@ -527,7 +553,13 @@ export class VectorTileDataEmitter {
const lineUvs: number[] = [];
const lineOffsets: number[] = [];
polyline.positions.forEach(pos => {
webMercatorTile2TargetWorld(extents, this.m_decodeInfo, pos, tmpV3);
webMercatorTile2TargetWorld(
extents,
this.m_decodeInfo,
pos,
tmpV3,
scaleHeights
);
worldLine.push(tmpV3.x, tmpV3.y, tmpV3.z);

if (computeTexCoords) {
Expand Down Expand Up @@ -770,6 +802,8 @@ export class VectorTileDataEmitter {
const env = context.env;
this.processFeatureCommon(env);

const scaleHeights = false; // No need to scale height, source data is 2D.

techniques.forEach(technique => {
if (technique === undefined) {
return;
Expand Down Expand Up @@ -913,7 +947,8 @@ export class VectorTileDataEmitter {
extents,
this.m_decodeInfo,
tmpV2.copy(curr),
tmpV3
tmpV3,
scaleHeights
);
line.push(tmpV3.x, tmpV3.y, tmpV3.z);

Expand All @@ -923,7 +958,8 @@ export class VectorTileDataEmitter {
extents,
this.m_decodeInfo,
tmpV2.copy(next),
tmpV4
tmpV4,
scaleHeights
);
line.push(tmpV4.x, tmpV4.y, tmpV4.z);

Expand All @@ -941,7 +977,8 @@ export class VectorTileDataEmitter {
extents,
this.m_decodeInfo,
tmpV2.copy(next),
tmpV3
tmpV3,
scaleHeights
);
line.push(tmpV3.x, tmpV3.y, tmpV3.z);
}
Expand Down Expand Up @@ -1307,16 +1344,8 @@ export class VectorTileDataEmitter {

const tileLevel = this.m_decodeInfo.tileKey.level;

const SCALED_EXTRUSION_MIN_STORAGE_LEVEL = 12;

// Unless explicitly defined do not apply the projection
// scale factor to convert meters to world space units
// if the tile's level is less than `SCALED_EXTRUSION_MIN_STORAGE_LEVEL`.
const styleSetConstantHeight = evaluateTechniqueAttr(
context,
extrudedPolygonTechnique.constantHeight,
tileLevel < SCALED_EXTRUSION_MIN_STORAGE_LEVEL
);
const scaleHeights =
isExtruded && scaleHeight(context, extrudedPolygonTechnique, tileLevel);

this.m_decodeInfo.tileBounds.getCenter(tempTileOrigin);

Expand Down Expand Up @@ -1541,25 +1570,18 @@ export class VectorTileDataEmitter {

// Assemble the vertex buffer.
for (let i = 0; i < vertices.length; i += vertexStride) {
webMercatorTile2TargetTile(
webMercatorTile2TargetWorld(
extents,
this.m_decodeInfo,
tmpV2.set(vertices[i], vertices[i + 1]),
tmpV3,
false, // no need to scale height (source data is 2D).
true
);

let scaleFactor = 1.0;
if (isExtruded && styleSetConstantHeight !== true) {
tempVertOrigin.set(
tempTileOrigin.x + tmpV3.x,
tempTileOrigin.y + tmpV3.y,
tempTileOrigin.z + tmpV3.z
);
scaleFactor = this.m_decodeInfo.targetProjection.getScaleFactor(
tempVertOrigin
);
}
const scaleFactor = scaleHeights
? this.m_decodeInfo.targetProjection.getScaleFactor(tmpV3)
: 1.0;
this.m_maxGeometryHeight = Math.max(
this.m_maxGeometryHeight,
scaleFactor * height
Expand All @@ -1570,11 +1592,9 @@ export class VectorTileDataEmitter {
);

if (isSpherical) {
tempVertNormal
.set(tmpV3.x, tmpV3.y, tmpV3.z)
.add(this.center)
.normalize();
tempVertNormal.set(tmpV3.x, tmpV3.y, tmpV3.z).normalize();
}
tmpV3.sub(this.center);

tempFootDisp.copy(tempVertNormal).multiplyScalar(floorHeight * scaleFactor);
positions.push(
Expand Down
Loading

0 comments on commit 8416574

Please sign in to comment.