Hi Michael,

"Bishop, Michael W. CTR USJFCOM JFL" <[email protected]> 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.

Reply via email to