@itwin/core-frontend
Version:
iTwin.js frontend components
127 lines • 6.24 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FeatureGeometryBaseRenderer = void 0;
/** Internal implementation of [[FeatureGeometryRenderer]]
* @internal
*/
class FeatureGeometryBaseRenderer {
_transform;
constructor(world2PixelTransform) {
this._transform = world2PixelTransform;
}
get transform() { return this._transform; }
/**
* Render a path on the renderer's context.
* Note: Inputs are designed based on the PBF format, to avoid any data transformation.
* @param geometryLengths Array be used to determine the start and end of each sub-path / rings. (i.e. [5,5] = two rings of 5 vertices)
* @param geometryCoords Array that linearly encodes the vertices of each sub-path of a polyline / ring of a polygon
* @param fill Indicates if the path should be filled or not.
* @param stride Dimension of each vertices (i.e. 2 or 3. 3 could be X,Y,Z, X,YM) Currently 3rd dimension is ignored.
*/
async renderPath(geometryLengths, geometryCoords, fill, stride, relativeCoords) {
if (stride < 2 || stride > 3) {
return;
}
// Keep track of our position in the in the 'coords' array:
// Every time we loop on the 'lengths' array, the position
// to start reading vertices in the 'coords' must be the sum of all previously read vertices.
let coordsOffset = 0;
// Begin the path here.
// Note: Even though path is closed inside the 'geometryLengths' loop,
// it's import to begin the path only once.
this.beginPath();
for (const vertexCount of geometryLengths) {
let lastPtX = 0, lastPtY = 0;
for (let vertexIdx = 0; vertexIdx < vertexCount; vertexIdx++) {
let pX = geometryCoords[coordsOffset + (vertexIdx * stride)];
let pY = geometryCoords[coordsOffset + (vertexIdx * stride) + 1];
if (vertexIdx === 0) {
// first vertex is always "absolute" and must be drawn as 'moveTo' (i.e. not lineTo)
if (relativeCoords) {
lastPtX = pX;
lastPtY = pY;
}
if (this._transform) {
const transformedPoint = this._transform.multiplyPoint2d({ x: pX, y: pY });
pX = transformedPoint.x;
pY = transformedPoint.y;
}
this.moveTo(pX, pY);
}
else {
// Following vertices are relative to the previous one (sadly not really well documented by ESRI)
// typically this happens when 'coordinates quantization' is active (i.e. no client side transformation is needed)
if (relativeCoords) {
pX = lastPtX = lastPtX + pX;
pY = lastPtY = lastPtY + pY;
}
if (this._transform) {
const transformedPoint = this._transform.multiplyPoint2d({ x: pX, y: pY });
pX = transformedPoint.x;
pY = transformedPoint.y;
}
this.lineTo(pX, pY);
}
}
coordsOffset += stride * vertexCount;
if (fill) {
// ClosePath but do not 'fill' here, only at the very end (otherwise it will mess up holes)
this.closePath();
}
}
if (fill) {
await this.fill();
}
await this.stroke(); // draw line path or polygon outline
}
/**
* Render a point on the renderer's context.
* Note: Inputs are designed based on the PBF format, to avoid any data transformation.
* @param geometryLengths Array be used to determine the start and end of each multi-point array, empty for single point.
* @param geometryCoords Array that linearly encodes vertices.
* @param stride Dimension of each vertices (i.e. 2 or 3. 3 could be X,Y,Z, X,YM) Currently 3rd dimension is ignored.
*/
async renderPoint(geometryLengths, geometryCoords, stride, relativeCoords) {
if (stride < 2 || stride > 3) {
return;
}
let coordsOffset = 0;
if (geometryLengths.length === 0) {
// Strangely, for points, 'lengths' array is empty, so we assume there is a single vertex in 'coords' array.
if (geometryCoords.length >= stride) {
if (this._transform) {
const transformedPoint = this._transform.multiplyPoint2d({ x: geometryCoords[0], y: geometryCoords[1] });
this.drawPoint(transformedPoint.x, transformedPoint.y);
}
else {
this.drawPoint(geometryCoords[0], geometryCoords[1]);
}
}
}
else {
// MULTI-POINTS: Needs testing
// I assume 'lengths' array will get populated and 'coords' array will look similar to line/polygons.
for (const vertexCount of geometryLengths) {
let lastPtX = 0, lastPtY = 0;
for (let vertexIdx = 0; vertexIdx < vertexCount; vertexIdx++) {
let pX = geometryCoords[coordsOffset + (vertexIdx * stride)];
let pY = geometryCoords[coordsOffset + (vertexIdx * stride) + 1];
if (relativeCoords) {
pX = lastPtX = lastPtX + pX;
pY = lastPtY = lastPtY + pY;
}
if (this._transform) {
const transformedPoint = this._transform.multiplyPoint2d({ x: pX, y: pY });
pX = transformedPoint.x;
pY = transformedPoint.y;
}
this.drawPoint(pX, pY);
}
coordsOffset += stride * vertexCount;
}
}
await this.finishPoints();
}
}
exports.FeatureGeometryBaseRenderer = FeatureGeometryBaseRenderer;
//# sourceMappingURL=FeatureGeometryRenderer.js.map