You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-users@xmlgraphics.apache.org by "Bishop, Michael W. CTR USJFCOM JFL" <mi...@jfcom.mil> on 2009/01/20 04:09:27 UTC

Understanding CTMs...

Hi all,
 
I'm still having a problem finding out if a select box drawn on the canvas completely bounds an element drawn on a document because I can't get my coordinate systems straight.  So I figure I need to get my understanding of CTMs correct.
 
SVGLocatable.getCTM():  This CTM is from what I understand, the "transform" applied to that element.
SVGLocatable.getScreenCTM():  This CTM transforms points from document coordinates to screen (canvas) coordinates.
 
In an attempt to find out if a select box drawn with the mouse completely bounds other elements, I decided to try and transform everything to document coordinates.
 
----------------
Select Box
----------------
When the mouse is pressed, I record the x, y coordinates as given from a MouseEvent attached to the JSVGCanvas.  When the mouse is dragged and released, I record the x, y coordinates again.  Now I have a select box in mouse/canvas coordinates.
 
Now I take those coordinates and push them through the document's root element inverse of the screen CTM:
 
SVGLocatable rootLoc = (SVGLocatable) svgDocument.getDocumentElement();
SVGMatrix matrix = rootLoc.getScreenCTM().inverse();
 
This SHOULD be transforming the select box from mouse/canvas coordinates to document coordinates.
--------------
Elements
--------------
 
Elements already on the document are drawn in a similar manner.  In the case of a <rect> element, I record x and y as stated above and create a <rect> element with x, y, w, and h.  Then I give the <rect> element a transform attribute that represents the inverse of the JSVGCanvas's viewing transform.  This way, a user can draw what they see no matter how the canvas is translated, zoomed, etc.
 
In order to translate an element to proper document coordinates, I get the bounding box of the element (SVGLocatable.getBBox), then push that bounding box through the element's CTM (SVGLocatable.getCTM).
 
At this point, both the select box and the potentially selected elements SHOULD be in the same coordinate system.
 
-----------
Results
-----------
 
I get expected results MOST of the time.  This works perfectly (zoom, pan, etc) UNLESS the size of the document does not match the size of the canvas.  An 800x600 document in a 800x600 canvas works perfectly.  A 1000x600 document in a 800x600 canvas (letterboxing on the top and bottom) does NOT.
 
I'm definitely doing something wrong, but I'm not sure what and I keep coming back to this problem week after week.  Someone's got to understand what's going on.  The end goal is simply to have the select box and the elements in the same coordinate system so I can figure out which elements are bounded by the select box.
 
----------------------------------------------------------------------------------------------------------------------------------
Select Coodinates -> rootElement.getScreenCTM().inverse() == Document coordinates (?)
Element Bounding Box -> element.getCTM() == Document coordinates (?)
 
This works unless canvas size <> document size.
----------------------------------------------------------------------------------------------------------------------------------
 
Any guidance is much appreciated.
 
Michael Bishop

---------------------------------------------------------------------
To unsubscribe, e-mail: batik-users-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: batik-users-help@xmlgraphics.apache.org


RE: Understanding CTMs...

Posted by "Bishop, Michael W. CTR USJFCOM JFL" <mi...@jfcom.mil>.
Hi Thomas,
 
Thanks so much.  I never would've figured that out on my own.  Switching my method calls to getTransformToElement produces exactly the results I'm looking for.  I am currently using a Swing mouse event, but I also have a DOM event for mouse up/down and will switch over.
 
I assume client x/y are the coordinates on the document?  That would eliminate the need to take my Swing x/y and push them through the inverse of the canvas' viewing transform?  Might save me a step or two.
 
Michael

________________________________

From: thomas.deweese@kodak.com [mailto:thomas.deweese@kodak.com]
Sent: Tue 1/20/2009 6:12 AM
To: batik-users@xmlgraphics.apache.org
Cc: batik-users@xmlgraphics.apache.org
Subject: Re: Understanding CTMs...



Hi Michael,

"Bishop, Michael W. CTR USJFCOM JFL" <mi...@jfcom.mil> wrote on 01/19/2009 10:09:27 PM:

> I'm still having a problem finding out if a select box drawn on the 
> canvas completely bounds an element drawn on a document because I 
> can't get my coordinate systems straight.  So I figure I need to get
> my understanding of CTMs correct.
>  
> SVGLocatable.getCTM():  This CTM is from what I understand, the 
                         "transform" applied to that element.

   No this is a _totally_ useless method in the SVG DOM. 
Don't ever use it.  Use getTransformToElement with what ever 
SVG element you want the transform to (in your case the 
root SVG element). 

> SVGLocatable.getScreenCTM():  This CTM transforms points from 
> document coordinates to screen (canvas) coordinates.

   This is correct,  I'll just mention that the destination 
coordinate system for this is the DOM mouse event 
'clientX'/'clientY' not the 'screenX'/'screenY' values. 

> ----------------
> Select Box
> ----------------
> When the mouse is pressed, I record the x, y coordinates as given 
> from a MouseEvent attached to the JSVGCanvas.  When the mouse is 
> dragged and released, I record the x, y coordinates again.  Now I 
> have a select box in mouse/canvas coordinates.

   You are using a DOM mouse event or a Swing mouse event? 
I don't know how big a pain it would be for you but the DOM mouse 
event is recommended. 

> Now I take those coordinates and push them through the document's 
> root element inverse of the screen CTM:
>  
> SVGLocatable rootLoc = (SVGLocatable) svgDocument.getDocumentElement();
> SVGMatrix matrix = rootLoc.getScreenCTM().inverse();
>  
> This SHOULD be transforming the select box from mouse/canvas 
> coordinates to document coordinates.

   This looks fine. 

> --------------
> Elements
> --------------
>  
> Elements already on the document are drawn in a similar manner.  In 
> the case of a <rect> element, I record x and y as stated above and 
> create a <rect> element with x, y, w, and h.  Then I give the <rect>
> element a transform attribute that represents the inverse of the 
> JSVGCanvas's viewing transform.  This way, a user can draw what they
> see no matter how the canvas is translated, zoomed, etc.
>  
> In order to translate an element to proper document coordinates, I 
> get the bounding box of the element (SVGLocatable.getBBox), then 
> push that bounding box through the element's CTM (SVGLocatable.getCTM).

   As I say above don't ever use getCTM.  use getTransformToElement. 

> At this point, both the select box and the potentially selected 
> elements SHOULD be in the same coordinate system.

   It's close but not quite... 

> -----------
> Results
> -----------
>  
> I get expected results MOST of the time.  This works perfectly 
> (zoom, pan, etc) UNLESS the size of the document does not match the 
> size of the canvas.  An 800x600 document in a 800x600 canvas works 
> perfectly.  A 1000x600 document in a 800x600 canvas (letterboxing on
> the top and bottom) does NOT.

   This is exactly the sort of problem 'getCTM' causes.  It goes 
to the 'viewport' coordinate system it does not go to the user-space 
coordinate system of the nearest viewport element.  The difference 
is of course totally opaque to anyone who hasn't read the SVG 
specification cover to cover.  This is further confused by the fact 
that the Adobe SVG renderer used getCTM to return the current 
element's transform only. 

> I'm definitely doing something wrong, but I'm not sure what and I 
> keep coming back to this problem week after week.  Someone's got to 
> understand what's going on.  The end goal is simply to have the 
> select box and the elements in the same coordinate system so I can 
> figure out which elements are bounded by the select box.


Re: Understanding CTMs...

Posted by th...@kodak.com.
Hi Michael,

"Bishop, Michael W. CTR USJFCOM JFL" <mi...@jfcom.mil> wrote 
on 01/19/2009 10:09:27 PM:

> I'm still having a problem finding out if a select box drawn on the 
> canvas completely bounds an element drawn on a document because I 
> can't get my coordinate systems straight.  So I figure I need to get
> my understanding of CTMs correct.
> 
> SVGLocatable.getCTM():  This CTM is from what I understand, the 
                          "transform" applied to that element.

   No this is a _totally_ useless method in the SVG DOM.
Don't ever use it.  Use getTransformToElement with what ever
SVG element you want the transform to (in your case the
root SVG element).

> SVGLocatable.getScreenCTM():  This CTM transforms points from 
> document coordinates to screen (canvas) coordinates.

   This is correct,  I'll just mention that the destination
coordinate system for this is the DOM mouse event 
'clientX'/'clientY' not the 'screenX'/'screenY' values.

> ----------------
> Select Box
> ----------------
> When the mouse is pressed, I record the x, y coordinates as given 
> from a MouseEvent attached to the JSVGCanvas.  When the mouse is 
> dragged and released, I record the x, y coordinates again.  Now I 
> have a select box in mouse/canvas coordinates.

   You are using a DOM mouse event or a Swing mouse event?
I don't know how big a pain it would be for you but the DOM mouse
event is recommended.

> Now I take those coordinates and push them through the document's 
> root element inverse of the screen CTM:
> 
> SVGLocatable rootLoc = (SVGLocatable) svgDocument.getDocumentElement();
> SVGMatrix matrix = rootLoc.getScreenCTM().inverse();
> 
> This SHOULD be transforming the select box from mouse/canvas 
> coordinates to document coordinates.

   This looks fine.

> --------------
> Elements
> --------------
> 
> Elements already on the document are drawn in a similar manner.  In 
> the case of a <rect> element, I record x and y as stated above and 
> create a <rect> element with x, y, w, and h.  Then I give the <rect>
> element a transform attribute that represents the inverse of the 
> JSVGCanvas's viewing transform.  This way, a user can draw what they
> see no matter how the canvas is translated, zoomed, etc.
> 
> In order to translate an element to proper document coordinates, I 
> get the bounding box of the element (SVGLocatable.getBBox), then 
> push that bounding box through the element's CTM (SVGLocatable.getCTM).

   As I say above don't ever use getCTM.  use getTransformToElement.

> At this point, both the select box and the potentially selected 
> elements SHOULD be in the same coordinate system.

   It's close but not quite...

> -----------
> Results
> -----------
> 
> I get expected results MOST of the time.  This works perfectly 
> (zoom, pan, etc) UNLESS the size of the document does not match the 
> size of the canvas.  An 800x600 document in a 800x600 canvas works 
> perfectly.  A 1000x600 document in a 800x600 canvas (letterboxing on
> the top and bottom) does NOT.

   This is exactly the sort of problem 'getCTM' causes.  It goes
to the 'viewport' coordinate system it does not go to the user-space
coordinate system of the nearest viewport element.  The difference
is of course totally opaque to anyone who hasn't read the SVG
specification cover to cover.  This is further confused by the fact
that the Adobe SVG renderer used getCTM to return the current
element's transform only.

> I'm definitely doing something wrong, but I'm not sure what and I 
> keep coming back to this problem week after week.  Someone's got to 
> understand what's going on.  The end goal is simply to have the 
> select box and the elements in the same coordinate system so I can 
> figure out which elements are bounded by the select box.