0

Consider the following toy data:

clear
input double x1 float y1
                   0         0
.0013440860215053765 .02503477
.0013440860215053765 .05006954
 .005376344086021506  .0751043
 .009408602150537635 .10013908
  .01747311827956989 .12482615
  .03225806451612903  .1498609
 .056451612903225805  .1748957
  .07661290322580645 .19993046
  .09946236559139784 .22496523
  .15725806451612903       .25
   .2110215053763441  .2750348
  .32661290322580644  .3000695
   .3803763440860215  .3251043
   .4986559139784946  .3497914
    .603494623655914  .3748261
    .706989247311828  .3998609
   .7661290322580645  .4248957
   .8064516129032258  .4499305
    .885752688172043  .4749652
   .9099462365591398        .5
                   1  .5250348
   .9811827956989247  .5500696
   .8870967741935484  .5751043
   .7661290322580645  .5997913
   .6599462365591398  .6248261
   .5873655913978495  .6498609
   .5282258064516129  .6748957
  .40053763440860213  .6999304
   .3279569892473118  .7249652
   .2163978494623656       .75
  .15053763440860216  .7750348
  .09408602150537634  .8000696
  .06586021505376344  .8247566
  .04973118279569892  .8497913
 .024193548387096774  .8748261
 .025537634408602152  .8998609
 .006720430107526882  .9248957
 .002688172043010753  .9499304
 .004032258064516129  .9749652
                   0         1
end

twoway scatter y1 x1

enter image description here

When I try to rotate the entire graph by say 20 degrees counter-clockwise:

local theta = 0.349066

generate x2 = (x1 * cos(`theta') ) - (y1 * sin(`theta') )  
generate y2 = (x1 * sin(`theta') ) - (y1 * cos(`theta') ) 

The coordinates transform as follows:

clear
input float(x2 y2)
          0           0
-.007299372 -.023065284
 -.01586177  -.04659027
-.020635087  -.06873614
-.025408404  -.09088202
-.026273714  -.11132205
 -.02094281  -.12979028
-.006770712  -.14504059
.0036123034     -.16167
 .016521374     -.17738
  .06226916   -.1811377
  .10422786   -.1862745
  .20428585   -.1702649
  .24624455   -.1754017
   .3489475   -.1581459
   .4389013  -.14581393
    .527592  -.13394167
  .57460284  -.13723963
   .6039312   -.1469735
   .6698875   -.1433759
   .6840596   -.1586262
     .76012    -.151351
   .7338752  -.18131188
   .6369009  -.23701614
  .51478493   -.3015878
   .4064434   -.3614295
   .3296775   -.4097785
  .26554185  -.45353055
  .13699183  -.52072746
  .06022594   -.5690765
 -.05316776    -.630757
 -.12361852   -.6768075
  -.1852281   -.7196401
 -.22019514   -.7524921
 -.24391386   -.7815335
  -.2764738   -.8137929
 -.28377315   -.8368582
  -.3100179   -.8668191
  -.3223694   -.8917232
  -.3296688   -.9147884
  -.3420203   -.9396926
end

twoway scatter y2 x2

enter image description here

What am I missing?

Note that I have also tried to center the values first around a specific point.

In addition, I would also like the solution to account for different axes scales and graph aspect ratio.

For example:

clear
input float y double x
-2013                 .001
-1941 .0010053763440860215
-1869 .0010053763440860215
-1797 .0010215053763440861
-1725 .0010376344086021505
-1654 .0010698924731182796
-1582 .0011290322580645162
-1510 .0012258064516129032
-1438 .0013064516129032257
-1366 .0013978494623655914
-1294 .0016290322580645162
-1222 .0018440860215053765
-1150 .0023064516129032257
-1078 .0025215053763440864
-1007 .0029946236559139786
 -935  .003413978494623656
 -863  .003827956989247312
 -791  .004064516129032258
 -719  .004225806451612904
 -647  .004543010752688172
 -575  .004639784946236559
 -503                 .005
 -431 .0049247311827956995
 -359  .004548387096774194
 -288  .004064516129032258
 -216 .0036397849462365592
 -144  .003349462365591398
  -72 .0031129032258064514
    0 .0026021505376344085
   72  .002311827956989247
  144 .0018655913978494624
  216 .0016021505376344087
  288 .0013763440860215053
  359 .0012634408602150537
  431 .0011989247311827958
  503 .0010967741935483872
  575 .0011021505376344087
  647 .0010268817204301076
  719  .001010752688172043
  791 .0010161290322580644
  863                 .001
end

twoway scatter y x

enter image description here

The y-xis of this graph is 4 inches while the x-axis is 5.5 inches (aspect ratio of 1.375).

I have consulted a number of posts including the following:

I hope what I am trying to do is clear but I will be happy to clarify further.

1 Answers1

1

The formulas for rotation are the following:

 generate x2 = (x1 * cos(`theta') ) - (y1 * sin(`theta') )  
 generate y2 = (x1 * sin(`theta') ) + (y1 * cos(`theta') ) 

These perform rotation about point (0,0).

To make rotation about specific center point (cx, cy), one can apply the next approach:

 generate x2 = cx + ((x1 - cx) * cos(`theta') ) - ((y1 - cy) * sin(`theta') )  
 generate y2 = cy + ((x1 - cx) * sin(`theta') ) + ((y1 - cy) * cos(`theta') ) 

The above formulas represent affine transformation matrix. To account for axes scale you have to multiply result matrix by scaling matrix - it is very simple, just multiply x or y by coefficient according to axis/axis ratio.

But seems you want to rotate already stretched visual representation. Say your plot is stretched along OX in 5 times. In this case at first multiply internal data x-coordinates by 5, make rotation (note - scale rotation center too), then divide by 5.

For your first example the x-axis is ~1.5 times longer. So we can multiply x-column by 1.5, rotate by 20 degrees, and divide by 1.5. If axes preserve their length, we should see the same plot rotated by 20 degrees. However, data ranges have changed, and plot is resized! Angle is not 20 degrees exactly. This effect will be more evident on the second example with huge axes scale difference.

If ranges remain the same after rotation, I expect that described approach should give correct angles. It might be checked with simple pixel plotting, but I'm afraid this simulation won't reproduce behavior of your plotting system. With automatic axes ranges, exact angles are not possible.

MBo
  • 77,366
  • 5
  • 53
  • 86
  • @PearlySpencer: The placeholder 5 is the “slope coefficient” I defined at your linked question. Note that, since your (physical) plot area is rectangular, there is every chance you will rotate data out of the frame. If you extend the plot area asymmetrically in response, you will of course distort your rotated shape. – Davis Herring Apr 02 '19 at 15:33
  • If ranges remain the same after rotation, I expect that described approach should give correct angles. It might be checked with simple pixel plotting, but I'm afraid this simulation won't reproduce behavior of your plotting system – MBo Apr 02 '19 at 16:35
  • Will try it and will bug you again if necessary. Thanks. –  Apr 02 '19 at 16:36
  • @DavisHerring Feel free to answer the question if you have some time. –  Apr 02 '19 at 16:45
  • @PearlySpencer: Aside from the fact that you should scale ***y*** up by (my) *v* before the rotation (and when adjusting the center) and down by it afterwards (I thought in haste that it was *x* earlier), I see nothing missing from this answer and comments. I do note (more explicitly than this answer does) that you can multiply all three matrices together to get one transformation to apply efficiently. – Davis Herring Apr 03 '19 at 00:28