Hello,

I think I have the basic idea down, but I seem to be doing something wrong when I translate.

Basicly here is what I am doing:
1. I find the user coordinates based on the screen location of the top left corner of the JSVGCanvas.
2. Apply my scaling.
3. Again find the user coordinates based on the screen location of the top left corner of the JSVGCanvas.
4. Translate the rendering transform based on the difference of the first and second points I found.


Currently, when I do my translation I do not get anywhere near to my original location. My guess is I either do not fully comprehend what is going on with rendering transform, or I am making a simple math error that another set of eyes may be able to easily catch.

Here is the code:

  private void setScale(double factor){
       double currentScale;
       float s;
       AffineTransform at, rendT;
       Point start, end, canvasLoc;

if(factor != 0){
//find the starting location
canvasLoc = SVGCanvas.getLocationOnScreen();
start = getUserCoordinates((float)canvasLoc.getX(),(float)canvasLoc.getY());


           //calculate the new scale, based on the factor, and apply it
           currentScale = SVGDoc.getRootElement().getCurrentScale();
           s = (new Float(currentScale * factor)).floatValue();
           SVGDoc.getRootElement().setCurrentScale(s);

//Find the ending location
end = getUserCoordinates((float)canvasLoc.getX(),(float)canvasLoc.getY());


//translate the drawing back to its original postion
at = new AffineTransform();
//
//I am assuming this line is where I am making a mistake.
//Perhaps I need to somehow take the scaling into account before translating??
at.translate(-(end.getX() - start.getX()), -(end.getY() - start.getY()));
//
rendT = SVGCanvas.getRenderingTransform();
rendT.concatenate(at);
SVGCanvas.setRenderingTransform(rendT, true);
}
}


/*This method is taken almost directly from the example on the Batik website*/
private Point getUserCoordinates(float x, float y){
SVGMatrix mat, imat;
SVGPoint cPt;
Point p;


       mat  = SVGDoc.getRootElement().getScreenCTM();
       imat = mat.inverse();
       cPt  = SVGDoc.getRootElement().createSVGPoint();
       cPt.setX(x);
       cPt.setY(y);
       cPt = cPt.matrixTransform(imat);
       p = new Point();
       p.setLocation(cPt.getX(), cPt.getY());
       return p;
   }

Any help is greatly appreciated.

Thank you,
TJ Teegan

From: Thomas DeWeese <[EMAIL PROTECTED]>
Reply-To: "Batik Users" <[EMAIL PROTECTED]>
To: Batik Users <[EMAIL PROTECTED]>
Subject: Re: Changing scale while maintaining screen position
Date: Mon, 15 Nov 2004 21:21:33 -0500

TJ Teegan wrote:

I have a feeling I am making this harder than it needs to be.

I don't think you are ;)

Here is what I am trying to accomplish. I would like to create a method by which I can increase or decrease the scale on the root element while maintaining the drawings current position on the screen.

For example, If in the user coordinate system the point -300,400 is in the center of my monitor after I change the scale I would like the point -300,400 to still be in the center of the monitor.

This is the code to do this from the JSVGComponent, this is a bit more complex than what you _really_ need because you probably aren't concerned about rotation or shear, just scale and translate, but the basic technique is similar.

            // Here we map the old center of the component down to
            // the user coodinate system with the old viewing
            // transform and then back to the screen with the
            // new viewing transform.  We then adjust the rendering
            // transform so it lands in the same place.
            Point2D pt = new Point2D.Float(oldD.width/2.0f,
                                           oldD.height/2.0f);
            AffineTransform rendAT = getRenderingTransform();
            if (rendAT != null) {
                try {
                    AffineTransform invRendAT = rendAT.createInverse();
                    pt = invRendAT.transform(pt, null);
                } catch (NoninvertibleTransformException e) { }
            }
            if (vt != null) {
                try {
                    AffineTransform invVT = vt.createInverse();
                    pt = invVT.transform(pt, null);
                } catch (NoninvertibleTransformException e) { }
            }
            if (at != null)
                pt = at.transform(pt, null);
            if (rendAT != null)
                pt = rendAT.transform(pt, null);

            // Now figure out how far we need to shift things
            // to get the center point to line up again.
            float dx = (float)((d.width/2.0f) -pt.getX());
            float dy = (float)((d.height/2.0f)-pt.getY());
            // Round the values to nearest integer.
            dx = (int)((dx < 0)?(dx - .5):(dx + .5));
            dy = (int)((dy < 0)?(dy - .5):(dy + .5));
            if ((dx != 0) || (dy != 0)) {
                rendAT.preConcatenate
                    (AffineTransform.getTranslateInstance(dx, dy));
                setRenderingTransform(rendAT, false);
            }

This works fine, except the position of the drawing on the screen is changed. I should note - I have setRecenterOnResize set to false and the JSVGCanvas is contained in a JSVGScrollPane.

You will need to adjust the translate portion to componsate for the change caused by the scale change.


--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]


_________________________________________________________________
On the road to retirement? Check out MSN Life Events for advice on how to get there! http://lifeevents.msn.com/category.aspx?cid=Retirement



--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]



Reply via email to