| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529 | import arrayRemoveDuplicates from "./arrayRemoveDuplicates.js";import BoundingRectangle from "./BoundingRectangle.js";import BoundingSphere from "./BoundingSphere.js";import Cartesian2 from "./Cartesian2.js";import Cartesian3 from "./Cartesian3.js";import Check from "./Check.js";import ComponentDatatype from "./ComponentDatatype.js";import CoplanarPolygonGeometryLibrary from "./CoplanarPolygonGeometryLibrary.js";import defaultValue from "./defaultValue.js";import defined from "./defined.js";import Ellipsoid from "./Ellipsoid.js";import Geometry from "./Geometry.js";import GeometryAttribute from "./GeometryAttribute.js";import GeometryAttributes from "./GeometryAttributes.js";import GeometryInstance from "./GeometryInstance.js";import GeometryPipeline from "./GeometryPipeline.js";import IndexDatatype from "./IndexDatatype.js";import CesiumMath from "./Math.js";import Matrix3 from "./Matrix3.js";import PolygonGeometryLibrary from "./PolygonGeometryLibrary.js";import PolygonPipeline from "./PolygonPipeline.js";import PrimitiveType from "./PrimitiveType.js";import Quaternion from "./Quaternion.js";import VertexFormat from "./VertexFormat.js";const scratchPosition = new Cartesian3();const scratchBR = new BoundingRectangle();const stScratch = new Cartesian2();const textureCoordinatesOrigin = new Cartesian2();const scratchNormal = new Cartesian3();const scratchTangent = new Cartesian3();const scratchBitangent = new Cartesian3();const centerScratch = new Cartesian3();const axis1Scratch = new Cartesian3();const axis2Scratch = new Cartesian3();const quaternionScratch = new Quaternion();const textureMatrixScratch = new Matrix3();const tangentRotationScratch = new Matrix3();const surfaceNormalScratch = new Cartesian3();function createGeometryFromPolygon(  polygon,  vertexFormat,  boundingRectangle,  stRotation,  projectPointTo2D,  normal,  tangent,  bitangent) {  const positions = polygon.positions;  let indices = PolygonPipeline.triangulate(polygon.positions2D, polygon.holes);  /* If polygon is completely unrenderable, just use the first three vertices */  if (indices.length < 3) {    indices = [0, 1, 2];  }  const newIndices = IndexDatatype.createTypedArray(    positions.length,    indices.length  );  newIndices.set(indices);  let textureMatrix = textureMatrixScratch;  if (stRotation !== 0.0) {    let rotation = Quaternion.fromAxisAngle(      normal,      stRotation,      quaternionScratch    );    textureMatrix = Matrix3.fromQuaternion(rotation, textureMatrix);    if (vertexFormat.tangent || vertexFormat.bitangent) {      rotation = Quaternion.fromAxisAngle(        normal,        -stRotation,        quaternionScratch      );      const tangentRotation = Matrix3.fromQuaternion(        rotation,        tangentRotationScratch      );      tangent = Cartesian3.normalize(        Matrix3.multiplyByVector(tangentRotation, tangent, tangent),        tangent      );      if (vertexFormat.bitangent) {        bitangent = Cartesian3.normalize(          Cartesian3.cross(normal, tangent, bitangent),          bitangent        );      }    }  } else {    textureMatrix = Matrix3.clone(Matrix3.IDENTITY, textureMatrix);  }  const stOrigin = textureCoordinatesOrigin;  if (vertexFormat.st) {    stOrigin.x = boundingRectangle.x;    stOrigin.y = boundingRectangle.y;  }  const length = positions.length;  const size = length * 3;  const flatPositions = new Float64Array(size);  const normals = vertexFormat.normal ? new Float32Array(size) : undefined;  const tangents = vertexFormat.tangent ? new Float32Array(size) : undefined;  const bitangents = vertexFormat.bitangent    ? new Float32Array(size)    : undefined;  const textureCoordinates = vertexFormat.st    ? new Float32Array(length * 2)    : undefined;  let positionIndex = 0;  let normalIndex = 0;  let bitangentIndex = 0;  let tangentIndex = 0;  let stIndex = 0;  for (let i = 0; i < length; i++) {    const position = positions[i];    flatPositions[positionIndex++] = position.x;    flatPositions[positionIndex++] = position.y;    flatPositions[positionIndex++] = position.z;    if (vertexFormat.st) {      const p = Matrix3.multiplyByVector(        textureMatrix,        position,        scratchPosition      );      const st = projectPointTo2D(p, stScratch);      Cartesian2.subtract(st, stOrigin, st);      const stx = CesiumMath.clamp(st.x / boundingRectangle.width, 0, 1);      const sty = CesiumMath.clamp(st.y / boundingRectangle.height, 0, 1);      textureCoordinates[stIndex++] = stx;      textureCoordinates[stIndex++] = sty;    }    if (vertexFormat.normal) {      normals[normalIndex++] = normal.x;      normals[normalIndex++] = normal.y;      normals[normalIndex++] = normal.z;    }    if (vertexFormat.tangent) {      tangents[tangentIndex++] = tangent.x;      tangents[tangentIndex++] = tangent.y;      tangents[tangentIndex++] = tangent.z;    }    if (vertexFormat.bitangent) {      bitangents[bitangentIndex++] = bitangent.x;      bitangents[bitangentIndex++] = bitangent.y;      bitangents[bitangentIndex++] = bitangent.z;    }  }  const attributes = new GeometryAttributes();  if (vertexFormat.position) {    attributes.position = new GeometryAttribute({      componentDatatype: ComponentDatatype.DOUBLE,      componentsPerAttribute: 3,      values: flatPositions,    });  }  if (vertexFormat.normal) {    attributes.normal = new GeometryAttribute({      componentDatatype: ComponentDatatype.FLOAT,      componentsPerAttribute: 3,      values: normals,    });  }  if (vertexFormat.tangent) {    attributes.tangent = new GeometryAttribute({      componentDatatype: ComponentDatatype.FLOAT,      componentsPerAttribute: 3,      values: tangents,    });  }  if (vertexFormat.bitangent) {    attributes.bitangent = new GeometryAttribute({      componentDatatype: ComponentDatatype.FLOAT,      componentsPerAttribute: 3,      values: bitangents,    });  }  if (vertexFormat.st) {    attributes.st = new GeometryAttribute({      componentDatatype: ComponentDatatype.FLOAT,      componentsPerAttribute: 2,      values: textureCoordinates,    });  }  return new Geometry({    attributes: attributes,    indices: newIndices,    primitiveType: PrimitiveType.TRIANGLES,  });}/** * A description of a polygon composed of arbitrary coplanar positions. * * @alias CoplanarPolygonGeometry * @constructor * * @param {Object} options Object with the following properties: * @param {PolygonHierarchy} options.polygonHierarchy A polygon hierarchy that can include holes. * @param {Number} [options.stRotation=0.0] The rotation of the texture coordinates, in radians. A positive rotation is counter-clockwise. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference. * * @example * const polygonGeometry = new Cesium.CoplanarPolygonGeometry({ *  polygonHierarchy: new Cesium.PolygonHierarchy( *     Cesium.Cartesian3.fromDegreesArrayHeights([ *      -90.0, 30.0, 0.0, *      -90.0, 30.0, 300000.0, *      -80.0, 30.0, 300000.0, *      -80.0, 30.0, 0.0 *   ])) * }); * */function CoplanarPolygonGeometry(options) {  options = defaultValue(options, defaultValue.EMPTY_OBJECT);  const polygonHierarchy = options.polygonHierarchy;  //>>includeStart('debug', pragmas.debug);  Check.defined("options.polygonHierarchy", polygonHierarchy);  //>>includeEnd('debug');  const vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT);  this._vertexFormat = VertexFormat.clone(vertexFormat);  this._polygonHierarchy = polygonHierarchy;  this._stRotation = defaultValue(options.stRotation, 0.0);  this._ellipsoid = Ellipsoid.clone(    defaultValue(options.ellipsoid, Ellipsoid.WGS84)  );  this._workerName = "createCoplanarPolygonGeometry";  /**   * The number of elements used to pack the object into an array.   * @type {Number}   */  this.packedLength =    PolygonGeometryLibrary.computeHierarchyPackedLength(polygonHierarchy) +    VertexFormat.packedLength +    Ellipsoid.packedLength +    2;}/** * A description of a coplanar polygon from an array of positions. * * @param {Object} options Object with the following properties: * @param {Cartesian3[]} options.positions An array of positions that defined the corner points of the polygon. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. * @param {Number} [options.stRotation=0.0] The rotation of the texture coordinates, in radians. A positive rotation is counter-clockwise. * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference. * @returns {CoplanarPolygonGeometry} * * @example * // create a polygon from points * const polygon = Cesium.CoplanarPolygonGeometry.fromPositions({ *   positions : Cesium.Cartesian3.fromDegreesArray([ *     -72.0, 40.0, *     -70.0, 35.0, *     -75.0, 30.0, *     -70.0, 30.0, *     -68.0, 40.0 *   ]) * }); * const geometry = Cesium.PolygonGeometry.createGeometry(polygon); * * @see PolygonGeometry#createGeometry */CoplanarPolygonGeometry.fromPositions = function (options) {  options = defaultValue(options, defaultValue.EMPTY_OBJECT);  //>>includeStart('debug', pragmas.debug);  Check.defined("options.positions", options.positions);  //>>includeEnd('debug');  const newOptions = {    polygonHierarchy: {      positions: options.positions,    },    vertexFormat: options.vertexFormat,    stRotation: options.stRotation,    ellipsoid: options.ellipsoid,  };  return new CoplanarPolygonGeometry(newOptions);};/** * Stores the provided instance into the provided array. * * @param {CoplanarPolygonGeometry} value The value to pack. * @param {Number[]} array The array to pack into. * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements. * * @returns {Number[]} The array that was packed into */CoplanarPolygonGeometry.pack = function (value, array, startingIndex) {  //>>includeStart('debug', pragmas.debug);  Check.typeOf.object("value", value);  Check.defined("array", array);  //>>includeEnd('debug');  startingIndex = defaultValue(startingIndex, 0);  startingIndex = PolygonGeometryLibrary.packPolygonHierarchy(    value._polygonHierarchy,    array,    startingIndex  );  Ellipsoid.pack(value._ellipsoid, array, startingIndex);  startingIndex += Ellipsoid.packedLength;  VertexFormat.pack(value._vertexFormat, array, startingIndex);  startingIndex += VertexFormat.packedLength;  array[startingIndex++] = value._stRotation;  array[startingIndex] = value.packedLength;  return array;};const scratchEllipsoid = Ellipsoid.clone(Ellipsoid.UNIT_SPHERE);const scratchVertexFormat = new VertexFormat();const scratchOptions = {  polygonHierarchy: {},};/** * Retrieves an instance from a packed array. * * @param {Number[]} array The packed array. * @param {Number} [startingIndex=0] The starting index of the element to be unpacked. * @param {CoplanarPolygonGeometry} [result] The object into which to store the result. * @returns {CoplanarPolygonGeometry} The modified result parameter or a new CoplanarPolygonGeometry instance if one was not provided. */CoplanarPolygonGeometry.unpack = function (array, startingIndex, result) {  //>>includeStart('debug', pragmas.debug);  Check.defined("array", array);  //>>includeEnd('debug');  startingIndex = defaultValue(startingIndex, 0);  const polygonHierarchy = PolygonGeometryLibrary.unpackPolygonHierarchy(    array,    startingIndex  );  startingIndex = polygonHierarchy.startingIndex;  delete polygonHierarchy.startingIndex;  const ellipsoid = Ellipsoid.unpack(array, startingIndex, scratchEllipsoid);  startingIndex += Ellipsoid.packedLength;  const vertexFormat = VertexFormat.unpack(    array,    startingIndex,    scratchVertexFormat  );  startingIndex += VertexFormat.packedLength;  const stRotation = array[startingIndex++];  const packedLength = array[startingIndex];  if (!defined(result)) {    result = new CoplanarPolygonGeometry(scratchOptions);  }  result._polygonHierarchy = polygonHierarchy;  result._ellipsoid = Ellipsoid.clone(ellipsoid, result._ellipsoid);  result._vertexFormat = VertexFormat.clone(vertexFormat, result._vertexFormat);  result._stRotation = stRotation;  result.packedLength = packedLength;  return result;};/** * Computes the geometric representation of an arbitrary coplanar polygon, including its vertices, indices, and a bounding sphere. * * @param {CoplanarPolygonGeometry} polygonGeometry A description of the polygon. * @returns {Geometry|undefined} The computed vertices and indices. */CoplanarPolygonGeometry.createGeometry = function (polygonGeometry) {  const vertexFormat = polygonGeometry._vertexFormat;  const polygonHierarchy = polygonGeometry._polygonHierarchy;  const stRotation = polygonGeometry._stRotation;  let outerPositions = polygonHierarchy.positions;  outerPositions = arrayRemoveDuplicates(    outerPositions,    Cartesian3.equalsEpsilon,    true  );  if (outerPositions.length < 3) {    return;  }  let normal = scratchNormal;  let tangent = scratchTangent;  let bitangent = scratchBitangent;  let axis1 = axis1Scratch;  const axis2 = axis2Scratch;  const validGeometry = CoplanarPolygonGeometryLibrary.computeProjectTo2DArguments(    outerPositions,    centerScratch,    axis1,    axis2  );  if (!validGeometry) {    return undefined;  }  normal = Cartesian3.cross(axis1, axis2, normal);  normal = Cartesian3.normalize(normal, normal);  if (    !Cartesian3.equalsEpsilon(      centerScratch,      Cartesian3.ZERO,      CesiumMath.EPSILON6    )  ) {    const surfaceNormal = polygonGeometry._ellipsoid.geodeticSurfaceNormal(      centerScratch,      surfaceNormalScratch    );    if (Cartesian3.dot(normal, surfaceNormal) < 0) {      normal = Cartesian3.negate(normal, normal);      axis1 = Cartesian3.negate(axis1, axis1);    }  }  const projectPoints = CoplanarPolygonGeometryLibrary.createProjectPointsTo2DFunction(    centerScratch,    axis1,    axis2  );  const projectPoint = CoplanarPolygonGeometryLibrary.createProjectPointTo2DFunction(    centerScratch,    axis1,    axis2  );  if (vertexFormat.tangent) {    tangent = Cartesian3.clone(axis1, tangent);  }  if (vertexFormat.bitangent) {    bitangent = Cartesian3.clone(axis2, bitangent);  }  const results = PolygonGeometryLibrary.polygonsFromHierarchy(    polygonHierarchy,    projectPoints,    false  );  const hierarchy = results.hierarchy;  const polygons = results.polygons;  if (hierarchy.length === 0) {    return;  }  outerPositions = hierarchy[0].outerRing;  const boundingSphere = BoundingSphere.fromPoints(outerPositions);  const boundingRectangle = PolygonGeometryLibrary.computeBoundingRectangle(    normal,    projectPoint,    outerPositions,    stRotation,    scratchBR  );  const geometries = [];  for (let i = 0; i < polygons.length; i++) {    const geometryInstance = new GeometryInstance({      geometry: createGeometryFromPolygon(        polygons[i],        vertexFormat,        boundingRectangle,        stRotation,        projectPoint,        normal,        tangent,        bitangent      ),    });    geometries.push(geometryInstance);  }  const geometry = GeometryPipeline.combineInstances(geometries)[0];  geometry.attributes.position.values = new Float64Array(    geometry.attributes.position.values  );  geometry.indices = IndexDatatype.createTypedArray(    geometry.attributes.position.values.length / 3,    geometry.indices  );  const attributes = geometry.attributes;  if (!vertexFormat.position) {    delete attributes.position;  }  return new Geometry({    attributes: attributes,    indices: geometry.indices,    primitiveType: geometry.primitiveType,    boundingSphere: boundingSphere,  });};export default CoplanarPolygonGeometry;
 |