- All Implemented Interfaces:
Localized
- Direct Known Subclasses:
PlanarCanvas
This Canvas
base class does not draw anything by itself.
Subclasses are responsible for drawing graphic elements.
The visual contents are usually geographic located symbols, features or images,
but some implementations can also manage non-geographic elements like a map scale.
A Canvas
manages four fundamental properties:
- The coordinate reference system to use for displaying data.
- The location of data to display in all dimensions, including the dimensions not shown by the display device (for example time).
- The size of the display device, in units of the display coordinate system (typically pixels).
- The conversion from the Coordinate Reference System to the display coordinate system.
Coordinate Reference Systems
There is three Coordinate Reference Systems involved in the rendering of geospatial data:- The data CRS is specific to the data to be displayed. It may be anything convertible to the objective CRS. Different graphic elements may use different data CRS, potentially with a different number of dimensions.
- The objective CRS is the common CRS in which all data
are converted before to be displayed. If the objective CRS involves a map projection,
it determines the deformation of shapes that user will see on the display device.
The objective CRS should have the same number of dimensions than the display device
(often 2). Its domain of validity should be wide enough for encompassing all data.
The
CRS.suggestCommonTarget(…)
method may be helpful for choosing an objective CRS from a set of data CRS. - The display CRS is the coordinate system of the display device. The conversion from objective CRS to display CRS should be an affine transform with a scale, a translation and optionally a rotation. This conversion changes every time that the user zooms or scrolls on viewed data.
Location of data to display
In addition of above-cited Coordinate Reference Systems, aCanvas
also contains a point of interest.
The point of interest is often, but not necessarily, at the center of display area.
It defines the position where resolutions will be computed,
and the position to keep fixed when scales and rotations are applied.
The point of interest can be expressed in any CRS; it does not need to be the objective CRS or the CRS of any data. However, the CRS of that point must have enough dimensions for being convertible to the CRS of all data. This rule implies that the number of dimensions of the point of interest is equal or greater than the highest number of dimensions found in data. The purpose is not only to specify which point to show in (typically) the center of the display area, but also to specify which slice to select in all dimensions not shown by the display device.
Example
If some data have (x,y,z) dimensions and other data have (x,y,t) dimensions, then the point of interest shall contain coordinate values for at least all of the (x,y,z,t) dimensions (i.e. it must be 4-dimensional, even if all data in this example are 3-dimensional). If the display device is a two-dimensional screen showing map in the (x,y) dimensions (horizontal plane), then the point of interest defines the z value (elevation or depth) and the t value (date and time) of the slice to show.Display device size
The geographic extent of data to be rendered is constrained by the zoom level and the display device size. The display size is given bygetDisplayBounds()
as an envelope having the number of dimensions of
the display device. The display bounds is usually given in pixel units, but other
units such as Units.POINT
are also authorized.
The zoom level is given indirectly by the getObjectiveToDisplay()
transform.
The display device may have a wraparound axis, for example in the spherical coordinate system of a planetarium.
Multi-threading
Canvas
is not thread-safe. Synchronization, if desired, must be done by the caller.
Another common strategy is to interact with Canvas
from a single thread,
for example the Swing or JavaFX event queue.- Since:
- 1.1
-
Field Summary
Modifier and TypeFieldDescriptionstatic final String
The "displayBounds" property name, used for notifications about changes in bounds of display device.static final String
The "objectiveCRS" property name, used for notifications about changes in objective CRS.static final String
The "objectiveToDisplay" property name, used for notifications about changes in objective to display conversion.static final String
The "pointOfInterest" property name, used for notifications about changes in point of interest. -
Constructor Summary
ModifierConstructorDescriptionprotected
Canvas
(EngineeringCRS displayCRS, Locale locale) Creates a new canvas for a display device using the given coordinate reference system. -
Method Summary
Modifier and TypeMethodDescriptionfinal void
addPropertyChangeListener
(String propertyName, PropertyChangeListener listener) Registers a listener for the property of the given name.protected void
Notifies all registered listeners that a property changed its value.protected void
firePropertyChange
(String propertyName, Object oldValue, Object newValue) Notifies all registered listeners that a property of the given name changed its value.Returns the size and location of the display device.final EngineeringCRS
Returns the Coordinate Reference System of the display device.Returns the geographic bounding box encompassing the area shown on the display device.Returns canvas properties (CRS, display bounds, conversion) encapsulated in a grid geometry.Returns the locale used for texts or for producing some error messages.Returns the Coordinate Reference System in which all data are transformed before displaying.Returns the (usually affine) conversion from objective CRS to display coordinate system.getPointOfInterest
(boolean objective) Returns the coordinates of a point considered representative of the data.Returns an estimation of the resolution (in metres) at the point of interest.protected final boolean
hasPropertyChangeListener
(String propertyName) Returnstrue
if the given property has at least one listener.final void
removePropertyChangeListener
(String propertyName, PropertyChangeListener listener) Unregisters a property listener.void
setDisplayBounds
(Envelope newValue) Sets the size and location of the display device.void
setGridGeometry
(GridGeometry newValue) Sets canvas properties from the given grid geometry.void
setObjectiveCRS
(CoordinateReferenceSystem newValue, DirectPosition anchor) Sets the Coordinate Reference System in which all data are transformed before displaying.void
setObjectiveToDisplay
(LinearTransform newValue) Sets the conversion from objective CRS to display coordinate system.void
setPointOfInterest
(DirectPosition newValue) Sets the coordinates of a representative point inside the data bounding box.
-
Field Details
-
OBJECTIVE_CRS_PROPERTY
The "objectiveCRS" property name, used for notifications about changes in objective CRS. The objective CRS is the Coordinate Reference System in which all data are transformed before displaying. Its number of dimension is the determined by the display device (two for flat screens). Associated values are instances ofCoordinateReferenceSystem
.- See Also:
-
OBJECTIVE_TO_DISPLAY_PROPERTY
The "objectiveToDisplay" property name, used for notifications about changes in objective to display conversion. This conversion maps coordinates in the objective CRS to coordinates in the display CRS. Associated values are instances ofLinearTransform
. The event class is theTransformChangeEvent
specialization.- See Also:
-
DISPLAY_BOUNDS_PROPERTY
The "displayBounds" property name, used for notifications about changes in bounds of display device. It may be for example changes in the size of the window were data are shown. Associated values are instances ofEnvelope
.- See Also:
-
POINT_OF_INTEREST_PROPERTY
The "pointOfInterest" property name, used for notifications about changes in point of interest. The point of interest defines the location of a representative point, typically (but not necessarily) in the center of the data bounding box. It defines also the slice coordinate values in all dimensions beyond the ones shown by the device. Associated values are instances ofDirectPosition
.- See Also:
-
-
Constructor Details
-
Canvas
Creates a new canvas for a display device using the given coordinate reference system. The display CRS of a canvas cannot be changed after construction. Its coordinate system depends on the display device shape (for example a two-dimensional Cartesian coordinate system for flat screens, or a polar or spherical coordinate system for planetarium domes). The axis units of measurement are typically (but not necessarily)Units.PIXEL
for Cartesian coordinate systems, withUnits.DEGREE
in polar, cylindrical or spherical coordinate systems.- Parameters:
displayCRS
- the coordinate system of the display device.locale
- the locale to use for labels and some messages, ornull
for default.
-
-
Method Details
-
getLocale
Returns the locale used for texts or for producing some error messages. May benull
if no locale has been specified, in which case the system default should be used.- Specified by:
getLocale
in interfaceLocalized
- Returns:
- the locale for messages, or
null
if not explicitly defined.
-
getDisplayCRS
Returns the Coordinate Reference System of the display device. The axis units of measurement are typically (but not necessarily)Units.PIXEL
for Cartesian coordinate systems, withUnits.DEGREE
in polar, cylindrical or spherical coordinate systems. The coordinate system may have a wraparound axis for some "exotic" display devices (e.g. planetarium dome).Note that the
CRS.findOperation(…)
static method can generally not handle this display CRS. To apply coordinate operations on display coordinates,getObjectiveToDisplay()
transform must be inverted and used.Usage note
Invoking this method is rarely needed. It is sufficient to said that a display CRS exists at least conceptually, and that we define a conversion from the objective CRS to that display CRS. This method may be useful when the subclasses may be something else thanPlanarCanvas
, in which case the caller may want more information about the geometry of the display device.- Returns:
- the Coordinate Reference System of the display device.
- See Also:
-
getObjectiveCRS
Returns the Coordinate Reference System in which all data are transformed before displaying. After conversion to this CRS, coordinates should be related to the display device coordinates with only a final scale, a translation and optionally a rotation remaining to apply.This value may be
null
on newly createdCanvas
, before data are added and canvas is configured. It should not benull
anymore once aCanvas
is ready for displaying.- Returns:
- the Coordinate Reference System in which to transform all data before displaying.
- See Also:
-
setObjectiveCRS
public void setObjectiveCRS(CoordinateReferenceSystem newValue, DirectPosition anchor) throws RenderException Sets the Coordinate Reference System in which all data are transformed before displaying. The new CRS must be compatible with the previous CRS, i.e. a coordinate operation between the two CRSs shall exist. If this is not the case (e.g. for rendering completely new data), usesetGridGeometry(GridGeometry)
instead.The given CRS should have a domain of validity wide enough for encompassing all data (the
CRS.suggestCommonTarget(…)
method may be helpful for choosing an objective CRS from a set of data CRS). If the given value is different than the previous value, then a change event is sent to all listeners registered for the "objectiveCRS" property.If the transform between old and new CRS is not identity, then this method recomputes the objective to display conversion in a way preserving the display coordinates of the given anchor, together with the scales and orientations of features in close neighborhood of that point. This calculation may cause "objectiveToDisplay" property change event with the
TransformChangeEvent.Reason.CRS_CHANGE
reason to be sent to listeners. That event is sent after the above-cited "objectiveCRS" event (note that "pointOfInterest" stay unchanged). All those change events are sent only after all property values have been updated to their new values.- Parameters:
newValue
- the new Coordinate Reference System in which to transform all data before displaying.anchor
- the point to keep at fixed display coordinates, expressed in any compatible CRS. Ifnull
, defaults to point of interest. If non-null, the anchor must be associated to a CRS.- Throws:
NullPointerException
- if the given CRS is null.MismatchedDimensionException
- if the given CRS does not have the number of dimensions of the display device.RenderException
- if the objective CRS cannot be set to the given value for another reason.
-
getObjectiveToDisplay
Returns the (usually affine) conversion from objective CRS to display coordinate system. The source coordinates shall be in the CRS given bygetObjectiveCRS()
and the converted coordinates will be in the CRS given bygetDisplayCRS()
.The objective to display conversion changes every time that user zooms or scrolls on viewed data. However, the transform returned by this method is a snapshot taken at the time this method is invoked; subsequent changes in the objective to display conversion are not reflected in the returned transform.
- Returns:
- snapshot of the (usually affine) conversion from objective CRS
to display coordinate system (never
null
). - See Also:
-
setObjectiveToDisplay
Sets the conversion from objective CRS to display coordinate system. If the given value is different than the previous value, then a change event is sent to all listeners registered for the "objectiveToDisplay" property. The event reason isTransformChangeEvent.Reason.ASSIGNMENT
.Invoking this method has the effect of changing the viewed area, the zoom level or the rotation of the map. It does not update the "pointOfInterest" property however. The point of interest may move outside the view area as a result of this method call.
- Parameters:
newValue
- the new objective to display conversion.- Throws:
IllegalArgumentException
- if given the transform does not have the expected number of dimensions or is not affine.RenderException
- if the objective to display transform cannot be set to the given value for another reason.
-
getDisplayBounds
Returns the size and location of the display device. The unit of measurement is typically (but not necessarily) pixels. The coordinate values are often integers, but this is not mandatory. The coordinate reference system is given bygetDisplayCRS()
.This value may be
null
on newly createdCanvas
, before data are added and canvas is configured. It should not benull
anymore once aCanvas
is ready for displaying.- Returns:
- size and location of the display device.
- See Also:
-
setDisplayBounds
Sets the size and location of the display device. The envelope CRS shall be either the display CRS or unspecified, in which case the display CRS is assumed. Unit of measurement is typically (but not necessarily)Units.PIXEL
. If the given value is different than the previous value, then a change event is sent to all listeners registered for the "displayBounds" property.- Parameters:
newValue
- the new display bounds.- Throws:
IllegalArgumentException
- if the given envelope does not have the expected CRS or number of dimensions.RenderException
- if the display bounds cannot be set to the given value for another reason.
-
getPointOfInterest
Returns the coordinates of a point considered representative of the data. This is typically (but not necessarily) the center of data bounding box. This point is used for example as the default location where to compute resolution (the resolution may vary at each pixel because of map projection deformations). This position may become outside the viewing area after zooms or translations have been applied.The coordinates can be given in their original CRS or in the objective CRS. If
objective
isfalse
, then the returned position can be expressed in any CRS convertible to data or objective CRS. If that CRS has more dimensions than the objective CRS, then the supplemental dimensions specify which slice to show (for example the depth of the horizontal plane to display, or the date of the dynamic phenomenon to display. See class javadoc for more discussion.) Ifobjective
istrue
, then the position is transformed to the objective CRS.This value is initially
null
. A value should be specified either by invokingsetPointOfInterest(DirectPosition)
orsetGridGeometry(GridGeometry)
.- Parameters:
objective
- whether to return a position transformed to objective CRS.- Returns:
- coordinates of a representative point, or
null
if unspecified. - See Also:
-
setPointOfInterest
Sets the coordinates of a representative point inside the data bounding box. If the given value is different than the previous value, then a change event is sent to all listeners registered for the "pointOfInterest" property.- Parameters:
newValue
- the new coordinates of a representative point.- Throws:
NullPointerException
- if the given position is null.IllegalArgumentException
- if the given position does not have a CRS.RenderException
- if the point of interest cannot be set to the given value.
-
getGridGeometry
Returns canvas properties (CRS, display bounds, conversion) encapsulated in a grid geometry. This is a convenience method for interoperability with grid coverage API. IfsetGridGeometry(GridGeometry)
has been invoked with a non-null value and no otherCanvas
property changed since that method call, then this method returns that value. Otherwise this method computes a grid geometry as described below.The set of
GridGeometry
dimensions includes all the dimensions of the objective CRS, augmented with all (if possible) or some supplemental dimensions found in the point of interest. For example if the canvas manages only (x,y) coordinates but the point of interest includes also a t coordinate, then a third dimension (which we call the supplemental dimension) for t is added to the CRS,GridExtent
and "grid to CRS" transform of the returned grid geometry.Canvas properties → grid geometry properties Grid geometry element Display dimensions Supplemental dimensions GridGeometry.getCoordinateReferenceSystem()
getObjectiveCRS()
.Some of getPointOfInterest(false).getCoordinateReferenceSystem()
GridGeometry.getExtent()
getDisplayBounds()
rounded to enclosing (floor and ceil) integers[0 … 0] GridGeometry.getGridToCRS(PixelInCell)
Inverse of getObjectiveToDisplay()
Some point of interest coordinates as translation terms GridGeometry.getGridToCRS(PixelInCell)
transform built by this method is always aLinearTransform
. This linearity implies that the grid geometry CRS cannot be the Point Of Interest (POI) CRS, unless conversion from POI CRS to objective CRS is linear.- Returns:
- a grid geometry encapsulating canvas properties, including supplemental dimensions if possible.
- Throws:
RenderException
- if the grid geometry cannot be computed.
-
setGridGeometry
Sets canvas properties from the given grid geometry. This convenience method converts the coordinate reference system, "grid to CRS" transform and extent of the given grid geometry toCanvas
properties. If the given value is different than the previous value, then change events are sent to all listeners registered for the "displayBounds", "objectiveCRS", "objectiveToDisplay" (withTransformChangeEvent.Reason.GRID_GEOMETRY_CHANGE
reason), and/or "pointOfInterest" properties, in that order.The value given to this method will be returned by
getGridGeometry()
as long as none of above cited properties is changed. If one of those properties changes (for example if the user zooms or pans the map), then a new grid geometry will be computed. There is no guarantee that the recomputed grid geometry will be similar to the grid geometry specified to this method. For example, theGridExtent
in supplemental dimensions may be different.- Parameters:
newValue
- the grid geometry from which to get new canvas properties.- Throws:
RenderException
- if the given grid geometry cannot be converted to canvas properties.
-
getGeographicArea
Returns the geographic bounding box encompassing the area shown on the display device. If the objective CRS is not convertible to a geographic CRS, then this method returns an empty value.- Returns:
- geographic bounding box encompassing the viewed area.
- Throws:
RenderException
- in an error occurred while computing the geographic area.- See Also:
-
getSpatialResolution
Returns an estimation of the resolution (in metres) at the point of interest. If the objective CRS is not convertible to a geographic CRS, then this method returns an empty value.- Returns:
- estimation of the resolution in metres at current point of interest.
- Throws:
RenderException
- in an error occurred while computing the resolution.
-
addPropertyChangeListener
Registers a listener for the property of the given name. The listener will be notified every time that the property of the given name got a new value. If the same listener is registered twice for the same property, then it will be notified twice (this method does not perform duplication checks).- Parameters:
propertyName
- name of the property to listen (should be one of the*_PROPERTY
constants).listener
- property listener to register.
-
removePropertyChangeListener
public final void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) Unregisters a property listener. The givenpropertyName
should be the name used during listener registration. If the specified listener is not registered for the named property, then nothing happen. If the listener has been registered twice, then only one registration is removed (one registration will remain).- Parameters:
propertyName
- name of the listened property.listener
- property listener to unregister.
-
hasPropertyChangeListener
Returnstrue
if the given property has at least one listener.- Parameters:
propertyName
- name of the property to test.- Returns:
true
if the given property has at least one listener.
-
firePropertyChange
Notifies all registered listeners that a property of the given name changed its value. The change event source will bethis
. It is caller responsibility to verify that the old and new values are different (this method does not check for equality).- Parameters:
propertyName
- name of the property that changed its value.oldValue
- the old property value (may benull
).newValue
- the new property value (may benull
).- See Also:
-
firePropertyChange
Notifies all registered listeners that a property changed its value. It is caller responsibility to verify that the event source and property name are valid.- Parameters:
event
- the event to forward. Cannot be null.- See Also:
-