123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703 |
- import Cartesian3 from "../Core/Cartesian3.js";
- import defined from "../Core/defined.js";
- import Cartographic from "../Core/Cartographic.js";
- import Ellipsoid from "../Core/Ellipsoid.js";
- import Intersect from "../Core/Intersect.js";
- import Matrix3 from "../Core/Matrix3.js";
- import Plane from "../Core/Plane.js";
- import CoplanarPolygonOutlineGeometry from "../Core/CoplanarPolygonOutlineGeometry.js";
- import BoundingSphere from "../Core/BoundingSphere.js";
- import Check from "../Core/Check.js";
- import ColorGeometryInstanceAttribute from "../Core/ColorGeometryInstanceAttribute.js";
- import defaultValue from "../Core/defaultValue.js";
- import GeometryInstance from "../Core/GeometryInstance.js";
- import Matrix4 from "../Core/Matrix4.js";
- import PerInstanceColorAppearance from "./PerInstanceColorAppearance.js";
- import Primitive from "./Primitive.js";
- import S2Cell from "../Core/S2Cell.js";
- let centerCartographicScratch = new Cartographic();
- /**
- * A tile bounding volume specified as an S2 cell token with minimum and maximum heights.
- * The bounding volume is a k DOP. A k-DOP is the Boolean intersection of extents along k directions.
- *
- * @alias TileBoundingS2Cell
- * @constructor
- *
- * @param {object} options Object with the following properties:
- * @param {string} options.token The token of the S2 cell.
- * @param {number} [options.minimumHeight=0.0] The minimum height of the bounding volume.
- * @param {number} [options.maximumHeight=0.0] The maximum height of the bounding volume.
- * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid.
- * @param {boolean} [options.computeBoundingVolumes=true] True to compute the {@link TileBoundingS2Cell#boundingVolume} and
- * {@link TileBoundingS2Cell#boundingSphere}. If false, these properties will be undefined.
- *
- * @private
- */
- function TileBoundingS2Cell(options) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object("options", options);
- Check.typeOf.string("options.token", options.token);
- //>>includeEnd('debug');
- const s2Cell = S2Cell.fromToken(options.token);
- const minimumHeight = defaultValue(options.minimumHeight, 0.0);
- const maximumHeight = defaultValue(options.maximumHeight, 0.0);
- const ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);
- this.s2Cell = s2Cell;
- this.minimumHeight = minimumHeight;
- this.maximumHeight = maximumHeight;
- this.ellipsoid = ellipsoid;
- const boundingPlanes = computeBoundingPlanes(
- s2Cell,
- minimumHeight,
- maximumHeight,
- ellipsoid
- );
- this._boundingPlanes = boundingPlanes;
- // Pre-compute vertices to speed up the plane intersection test.
- const vertices = computeVertices(boundingPlanes);
- this._vertices = vertices;
- // Pre-compute edge normals to speed up the point-polygon distance check in distanceToCamera.
- this._edgeNormals = new Array(6);
- this._edgeNormals[0] = computeEdgeNormals(
- boundingPlanes[0],
- vertices.slice(0, 4)
- );
- let i;
- // Based on the way the edge normals are computed, the edge normals all point away from the "face"
- // of the polyhedron they surround, except the plane for the top plane. Therefore, we negate the normals
- // for the top plane.
- for (i = 0; i < 4; i++) {
- this._edgeNormals[0][i] = Cartesian3.negate(
- this._edgeNormals[0][i],
- this._edgeNormals[0][i]
- );
- }
- this._edgeNormals[1] = computeEdgeNormals(
- boundingPlanes[1],
- vertices.slice(4, 8)
- );
- for (i = 0; i < 4; i++) {
- // For each plane, iterate through the vertices in CCW order.
- this._edgeNormals[2 + i] = computeEdgeNormals(boundingPlanes[2 + i], [
- vertices[i % 4],
- vertices[(i + 1) % 4],
- vertices[4 + ((i + 1) % 4)],
- vertices[4 + i],
- ]);
- }
- this._planeVertices = [
- this._vertices.slice(0, 4),
- this._vertices.slice(4, 8),
- ];
- for (i = 0; i < 4; i++) {
- this._planeVertices.push([
- this._vertices[i % 4],
- this._vertices[(i + 1) % 4],
- this._vertices[4 + ((i + 1) % 4)],
- this._vertices[4 + i],
- ]);
- }
- const center = s2Cell.getCenter();
- centerCartographicScratch = ellipsoid.cartesianToCartographic(
- center,
- centerCartographicScratch
- );
- centerCartographicScratch.height = (maximumHeight + minimumHeight) / 2;
- this.center = ellipsoid.cartographicToCartesian(
- centerCartographicScratch,
- center
- );
- this._boundingSphere = BoundingSphere.fromPoints(vertices);
- }
- const centerGeodeticNormalScratch = new Cartesian3();
- const topCartographicScratch = new Cartographic();
- const topScratch = new Cartesian3();
- const vertexCartographicScratch = new Cartographic();
- const vertexScratch = new Cartesian3();
- const vertexGeodeticNormalScratch = new Cartesian3();
- const sideNormalScratch = new Cartesian3();
- const sideScratch = new Cartesian3();
- /**
- * Computes bounding planes of the kDOP.
- * @private
- */
- function computeBoundingPlanes(
- s2Cell,
- minimumHeight,
- maximumHeight,
- ellipsoid
- ) {
- const planes = new Array(6);
- const centerPoint = s2Cell.getCenter();
- // Compute top plane.
- // - Get geodetic surface normal at the center of the S2 cell.
- // - Get center point at maximum height of bounding volume.
- // - Create top plane from surface normal and top point.
- const centerSurfaceNormal = ellipsoid.geodeticSurfaceNormal(
- centerPoint,
- centerGeodeticNormalScratch
- );
- const topCartographic = ellipsoid.cartesianToCartographic(
- centerPoint,
- topCartographicScratch
- );
- topCartographic.height = maximumHeight;
- const top = ellipsoid.cartographicToCartesian(topCartographic, topScratch);
- const topPlane = Plane.fromPointNormal(top, centerSurfaceNormal);
- planes[0] = topPlane;
- // Compute bottom plane.
- // - Iterate through bottom vertices
- // - Get distance from vertex to top plane
- // - Find longest distance from vertex to top plane
- // - Translate top plane by the distance
- let maxDistance = 0;
- let i;
- const vertices = [];
- let vertex, vertexCartographic;
- for (i = 0; i < 4; i++) {
- vertex = s2Cell.getVertex(i);
- vertices[i] = vertex;
- vertexCartographic = ellipsoid.cartesianToCartographic(
- vertex,
- vertexCartographicScratch
- );
- vertexCartographic.height = minimumHeight;
- const distance = Plane.getPointDistance(
- topPlane,
- ellipsoid.cartographicToCartesian(vertexCartographic, vertexScratch)
- );
- if (distance < maxDistance) {
- maxDistance = distance;
- }
- }
- const bottomPlane = Plane.clone(topPlane);
- // Negate the normal of the bottom plane since we want all normals to point "outwards".
- bottomPlane.normal = Cartesian3.negate(
- bottomPlane.normal,
- bottomPlane.normal
- );
- bottomPlane.distance = bottomPlane.distance * -1 + maxDistance;
- planes[1] = bottomPlane;
- // Compute side planes.
- // - Iterate through vertices (in CCW order, by default)
- // - Get a vertex and another vertex adjacent to it.
- // - Compute geodetic surface normal at one vertex.
- // - Compute vector between vertices.
- // - Compute normal of side plane. (cross product of top dir and side dir)
- for (i = 0; i < 4; i++) {
- vertex = vertices[i];
- const adjacentVertex = vertices[(i + 1) % 4];
- const geodeticNormal = ellipsoid.geodeticSurfaceNormal(
- vertex,
- vertexGeodeticNormalScratch
- );
- const side = Cartesian3.subtract(adjacentVertex, vertex, sideScratch);
- let sideNormal = Cartesian3.cross(side, geodeticNormal, sideNormalScratch);
- sideNormal = Cartesian3.normalize(sideNormal, sideNormal);
- planes[2 + i] = Plane.fromPointNormal(vertex, sideNormal);
- }
- return planes;
- }
- let n0Scratch = new Cartesian3();
- let n1Scratch = new Cartesian3();
- let n2Scratch = new Cartesian3();
- let x0Scratch = new Cartesian3();
- let x1Scratch = new Cartesian3();
- let x2Scratch = new Cartesian3();
- const t0Scratch = new Cartesian3();
- const t1Scratch = new Cartesian3();
- const t2Scratch = new Cartesian3();
- let f0Scratch = new Cartesian3();
- let f1Scratch = new Cartesian3();
- let f2Scratch = new Cartesian3();
- let sScratch = new Cartesian3();
- const matrixScratch = new Matrix3();
- /**
- * Computes intersection of 3 planes.
- * @private
- */
- function computeIntersection(p0, p1, p2) {
- n0Scratch = p0.normal;
- n1Scratch = p1.normal;
- n2Scratch = p2.normal;
- x0Scratch = Cartesian3.multiplyByScalar(p0.normal, -p0.distance, x0Scratch);
- x1Scratch = Cartesian3.multiplyByScalar(p1.normal, -p1.distance, x1Scratch);
- x2Scratch = Cartesian3.multiplyByScalar(p2.normal, -p2.distance, x2Scratch);
- f0Scratch = Cartesian3.multiplyByScalar(
- Cartesian3.cross(n1Scratch, n2Scratch, t0Scratch),
- Cartesian3.dot(x0Scratch, n0Scratch),
- f0Scratch
- );
- f1Scratch = Cartesian3.multiplyByScalar(
- Cartesian3.cross(n2Scratch, n0Scratch, t1Scratch),
- Cartesian3.dot(x1Scratch, n1Scratch),
- f1Scratch
- );
- f2Scratch = Cartesian3.multiplyByScalar(
- Cartesian3.cross(n0Scratch, n1Scratch, t2Scratch),
- Cartesian3.dot(x2Scratch, n2Scratch),
- f2Scratch
- );
- matrixScratch[0] = n0Scratch.x;
- matrixScratch[1] = n1Scratch.x;
- matrixScratch[2] = n2Scratch.x;
- matrixScratch[3] = n0Scratch.y;
- matrixScratch[4] = n1Scratch.y;
- matrixScratch[5] = n2Scratch.y;
- matrixScratch[6] = n0Scratch.z;
- matrixScratch[7] = n1Scratch.z;
- matrixScratch[8] = n2Scratch.z;
- const determinant = Matrix3.determinant(matrixScratch);
- sScratch = Cartesian3.add(f0Scratch, f1Scratch, sScratch);
- sScratch = Cartesian3.add(sScratch, f2Scratch, sScratch);
- return new Cartesian3(
- sScratch.x / determinant,
- sScratch.y / determinant,
- sScratch.z / determinant
- );
- }
- /**
- * Compute the vertices of the kDOP.
- * @private
- */
- function computeVertices(boundingPlanes) {
- const vertices = new Array(8);
- for (let i = 0; i < 4; i++) {
- // Vertices on the top plane.
- vertices[i] = computeIntersection(
- boundingPlanes[0],
- boundingPlanes[2 + ((i + 3) % 4)],
- boundingPlanes[2 + (i % 4)]
- );
- // Vertices on the bottom plane.
- vertices[i + 4] = computeIntersection(
- boundingPlanes[1],
- boundingPlanes[2 + ((i + 3) % 4)],
- boundingPlanes[2 + (i % 4)]
- );
- }
- return vertices;
- }
- let edgeScratch = new Cartesian3();
- let edgeNormalScratch = new Cartesian3();
- /**
- * Compute edge normals on a plane.
- * @private
- */
- function computeEdgeNormals(plane, vertices) {
- const edgeNormals = [];
- for (let i = 0; i < 4; i++) {
- edgeScratch = Cartesian3.subtract(
- vertices[(i + 1) % 4],
- vertices[i],
- edgeScratch
- );
- edgeNormalScratch = Cartesian3.cross(
- plane.normal,
- edgeScratch,
- edgeNormalScratch
- );
- edgeNormalScratch = Cartesian3.normalize(
- edgeNormalScratch,
- edgeNormalScratch
- );
- edgeNormals[i] = Cartesian3.clone(edgeNormalScratch);
- }
- return edgeNormals;
- }
- Object.defineProperties(TileBoundingS2Cell.prototype, {
- /**
- * The underlying bounding volume.
- *
- * @memberof TileOrientedBoundingBox.prototype
- *
- * @type {object}
- * @readonly
- */
- boundingVolume: {
- get: function () {
- return this;
- },
- },
- /**
- * The underlying bounding sphere.
- *
- * @memberof TileOrientedBoundingBox.prototype
- *
- * @type {BoundingSphere}
- * @readonly
- */
- boundingSphere: {
- get: function () {
- return this._boundingSphere;
- },
- },
- });
- const facePointScratch = new Cartesian3();
- /**
- * The distance to point check for this kDOP involves checking the signed distance of the point to each bounding
- * plane. A plane qualifies for a distance check if the point being tested against is in the half-space in the direction
- * of the normal i.e. if the signed distance of the point from the plane is greater than 0.
- *
- * There are 4 possible cases for a point if it is outside the polyhedron:
- *
- * \ X / X \ / \ / \ /
- * ---\---------/--- ---\---------/--- ---X---------/--- ---\---------/---
- * \ / \ / \ / \ /
- * ---\-----/--- ---\-----/--- ---\-----/--- ---\-----/---
- * \ / \ / \ / \ /
- * \ /
- * \
- * / \
- * / X \
- *
- * I II III IV
- *
- * Case I: There is only one plane selected.
- * In this case, we project the point onto the plane and do a point polygon distance check to find the closest point on the polygon.
- * The point may lie inside the "face" of the polygon or outside. If it is outside, we need to determine which edges to test against.
- *
- * Case II: There are two planes selected.
- * In this case, the point will lie somewhere on the line created at the intersection of the selected planes or one of the planes.
- *
- * Case III: There are three planes selected.
- * In this case, the point will lie on the vertex, at the intersection of the selected planes.
- *
- * Case IV: There are more than three planes selected.
- * Since we are on an ellipsoid, this will only happen in the bottom plane, which is what we will use for the distance test.
- */
- TileBoundingS2Cell.prototype.distanceToCamera = function (frameState) {
- //>>includeStart('debug', pragmas.debug);
- Check.defined("frameState", frameState);
- //>>includeEnd('debug');
- const point = frameState.camera.positionWC;
- const selectedPlaneIndices = [];
- const vertices = [];
- let edgeNormals;
- if (Plane.getPointDistance(this._boundingPlanes[0], point) > 0) {
- selectedPlaneIndices.push(0);
- vertices.push(this._planeVertices[0]);
- edgeNormals = this._edgeNormals[0];
- } else if (Plane.getPointDistance(this._boundingPlanes[1], point) > 0) {
- selectedPlaneIndices.push(1);
- vertices.push(this._planeVertices[1]);
- edgeNormals = this._edgeNormals[1];
- }
- let i;
- let sidePlaneIndex;
- for (i = 0; i < 4; i++) {
- sidePlaneIndex = 2 + i;
- if (
- Plane.getPointDistance(this._boundingPlanes[sidePlaneIndex], point) > 0
- ) {
- selectedPlaneIndices.push(sidePlaneIndex);
- // Store vertices in CCW order.
- vertices.push(this._planeVertices[sidePlaneIndex]);
- edgeNormals = this._edgeNormals[sidePlaneIndex];
- }
- }
- // Check if inside all planes.
- if (selectedPlaneIndices.length === 0) {
- return 0.0;
- }
- // We use the skip variable when the side plane indices are non-consecutive.
- let facePoint;
- let selectedPlane;
- if (selectedPlaneIndices.length === 1) {
- // Handles Case I
- selectedPlane = this._boundingPlanes[selectedPlaneIndices[0]];
- facePoint = closestPointPolygon(
- Plane.projectPointOntoPlane(selectedPlane, point, facePointScratch),
- vertices[0],
- selectedPlane,
- edgeNormals
- );
- return Cartesian3.distance(facePoint, point);
- } else if (selectedPlaneIndices.length === 2) {
- // Handles Case II
- // Since we are on the ellipsoid, the dihedral angle between a top plane and a side plane
- // will always be acute, so we can do a faster check there.
- if (selectedPlaneIndices[0] === 0) {
- const edge = [
- this._vertices[
- 4 * selectedPlaneIndices[0] + (selectedPlaneIndices[1] - 2)
- ],
- this._vertices[
- 4 * selectedPlaneIndices[0] + ((selectedPlaneIndices[1] - 2 + 1) % 4)
- ],
- ];
- facePoint = closestPointLineSegment(point, edge[0], edge[1]);
- return Cartesian3.distance(facePoint, point);
- }
- let minimumDistance = Number.MAX_VALUE;
- let distance;
- for (i = 0; i < 2; i++) {
- selectedPlane = this._boundingPlanes[selectedPlaneIndices[i]];
- facePoint = closestPointPolygon(
- Plane.projectPointOntoPlane(selectedPlane, point, facePointScratch),
- vertices[i],
- selectedPlane,
- this._edgeNormals[selectedPlaneIndices[i]]
- );
- distance = Cartesian3.distanceSquared(facePoint, point);
- if (distance < minimumDistance) {
- minimumDistance = distance;
- }
- }
- return Math.sqrt(minimumDistance);
- } else if (selectedPlaneIndices.length > 3) {
- // Handles Case IV
- facePoint = closestPointPolygon(
- Plane.projectPointOntoPlane(
- this._boundingPlanes[1],
- point,
- facePointScratch
- ),
- this._planeVertices[1],
- this._boundingPlanes[1],
- this._edgeNormals[1]
- );
- return Cartesian3.distance(facePoint, point);
- }
- // Handles Case III
- const skip =
- selectedPlaneIndices[1] === 2 && selectedPlaneIndices[2] === 5 ? 0 : 1;
- // Vertex is on top plane.
- if (selectedPlaneIndices[0] === 0) {
- return Cartesian3.distance(
- point,
- this._vertices[(selectedPlaneIndices[1] - 2 + skip) % 4]
- );
- }
- // Vertex is on bottom plane.
- return Cartesian3.distance(
- point,
- this._vertices[4 + ((selectedPlaneIndices[1] - 2 + skip) % 4)]
- );
- };
- const dScratch = new Cartesian3();
- const pL0Scratch = new Cartesian3();
- /**
- * Finds point on a line segment closest to a given point.
- * @private
- */
- function closestPointLineSegment(p, l0, l1) {
- const d = Cartesian3.subtract(l1, l0, dScratch);
- const pL0 = Cartesian3.subtract(p, l0, pL0Scratch);
- let t = Cartesian3.dot(d, pL0);
- if (t <= 0) {
- return l0;
- }
- const dMag = Cartesian3.dot(d, d);
- if (t >= dMag) {
- return l1;
- }
- t = t / dMag;
- return new Cartesian3(
- (1 - t) * l0.x + t * l1.x,
- (1 - t) * l0.y + t * l1.y,
- (1 - t) * l0.z + t * l1.z
- );
- }
- const edgePlaneScratch = new Plane(Cartesian3.UNIT_X, 0.0);
- /**
- * Finds closes point on the polygon, created by the given vertices, from
- * a point. The test point and the polygon are all on the same plane.
- * @private
- */
- function closestPointPolygon(p, vertices, plane, edgeNormals) {
- let minDistance = Number.MAX_VALUE;
- let distance;
- let closestPoint;
- let closestPointOnEdge;
- for (let i = 0; i < vertices.length; i++) {
- const edgePlane = Plane.fromPointNormal(
- vertices[i],
- edgeNormals[i],
- edgePlaneScratch
- );
- const edgePlaneDistance = Plane.getPointDistance(edgePlane, p);
- // Skip checking against the edge if the point is not in the half-space that the
- // edgePlane's normal points towards i.e. if the edgePlane is facing away from the point.
- if (edgePlaneDistance < 0) {
- continue;
- }
- closestPointOnEdge = closestPointLineSegment(
- p,
- vertices[i],
- vertices[(i + 1) % 4]
- );
- distance = Cartesian3.distance(p, closestPointOnEdge);
- if (distance < minDistance) {
- minDistance = distance;
- closestPoint = closestPointOnEdge;
- }
- }
- if (!defined(closestPoint)) {
- return p;
- }
- return closestPoint;
- }
- /**
- * Determines which side of a plane this volume is located.
- *
- * @param {Plane} plane The plane to test against.
- * @returns {Intersect} {@link Intersect.INSIDE} if the entire volume is on the side of the plane
- * the normal is pointing, {@link Intersect.OUTSIDE} if the entire volume is
- * on the opposite side, and {@link Intersect.INTERSECTING} if the volume
- * intersects the plane.
- */
- TileBoundingS2Cell.prototype.intersectPlane = function (plane) {
- //>>includeStart('debug', pragmas.debug);
- Check.defined("plane", plane);
- //>>includeEnd('debug');
- let plusCount = 0;
- let negCount = 0;
- for (let i = 0; i < this._vertices.length; i++) {
- const distanceToPlane =
- Cartesian3.dot(plane.normal, this._vertices[i]) + plane.distance;
- if (distanceToPlane < 0) {
- negCount++;
- } else {
- plusCount++;
- }
- }
- if (plusCount === this._vertices.length) {
- return Intersect.INSIDE;
- } else if (negCount === this._vertices.length) {
- return Intersect.OUTSIDE;
- }
- return Intersect.INTERSECTING;
- };
- /**
- * Creates a debug primitive that shows the outline of the tile bounding
- * volume.
- *
- * @param {Color} color The desired color of the primitive's mesh
- * @return {Primitive}
- */
- TileBoundingS2Cell.prototype.createDebugVolume = function (color) {
- //>>includeStart('debug', pragmas.debug);
- Check.defined("color", color);
- //>>includeEnd('debug');
- const modelMatrix = new Matrix4.clone(Matrix4.IDENTITY);
- const topPlanePolygon = new CoplanarPolygonOutlineGeometry({
- polygonHierarchy: {
- positions: this._planeVertices[0],
- },
- });
- const topPlaneGeometry = CoplanarPolygonOutlineGeometry.createGeometry(
- topPlanePolygon
- );
- const topPlaneInstance = new GeometryInstance({
- geometry: topPlaneGeometry,
- id: "outline",
- modelMatrix: modelMatrix,
- attributes: {
- color: ColorGeometryInstanceAttribute.fromColor(color),
- },
- });
- const bottomPlanePolygon = new CoplanarPolygonOutlineGeometry({
- polygonHierarchy: {
- positions: this._planeVertices[1],
- },
- });
- const bottomPlaneGeometry = CoplanarPolygonOutlineGeometry.createGeometry(
- bottomPlanePolygon
- );
- const bottomPlaneInstance = new GeometryInstance({
- geometry: bottomPlaneGeometry,
- id: "outline",
- modelMatrix: modelMatrix,
- attributes: {
- color: ColorGeometryInstanceAttribute.fromColor(color),
- },
- });
- const sideInstances = [];
- for (let i = 0; i < 4; i++) {
- const sidePlanePolygon = new CoplanarPolygonOutlineGeometry({
- polygonHierarchy: {
- positions: this._planeVertices[2 + i],
- },
- });
- const sidePlaneGeometry = CoplanarPolygonOutlineGeometry.createGeometry(
- sidePlanePolygon
- );
- sideInstances[i] = new GeometryInstance({
- geometry: sidePlaneGeometry,
- id: "outline",
- modelMatrix: modelMatrix,
- attributes: {
- color: ColorGeometryInstanceAttribute.fromColor(color),
- },
- });
- }
- return new Primitive({
- geometryInstances: [
- sideInstances[0],
- sideInstances[1],
- sideInstances[2],
- sideInstances[3],
- bottomPlaneInstance,
- topPlaneInstance,
- ],
- appearance: new PerInstanceColorAppearance({
- translucent: false,
- flat: true,
- }),
- asynchronous: false,
- });
- };
- export default TileBoundingS2Cell;
|