NCL Home > Documentation > HLUs > Classes

PlotManager class

The PlotManager allows a plot object to manage overlays and annotations.


Header file:		ncarg/hlu/PlotManager.h
Class name:		plotManagerClass
Class pointer:		<Not referenceable>
Fortran class function:	<Not referenceable>
Superclass:		Transform
Composite classes:	LabelBar,Legend,TickMark,Title

Class-defined types

Type name:		NhlTAnnotationDisplayMode
typedef enum _NhlAnnotationDisplayMode {
	NhlNOCREATE	= -1,	/* "NoCreate"	 */
	NhlNEVER	= 0,	/* "Never"	 */
	NhlALWAYS	= 1,	/* "Always" 	 */
	NhlCONDITIONAL	= 2	/* "Conditional" */
} NhlAnnotationDisplayMode;


Local resources

PlotManager resources are available to objects of the Transform class that include PlotManager as a composite class member, providing that the Transform class resource tfPlotManagerOn is set to its default value, True, when the object is created. Currently, there are seven composite classes that include the PlotManager:
|		PlotManager Resource Set			|
| pmOverlaySequenceIds		NhlTObjIdGenArray	G	|
|	PmOverlaySequenceIds		NULL			|
| pmAnnoViews			NhlTObjIdGenArray	CSG	|
|	PmAnnoViews			NULL			|
| pmAnnoManagers		NhlTObjIdGenArray	G	|
|	PmAnnoManagers			NULL			|
| pmTitleDisplayMode		NhlTAnnotationDisplayMode RCSG	|
|	PmDisplayTitles			NoCreate		|
| pmTitleZone			NhlTInteger		RCSG	|
|	PmTitleZone			4			|
| pmTickMarkDisplayMode		NhlTAnnotationDisplayMode RCSG	|
|	PmDisplayTickMarks		NoCreate		|
| pmTickMarkZone		NhlTInteger		RCSG	|
|	PmTickMarkZone			2			|
| pmLabelBarDisplayMode		NhlTAnnotationDisplayMode RCSG	|
|	PmDisplayLabelBar		NoCreate		|
| pmLabelBarWidthF		NhlTFloat		RCSG	|
|	PmLabelBarWidthF		0.15			|
| pmLabelBarHeightF		NhlTFloat		RCSG	|
|	PmLabelBarHeightF		0.6			|
| pmLabelBarKeepAspect		NhlTBoolean		RCSG	|
|	PmLabelBarKeepAspect		False			|
| pmLabelBarZone		NhlTInteger		RCSG	|
|	PmLabelBarZone			6			|
| pmLabelBarSide		NhlTJustification	RCSG	|
|	PmLabelBarSide			Right			|
| pmLabelBarParallelPosF	NhlTFloat		RCSG	|
|	PmLabelBarParallelPosF		0.5			|
| pmLabelBarOrthogonalPosF	NhlTFloat		RCSG	|
|	PmLabelBarOrthogonalPosF	0.02			|
| pmLegendDisplayMode		NhlTAnnotationDisplayMode RCSG	|
|	PmDisplayLegend			NoCreate		|
| pmLegendWidthF		NhlTFloat		RCSG	|
|	PmLegendWidthF			0.55			|
| pmLegendHeightF		NhlTFloat		RCSG	|
|	PmLegendHeightF			0.18			|
| pmLegendKeepAspect		NhlTBoolean		RCSG	|
|	PmLegendKeepAspect		False			|
| pmLegendZone			NhlTInteger		RCSG	|
|	PmLegendZone			7			|
| pmLegendSide			NhlTPosition		RCSG	|
|	PmLegendSide			Bottom			|
| pmLegendParallelPosF	 	NhlTFloat		RCSG	|
|	PmLegendParallelPosF		0.5			|
| pmLegendOrthogonalPosF	NhlTFloat		RCSG	|
|	PmLegendOrthogonalPosF		0.02			|

Composite resources

TickMark resources

If pmTickMarkDisplayMode has the value NoCreate when a PlotManager composite object is created, no TickMark resources are available. Otherwise, you can set all TickMark resources for PlotManager composite objects except for the following resources that PlotManager disables: PlotManager sets these resources itself based on its knowledge of the current transformation. Note that the TickMark object does not currently support ticks for Map transformations.

Title resources

If pmTitleDisplayMode has the value NoCreate when a PlotManager composite object is created, no Title resources are available. Otherwise, you can set all Title resources for PlotManager composite objects. However, note that PlotManager intercepts three Title resources, as follows:
  • tiMainFontHeightF
    PlotManager sets the default value of tiMainFontHeightF dynamically based on the ratio of the actual plot viewport width to a reference viewport width of 0.6 and a reference font height of 0.025.
  • tiXAxisFontHeightF
    PlotManager sets the default value of tiXAxisFontHeightF dynamically based on the ratio of the actual plot viewport width to a reference viewport width of 0.6 and a reference font height of 0.025.
  • tiYAxisFontHeightF
    PlotManager sets the default value of tiYAxisFontHeightF dynamically based on the ratio of the actual plot viewport height to a reference viewport height of 0.6 and a reference font height of 0.025.

LabelBar resources

If pmLabelBarDisplayMode has the value NoCreate when a PlotManager composite object is created, no LabelBar resources are available. Otherwise, you can set all LabelBar resources for PlotManager composite objects, except for the following disabled resource: PlotManager intercepts two LabelBar resources, as follows:
  • lbJustification
    PlotManager sets the initial default value of lbJustification to CenterCenter. It then constrains the value of this resource using the rules of the PlotManager Location Control Model.
  • lbOrientation
    At initialization and whenever the value of lbOrientation changes, PlotManager checks the currently set values of pmLabelBarWidthF and pmLabelBarHeightF. If neither resource is explicitly set, it swaps their values if the longest dimension is not currently parallel to the orientation.

Legend resources

If pmLegendDisplayMode has the value NoCreate when a PlotManager composite object is created, no Legend resources are available. Otherwise, you can set all Legend resources for PlotManager composite objects, except for the following disabled resource: PlotManager intercepts one Legend resource, as follows:

Superclass resources

You can set all resources defined by the superclasses of the PlotManager object class in any plot object containing a PlotManager, including:


When an instance of the Transform class is instantiated with an active PlotManager, it becomes a plot object. A plot object can assume control of an arbitrary number of View objects, effectively organizing a collection of unrelated objects into a single plottable entity called simply a plot. The controlling plot object is known as the base plot; the objects it controls are plot members. When the base plot is drawn, all its plot members are drawn automatically. If you reposition the base plot, or resize it, or modify the data coordinate space in some way, all the plot members adjust themselves appropriately.

You never create an object belonging to the PlotManager class directly. Instead, the functionality of the PlotManager class becomes available to classes derived from Transform that include the PlotManager as a composite class member. By convention, these classes include the word Plot as part of their name. Currently, the following composite classes contain the PlotManager class: ContourPlot, MapPlot, LogLinPlot, IrregularPlot, StreamlinePlot, VectorPlot, and XyPlot. Each of these classes provides the capabilities of the PlotManager class by default, and therefore their instantiations are, by default, plot objects. Note that since all plot objects incorporate PlotManager functionality as an integral part of their behavior, it is equivalent -- when speaking of something that a plot object's PlotManager does -- simply to say that the plot object does it.

You may turn off the PlotManager capabilities for a Transform object by setting the Transform class resource tfPlotManagerOn to False when the object is created. However, note that you cannot turn the object's PlotManager capabilities back on at a later time. An object created with its PlotManager disabled is not a plot object; instead it is called a simple transform. A simple transform can still function as a plot member.

There are two basic kinds of plot members: overlays and annotations. An overlay must be a transform, either a plot object (with or without its own plot members) or a simple transform. An annotation, on the other hand, can be any view from a simple TextItem to a plot object with its own plot members.

The base plot transforms an overlay's data coordinate space into its own coordinate space. Any portion of the overlay's coordinate space that lies outside the coordinate space of the base plot is clipped. The viewport of the overlay is modified to match that of the base plot. In addition, if the overlay is a plot object with plot members of its own, the base plot assumes responsibility for sizing and locating the overlay's plot members, just as if it owned them.

The base plot locates and sizes an annotation relative to its viewport or to its data coordinate space. Unlike an overlay, however, there is no fixed relationship between the base plot's data coordinate space and the annotation's data coordinate space. In fact, ordinary views, from which annotations are created, do not even have a data coordinate space. The viewport of an annotation may fall inside or outside the viewport of the base plot. If the annotation happens to be a plot object, it does not give up control of its own plot members to the base plot. Indeed, an annotation plot is itself a base plot. However, since an annotation is itself managed by a base plot, an annotation plot is a subordinate base plot. A subordinate base plot and the plot members it manages are known collectively as a subplot.

In contrast to a subordinate base plot, a base plot that manages itself (i.e. is not a plot member) is called a primary base plot. Note that all plot objects are, at creation, primary base plots. When a plot object becomes an overlay, it loses its base plot status. If it is added as an annotation, its status changes to subordinate base plot. The primary base plot controls the drawing of all its plot members, and you can only cause a plot member to be drawn by calling the NhlDraw function on the primary base plot. Attempting to draw any plot member (even a subordinate base plot) directly results in an error. Similarly, you cannot change the workstation of a plot member directly. When you change the workstation of the primary base plot, the workstation of all its plot members changes to match. Also, while an object is a plot member, you cannot add it to any other (or even the same) plot object, either as an overlay or as an annotation. If you need to do any of these things with a plot member, you must first remove it from the plot object that owns it.

Adding and removing overlays

You add the plot object that is to become an overlay to a base plot using the NhlAddOverlay function. The plot object must belong to the same Workstation as the base plot. You may call the function repeatedly to overlay multiple plot objects over a single base plot. Note that you can only add an overlay to a primary or subordinate base plot. Attempts to add an overlay to a plot that is itself an overlay will result in an error.

The overlays under the control of a single base plot are ordered, with the base plot first and each overlay following sequentially. The NhlAddOverlay function has a parameter that allows you to specify where to add a plot into the overlay sequence. This sequence determines the basic drawing order of the plot: the base plot is drawn first; each succeeding overlay is drawn on top of previous objects in the sequence. However, the PlotManager actually supports three drawing phases, known as the predraw phase, the draw phase, and the postdraw phase. Some plot objects, such as ContourPlot and MapPlot also support these drawing phases, allowing you to specify that certain elements of the plot, such as labels, fill, or lines, be rendered during a specific drawing phase. When the PlotManager executes a Draw command, it first performs the predraw phase for each plot object in the overlay sequence, then the draw, and finally the postdraw. By manipulating both the overlay sequence and the draw phase, you gain considerable flexibility in controlling which elements of the plot appear on top.

You can remove an overlay from a base plot by calling the function NhlRemoveOverlay. If the overlay you are removing is a plot object with overlays of its own, you can choose to remove them along with the specified overlay, or leave them behind with the base plot. Annotations originally belonging to the overlay are always removed along with it. If you call NhlRemoveOverlay on the base plot, the effect is to restore all its plot members to their original state before being added to the current base plot.

Adding and removing annotations

There are three ways for a View class object to become an annotation. First, it may be a composite class member of the PlotManager class, and therefore instantiated along with the PlotManager object itself when the plot object is created. The PlotManager class contains four composite classes that are used as annotations: TickMark, Title, LabelBar, and Legend. These are known as intrinsic annotations. Second, a plot object may create View objects of its own and then depend on the PlotManager to manage them as annotations. An example is the ContourPlot object's informational label. An annotation such as this is called an embedded annotation. Finally, you may create arbitrary View objects at the user level and add them as annotations to a plot object. These are called external annotations.

You may add a group of View objects as annotations to any plot object by setting the PlotManager array resource pmAnnoViews with the ids of the View objects. Annotations added in this manner replace any previously added external annotations. Alternatively, you can add a single View object as an annotation by calling the function NhlAddAnnotation. In this case, the View id is appended to the existing pmAnnoViews array. Either way, for each View object added, the PlotManager creates an AnnoManager object containing resources that allow all external annotations to be controlled in a uniform manner. Unlike overlays, you can add an annotation to any plot object, even if it is not currently a primary or subordinate base plot. The base plot that manages the plot object will immediately assume responsibility for locating and sizing the annotation.

If you add the annotation by calling NhlAddAnnotation, the id of the AnnoManager object created to control the view is the return value of the function. In any case, you can retrieve the id of the AnnoManager object by getting the value of the PlotManager array resource pmAnnoManagers. Each element of this array contains the id of the AnnoManager for the View object whose id is contained in the corresponding element of pmAnnoViews. Since the view has been informed of its status as an annotation, you can also retrieve the AnnoManager object id from the view itself, by getting the value of the resource vpAnnoManagerId. You may remove external annotations one at a time by calling the function NhlRemoveAnnotation. Note that the pmAnnoViews and pmAnnoManagers arrays only apply to external annotations (annotations added by the user). The PlotManager handles intrinsic and embedded annotations internally.

The AnnoManager object contains resources that allow you to fix the location and size of the annotation view relative to the viewport or the data coordinate space of the base plot. If the annotation is placed relative to the viewport, you use AnnoManager resources that conform to the PlotManager Location Control Model.

PlotManager Location Control Model

The PlotManager implements a scheme of annotation zones to simplify management of multiple annotations. Although at first glance it may seem somewhat complex, in practice it should be quite simple to use. You can place an annotation relative to any side of the plot viewport without reference to the viewport size or position. Simply by assigning different zones you can ensure (except under certain circumstances involving annotation plots, discussed below) that annotations do not overlap each other. And if you decide to change the viewport side where an annotation is located, you can generally expect that the new location will still look reasonable. Note, however, that the scheme does not currently prevent annotations from being located partially or completely outside the plot frame. If an annotation seems to have disappeared, you should check to make sure the current configuration has not caused it to appear outside the viewable area.

Standard zones

Zones are numbered beginning at 0, and you may use as many zones as necessary to locate annotations. Zones 0 and 1 have special characteristics that differ from the standard zones. However, note that for the purposes of establishing zonal boundaries, the bounding box of zone 1 is considered to be the plot viewport boundary. Beginning with zone 2, each zone extends outward from the bounding box of the previous zone. When the size and/or position of objects within a zone change, causing the zone's bounding box to expand or contract, the zones outside automatically adjust their shape and position to accommodate.

For an external annotation, you choose the zone by setting the AnnoManager resource, amZone. Intrinsic and embedded annotations that adhere to the PlotManager Location Control Model will have an equivalent resource with a name specific to the particular resource. Thus, the PlotManager's intrinsic LabelBar annotation has the resource pmLabelBarZone, and ContourPlot provides the resource cnInfoLabelZone for its embedded informational label annotation.

Once you have established the zone, you decide which side of the zone's interior boundary to use as a basis for determining the annotation's relative position. Here you use the AnnoManager resource amSide or some intrinsic or embedded equivalent. Selection of a side determines a coordinate system with one axis parallel to the side and another orthogonal to it. The origin of this system is on the side line at the point where the projection of the left or bottom edge of the viewport (whichever is perpendicular) crosses. The direction of the parallel axis is always toward increasing NDC values, while the direction of the orthogonal axis is outward from the center of the plot. You establish a position for the annotation relative to the zonal side origin by setting parallel and orthogonal positional resources. For the AnnoManager object, these are amParallelPosF and amOrthogonalPosF. The units of the parallel position resource are 'fraction of the viewport width' if the side resource is Top or Bottom and 'fraction of viewport height' otherwise. Thus the value 1.0 in parallel position units represents either the right or top edge of the viewport, depending on the value of the side resource. When the units of the parallel position resource are 'fraction of the viewport width' the units of the orthogonal position resource are 'fraction of viewport height' and vice versa. This implies that, unless the viewport is square, the parallel and orthogonal units are not equal in size. The orthogonal position resource is constrained to positive values in order to prevent location of an annotation within a zone lower than its assigned zone.

Finally, you control the point of the annotation to be placed at the established location. Annotations that follow the model support a resource of type NhlJustification. However the justification point of these annotations is constrained to fall along the side of the annotation parallel with and closest to the zone's interior boundary side. Therefore, depending on the side, you have a choice of three different possibilities. For the top or bottom sides, you can choose between left, center, and right. For left or right sides, you can choose between bottom, center, and top. Effectively, this constraint enforces the requirement that no part of an annotation's extent be located in a zone with a lower number than its assigned zone. Note that constraining the justification point does not imply that the value of the resource as set by the user is modified; rather it means that the lower-level code acts as if the justification were set to the constrained value.

Annotation plots

Note that while the outer boundary of each annotation zone is based on the bounding boxes of the annotations it contains, annotations are positioned within a zone based on their viewports. For a basic view, such as a TextItem, its viewport and bounding box are the same. However, the bounding box of an annotation plot (a subordinate base plot) with its own annotations may extend outside its viewport. If the bounding box is outside the viewport in the negative orthogonal direction (toward the base plot's center), the subordinate base plot's annotations will overlap elements of the base plot. To avoid overlap in this case, you must remove all annotations along the inner side of the subordinate base plot.

Special zones

An annotation in one of the standard annotation zones cannot appear within the viewport of the base plot, and there is no way to make it overlay another annotation. Annotations placed in zones 0 and 1 have neither of these restrictions. Moreover, the actual bounding box of the annotation objects in these zones does not influence the boundaries of the standard annotation zones. Basically, zones 0 and 1 offer several convenient coordinate systems for placing objects anywhere within the plot frame.

The origin of zone 0 is the plot or subplot viewport center. The side resource (amSide for the AnnoManager object) still determines the directions of the parallel and orthogonal axes, just as for the standard annotation zones. Units are still either 'fraction of viewport width' or 'fraction of viewport height,' as appropriate. The positive direction for the parallel axis is still in the direction of increasing NDC values, and for the orthogonal axis away from the viewport center. Note that this means that values of 0.5, either for the parallel position resource or for the orthogonal position resource, fall on the viewport boundary. Both the parallel position and the orthogonal position may take on negative values. The justification resource is also unconstrained and therefore can take on any of the nine values available for the NhlJustification type.

Zone 1 has its origin at one of the viewport corners, and its parallel axis is coincident with the viewport side specified by the side resource. Unlike all other annotation zones, however, the direction of the orthogonal axis is toward rather than away from the viewport center. The parallel axis is still directed toward increasing NDC values, and like all other zones, the units are either 'fraction of viewport width' or 'fraction of viewport height,' as appropriate. As with zone 0, both the parallel position and the orthogonal position may take on negative values, and the justification resource is unconstrained. Note in particular that when the side resource is set to Bottom, the coordinate system has the origin at the lower left and the directionality of a standard Cartesian system (although the units are not necessarily of equal length in the X and Y directions). Also note that whatever the value of side, if you set both the parallel and orthogonal position resources to 1.0, you specify the location of the viewport corner opposite the origin.

Data-tracking annotations

Annotations positioned relative to the data coordinate space of the base plot are called data-tracking annotations. You set their location using a different set of positional resources. In the AnnoManager object, these are the resources amDataXF and amDataYF. There is no restriction on data-tracking annotations overlaying another plot feature. Therefore, these annotations are treated as belonging to zone 0 as far as their relationship to other annotations is concerned. Like other zone 0 annotations, data-tracking annotations can take on any value of the justification resource.

Support functions

PlotManager does not define any support functions. However, a number of the Transform support functions are designed to be used with objects of classes that use the PlotManager as a composite class member.


1. Resources allowing the user to control the order of drawing of overlays within a single draw phase, have not yet been implemented.

2. Resources allowing the user to restrict the bounding box of the complete plot to a portion of the viewspace have not yet been implemented.

See also