Transformations between view and model coordinates

An important aspect of working with an ILcdGXYView is the ability to transform between view coordinates and model coordinates.

For an introduction of the coordinate systems that are used internally by an ILcdGXYView, see Coordinate systems and transformations. That article discusses the classes used to transform data from one coordinate system to another as well.

This article describes in more detail how to transform view coordinates to model coordinates. A typical application of such a transformation is to find out which objects in a model are located under the mouse cursor. The cursor position is defined in view coordinates, and to find the corresponding domain objects, the application needs to transform the cursor’s position to model coordinates.

This transformation happens in two steps:

  1. The first step is a transformation from view coordinates to world coordinates. This step is performed using an ILcdGXYViewXYWorldTransformation.

  2. The second step is to transform the world coordinates to model coordinates, using an ILcdModelXYWorldTransformation.

The most convenient way to obtain the appropriate transformation classes is through an ILcdGXYContext. An ILcdGXYContext is typically used by painters and editors, as described in Painting and editing domain objects in a GXY view.

In other situations, the class TLcdGXYContext can be used to construct a context manually. TLcdGXYContext must be provided with an ILcdGXYView and an ILcdGXYLayer. The context then provides immediate access to the transformations needed.

From view coordinates to world coordinates

To go from view to world coordinates, the ILcdGXYViewXYWorldTransformation is obtained from the ILcdGXYContext. You can then use either viewAWTPoint2worldSFCT() or viewXYPoint2worldSFCT() to transform from view coordinates to world coordinates. The former method requires a Point as input, the latter requires an ILcdPoint. Both methods store the transformed result in a side effect parameter. Note that this parameter should be of type TLcdXYPoint rather than TLcdLonLatPoint, as the latter cannot represent coordinates with the large range that is usually required for world coordinates.

Note that the methods mentioned above operate on points. Equivalent methods enable you to transform bounding boxes: ILcdGXYViewXYWorldTransformation has methods viewAWTBounds2worldSFCT() and viewXYBounds2worldSFCT()

From world coordinates to model coordinates

Given the world coordinates, you can now obtain the ILcdModelXYWorldTransformation from the ILcdGXYContext and continue with the transformation to model coordinates. This is done using the worldPoint2modelSFCT() method. The SFCT model point in this method should be an ILcdPoint that can be used in the reference of the model to which you are transforming, a TLcdLonLatHeightPoint for geodetic references or a TLcdXYZPoint for other references.

Note that the methods mentioned above operate on points. An equivalent method enables you to transform bounding boxes: ILcdModelXYWorldTransformation has a method worldBounds2modelSFCT()

From model coordinates to view coordinates

The methods discussed in the previous sections have counterparts that work in the opposite direction, which allows for the transformation from model coordinates to view coordinates. Be aware however that an ILcdBounds may be enlarged as a result of the transformation. Therefore, transforming a bounding box from view to model coordinates and back may produce a result that differs significantly from the input.

Program: Transforming a bounding box from view to model coordinates, taken from samples.gxy.transformation, shows how to transform an ILcdBounds from view to model coordinates.

Program: Transforming a bounding box from view to model coordinates (from samples/gxy/transformation/mouseToGeodetic/TransformCoordinatesController)
/**
 * Computes a bounding box in model coordinates that corresponds to the given
 * rectangle in view coordinates.
 *
 * @param aViewBounds The rectangle in view coordinates (pixels)
 * @param aView  the ILcdGXYView on which the rectangle is located
 * @param aLayer the ILcdGXYLayer for whose model we're computing the bounds
 * @return an ILcdBounds in model coordinates
 * @throws TLcdOutOfBoundsException
 *          if the world to model transformation is unsuccessful
 */
private ILcdBounds getModelBoundsForViewBounds(
    Rectangle aViewBounds,
    ILcdGXYView aView,
    ILcdGXYLayer aLayer
                                              ) throws TLcdOutOfBoundsException {

  // The (2D) world coordinate system works with XY coordinates.
  TLcdXYBounds worldBounds = new TLcdXYBounds();

  // The model coordinate system isn't known. The model reference helps
  // to create compatible bounds (e.g. XY or LonLat).
  ILcdPoint modelPoint = aLayer.getModel().getModelReference().makeModelPoint();
  ILcd3DEditableBounds modelBounds = modelPoint.getBounds().cloneAs3DEditableBounds();

  // We use TLcdGXYContext to easily obtain the appropriate transformations.
  TLcdGXYContext context = new TLcdGXYContext(aView, aLayer);

  // Transform from view to world and from world to model coordinates.
  // Various other methods are available on the transformations, for example to transform
  // just points.
  context.getGXYViewXYWorldTransformation().viewAWTBounds2worldSFCT(aViewBounds, worldBounds);
  context.getModelXYWorldTransformation().worldBounds2modelSFCT(worldBounds, modelBounds);

  return modelBounds;
}