File

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

Extends

AcEntity

Index

Properties
Methods
Accessors

Constructor

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

Properties

Private _enableEdit
_enableEdit:
Default value : true
Private _labels
_labels: LabelProps[]
Type : LabelProps[]
Default value : []
Private _outlineInstance
_outlineInstance: null
Type : null
Default value : null
Private _pointProps
_pointProps: PointProps
Type : PointProps
Private doneCreation
doneCreation:
Default value : false
Private lastDraggedToPosition
lastDraggedToPosition: any
Type : any
Private movingPoint
movingPoint: EditPoint
Type : EditPoint
Private polylineProps
polylineProps: PolylineProps
Type : PolylineProps
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
endMoveShape
endMoveShape()
Returns : void
getId
getId()
Returns : string
getPoints
getPoints()
Returns : EditPoint[]
getPointsCount
getPointsCount()
Returns : number
getPositions
getPositions()
Returns : Cartesian3[]
getPositionsCallbackProperty
getPositionsCallbackProperty()
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
moveShape
moveShape(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
setManually
setManually(points: literal type[] | Cartesian3[], polylineProps?: PolylineProps)
Parameters :
Name Type Optional
points literal type[] | Cartesian3[] No
polylineProps PolylineProps Yes
Returns : void
Private setMiddleVirtualPoint
setMiddleVirtualPoint(firstP: EditPoint, secondP: EditPoint)
Parameters :
Name Type Optional
firstP EditPoint No
secondP EditPoint No
Returns : EditPoint
update
update()
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, point: EditPoint[])
Parameters :
Name Type Optional Default value
renderPolylines No true
point EditPoint[] No
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
props
getprops()
setprops(value)
Parameters :
Name Optional
value No
Returns : void
pointProps
getpointProps()
setpointProps(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 { PointProps } from './point-edit-options';
import { PolylineEditOptions, PolylineProps } from './polyline-edit-options';
import { GeoUtilsService } from '../../angular-cesium/services/geo-utils/geo-utils.service';
import { defaultLabelProps, LabelProps } from './label-props';

export class EditablePolyline extends AcEntity {
  private positions: EditPoint[] = [];

  private polylines: EditPolyline[] = [];
  private movingPoint: EditPoint;
  private doneCreation = false;
  private _enableEdit = true;
  private _pointProps: PointProps;
  private polylineProps: PolylineProps;
  private lastDraggedToPosition: any;
  private _labels: LabelProps[] = [];
  private _outlineInstance = null;

  constructor(private id: string,
              private pointsLayer: AcLayerComponent,
              private polylinesLayer: AcLayerComponent,
              private coordinateConverter: CoordinateConverter,
              private scene: any,
              private editOptions: PolylineEditOptions,
              positions?: Cartesian3[]) {
    super();
    this._pointProps = {...editOptions.pointProps};
    this.props = {...editOptions.polylineProps};
    if (positions && positions.length >= 2) {
      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 props(): PolylineProps {
    return this.polylineProps;
  }

  set props(value: PolylineProps) {
    this.polylineProps = value;
  }

  get pointProps(): PointProps {
    return this._pointProps;
  }

  set pointProps(value: PointProps) {
    this._pointProps = 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.doneCreation = true;
  }

  setManually(points: {
    position: Cartesian3,
    pointProp?: PointProps
  }[] | Cartesian3[], polylineProps?: PolylineProps) {
    if (!this.doneCreation) {
      throw new Error('Update manually only in edit mode, after polyline 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._pointProps);
      }
      newPoints.push(newPoint);
    }
    this.positions = newPoints;
    this.polylineProps = polylineProps ? polylineProps : this.polylineProps;

    this.updatePointsLayer(true, ...this.positions);
    this.addAllVirtualEditPoints();
  }

  private addAllVirtualEditPoints() {
    const currentPoints = [...this.positions];
    currentPoints.forEach((pos, index) => {
      if (index !== currentPoints.length - 1) {
        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._pointProps);
    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); // actual 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(false, firstMidPoint, secMidPoint, point);

  }

  private renderPolylines() {
    const realPoints = this.positions.filter(point => !point.isVirtualEditPoint());
    if (this.polylineProps.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.polylineProps.width,
          loop: false
        }),
        id: 'edit-polygon-outline-' + this.id,
        attributes: {
          color: Cesium.ColorGeometryInstanceAttribute.fromColor(this.polylineProps.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) => {
        if (index !== realPoints.length - 1) {
          const nextIndex = (index + 1);
          const nextPoint = realPoints[nextIndex];
          const polyline = new EditPolyline(this.id, point.getPosition(), nextPoint.getPosition(), this.polylineProps);
          this.polylines.push(polyline);
          this.polylinesLayer.update(polyline, polyline.getId());
        }
      });
    }
  }

  addPointFromExisting(position: Cartesian3) {
    const newPoint = new EditPoint(this.id, position, this._pointProps);
    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._pointProps);
      this.positions.push(firstPoint);
      this.updatePointsLayer(true, firstPoint);
    }

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

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

  movePointFinish(editPoint: EditPoint) {
    if (this.editOptions.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.editOptions.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);

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

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

  moveShape(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(true, ...this.positions);
    this.lastDraggedToPosition = draggedToPosition;
  }

  endMoveShape() {
    this.lastDraggedToPosition = undefined;
    this.updatePointsLayer(true, ...this.positions);
  }

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

    this.renderPolylines();
  }

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

    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);
  }

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

  getPositionsCallbackProperty(): Cartesian3[] {
    return new Cesium.CallbackProperty(this.getPositions.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 updatePointsLayer(renderPolylines = true, ...point: EditPoint[]) {
    if (renderPolylines) {
      this.renderPolylines();
    }
    point.forEach(p => this.pointsLayer.update(p, p.getId()));
  }

  update() {
    this.updatePointsLayer();
  }

  dispose() {
    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 ""