High-level overview

  • Mark existing objects on a map as observers

  • Mark other objects on the map as being under observation by one or more observers

  • Visualize the results of the visibility calculations on the map

To learn more about visibility calculations in LuciadLightspeed, see About shape visibility.

The most important classes are:

  • TLcyShapeVisibilityManager: a manager that allows you to create observer object (TLcyShapeObserver) instances for an existing object on the map.

  • TLcyShapeObserver: the observer domain object. It has methods to:

    • Start observing another object

    • Stop observing another object

    • Obtain a reference to the objects that are being observed

    • Obtain a reference to the object for which the observer was created

  • TLcyShapeObservationResult: the domain object representing the result of the visibility calculation. The result has methods to:

    • Obtain a reference to the observers

    • Obtain a reference to the object that is being observed

    • Obtain the ILcdReferencedMatrixView, which is the result of the visibility calculation

Creating an observer

You create an observer through the TLcyShapeVisibilityManager:

//Retrieve the manager from the services
TLcyShapeVisibilityManager manager = aLucyEnv.getService(TLcyShapeVisibilityManager.class);

//Ask the manager to create an observer for the specified domain object
//Interacting with the manager must happen on the AWT thread (Event Dispatch Thread)
if (manager.canAddObserver(aDomainObjectContext)) {
  TLcyShapeObserver pointObserver = manager.addObserver(aDomainObjectContext);
}

The addObserver method:

  • Creates the observer.

  • Adds it to the map. If it is the first observer, the necessary layers are added to the map.

  • Returns the created observer.

create observer

The created observer is automatically kept in-sync with the object for which it was created:

  • If the object moves, the observer is moved as well. New visibility calculations are automatically triggered.

  • If the object is removed, the observer will be removed as well. If the observer is removed:

    • All calculation results with that observer as the single observer are removed as well.

    • All results with multiple observers including the removed observer, are re-calculated.

Start observing an object

The TLcyShapeObserver class has methods to start and stop observing an object:

//Find the observer model in the view
ILcdModel pointObserverModel = view.getLayers()
                                   .stream()
                                   .map(ILcdLayer::getModel)
                                   .filter(model -> Objects.equals(TLcyShapeVisibilityAddOn.OBSERVER_MODEL_TYPE_NAME, model.getModelDescriptor().getTypeName()))
                                   .findFirst()
                                   .orElseThrow(() -> new RuntimeException("Cannot find the model containing the observers"));
//Let the observer observe another shape
//As this modifies the point observer, it requires a lock on the point observer model
try (TLcdLockUtil.Lock autoUnlock = TLcdLockUtil.writeLock(pointObserverModel)) {
  if (pointObserver.canObserve(aDomainObjectContextToObserve)) {
    //Tell the observer to start observing another object
    pointObserver.startObserving(aDomainObjectContextToObserve);
    //Indicate to the model that the observer has been changed
    pointObserverModel.elementChanged(pointObserver, ILcdModel.FIRE_LATER);
  }
} finally {
  pointObserverModel.fireCollectedModelChanges();
}

Calling the startObserving method:

  • Creates a TLcyShapeObservationResult if necessary. If the object is already under observation by another observer, the existing result will be re-used and updated. If it is not, a new result instance is created.

  • Adds the calculation result to the map. If necessary, a layer for the results is added to the map

  • Returns the result. At this point, the visibility calculation in the result hasn’t been updated yet for the new observer.

  • A new calculation is scheduled on a background thread. When that thread completes the calculation, it will update the result.

start observing