File

projects/angular-cesium/src/lib/angular-cesium-widgets/models/editable-polygon.ts

Extends

AcEntity

Index

Properties
Methods
Accessors

Constructor

constructor(id: string, polygonsLayer: AcLayerComponent, pointsLayer: AcLayerComponent, polylinesLayer: AcLayerComponent, coordinateConverter: CoordinateConverter, scene: any, polygonOptions: PolygonEditOptions, positions?: Cartesian3[])
Parameters :
Name Type Optional
id string No
polygonsLayer AcLayerComponent No
pointsLayer AcLayerComponent No
polylinesLayer AcLayerComponent No
coordinateConverter CoordinateConverter No
scene any No
polygonOptions PolygonEditOptions No
positions Cartesian3[] Yes

Properties

Private _defaultPointProps
_defaultPointProps: PointProps
Type : PointProps
Private _defaultPolylineProps
_defaultPolylineProps: PolylineProps
Type : PolylineProps
Private _enableEdit
_enableEdit:
Default value : true
Private _labels
_labels: LabelProps[]
Type : LabelProps[]
Default value : []
Private _outlineInstance
_outlineInstance: null
Type : null
Default value : null
Private _polygonProps
_polygonProps: PolygonProps
Type : PolygonProps
Private doneCreation
doneCreation:
Default value : false
Private lastDraggedToPosition
lastDraggedToPosition: Cartesian3
Type : Cartesian3
Private movingPoint
movingPoint: EditPoint
Type : EditPoint
Private polylines
polylines: EditPolyline[]
Type : EditPolyline[]
Default value : []
Private positions
positions: EditPoint[]
Type : EditPoint[]
Default value : []

Methods

Private addAllVirtualEditPoints
addAllVirtualEditPoints()
Returns : void
addLastPoint
addLastPoint(position: Cartesian3)
Parameters :
Name Type Optional
position Cartesian3 No
Returns : void
addPoint
addPoint(position: Cartesian3)
Parameters :
Name Type Optional
position Cartesian3 No
Returns : void
addPointFromExisting
addPointFromExisting(position: Cartesian3)
Parameters :
Name Type Optional
position Cartesian3 No
Returns : void
changeVirtualPointToRealPoint
changeVirtualPointToRealPoint(point: EditPoint)
Parameters :
Name Type Optional
point EditPoint No
Returns : void
Private createFromExisting
createFromExisting(positions: Cartesian3[])
Parameters :
Name Type Optional
positions Cartesian3[] No
Returns : void
dispose
dispose()
Returns : void
endMovePolygon
endMovePolygon()
Returns : void
getId
getId()
Returns : string
getPoints
getPoints()
Returns : EditPoint[]
getPointsCount
getPointsCount()
Returns : number
getPositionsHierarchy
getPositionsHierarchy()
Returns : Cartesian3[]
getPositionsHierarchyCallbackProperty
getPositionsHierarchyCallbackProperty()
Returns : Cartesian3[]
getRealPoints
getRealPoints()
Returns : EditPoint[]
getRealPositions
getRealPositions()
Returns : Cartesian3[]
movePoint
movePoint(toPosition: Cartesian3, editPoint: EditPoint)
Parameters :
Name Type Optional
toPosition Cartesian3 No
editPoint EditPoint No
Returns : void
movePointFinish
movePointFinish(editPoint: EditPoint)
Parameters :
Name Type Optional
editPoint EditPoint No
Returns : void
movePolygon
movePolygon(startMovingPosition: Cartesian3, draggedToPosition: Cartesian3)
Parameters :
Name Type Optional
startMovingPosition Cartesian3 No
draggedToPosition Cartesian3 No
Returns : void
moveTempMovingPoint
moveTempMovingPoint(toPosition: Cartesian3)
Parameters :
Name Type Optional
toPosition Cartesian3 No
Returns : void
removePoint
removePoint(pointToRemove: EditPoint)
Parameters :
Name Type Optional
pointToRemove EditPoint No
Returns : void
Private removePosition
removePosition(point: EditPoint)
Parameters :
Name Type Optional
point EditPoint No
Returns : void
Private renderPolylines
renderPolylines()
Returns : void
Private setMiddleVirtualPoint
setMiddleVirtualPoint(firstP: EditPoint, secondP: EditPoint)
Parameters :
Name Type Optional
firstP EditPoint No
secondP EditPoint No
Returns : EditPoint
setPointsManually
setPointsManually(points: literal type[] | Cartesian3[], polygonProps?: PolygonProps)
Parameters :
Name Type Optional
points literal type[] | Cartesian3[] No
polygonProps PolygonProps Yes
Returns : void
Private updateMiddleVirtualPoint
updateMiddleVirtualPoint(virtualEditPoint: EditPoint, prevPoint: EditPoint, nextPoint: EditPoint)
Parameters :
Name Type Optional
virtualEditPoint EditPoint No
prevPoint EditPoint No
nextPoint EditPoint No
Returns : void
Private updatePointsLayer
updatePointsLayer(renderPolylines, points: EditPoint[])
Parameters :
Name Type Optional Default value
renderPolylines No true
points EditPoint[] No
Returns : void
Private updatePolygonsLayer
updatePolygonsLayer()
Returns : void
Static create
create(json?: any)
Inherited from AcEntity
Defined in AcEntity:18

Creates entity from a json

Parameters :
Name Type Optional Description
json any Yes

entity object

Returns : any

entity as AcEntity

Accessors

labels
getlabels()
setlabels(labels: [])
Parameters :
Name Type Optional
labels [] No
Returns : void
defaultPolylineProps
getdefaultPolylineProps()
setdefaultPolylineProps(value)
Parameters :
Name Optional
value No
Returns : void
defaultPointProps
getdefaultPointProps()
setdefaultPointProps(value)
Parameters :
Name Optional
value No
Returns : void
polygonProps
getpolygonProps()
setpolygonProps(value)
Parameters :
Name Optional
value No
Returns : void
enableEdit
getenableEdit()
setenableEdit(value: boolean)
Parameters :
Name Type Optional
value boolean No
Returns : void
import { AcEntity } from '../../angular-cesium/models/ac-entity';
import { EditPoint } from './edit-point';
import { EditPolyline } from './edit-polyline';
import { AcLayerComponent } from '../../angular-cesium/components/ac-layer/ac-layer.component';
import { Cartesian3 } from '../../angular-cesium/models/cartesian3';
import { CoordinateConverter } from '../../angular-cesium/services/coordinate-converter/coordinate-converter.service';
import { GeoUtilsService } from '../../angular-cesium/services/geo-utils/geo-utils.service';
import { PolygonEditOptions, PolygonProps } from './polygon-edit-options';
import { PointProps } from './point-edit-options';
import { PolylineProps } from './polyline-edit-options';
import { defaultLabelProps, LabelProps } from './label-props';

export class EditablePolygon extends AcEntity {
  private positions: EditPoint[] = [];
  private polylines: EditPolyline[] = [];
  private movingPoint: EditPoint;
  private doneCreation = false;
  private _enableEdit = true;
  private _polygonProps: PolygonProps;
  private _defaultPointProps: PointProps;
  private _defaultPolylineProps: PolylineProps;
  private lastDraggedToPosition: Cartesian3;
  private _labels: LabelProps[] = [];
  private _outlineInstance = null;

  constructor(private id: string,
              private polygonsLayer: AcLayerComponent,
              private pointsLayer: AcLayerComponent,
              private polylinesLayer: AcLayerComponent,
              private coordinateConverter: CoordinateConverter,
              private scene: any,
              private polygonOptions: PolygonEditOptions,
              positions?: Cartesian3[]) {
    super();
    this.polygonProps = {...polygonOptions.polygonProps};
    this.defaultPointProps = {...polygonOptions.pointProps};
    this.defaultPolylineProps = {...polygonOptions.polylineProps};
    if (positions && positions.length >= 3) {
      this.createFromExisting(positions);
    }
  }

  get labels(): LabelProps[] {
    return this._labels;
  }

  set labels(labels: LabelProps[]) {
    if (!labels) {
      return;
    }
    const positions = this.getRealPositions();
    this._labels = labels.map((label, index) => {
      if (!label.position) {
        label.position = positions[index];
      }

      return Object.assign({}, defaultLabelProps, label);
    });
  }

  get defaultPolylineProps(): PolylineProps {
    return this._defaultPolylineProps;
  }

  set defaultPolylineProps(value: PolylineProps) {
    this._defaultPolylineProps = value;
  }

  get defaultPointProps(): PointProps {
    return this._defaultPointProps;
  }

  get polygonProps(): PolygonProps {
    return this._polygonProps;
  }

  set polygonProps(value: PolygonProps) {
    this._polygonProps = value;
  }

  set defaultPointProps(value: PointProps) {
    this._defaultPointProps = value;
  }

  get enableEdit() {
    return this._enableEdit;
  }

  set enableEdit(value: boolean) {
    this._enableEdit = value;
    this.positions.forEach(point => {
      point.show = value;
      this.updatePointsLayer(false, point);
    });
  }

  private createFromExisting(positions: Cartesian3[]) {
    positions.forEach((position) => {
      this.addPointFromExisting(position);
    });
    this.addAllVirtualEditPoints();
    this.updatePolygonsLayer();
    this.doneCreation = true;
  }

  setPointsManually(points: { position: Cartesian3, pointProps: PointProps }[] | Cartesian3[], polygonProps?: PolygonProps) {
    if (!this.doneCreation) {
      throw new Error('Update manually only in edit mode, after polygon is created');
    }

    this.positions.forEach(p => this.pointsLayer.remove(p.getId()));
    const newPoints: EditPoint[] = [];
    for (let i = 0; i < points.length; i++) {
      const pointOrCartesian: any = points[i];
      let newPoint = null;
      if (pointOrCartesian.pointProps) {
        newPoint = new EditPoint(this.id, pointOrCartesian.position, pointOrCartesian.pointProps);
      } else {
        newPoint = new EditPoint(this.id, pointOrCartesian, this.defaultPointProps);
      }
      newPoints.push(newPoint);
    }
    this.positions = newPoints;
    this.polygonProps = polygonProps ? polygonProps : this.polygonProps;
    this.updatePointsLayer(true, ...this.positions);
    this.addAllVirtualEditPoints();
    this.updatePolygonsLayer();
  }

  private addAllVirtualEditPoints() {
    const currentPoints = [...this.positions];
    currentPoints.forEach((pos, index) => {
      const currentPoint = pos;
      const nextIndex = (index + 1) % (currentPoints.length);
      const nextPoint = currentPoints[nextIndex];
      const midPoint = this.setMiddleVirtualPoint(currentPoint, nextPoint);
      this.updatePointsLayer(false, midPoint);
    });
  }

  private setMiddleVirtualPoint(firstP: EditPoint, secondP: EditPoint): EditPoint {
    const midPointCartesian3 = Cesium.Cartesian3.lerp(firstP.getPosition(), secondP.getPosition(), 0.5, new Cesium.Cartesian3());
    const midPoint = new EditPoint(this.id, midPointCartesian3, this.defaultPointProps);
    midPoint.setVirtualEditPoint(true);

    const firstIndex = this.positions.indexOf(firstP);
    this.positions.splice(firstIndex + 1, 0, midPoint);
    return midPoint;
  }

  private updateMiddleVirtualPoint(virtualEditPoint: EditPoint, prevPoint: EditPoint, nextPoint: EditPoint) {
    const midPointCartesian3 = Cesium.Cartesian3.lerp(prevPoint.getPosition(), nextPoint.getPosition(), 0.5, new Cesium.Cartesian3());
    virtualEditPoint.setPosition(midPointCartesian3);
  }

  changeVirtualPointToRealPoint(point: EditPoint) {
    point.setVirtualEditPoint(false); // virtual point becomes a real point
    const pointsCount = this.positions.length;
    const pointIndex = this.positions.indexOf(point);
    const nextIndex = (pointIndex + 1) % (pointsCount);
    const preIndex = ((pointIndex - 1) + pointsCount) % pointsCount;

    const nextPoint = this.positions[nextIndex];
    const prePoint = this.positions[preIndex];

    const firstMidPoint = this.setMiddleVirtualPoint(prePoint, point);
    const secMidPoint = this.setMiddleVirtualPoint(point, nextPoint);
    this.updatePointsLayer(true, firstMidPoint, secMidPoint, point);
    this.updatePolygonsLayer();

  }

  private renderPolylines() {
    const realPoints = this.positions.filter(pos => !pos.isVirtualEditPoint());
    if (this.defaultPolylineProps.useGroundPrimitiveOutline) {
      if (realPoints.length < 2) {
        return;
      }
      this.scene.groundPrimitives.remove(this._outlineInstance);
      const instance = new Cesium.GeometryInstance({
        geometry: new Cesium.GroundPolylineGeometry({
          positions: this.positions.map(p => p.getPosition()),
          width: this.defaultPolylineProps.width,
          loop: true
        }),
        id: 'edit-ground-primitive-' + this.id,
        attributes: {
          color: Cesium.ColorGeometryInstanceAttribute.fromColor(this.defaultPolylineProps.material())
        }
      });
      this._outlineInstance = this.scene.groundPrimitives.add(
        new Cesium.GroundPolylinePrimitive({
          geometryInstances: instance,
          asynchronous: false,
          appearance: new Cesium.PolylineColorAppearance()
        })
      );
    } else {
      this.polylines.forEach(polyline => this.polylinesLayer.remove(polyline.getId()));
      this.polylines = [];
      realPoints.forEach((point, index) => {
        const nextIndex = (index + 1) % (realPoints.length);
        const nextPoint = realPoints[nextIndex];
        const polyline = new EditPolyline(this.id, point.getPosition(), nextPoint.getPosition(), this.defaultPolylineProps);
        this.polylines.push(polyline);
        this.polylinesLayer.update(polyline, polyline.getId());
      });
    }
  }

  addPointFromExisting(position: Cartesian3) {
    const newPoint = new EditPoint(this.id, position, this.defaultPointProps);
    this.positions.push(newPoint);
    this.updatePointsLayer(true, newPoint);
  }


  addPoint(position: Cartesian3) {
    if (this.doneCreation) {
      return;
    }
    const isFirstPoint = !this.positions.length;
    if (isFirstPoint) {
      const firstPoint = new EditPoint(this.id, position, this.defaultPointProps);
      this.positions.push(firstPoint);
      this.updatePointsLayer(true, firstPoint);
    }

    this.movingPoint = new EditPoint(this.id, position.clone(), this.defaultPointProps);
    this.positions.push(this.movingPoint);

    this.updatePointsLayer(true, this.movingPoint);
    this.updatePolygonsLayer();
  }

  movePointFinish(editPoint: EditPoint) {
    if (this.polygonOptions.clampHeightTo3D) {
      editPoint.props.disableDepthTestDistance = Number.POSITIVE_INFINITY;
      this.updatePointsLayer(false, editPoint);
    }
  }

  movePoint(toPosition: Cartesian3, editPoint: EditPoint) {
    editPoint.setPosition(toPosition);
    if (this.doneCreation) {
      if (editPoint.props.disableDepthTestDistance && this.polygonOptions.clampHeightTo3D) {
        // To avoid bug with pickPosition() on point with disableDepthTestDistance
        editPoint.props.disableDepthTestDistance = undefined;
        return; // ignore first move because the pickPosition() could be wrong
      }

      if (editPoint.isVirtualEditPoint()) {
        this.changeVirtualPointToRealPoint(editPoint);
      }
      const pointsCount = this.positions.length;
      const pointIndex = this.positions.indexOf(editPoint);
      const nextVirtualPoint = this.positions[(pointIndex + 1) % (pointsCount)];
      const nextRealPoint = this.positions[(pointIndex + 2) % (pointsCount)];
      const prevVirtualPoint = this.positions[((pointIndex - 1) + pointsCount) % pointsCount];
      const prevRealPoint = this.positions[((pointIndex - 2) + pointsCount) % pointsCount];
      this.updateMiddleVirtualPoint(nextVirtualPoint, editPoint, nextRealPoint);
      this.updateMiddleVirtualPoint(prevVirtualPoint, editPoint, prevRealPoint);
    }
    this.updatePolygonsLayer();
    this.updatePointsLayer(true, editPoint);
  }

  moveTempMovingPoint(toPosition: Cartesian3) {
    if (this.movingPoint) {
      this.movePoint(toPosition, this.movingPoint);
    }
  }

  movePolygon(startMovingPosition: Cartesian3, draggedToPosition: Cartesian3) {
    if (!this.doneCreation) {
      return;
    }
    if (!this.lastDraggedToPosition) {
      this.lastDraggedToPosition = startMovingPosition;
    }

    const delta = GeoUtilsService.getPositionsDelta(this.lastDraggedToPosition, draggedToPosition);
    this.positions.forEach(point => {
      const newPos = GeoUtilsService.addDeltaToPosition(point.getPosition(), delta, true);
      point.setPosition(newPos);
    });
    this.updatePointsLayer();
    this.lastDraggedToPosition = draggedToPosition;
    this.positions.forEach(point => this.updatePointsLayer(true, point));
  }

  endMovePolygon() {
    this.lastDraggedToPosition = undefined;
  }

  removePoint(pointToRemove: EditPoint) {
    this.removePosition(pointToRemove);
    this.positions
      .filter(p => p.isVirtualEditPoint())
      .forEach(p => this.removePosition(p));
    this.addAllVirtualEditPoints();

    this.renderPolylines();
    if (this.getPointsCount() >= 3) {
      this.polygonsLayer.update(this, this.id);
    }
  }

  addLastPoint(position: Cartesian3) {
    this.doneCreation = true;
    this.removePosition(this.movingPoint); // remove movingPoint
    this.movingPoint = null;
    this.updatePolygonsLayer();

    this.addAllVirtualEditPoints();
  }

  getRealPositions(): Cartesian3[] {
    return this.getRealPoints().map(position => position.getPosition());
  }

  getRealPoints(): EditPoint[] {
    return this.positions.filter(position => !position.isVirtualEditPoint() && position !== this.movingPoint);
  }

  getPoints(): EditPoint[] {
    return this.positions.filter(position => position !== this.movingPoint);
  }

  getPositionsHierarchy(): Cartesian3[] {
    const positions = this.positions.filter(position => !position.isVirtualEditPoint()).map(position => position.getPosition().clone());
    return new Cesium.PolygonHierarchy(positions);
  }

  getPositionsHierarchyCallbackProperty(): Cartesian3[] {
    return new Cesium.CallbackProperty(this.getPositionsHierarchy.bind(this), false);
  }

  private removePosition(point: EditPoint) {
    const index = this.positions.findIndex((p) => p === point);
    if (index < 0) {
      return;
    }
    this.positions.splice(index, 1);
    this.pointsLayer.remove(point.getId());
  }

  private updatePolygonsLayer() {
    if (this.getPointsCount() >= 3) {
      this.polygonsLayer.update(this, this.id);
    }
  }

  private updatePointsLayer(renderPolylines = true, ...points: EditPoint[]) {
    if (renderPolylines) {
      this.renderPolylines();
    }
    points.forEach(p => this.pointsLayer.update(p, p.getId()));
  }

  dispose() {
    this.polygonsLayer.remove(this.id);
    this.scene.groundPrimitives.remove(this._outlineInstance);
    this.positions.forEach(editPoint => {
      this.pointsLayer.remove(editPoint.getId());
    });
    this.polylines.forEach(line => this.polylinesLayer.remove(line.getId()));
    if (this.movingPoint) {
      this.pointsLayer.remove(this.movingPoint.getId());
      this.movingPoint = undefined;
    }
    this.positions.length = 0;
  }

  getPointsCount(): number {
    return this.positions.length;
  }

  getId() {
    return this.id;
  }
}

result-matching ""

    No results matching ""