Rotate plotted points of an ellipse to give a circle

谁说我不能喝 提交于 2019-12-10 18:31:17

问题


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?


回答1:


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":



来源:https://stackoverflow.com/questions/37193380/rotate-plotted-points-of-an-ellipse-to-give-a-circle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!