• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

IDML Rotation Matrix concern

People's Champ ,
Mar 02, 2018 Mar 02, 2018

Copy link to clipboard

Copied

Hi all,

I am trying to generate snippets on the fly and I having hard times trying to get some item rotated. Well I can rotate it. Problem is that it's then moved away.

I understand this displacement is due to the relation between itemTransform and the Spread coordinate space but I have no clue how to compute anything regarding to this in the snippet xml structure.

Capture d’écran 2018-03-03 à 00.24.57.png

For example, here, the black frame is the non rotated frame. I wish I can rotate so it matches the magenta frame. Right now, all I get is the blue one for as long as I express the itemTransform attribute that way:

itemTransform=".86 -.5 .5 .86 0 0"

Obviously I have to set tx and ty so the "blue" box is moved back to the magenta box actual position. Question is how to compute tx and ty in this case ?

<Rectangle Self="u348" ContentType="Unassigned" StoryTitle="$ID/" ECPageItemData="" ECPaginationPageItemData="1 0" ParentInterfaceChangeCount="" TargetInterfaceChangeCount="" LastUpdatedInterfaceChangeCount="" OverriddenPageItemProps="" HorizontalLayoutConstraints="FlexibleDimension FixedDimension FlexibleDimension" VerticalLayoutConstraints="FlexibleDimension FixedDimension FlexibleDimension" FillColor="Color/Black" StrokeWeight="0" StrokeColor="Swatch/None" GradientFillStart="0 0" GradientFillLength="0" GradientFillAngle="0" GradientStrokeStart="0 0" GradientStrokeLength="0" GradientStrokeAngle="0" ItemLayer="uc5" Locked="false" LocalDisplaySetting="Default" GradientFillHiliteLength="0" GradientFillHiliteAngle="0" GradientStrokeHiliteLength="0" GradientStrokeHiliteAngle="0" AppliedObjectStyle="ObjectStyle/$ID/[Normal Graphics Frame]" Visible="true" Name="$ID/"
    ItemTransform=".86 -.5 .5 .86 0 0">
   
<Properties>
       
<PathGeometry>
           
<GeometryPathType PathOpen="false">
               
<PathPointArray>
                   
<PathPointType Anchor="1188.5 -1731.4685039368005" LeftDirection="1188.5 -1731.4685039368005" RightDirection="1188.5 -1731.4685039368005" />
                   
<PathPointType Anchor="1188.5 -1220.5" LeftDirection="1188.5 -1220.5" RightDirection="1188.5 -1220.5" />
                   
<PathPointType Anchor="3409.5 -1220.5" LeftDirection="3409.5 -1220.5" RightDirection="3409.5 -1220.5" />
                   
<PathPointType Anchor="3409.5 -1731.4685039368005" LeftDirection="3409.5 -1731.4685039368005" RightDirection="3409.5 -1731.4685039368005" />
               
</PathPointArray>
           
</GeometryPathType>
       
</PathGeometry>
   
</Properties>
</Rectangle>

TIA for any hints.

TOPICS
Scripting

Views

1.6K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Guide , Mar 05, 2018 Mar 05, 2018

Hi Loïc,

(My full answer just vanished so I need to start again but shall make it shorter.)

1. describes a pure rotation in InDesign, that is, centered on (0,0). But of course a rotation does not necessarily uses as its center the origin of the coordinate system under consideration.

2. If you need to reverse-engineer a rotation whose angle is known, a point M and its transformed point M', the first question is to determine the center of that rotation.

3. Your data tell us that:

M = (452.696629213484

...

Votes

Translate

Translate
People's Champ ,
Mar 02, 2018 Mar 02, 2018

Copy link to clipboard

Copied

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Mar 03, 2018 Mar 03, 2018

Copy link to clipboard

Copied

Hi Loïc,

You need to take into account the <PathPointArray> anchors since they represent the shape in its own space. As we shall see, there is a huge difference between a translation (which occurs through the transform matrix and after any other task) and the positioning of an object in its inner coordinate system.

It is easy to see that a rotation matrix applied to an off-centered object will cause it to move with respect to its barycenter. As we all learned from this internationaly-known guide the result of a pure rotation θ in InDesign is:

    (x',y') = (xcosθ+ysinθ, -xsinθ+ycosθ).

In your case you seem to have θ=30°. You didn't specify whether the initial matrix was [1 0 0 1 0 0], or if some tx,ty translation attributes were already in the place, but for my discussion I will assume the black rectangle originally untransformed. Hence, considering the anchor coordinates found in the IDML, we start from something like this:

IDML-ROT01.png

If you apply the formula to a point (x,y), for example the bottom-left corner highlighted in the picture, you see that it moves to a location (x',y') that clearly reveals a shift of the entire block. Like in your original screenshot, the resulting rectangle (in blue) undergoes a move due to the fact that the original object is not centered on the origin.

So, that's the actual result of applying the matrix [0.866 -0.5 0.5 0.866 0 0 ] and indeed you need to compensate the trailing attributes if you want to reposition the barycenter of the rectangle where it originally was.

IDML-ROT02.png

This “translation fix” (dx, dy) should be computable from your data. First, calculate the center coordinates (x0,y0) of the original rectangle using the (min+max)/2 trick on the existing anchor points. Then calculate dx and dy as shown above.

In more generic terms:

// Rotation angle (deg -> rad)

// ---

const a = 30 * Math.PI/180;

// Rotation matrix will be

// [cosa -sina sina cosa  dx dy]

// ---

const cosa = Math.cos(a);

const sina = Math.sin(a);

// From IDML's <PathPointArray>

// ---

var x1 = 1188.5,

    x2 = 3409.5,

    y1 = -1731.4685039368005,

    y2 = -1220.5;

// Midpoint.

// ---

var x0 = (x1+x2)/2,

    y0 = (y1+y2)/2;

// Translation fix (dx,dy)

// [dx dy] = [1-cosa -sina sina 1-cosa] × [x0 y0]

// ---

var k = 1 - cosa;

var dx = k*x0 - sina*y0,

    dy = k*y0 + sina*x0;

// Final matrix.

// ---

var mx = [cosa, -sina, sina, cosa, dx, dy];

alert( '"'+mx.join(' ')+'"' );

// => "0.86602540378444 -0.5 0.5 0.86602540378444 1045.99972268378 951.755605822006"

Maybe a cleaner solution would be to change the anchor coordinates themselves to keep the rectangle originally centered (which seems even easier to do) and then avoid composing the rotation with a last-minute translation. Up to you to choose the best approach. IDML sucks in any case 😉

Best,

Marc

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
People's Champ ,
Mar 05, 2018 Mar 05, 2018

Copy link to clipboard

Copied

Hi Marc,

First of all, thanks for the answer and time taken. I have already downloaded, printed and read the internationaly-known guide​ you are talking about years ago But indeed those intricacies are really complex (a pure science topic by itself).

I see IDML handling as a way of doing most of the pageItem generation and manipulation out of the box. But yes it has a price.

I will let you know how that go.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
People's Champ ,
Mar 05, 2018 Mar 05, 2018

Copy link to clipboard

Copied

Hi Marc,

Thanks for the help, it was helpful. I wouldn't say I am out of troubles but my understanding of deep geometry is better

Anyway, I am confused on one point and maybe you or another brilliant mind can help.

I understood the formula :

    (x',y') = (xcosθ+ysinθ, -xsinθ+ycosθ).

I am converting AI templates to InDesign Snippets. Some shapes are rotated in AI and I am translating this in IDML.

So here is a shape in AI rotated by say 20°. I tried to compute the non rotated points by applying the upper formula with the reverse angle. PathPoints in AI have the same properties than InDesign (anchor,leftDirection and rightDirection).

So I was naively thinking that for example, pointA with x and y like [100,200] could be rotated back programmatically this way :

(100*cos(-20)+200sin(-20), -100(sin-20)+200cos(-20)).

But results are nothing like the coordinates AI returns.

For example:

452.696629213484,-365.887640449439 //x,y coordinates of the first point with 0° rotation

388.202515466231,-456.253631357617 //x,y coordinates of the first point with -35.6° rotation*

And applying the formula with positive 35.6 to reverse the rotation gives me

-474.746026657145,-336.785115033551

Shouldn't oppositing the applied rotation angle set the rotation back to 0? Shouldn't we get the initial geometric values ?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Mar 05, 2018 Mar 05, 2018

Copy link to clipboard

Copied

Hi Loïc,

(My full answer just vanished so I need to start again but shall make it shorter.)

1. describes a pure rotation in InDesign, that is, centered on (0,0). But of course a rotation does not necessarily uses as its center the origin of the coordinate system under consideration.

2. If you need to reverse-engineer a rotation whose angle is known, a point M and its transformed point M', the first question is to determine the center of that rotation.

3. Your data tell us that:

M = (452.696629213484, -365.887640449439)

transforms into

M' = (388.202515466231, -456.253631357617)

when it undergoes a rotation of angle -35.6°.

It is easy to see that the origin of this coordinate system cannot be the center of the rotation. It's less easy to compute its exact coordinates but I made a quick script to do the job for us:

var theta = (-35.6)*Math.PI/180;

// M1 -> M2

var x1 = 452.696629213484,

    y1 = -365.887640449439;

var x2 = 388.202515466231,

    y2 = -456.253631357617;

var dx = x2-x1,

    dy = y2-y1,

    d = Math.sqrt(dx*dx+dy*dy);

var OI = d/(2*Math.tan(theta/2));

var xi = (x1+x2)/2,

    yi = (y1+y2)/2,

    alpha = Math.atan(-dy/dx);

var x0 = xi + OI*Math.sin(alpha),

    y0 = yi + OI*Math.cos(alpha);

alert( [x0,y0].join('\r') );

which prompts:

O = (561.178125659198, -511.50845807588)

And indeed this seems to match:

RotationCenter.png

Now you have your translation components and can use them to reverse the operation.

Hope that helps.

@+

Marc

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
People's Champ ,
Mar 05, 2018 Mar 05, 2018

Copy link to clipboard

Copied

Thanks a lot Marc for your help on that difficult topic.

Just to keep on talking about this. As I was trying to keep on getting this, I applied the rotation formula inside Illustrator. I centered object on the 0,0 point and duplicated the initial page item. Then I set all path points so they are "rotated" through the formula.

What's weird is that the object doesn't seem well rotated. It's like over rotated. The blue shape is the starting point. Green is the correctly yet manually rotated and the orange is the result of the path points computation. I would have expected the orange to be on the green position.

Anyway, it's food for thought. You gave me great code I need to digest and reproduce. I will score your post as correct as I don't doubt a second it will be. But I am even more interesting in getting this than just copy pasting your generous code

Capture d’écran 2018-03-05 à 23.46.36.png

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Mar 05, 2018 Mar 05, 2018

Copy link to clipboard

Copied

Hi Loïc,

Sorry for asking a stupid question: Are you sure you don't forget to convert degree angles into radians?

rad = deg * (Math.PI / 180);

Indeed, Math.cos, Math.sin, etc always expect radians.

This code works for me:

var a = -36*(Math.PI/180),

    cosa = Math.cos(a),

    sina = Math.sin(a);

// Assuming your rectangle is selected in InDesign.

var poly = app.selection[0].duplicate(),

    ep = poly.paths[0].entirePath,

    i,x,y;

for( i=ep.length ; i-- ; )

{

    x = ep[0];

    y = ep[1];

    ep[0] =  x*cosa + y*sina;  // x'

    ep[1] = -x*sina + y*cosa;  // y'

}

poly.paths[0].entirePath = ep;

@+

Marc

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
People's Champ ,
Mar 06, 2018 Mar 06, 2018

Copy link to clipboard

Copied

"Stupid is as stupid does" as said a great mind once

You got me. My main issue was indeed in that non degree to rad conversion. Once I did that, everything has felt in the right place. Pieces of the jigsaw start to fit together and you was really helpful on this one. Not only by providing snippets but by taking the time to clarify those kind of complex geometric intricacies.

Thanks a lot Marc Autret​ !

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
People's Champ ,
Mar 06, 2018 Mar 06, 2018

Copy link to clipboard

Copied

LATEST

Ok, I got it allright eventually Thanks again Marc Autret

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines