| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427 | import arrayRemoveDuplicates from "../Core/arrayRemoveDuplicates.js";import BoundingSphere from "../Core/BoundingSphere.js";import Cartesian3 from "../Core/Cartesian3.js";import Color from "../Core/Color.js";import defaultValue from "../Core/defaultValue.js";import defined from "../Core/defined.js";import DeveloperError from "../Core/DeveloperError.js";import DistanceDisplayCondition from "../Core/DistanceDisplayCondition.js";import Matrix4 from "../Core/Matrix4.js";import PolylinePipeline from "../Core/PolylinePipeline.js";import Material from "./Material.js";/** * A renderable polyline. Create this by calling {@link PolylineCollection#add} * * @alias Polyline * @internalConstructor * @class * * @param {Object} options Object with the following properties: * @param {Boolean} [options.show=true] <code>true</code> if this polyline will be shown; otherwise, <code>false</code>. * @param {Number} [options.width=1.0] The width of the polyline in pixels. * @param {Boolean} [options.loop=false] Whether a line segment will be added between the last and first line positions to make this line a loop. * @param {Material} [options.material=Material.ColorType] The material. * @param {Cartesian3[]} [options.positions] The positions. * @param {Object} [options.id] The user-defined object to be returned when this polyline is picked. * @param {DistanceDisplayCondition} [options.distanceDisplayCondition] The condition specifying at what distance from the camera that this polyline will be displayed. * @param {PolylineCollection} polylineCollection The renderable polyline collection. * * @see PolylineCollection * */function Polyline(options, polylineCollection) {  options = defaultValue(options, defaultValue.EMPTY_OBJECT);  this._show = defaultValue(options.show, true);  this._width = defaultValue(options.width, 1.0);  this._loop = defaultValue(options.loop, false);  this._distanceDisplayCondition = options.distanceDisplayCondition;  this._material = options.material;  if (!defined(this._material)) {    this._material = Material.fromType(Material.ColorType, {      color: new Color(1.0, 1.0, 1.0, 1.0),    });  }  let positions = options.positions;  if (!defined(positions)) {    positions = [];  }  this._positions = positions;  this._actualPositions = arrayRemoveDuplicates(    positions,    Cartesian3.equalsEpsilon  );  if (this._loop && this._actualPositions.length > 2) {    if (this._actualPositions === this._positions) {      this._actualPositions = positions.slice();    }    this._actualPositions.push(Cartesian3.clone(this._actualPositions[0]));  }  this._length = this._actualPositions.length;  this._id = options.id;  let modelMatrix;  if (defined(polylineCollection)) {    modelMatrix = Matrix4.clone(polylineCollection.modelMatrix);  }  this._modelMatrix = modelMatrix;  this._segments = PolylinePipeline.wrapLongitude(    this._actualPositions,    modelMatrix  );  this._actualLength = undefined;  // eslint-disable-next-line no-use-before-define  this._propertiesChanged = new Uint32Array(NUMBER_OF_PROPERTIES);  this._polylineCollection = polylineCollection;  this._dirty = false;  this._pickId = undefined;  this._boundingVolume = BoundingSphere.fromPoints(this._actualPositions);  this._boundingVolumeWC = BoundingSphere.transform(    this._boundingVolume,    this._modelMatrix  );  this._boundingVolume2D = new BoundingSphere(); // modified in PolylineCollection}const POSITION_INDEX = (Polyline.POSITION_INDEX = 0);const SHOW_INDEX = (Polyline.SHOW_INDEX = 1);const WIDTH_INDEX = (Polyline.WIDTH_INDEX = 2);const MATERIAL_INDEX = (Polyline.MATERIAL_INDEX = 3);const POSITION_SIZE_INDEX = (Polyline.POSITION_SIZE_INDEX = 4);const DISTANCE_DISPLAY_CONDITION = (Polyline.DISTANCE_DISPLAY_CONDITION = 5);const NUMBER_OF_PROPERTIES = (Polyline.NUMBER_OF_PROPERTIES = 6);function makeDirty(polyline, propertyChanged) {  ++polyline._propertiesChanged[propertyChanged];  const polylineCollection = polyline._polylineCollection;  if (defined(polylineCollection)) {    polylineCollection._updatePolyline(polyline, propertyChanged);    polyline._dirty = true;  }}Object.defineProperties(Polyline.prototype, {  /**   * Determines if this polyline will be shown.  Use this to hide or show a polyline, instead   * of removing it and re-adding it to the collection.   * @memberof Polyline.prototype   * @type {Boolean}   */  show: {    get: function () {      return this._show;    },    set: function (value) {      //>>includeStart('debug', pragmas.debug);      if (!defined(value)) {        throw new DeveloperError("value is required.");      }      //>>includeEnd('debug');      if (value !== this._show) {        this._show = value;        makeDirty(this, SHOW_INDEX);      }    },  },  /**   * Gets or sets the positions of the polyline.   * @memberof Polyline.prototype   * @type {Cartesian3[]}   * @example   * polyline.positions = Cesium.Cartesian3.fromDegreesArray([   *     0.0, 0.0,   *     10.0, 0.0,   *     0.0, 20.0   * ]);   */  positions: {    get: function () {      return this._positions;    },    set: function (value) {      //>>includeStart('debug', pragmas.debug);      if (!defined(value)) {        throw new DeveloperError("value is required.");      }      //>>includeEnd('debug');      let positions = arrayRemoveDuplicates(value, Cartesian3.equalsEpsilon);      if (this._loop && positions.length > 2) {        if (positions === value) {          positions = value.slice();        }        positions.push(Cartesian3.clone(positions[0]));      }      if (        this._actualPositions.length !== positions.length ||        this._actualPositions.length !== this._length      ) {        makeDirty(this, POSITION_SIZE_INDEX);      }      this._positions = value;      this._actualPositions = positions;      this._length = positions.length;      this._boundingVolume = BoundingSphere.fromPoints(        this._actualPositions,        this._boundingVolume      );      this._boundingVolumeWC = BoundingSphere.transform(        this._boundingVolume,        this._modelMatrix,        this._boundingVolumeWC      );      makeDirty(this, POSITION_INDEX);      this.update();    },  },  /**   * Gets or sets the surface appearance of the polyline.  This can be one of several built-in {@link Material} objects or a custom material, scripted with   * {@link https://github.com/CesiumGS/cesium/wiki/Fabric|Fabric}.   * @memberof Polyline.prototype   * @type {Material}   */  material: {    get: function () {      return this._material;    },    set: function (material) {      //>>includeStart('debug', pragmas.debug);      if (!defined(material)) {        throw new DeveloperError("material is required.");      }      //>>includeEnd('debug');      if (this._material !== material) {        this._material = material;        makeDirty(this, MATERIAL_INDEX);      }    },  },  /**   * Gets or sets the width of the polyline.   * @memberof Polyline.prototype   * @type {Number}   */  width: {    get: function () {      return this._width;    },    set: function (value) {      //>>includeStart('debug', pragmas.debug)      if (!defined(value)) {        throw new DeveloperError("value is required.");      }      //>>includeEnd('debug');      const width = this._width;      if (value !== width) {        this._width = value;        makeDirty(this, WIDTH_INDEX);      }    },  },  /**   * Gets or sets whether a line segment will be added between the first and last polyline positions.   * @memberof Polyline.prototype   * @type {Boolean}   */  loop: {    get: function () {      return this._loop;    },    set: function (value) {      //>>includeStart('debug', pragmas.debug)      if (!defined(value)) {        throw new DeveloperError("value is required.");      }      //>>includeEnd('debug');      if (value !== this._loop) {        let positions = this._actualPositions;        if (value) {          if (            positions.length > 2 &&            !Cartesian3.equals(positions[0], positions[positions.length - 1])          ) {            if (positions.length === this._positions.length) {              this._actualPositions = positions = this._positions.slice();            }            positions.push(Cartesian3.clone(positions[0]));          }        } else if (          positions.length > 2 &&          Cartesian3.equals(positions[0], positions[positions.length - 1])        ) {          if (positions.length - 1 === this._positions.length) {            this._actualPositions = this._positions;          } else {            positions.pop();          }        }        this._loop = value;        makeDirty(this, POSITION_SIZE_INDEX);      }    },  },  /**   * Gets or sets the user-defined value returned when the polyline is picked.   * @memberof Polyline.prototype   * @type {*}   */  id: {    get: function () {      return this._id;    },    set: function (value) {      this._id = value;      if (defined(this._pickId)) {        this._pickId.object.id = value;      }    },  },  /**   * @private   */  pickId: {    get: function () {      return this._pickId;    },  },  /**   * Gets the destruction status of this polyline   * @memberof Polyline.prototype   * @type {Boolean}   * @default false   * @private   */  isDestroyed: {    get: function () {      return !defined(this._polylineCollection);    },  },  /**   * Gets or sets the condition specifying at what distance from the camera that this polyline will be displayed.   * @memberof Polyline.prototype   * @type {DistanceDisplayCondition}   * @default undefined   */  distanceDisplayCondition: {    get: function () {      return this._distanceDisplayCondition;    },    set: function (value) {      //>>includeStart('debug', pragmas.debug);      if (defined(value) && value.far <= value.near) {        throw new DeveloperError(          "far distance must be greater than near distance."        );      }      //>>includeEnd('debug');      if (        !DistanceDisplayCondition.equals(value, this._distanceDisplayCondition)      ) {        this._distanceDisplayCondition = DistanceDisplayCondition.clone(          value,          this._distanceDisplayCondition        );        makeDirty(this, DISTANCE_DISPLAY_CONDITION);      }    },  },});/** * @private */Polyline.prototype.update = function () {  let modelMatrix = Matrix4.IDENTITY;  if (defined(this._polylineCollection)) {    modelMatrix = this._polylineCollection.modelMatrix;  }  const segmentPositionsLength = this._segments.positions.length;  const segmentLengths = this._segments.lengths;  const positionsChanged =    this._propertiesChanged[POSITION_INDEX] > 0 ||    this._propertiesChanged[POSITION_SIZE_INDEX] > 0;  if (!Matrix4.equals(modelMatrix, this._modelMatrix) || positionsChanged) {    this._segments = PolylinePipeline.wrapLongitude(      this._actualPositions,      modelMatrix    );    this._boundingVolumeWC = BoundingSphere.transform(      this._boundingVolume,      modelMatrix,      this._boundingVolumeWC    );  }  this._modelMatrix = Matrix4.clone(modelMatrix, this._modelMatrix);  if (this._segments.positions.length !== segmentPositionsLength) {    // number of positions changed    makeDirty(this, POSITION_SIZE_INDEX);  } else {    const length = segmentLengths.length;    for (let i = 0; i < length; ++i) {      if (segmentLengths[i] !== this._segments.lengths[i]) {        // indices changed        makeDirty(this, POSITION_SIZE_INDEX);        break;      }    }  }};/** * @private */Polyline.prototype.getPickId = function (context) {  if (!defined(this._pickId)) {    this._pickId = context.createPickId({      primitive: this,      collection: this._polylineCollection,      id: this._id,    });  }  return this._pickId;};Polyline.prototype._clean = function () {  this._dirty = false;  const properties = this._propertiesChanged;  for (let k = 0; k < NUMBER_OF_PROPERTIES - 1; ++k) {    properties[k] = 0;  }};Polyline.prototype._destroy = function () {  this._pickId = this._pickId && this._pickId.destroy();  this._material = this._material && this._material.destroy();  this._polylineCollection = undefined;};export default Polyline;
 |