File

projects/angular-cesium/src/lib/angular-cesium-widgets/services/entity-editors/polyline-editor/polylines-editor.service.ts

Description

Service for creating editable polylines

  • You must provide PolylineEditorService yourself. PolygonsEditorService works together with <polylines-editor> component. Therefor you need to create <polylines-editor> for each PolylineEditorService, And of course somewhere under <ac-map>/
  • create for starting a creation of the shape over the map. Returns a extension of PolylineEditorObservable.
  • edit for editing shape over the map starting from a given positions. Returns an extension of PolylineEditorObservable.
  • To stop editing call dsipose() from the PolylineEditorObservable you get back from create() \ edit().

Labels over editted shapes Angular Cesium allows you to draw labels over a shape that is being edited with one of the editors. To add label drawing logic to your editor use the function setLabelsRenderFn() that is defined on the PolylineEditorObservable that is returned from calling create() \ edit() of one of the editor services. setLabelsRenderFn() - receives a callback that is called every time the shape is redrawn (except when the shape is being dragged). The callback is called with the last shape state and with an array of the current labels. The callback should return type LabelProps[]. You can also use updateLabels() to pass an array of labels of type LabelProps[] to be drawn.

usage:

 *  // Start creating polyline
 *  const editing$ = polylinesEditorService.create();
 *  this.editing$.subscribe(editResult => {
 *                console.log(editResult.positions);
 *        });
 *
 *  // Or edit polyline from existing polyline cartesian3 positions
 *  const editing$ = this.polylinesEditor.edit(initialPos);
 *
 *

Index

Properties
Methods

Methods

Private clampPoints
clampPoints(id, clampHeightTo3D: boolean, undefined: ClampTo3DOptions)
Parameters :
Name Type Optional
id No
clampHeightTo3D boolean No
ClampTo3DOptions No
Returns : void
create
create(options, eventPriority: number)
Parameters :
Name Type Optional Default value
options No DEFAULT_POLYLINE_OPTIONS
eventPriority number No 100
Private createEditorObservable
createEditorObservable(observableToExtend: any, id: string, finishCreation?: (position?: Cartesian3) => void)
Parameters :
Name Type Optional
observableToExtend any No
id string No
finishCreation function Yes
edit
edit(positions: Cartesian3[], options, priority: number)
Parameters :
Name Type Optional Default value
positions Cartesian3[] No
options No DEFAULT_POLYLINE_OPTIONS
priority number No 100
Private editPolyline
editPolyline(id: string, positions: Cartesian3[], priority: number, editSubject: Subject, options: PolylineEditOptions, editObservable?: PolylineEditorObservable)
Parameters :
Name Type Optional
id string No
positions Cartesian3[] No
priority number No
editSubject Subject<PolylineEditUpdate> No
options PolylineEditOptions No
editObservable PolylineEditorObservable Yes
Returns : any
Private getPoints
getPoints(id: string)
Parameters :
Name Type Optional
id string No
Returns : any
Private getPositions
getPositions(id: string)
Parameters :
Name Type Optional
id string No
Returns : any
init
init(mapEventsManager: MapEventsManagerService, coordinateConverter: CoordinateConverter, cameraService: CameraService, polylinesManager: PolylinesManagerService, cesiumViewer: CesiumService)
Parameters :
Name Type Optional
mapEventsManager MapEventsManagerService No
coordinateConverter CoordinateConverter No
cameraService CameraService No
polylinesManager PolylinesManagerService No
cesiumViewer CesiumService No
Returns : void
onUpdate
onUpdate()
Private screenToPosition
screenToPosition(cartesian2, clampHeightTo3D: boolean, undefined: ClampTo3DOptions)
Parameters :
Name Type Optional
cartesian2 No
clampHeightTo3D boolean No
ClampTo3DOptions No
Returns : any
Private setOptions
setOptions(options: PolylineEditOptions)
Parameters :
Name Type Optional
options PolylineEditOptions No
Returns : any
Private switchToEditMode
switchToEditMode(id, position, clientEditSubject, positions: Cartesian3[], eventPriority, polylineOptions, editorObservable, finishedCreate: boolean)
Parameters :
Name Type Optional
id No
position No
clientEditSubject No
positions Cartesian3[] No
eventPriority No
polylineOptions No
editorObservable No
finishedCreate boolean No
Returns : boolean

Properties

Private cameraService
cameraService: CameraService
Type : CameraService
Private cesiumScene
cesiumScene:
Private clampPointsDebounced
clampPointsDebounced:
Default value : debounce((id, clampHeightTo3D: boolean, clampHeightTo3DOptions) => { this.clampPoints(id, clampHeightTo3D, clampHeightTo3DOptions); }, 300)
Private coordinateConverter
coordinateConverter: CoordinateConverter
Type : CoordinateConverter
Private mapEventsManager
mapEventsManager: MapEventsManagerService
Type : MapEventsManagerService
Private observablesMap
observablesMap:
Default value : new Map<string, DisposableObservable<any>[]>()
Private polylinesManager
polylinesManager: PolylinesManagerService
Type : PolylinesManagerService
Private updatePublisher
updatePublisher:
Default value : publish<PolylineEditUpdate>()(this.updateSubject)
Private updateSubject
updateSubject:
Default value : new Subject<PolylineEditUpdate>()
import { publish, tap } from 'rxjs/operators';
import { Injectable } from '@angular/core';
import { MapEventsManagerService } from '../../../../angular-cesium/services/map-events-mananger/map-events-manager';
import { BehaviorSubject, Observable, Subject } from 'rxjs';
import { CesiumEvent } from '../../../../angular-cesium/services/map-events-mananger/consts/cesium-event.enum';
import { PickOptions } from '../../../../angular-cesium/services/map-events-mananger/consts/pickOptions.enum';
import { EditModes } from '../../../models/edit-mode.enum';
import { EditActions } from '../../../models/edit-actions.enum';
import { DisposableObservable } from '../../../../angular-cesium/services/map-events-mananger/disposable-observable';
import { CoordinateConverter } from '../../../../angular-cesium/services/coordinate-converter/coordinate-converter.service';
import { EditPoint } from '../../../models/edit-point';
import { CameraService } from '../../../../angular-cesium/services/camera/camera.service';
import { Cartesian3 } from '../../../../angular-cesium/models/cartesian3';
import { PolylinesManagerService } from './polylines-manager.service';
import { ClampTo3DOptions, PolylineEditOptions, PolylineProps } from '../../../models/polyline-edit-options';
import { PointProps } from '../../../models/point-edit-options';
import { PolylineEditUpdate } from '../../../models/polyline-edit-update';
import { PolylineEditorObservable } from '../../../models/polyline-editor-observable';
import { EditPolyline } from '../../../models';
import { LabelProps } from '../../../models/label-props';
import { debounce, generateKey } from '../../utils';
import { CesiumService } from '../../../../angular-cesium';

export const DEFAULT_POLYLINE_OPTIONS: PolylineEditOptions = {
  addPointEvent: CesiumEvent.LEFT_CLICK,
  addLastPointEvent: CesiumEvent.LEFT_DOUBLE_CLICK,
  removePointEvent: CesiumEvent.RIGHT_CLICK,
  dragPointEvent: CesiumEvent.LEFT_CLICK_DRAG,
  dragShapeEvent: CesiumEvent.LEFT_CLICK_DRAG,
  allowDrag: true,
  pointProps: {
    color: Cesium.Color.WHITE.withAlpha(0.95),
    outlineColor: Cesium.Color.BLACK.withAlpha(0.5),
    outlineWidth: 1,
    pixelSize: 15,
    virtualPointPixelSize: 8,
    show: true,
    showVirtual: true,
    disableDepthTestDistance: Number.POSITIVE_INFINITY,
  },
  polylineProps: {
    material: () => Cesium.Color.BLACK,
    width: 3,
    clampToGround: false,
    zIndex: 0,
    classificationType: Cesium.ClassificationType.BOTH,
    useGroundPrimitiveOutline: false
  },
  clampHeightTo3D: false,
  clampHeightTo3DOptions: {
    clampToTerrain: false,
    clampMostDetailed: true,
    clampToHeightPickWidth: 2,
  },
};

/**
 * Service for creating editable polylines
 *
 *  * You must provide `PolylineEditorService` yourself.
 * PolygonsEditorService works together with `<polylines-editor>` component. Therefor you need to create `<polylines-editor>`
 * for each `PolylineEditorService`, And of course somewhere under `<ac-map>`/
 *
 * + `create` for starting a creation of the shape over the map. Returns a extension of `PolylineEditorObservable`.
 * + `edit` for editing shape over the map starting from a given positions. Returns an extension of `PolylineEditorObservable`.
 * + To stop editing call `dsipose()` from the `PolylineEditorObservable` you get back from `create()` \ `edit()`.
 *
 * **Labels over editted shapes**
 * Angular Cesium allows you to draw labels over a shape that is being edited with one of the editors.
 * To add label drawing logic to your editor use the function `setLabelsRenderFn()` that is defined on the
 * `PolylineEditorObservable` that is returned from calling `create()` \ `edit()` of one of the editor services.
 * `setLabelsRenderFn()` - receives a callback that is called every time the shape is redrawn
 * (except when the shape is being dragged). The callback is called with the last shape state and with an array of the current labels.
 * The callback should return type `LabelProps[]`.
 * You can also use `updateLabels()` to pass an array of labels of type `LabelProps[]` to be drawn.
 *
 * usage:
 * ```typescript
 *  // Start creating polyline
 *  const editing$ = polylinesEditorService.create();
 *  this.editing$.subscribe(editResult => {
 *				console.log(editResult.positions);
 *		});
 *
 *  // Or edit polyline from existing polyline cartesian3 positions
 *  const editing$ = this.polylinesEditor.edit(initialPos);
 *
 * ```
 */
@Injectable()
export class PolylinesEditorService {
  private mapEventsManager: MapEventsManagerService;
  private updateSubject = new Subject<PolylineEditUpdate>();
  private updatePublisher = publish<PolylineEditUpdate>()(this.updateSubject); // TODO maybe not needed
  private coordinateConverter: CoordinateConverter;
  private cameraService: CameraService;
  private polylinesManager: PolylinesManagerService;
  private observablesMap = new Map<string, DisposableObservable<any>[]>();
  private cesiumScene;

  private clampPointsDebounced = debounce((id, clampHeightTo3D: boolean, clampHeightTo3DOptions) => {
    this.clampPoints(id, clampHeightTo3D, clampHeightTo3DOptions);
  }, 300);

  init(mapEventsManager: MapEventsManagerService,
       coordinateConverter: CoordinateConverter,
       cameraService: CameraService,
       polylinesManager: PolylinesManagerService,
       cesiumViewer: CesiumService) {
    this.mapEventsManager = mapEventsManager;
    this.coordinateConverter = coordinateConverter;
    this.cameraService = cameraService;
    this.polylinesManager = polylinesManager;
    this.updatePublisher.connect();

    this.cesiumScene = cesiumViewer.getScene();
  }

  onUpdate(): Observable<PolylineEditUpdate> {
    return this.updatePublisher;
  }

  private clampPoints(id, clampHeightTo3D: boolean, { clampToTerrain, clampMostDetailed, clampToHeightPickWidth }: ClampTo3DOptions) {
    if (clampHeightTo3D && clampMostDetailed) {
      const polyline = this.polylinesManager.get(id);
      const points = polyline.getPoints();

      if (!clampToTerrain) {
        // 3dTiles
        points.forEach(point => {
          point.setPosition(this.cesiumScene.clampToHeight(point.getPosition(), undefined, clampToHeightPickWidth));
        });
      } else {
        const cartographics = points.map(point => this.coordinateConverter.cartesian3ToCartographic(point.getPosition()));
        const promise = Cesium.sampleTerrain(this.cesiumScene.terrainProvider, 11, cartographics);
        Cesium.when(promise, function (updatedPositions) {
          points.forEach((point, index) => {
            point.setPosition(Cesium.Cartographic.toCartesian(updatedPositions[index]));
          });
        });
      }
    }
  }


  private screenToPosition(cartesian2, clampHeightTo3D: boolean, {clampToHeightPickWidth, clampToTerrain}: ClampTo3DOptions) {
    const cartesian3 = this.coordinateConverter.screenToCartesian3(cartesian2);

    // If cartesian3 is undefined then the point inst on the globe
    if (clampHeightTo3D && cartesian3) {
      const globePositionPick = () => {
        const ray = this.cameraService.getCamera().getPickRay(cartesian2);
        return this.cesiumScene.globe.pick(ray, this.cesiumScene);
      };

      // is terrain?
      if (clampToTerrain) {
        return globePositionPick();
      } else {
        const cartesian3PickPosition = this.cesiumScene.pickPosition(cartesian2);
        const latLon = CoordinateConverter.cartesian3ToLatLon(cartesian3PickPosition);
        if (latLon.height < 0) {// means nothing picked -> Validate it
          return globePositionPick();
        }
        return this.cesiumScene.clampToHeight(cartesian3PickPosition, undefined, clampToHeightPickWidth);
      }
    }

    return cartesian3;
  }

  create(options = DEFAULT_POLYLINE_OPTIONS, eventPriority = 100): PolylineEditorObservable {
    const positions: Cartesian3[] = [];
    const id = generateKey();
    const polylineOptions = this.setOptions(options);

    const clientEditSubject = new BehaviorSubject<PolylineEditUpdate>({
      id,
      editAction: null,
      editMode: EditModes.CREATE
    });
    let finishedCreate = false;

    this.updateSubject.next({
      id,
      positions,
      editMode: EditModes.CREATE,
      editAction: EditActions.INIT,
      polylineOptions: polylineOptions,
    });

    const finishCreation = (position: Cartesian3) => {
      return this.switchToEditMode(
        id,
        position,
        clientEditSubject,
        positions,
        eventPriority,
        polylineOptions,
        editorObservable,
        finishedCreate);
    };

    const mouseMoveRegistration = this.mapEventsManager.register({
      event: CesiumEvent.MOUSE_MOVE,
      pick: PickOptions.NO_PICK,
      priority: eventPriority,
      pickConfig: options.pickConfiguration,
    });
    const addPointRegistration = this.mapEventsManager.register({
      event: polylineOptions.addPointEvent,
      modifier: polylineOptions.addPointModifier,
      pick: PickOptions.NO_PICK,
      priority: eventPriority,
      pickConfig: options.pickConfiguration,
    });
    const addLastPointRegistration = this.mapEventsManager.register({
      event: polylineOptions.addLastPointEvent,
      modifier: polylineOptions.addLastPointModifier,
      pick: PickOptions.NO_PICK,
      priority: eventPriority,
      pickConfig: options.pickConfiguration,
    });

    this.observablesMap.set(id, [mouseMoveRegistration, addPointRegistration, addLastPointRegistration]);
    const editorObservable = this.createEditorObservable(clientEditSubject, id, finishCreation);

    mouseMoveRegistration.subscribe(({ movement: { endPosition } }) => {
      const position = this.screenToPosition(endPosition, polylineOptions.clampHeightTo3D, polylineOptions.clampHeightTo3DOptions);
      if (position) {
        this.updateSubject.next({
          id,
          positions: this.getPositions(id),
          editMode: EditModes.CREATE,
          updatedPosition: position,
          editAction: EditActions.MOUSE_MOVE,
        });
      }
    });

    addPointRegistration.subscribe(({ movement: { endPosition } }) => {
      if (finishedCreate) {
        return;
      }
      const position = this.screenToPosition(endPosition, polylineOptions.clampHeightTo3D, polylineOptions.clampHeightTo3DOptions);
      if (!position) {
        return;
      }
      const allPositions = this.getPositions(id);
      if (allPositions.find((cartesian) => cartesian.equals(position))) {
        return;
      }
      const updateValue = {
        id,
        positions: allPositions,
        editMode: EditModes.CREATE,
        updatedPosition: position,
        editAction: EditActions.ADD_POINT,
      };
      this.updateSubject.next(updateValue);
      clientEditSubject.next({
        ...updateValue,
        positions: this.getPositions(id),
        points: this.getPoints(id),
      });
      if (polylineOptions.maximumNumberOfPoints && allPositions.length + 1 === polylineOptions.maximumNumberOfPoints) {
        finishedCreate = finishCreation(position);
      }
    });

    addLastPointRegistration.subscribe(({ movement: { endPosition } }) => {
      const position = this.screenToPosition(endPosition, polylineOptions.clampHeightTo3D, polylineOptions.clampHeightTo3DOptions);
      if (!position) {
        return;
      }

      // Add last point to positions if not already added
      const allPositions = this.getPositions(id);
      if (!allPositions.find((cartesian) => cartesian.equals(position))) {
        const updateValue = {
          id,
          positions: allPositions,
          editMode: EditModes.CREATE,
          updatedPosition: position,
          editAction: EditActions.ADD_POINT,
        };
        this.updateSubject.next(updateValue);
        clientEditSubject.next({
          ...updateValue,
          positions: this.getPositions(id),
          points: this.getPoints(id),
        });
      }

      finishedCreate = finishCreation(position);
    });

    return editorObservable;
  }

  private switchToEditMode(id,
                           position,
                           clientEditSubject,
                           positions: Cartesian3[],
                           eventPriority,
                           polylineOptions,
                           editorObservable,
                           finishedCreate: boolean) {
    const update = {
      id,
      positions: this.getPositions(id),
      editMode: EditModes.CREATE,
      updatedPosition: position,
      editAction: EditActions.ADD_LAST_POINT,
    };
    this.updateSubject.next(update);
    clientEditSubject.next({
      ...update,
      positions: this.getPositions(id),
      points: this.getPoints(id),
    });

    const changeMode = {
      id,
      editMode: EditModes.CREATE,
      editAction: EditActions.CHANGE_TO_EDIT,
    };
    this.updateSubject.next(changeMode);
    clientEditSubject.next(changeMode);
    if (this.observablesMap.has(id)) {
      this.observablesMap.get(id).forEach(registration => registration.dispose());
    }
    this.observablesMap.delete(id);
    this.editPolyline(id, positions, eventPriority, clientEditSubject, polylineOptions, editorObservable);
    finishedCreate = true;
    return finishedCreate;
  }

  edit(positions: Cartesian3[], options = DEFAULT_POLYLINE_OPTIONS, priority = 100): PolylineEditorObservable {
    if (positions.length < 2) {
      throw new Error('Polylines editor error edit(): polyline should have at least 2 positions');
    }
    const id = generateKey();
    const polylineOptions = this.setOptions(options);
    const editSubject = new BehaviorSubject<PolylineEditUpdate>({
      id,
      editAction: null,
      editMode: EditModes.EDIT
    });
    const update = {
      id,
      positions: positions,
      editMode: EditModes.EDIT,
      editAction: EditActions.INIT,
      polylineOptions: polylineOptions,
    };
    this.updateSubject.next(update);
    editSubject.next({
      ...update,
      positions: this.getPositions(id),
      points: this.getPoints(id),
    });
    return this.editPolyline(
      id,
      positions,
      priority,
      editSubject,
      polylineOptions
    );
  }

  private editPolyline(id: string,
                       positions: Cartesian3[],
                       priority: number,
                       editSubject: Subject<PolylineEditUpdate>,
                       options: PolylineEditOptions,
                       editObservable?: PolylineEditorObservable) {
    this.clampPoints(id, options.clampHeightTo3D, options.clampHeightTo3DOptions);

    const pointDragRegistration = this.mapEventsManager.register({
      event: options.dragPointEvent,
      entityType: EditPoint,
      pick: PickOptions.PICK_FIRST,
      pickConfig: options.pickConfiguration,
      priority,
      pickFilter: entity => id === entity.editedEntityId,
    });

    const pointRemoveRegistration = this.mapEventsManager.register({
      event: options.removePointEvent,
      modifier: options.removePointModifier,
      entityType: EditPoint,
      pick: PickOptions.PICK_FIRST,
      pickConfig: options.pickConfiguration,
      priority,
      pickFilter: entity => id === entity.editedEntityId,
    });

    let shapeDragRegistration;
    if (options.allowDrag) {
      shapeDragRegistration = this.mapEventsManager.register({
        event: options.dragShapeEvent,
        entityType: EditPolyline,
        pick: PickOptions.PICK_FIRST,
        pickConfig: options.pickConfiguration,
        priority,
        pickFilter: entity => id === entity.editedEntityId,
      });
    }

    if (shapeDragRegistration) {
      shapeDragRegistration
        .pipe(tap(({ movement: { drop } }) => this.polylinesManager.get(id).enableEdit && this.cameraService.enableInputs(drop)))
        .subscribe(({ movement: { startPosition, endPosition, drop }, entities }) => {
          const endDragPosition = this.screenToPosition(endPosition, false, options.clampHeightTo3DOptions);
          const startDragPosition = this.screenToPosition(startPosition, false, options.clampHeightTo3DOptions);
          if (!endDragPosition) {
            return;
          }

          const update = {
            id,
            positions: this.getPositions(id),
            editMode: EditModes.EDIT,
            updatedPosition: endDragPosition,
            draggedPosition: startDragPosition,
            editAction: drop ? EditActions.DRAG_SHAPE_FINISH : EditActions.DRAG_SHAPE,
          };
          this.updateSubject.next(update);
          editSubject.next({
            ...update,
            positions: this.getPositions(id),
            points: this.getPoints(id),
          });
        });
    }

    pointDragRegistration.pipe(
      tap(({ movement: { drop } }) => this.polylinesManager.get(id).enableEdit && this.cameraService.enableInputs(drop)))
      .subscribe(({ movement: { endPosition, drop }, entities }) => {
        const position = this.screenToPosition(endPosition, options.clampHeightTo3D, options.clampHeightTo3DOptions);
        if (!position) {
          return;
        }
        const point: EditPoint = entities[0];

        const update = {
          id,
          positions: this.getPositions(id),
          editMode: EditModes.EDIT,
          updatedPosition: position,
          updatedPoint: point,
          editAction: drop ? EditActions.DRAG_POINT_FINISH : EditActions.DRAG_POINT,
        };
        this.updateSubject.next(update);
        editSubject.next({
          ...update,
          positions: this.getPositions(id),
          points: this.getPoints(id),
        });

        this.clampPointsDebounced(id, options.clampHeightTo3D, options.clampHeightTo3DOptions);
      });

    pointRemoveRegistration.subscribe(({ entities }) => {
      const point: EditPoint = entities[0];
      const allPositions = [...this.getPositions(id)];
      if (allPositions.length < 3) {
        return;
      }
      const index = allPositions.findIndex(position => point.getPosition().equals(position as Cartesian3));
      if (index < 0) {
        return;
      }

      const update = {
        id,
        positions: allPositions,
        editMode: EditModes.EDIT,
        updatedPoint: point,
        editAction: EditActions.REMOVE_POINT,
      };
      this.updateSubject.next(update);
      editSubject.next({
        ...update,
        positions: this.getPositions(id),
        points: this.getPoints(id),
      });

      this.clampPoints(id, options.clampHeightTo3D, options.clampHeightTo3DOptions);
    });

    const observables = [pointDragRegistration, pointRemoveRegistration];
    if (shapeDragRegistration) {
      observables.push(shapeDragRegistration);
    }
    this.observablesMap.set(id, observables);
    return this.createEditorObservable(editSubject, id);
  }

  private setOptions(options: PolylineEditOptions) {
    const defaultClone = JSON.parse(JSON.stringify(DEFAULT_POLYLINE_OPTIONS));
    const polylineOptions: PolylineEditOptions = Object.assign(defaultClone, options);
    polylineOptions.pointProps = {...DEFAULT_POLYLINE_OPTIONS.pointProps, ...options.pointProps};
    polylineOptions.polylineProps = {...DEFAULT_POLYLINE_OPTIONS.polylineProps, ...options.polylineProps};
    polylineOptions.clampHeightTo3DOptions = {...DEFAULT_POLYLINE_OPTIONS.clampHeightTo3DOptions, ...options.clampHeightTo3DOptions};

    if (options.clampHeightTo3D) {
      if (!this.cesiumScene.pickPositionSupported || !this.cesiumScene.clampToHeightSupported) {
        throw new Error(`Cesium pickPosition and clampToHeight must be supported to use clampHeightTo3D`);
      }

      if (this.cesiumScene.pickTranslucentDepth) {
        console.warn(`Cesium scene.pickTranslucentDepth must be false in order to make the editors work properly on 3D`);
      }

      if (polylineOptions.pointProps.color.alpha === 1 || polylineOptions.pointProps.outlineColor.alpha === 1) {
        console.warn('Point color and outline color must have alpha in order to make the editor work properly on 3D');
      }

      polylineOptions.allowDrag = false;
      polylineOptions.polylineProps.clampToGround = true;
      polylineOptions.pointProps.heightReference = polylineOptions.clampHeightTo3DOptions.clampToTerrain ?
        Cesium.HeightReference.CLAMP_TO_GROUND : Cesium.HeightReference.RELATIVE_TO_GROUND;
      polylineOptions.pointProps.disableDepthTestDistance = Number.POSITIVE_INFINITY;
    }
    return polylineOptions;
  }


  private createEditorObservable(observableToExtend: any, id: string, finishCreation?: (position: Cartesian3) => boolean)
                                                                                                      : PolylineEditorObservable {
    observableToExtend.dispose = () => {
      const observables = this.observablesMap.get(id);
      if (observables) {
        observables.forEach(obs => obs.dispose());
      }
      this.observablesMap.delete(id);
      this.updateSubject.next({
        id,
        editMode: EditModes.CREATE_OR_EDIT,
        editAction: EditActions.DISPOSE,
      });
    };

    observableToExtend.enable = () => {
      this.updateSubject.next({
        id,
        positions: this.getPositions(id),
        editMode: EditModes.EDIT,
        editAction: EditActions.ENABLE,
      });
    };

    observableToExtend.disable = () => {
      this.updateSubject.next({
        id,
        positions: this.getPositions(id),
        editMode: EditModes.EDIT,
        editAction: EditActions.DISABLE,
      });
    };

    observableToExtend.setManually = (points: {
      position: Cartesian3,
      pointProp?: PointProps
    }[] | Cartesian3[], polylineProps?: PolylineProps) => {
      const polyline = this.polylinesManager.get(id);
      polyline.setManually(points, polylineProps);
      this.updateSubject.next({
        id,
        editMode: EditModes.CREATE_OR_EDIT,
        editAction: EditActions.SET_MANUALLY,
      });
    };

    observableToExtend.setLabelsRenderFn = (callback: any) => {
      this.updateSubject.next({
        id,
        editMode: EditModes.CREATE_OR_EDIT,
        editAction: EditActions.SET_EDIT_LABELS_RENDER_CALLBACK,
        labelsRenderFn: callback,
      });
    };

    observableToExtend.updateLabels = (labels: LabelProps[]) => {
      this.updateSubject.next({
        id,
        editMode: EditModes.CREATE_OR_EDIT,
        editAction: EditActions.UPDATE_EDIT_LABELS,
        updateLabels: labels,
      });
    };

    observableToExtend.finishCreation = () => {
      if (!finishCreation) {
        throw new Error('Polylines editor error edit(): cannot call finishCreation() on edit');
      }

      return finishCreation(null);
    };

    observableToExtend.getCurrentPoints = () => this.getPoints(id);

    observableToExtend.getEditValue = () => observableToExtend.getValue();

    observableToExtend.getLabels = (): LabelProps[] => this.polylinesManager.get(id).labels;

    return observableToExtend as PolylineEditorObservable;
  }

  private getPositions(id: string) {
    const polyline = this.polylinesManager.get(id);
    return polyline.getRealPositions();
  }

  private getPoints(id: string) {
    const polyline = this.polylinesManager.get(id);
    return polyline.getRealPoints();
  }
}

result-matching ""

    No results matching ""