Reputation: 42293
I have an ellipse-shaped distribution that I think is a conic section. I want to rotate the points so that the distribution becomes circular-shaped, as if I was looking at the conic section directly over the top of the cone.
Here's some example data (generated using the function here)
X_df <-
structure(list(x = c(550.685479223573, 411.808342674744, 125.337513241526,
-46.6813176776531, 54.1090479024869, 335.045593380922, 538.806846993829,
476.123346783785, 207.359201714354, -23.3704356149293, -1.06902389582398,
252.471032092766, 502.461757269191, 522.09464005165, 290.954504794153,
22.4116013413886, -37.4399705577234, 166.122770874069, 446.874779008936,
547.271442128866, 372.271299246978, 84.7905677157295, -50.074206596271,
90.757431249567, 378.201298931732, 547.145608993239, 443.947162007208,
161.476775837252, -38.5517112166543, 25.2627436553199, 296.503160027896,
524.775126009974, 500.784559912938, 245.712512645379, -4.31860487373257,
-21.9661658669887, 211.218663607589, 479.198761786515, 535.314989389215,
330.010941011427, 50.0215808044216, -46.3823119064223, 130.383487121344,
416.170638042649, 549.268852072098, 407.813005658263, 119.940919946473,
-46.978590114418, 57.7409750579334, 340.505587064792, 539.650771180236,
472.254339573695, 201.890629521184, -25.163386210777, 1.25193046435474,
256.776302252232, 506.305676724803, 520.004964534048, 284.257495593069,
18.8183745840118, -35.9075114459174, 172.662124500953, 452.343060560759,
546.468842888411, 367.193523099128, 81.9151159445705, -49.726312730029,
95.1883131124973, 382.503271032958, 548.377552998115, 439.474201456606,
157.248088356873, -39.8634174011649, 28.665422852919, 301.243788141946,
526.815879166266, 497.683488701185, 240.939374274905, -7.78381612220116,
-19.3411744866129, 217.640180353188, 483.134755325255, 534.947529479343,
324.801587123232, 45.3957868762181, -45.0069945691924, 134.781896592204,
420.833721926428, 550.278658272823, 403.464000037755, 116.273973349216,
-48.5483252399878, 62.3918399072614, 345.924165684106, 540.282415561272,
468.621672005007, 195.304995872248, -28.2738679786754, 4.25351768918281,
262.272866287766, 509.296144374104), y = c(150.522375543584,
317.792592638159, 332.783726315973, 177.890614907595, -1.30774215535761,
-41.9959828735621, 94.0557252742373, 281.491416261009, 347.931229803675,
232.411150772918, 41.2498141860971, -50.240758928064, 42.4333078345691,
233.202857825371, 347.930304275537, 279.801242902484, 93.7702821671593,
-42.9605564915062, -0.128821245055916, 179.228629398932, 331.853832274807,
317.39347890031, 147.731418574477, -19.2449921421865, -31.3298018420377,
123.222814177221, 301.499351173211, 340.662811705721, 204.270915882133,
17.5570334546183, -47.8527634953491, 69.1925023774197, 260.846781070028,
350.702299892942, 255.267980339802, 64.3048063206447, -47.7550214881633,
21.0575085383169, 209.247480999408, 342.716023607699, 298.578792586917,
118.053124236616, -33.3190320226709, -16.5618829502486, 154.097078032767,
319.940208485997, 330.141085013461, 175.063055837321, -4.17911647131882,
-40.77087978947, 96.7492568480405, 284.629419943293, 347.18869555741,
228.951107374031, 37.6230640656836, -49.9549156886126, 45.2896584936418,
236.96620488459, 349.2183672397, 277.259838492706, 88.5019845874813,
-43.1419505604449, 1.98249146234145, 183.766146834555, 334.721418603224,
314.869389642466, 144.917094343997, -21.0615467657252, -29.137753346726,
126.928148173889, 305.196445845808, 339.338402720207, 201.609402013064,
15.0779976117978, -47.1046400880924, 71.7191693530443, 263.543031729657,
350.145628648054, 252.792513384296, 61.2531942049295, -49.0697852698499,
24.2068045114243, 212.793083656477, 343.533262533366, 295.969945687212,
115.135250419503, -34.4145910896749, -14.7817206225652, 156.282366465729,
322.116360452784, 328.626788731125, 171.323808201914, -6.54021515590322,
-40.1360134761796, 101.492490333309, 286.854230399582, 347.010792855229,
226.829162028581, 35.3880363162166, -50.8418314561365, 48.893760376765
)), .Names = c("x", "y"), row.names = c(NA, -101L), class = "data.frame")
Plot the ellipse, this resembles my actual data:
ggplot(X_df, aes(x, y)) +
geom_point() +
coord_equal()
I want to apply a function to the xy coords to rotate the ellipse around its long axis, moving the top of the ellipse towards me, and the bottom of the ellipse away from me, to get something like this (with equal dimension along the x-axis as the ellipse above, but different dimension along the y-axis):
I want to rotate my data like this ellipse is rotated to produce the circle, where I see the maximum distance between the top and bottom of the shape (ie. the longest possible axis perpendicular to the long axis), as the shape rotates around it long axis.
How can I do that?
Upvotes: 3
Views: 911
Reputation: 93821
It seems like what you're saying is that if I viewed the "circle" edge on from, say, x=-1000, y=0, I would see a line rotated counterclockwise (out of the xy-plane) away from the y axis. The goal is to rotate the circle back to the y-axis.
The angle of rotation is acos(1/ratio)
(0.839 radians or 48.06 degrees in this case) where ratio
is diff(range(X_df$x))/diff(range(X_df$y))
(assuming the axis of rotation is in the xy-plane and parallel to the x-axis and your data includes points on the x axis on both sides of the circle).
To, in effect, rotate the circle back to the xy-plane, you could just multiply the y points by ratio
and then, to maintain the same center, subtract (ratio - 1) * mean(X_df$y)
(where I've assumed the data points are evenly distributed about the circle).
In other words (or in code, actually):
ratio = diff(range(X_df$x))/diff(range(X_df$y))
X_df$ynew = ratio * X_df$y - (ratio - 1) * mean(X_df$y)
ggplot(X_df, aes(x, ynew)) +
geom_point() +
coord_equal()
Compare original to "rotated":
Upvotes: 2