Transforming canvas graphics

Many graphical editing programs support interactive scale, rotate, and translate (SRT) transformations. GrafEdit makes interactive transformations easy to implement for the most usual situations.

A common example involves rotating and scaling a graphic. When the end user rotates a graphic, a selection graphic of some kind rotates with the graphic. If the end user selects another graphic and then returns to select the original graphic, the selection graphic is oriented as it was when the graphic was last selected. That is, each graphic maintains its own axis of orientation. Scaling transformations generally work with respect to this axis of orientation.

When graphics maintain their own axis or orientation, rotate, scale, and translate operations must not change the points of the graphic. To keep from changing the points, the following must be implemented in your code:

MCanvasGraphic and MGraphic implement the virtual functions shown in Figure 27 and Figure 28 to give you the abovedescribed functionality without your having to write a lot of code to get it. You can always override the MCanvasGraphic functions to get any special behavior you might want such as support for generic transformation other than SRT transformations.



Concrete canvas graphics implement the virtual functions shown in Figure 29.


You implement the concrete canvas graphics functions in any MCanvasGraphic concrete classes. The code to do this is straightforward.

HandleDraw

The HandleDraw function draws the untransformed geometry into the provided drawing port. The attribute bundle and transformation matrix have already been applied to the drawing port that is passed into HandleDraw. The MGraphic::Draw function is implemented in terms of HandleDraw.

    virtual void HandleDraw( TGrafPort& ) const = 0;

HandleGetBounds

The HandleGetBounds
function returns the untransformed geometric bounds. The MGraphic GetGeometricBounds and GetLooseFitBounds functions are implemented in terms of HandleGetBounds.

    virtual TGRect HandleGetBounds() const = 0;

HandleHit

The HandleHit function is implemented to return True if the end user has selected a point on the graphic's geometry, and False if not. Your implementation for this function can call the
MGraphic GetGeometricBounds or GetLooseFitBounds functions, or call the Intersects function that is supported by most geometry classes, as shown in the example implementation below.

      Boolean
    TMyCanvasGraphic::HandleHit( const TGPoint& p ) const
    {
    if( fMyGeometry ) { TGRect rect ( p, p ); rect.Inset( TGPoint( -2., -2. ); return fMyGeometry->Intersects( rect ); } else return FALSE; }

HandleCreateInteractor

HandleCreateInteractor function
creates and returns an interactor based on the location of the hit point in the untransformed geometry.

      virtual TCanvasInteractor* HandleCreateInteractor( MCanvasSelection* adoptTarget,
                              MToolHandler*, const TGPoint& hit ) const;

HandleCreateFeedbacker

HandleCreateFeedbacker
creates and returns a feedback graphic that draws properly with respect to the untransformed graphic.

    virtual MCanvasGraphic* HandleCreateFeedbacker();
HandleCreateFeedbacker is also in TCanvasView, so if the canvas graphic returns no feedbacker, the default feedbacker provided by the canvas view is used.


[Contents] [Previous] [Next]
Click the icon to mail questions or corrections about this material to Taligent personnel.
Copyright©1995 Taligent,Inc. All rights reserved.

Generated with WebMaker