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

Creating and visualizing point-to-shape visibility calculations is a multi-step process:

  1. Create one or more observers

  2. For each of the created observers, indicate which objects they need to observe

Creating the observer

Use the TLcyShapeVisibilityManager to create an observer. This manager offers API to create observers for a domain object, and adds those observers to the map:

//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 created TLcyShapeObserver remains synchronized with the object for which it was created:

  • When the object moves, the observer moves as well.

  • When the object is removed from the map, the observer is removed as well.

Start observing an object

The TLcyShapeObserver instance offers the startObserving method to start 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();
}

Starting the observation of an object is considered a model change. This means that you need to start the observation under a write lock, as illustrated in the snippet.

As soon as the result of the calculation is available, it becomes visible on the map.

Stop observing an object

The TLcyShapeObserver instance also offers a stopObserving method to stop observing an object. Just like the startObserving method, you must call it under a write lock:

//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"));
//Stop observing a specific shape
//As this modifies the point observer, it requires a lock on the point observer model
try (TLcdLockUtil.Lock autoUnlock = TLcdLockUtil.writeLock(pointObserverModel)) {
  //Tell the observer to stop observing a specific object
  pointObserver.stopObserving(aDomainObjectContextToObserve);
  //Indicate to the model that the observer has been changed
  pointObserverModel.elementChanged(pointObserver, ILcdModel.FIRE_LATER);
} finally {
  pointObserverModel.fireCollectedModelChanges();
}