0

If I have a SVG rectangle with

[x1,y1,x2,y2] = [ 456.079, 402.645, 514.841, 527.925 ]

and its SVG matrix

[0, 1, -1, 0, 58.7617, 0]

How can I calculate x, y, w, h of the rectangle?

Spektre
  • 49,595
  • 11
  • 110
  • 380
Steven lee
  • 13
  • 1
  • 2
  • how are the values related? – Nina Scholz Oct 08 '20 at 07:28
  • with the matrix [1, 0, 0, 1, 0, 0] then x is the left position: x=x1, y is the top position y=y1, w is width of the rectangle w =x2-x1, h is height of the rectangle h = y2-y1 – Steven lee Oct 08 '20 at 07:37
  • wha do you have six values in the matrix (looks more like a vector ...)? – Nina Scholz Oct 08 '20 at 07:40
  • @NinaScholz its direct 2D homogenuous 3x3 transform matrix the last 3 elements are implicitly `(0,0,1)` that is how SVG defines it as there is no projection in it ... IIRC to transform vertexes you just need to multiply `position' = matrix*position` – Spektre Oct 08 '20 at 07:45
  • this is the matrix stored in pdf file – Steven lee Oct 08 '20 at 07:45
  • @ThiPhạm btw you should add the SVG rectangle as code (just copy the SVG as text no need for whole SVG just the RECT or may be even parrent G tag if the matrix is in there) so others are not confused and not adding invalid close votes (you got 2 just now).... – Spektre Oct 08 '20 at 08:20

1 Answers1

0

The matrix is direct 2D homogenuous 3x3 transform matrix where the last 3 missing elements are implicitly (0,0,1) as there is no projection in SVG. Its basically a 2D version of this.

So you need to implement 3x3 matrix * 3D vector multiplication V' = M*V where matrix M is your 6 values + (0,0,1) and 3D vector V is (x,y,w=1) the result is (x',y',w) where you can ignore the w'. So when written as code (taken from mine C++ SVG decoder/encoder I wrote few years ago) to transform vertexes just do this:

x'=M[4]+(M[0]*x)+(M[2]*y);
y'=M[5]+(M[1]*x)+(M[3]*y);

If you have also scale present then:

x'=M[4]+scalex*((M[0]*x)+(M[2]*y));
y'=M[5]+scaley*((M[1]*x)+(M[3]*y));

Where:

M[6]={ 0, 1, -1, 0, 58.7617, 0 };

Also if you want to transform vectors (or sizes like width,height,radius) instead of vertexes then the w=0 so the code ignores offset:

x'=(M[0]*x)+(M[2]*y);
y'=(M[1]*x)+(M[3]*y);

If you have also scale present then:

x'=scalex*((M[0]*x)+(M[2]*y));
y'=scaley*((M[1]*x)+(M[3]*y));

so transform position (x1,y1) with offset and (x2,y2) without (as its the width,height).

x=M[4]+(M[0]*x1)+(M[2]*y1);
y=M[5]+(M[1]*x1)+(M[3]*y1);
w=     (M[0]*x2)+(M[2]*y2);
h=     (M[1]*x2)+(M[3]*y2);

In case your SVG object parents has more matrices you need to apply them in order too.

Spektre
  • 49,595
  • 11
  • 110
  • 380
  • thanks, it's very helpful, and how can I find the angle? – Steven lee Oct 08 '20 at 08:12
  • @ThiPhạm its in the matrix ... IIRC its one of these `atan2(M[1],M[0])` or `atan2(M[2],M[0])` my bet its the latter one. The matrix contains 2 basis vectors (one for each axis) and offset I just do not remember if its stored in columns or rows and too lazy to analyze/reverse my old code... – Spektre Oct 08 '20 at 08:15
  • I think it's should be atan2(-M[1],M[0]) or atan2(M[2],M[0]) – Steven lee Oct 08 '20 at 08:19
  • @ThiPhạm depends on your coordinate system ... if your axises are x goes right and y up then no negation so most likely `atan2(M[2],M[0])` just try and see if the computed angle matches your SVG view – Spektre Oct 08 '20 at 08:22
  • one more thing, what happens if [x1,y1,x2,y2] = [ 456.079, 402.645, 514.841, 527.925 ] is the result of the rectangle after rotated, can I find the original x, y? – Steven lee Oct 09 '20 at 07:44
  • @Stevenlee in svg the stuff in ` – Spektre Oct 09 '20 at 09:49