首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何计算两个受约束线段的旋转角度?

如何计算两个受约束线段的旋转角度?
EN

Stack Overflow用户
提问于 2018-05-30 23:43:51
回答 1查看 201关注 0票数 2

我有两个向量,Y向对齐是固定的,因此X向对齐可以旋转。这些向量通过两个固定长度的线段连接在一起。给定两个向量之间的角度(82.74)和所有线段的长度,如何获得两个连接线段的角度(24.62和22.61)?

给定的内容:矢量的大小,以及X轴和OG之间的角度:

var magOG = 3,
    magOE = 4,
    magGH = 3,
    magEH = 2,
    angleGamma = 90;

这是我的起点:angleGamma = 90 -然后,我将拥有以下向量:

var vOG = new vec2(-3,0),
    vOE = new vec2(0,-4);

从现在开始,我将尝试获取angleGamma值小于90度的angleAlphaangleBeta

受约束线段的幅值:

段HG和HE必须满足以下条件:

/
|  OG*OG+ OE*OE = (HG + HE)*(HG + HE)
>
|  OG - HG = OE - HE
\

这将导致以下两个解决方案(如公认的答案-双边处理中所指出的):

Solution 1:
========================================================
HG = 0.5*(-Math.sqrt(OG*OG + OE*OE) + OG - OE)
HE = 0.5*(-Math.sqrt(OG*OG + OE*OE) - OG + OE)

Solution 2:
========================================================
HG = 0.5*(Math.sqrt(OG*OG + OE*OE) + OG - OE)
HE = 0.5*(Math.sqrt(OG*OG + OE*OE) - OG + OE)

SCRATCHPAD:

这是一个包含完整解决方案的游乐场。这里使用的可视化库是很棒的JSXGraph。感谢拜罗伊特大学数字技术移动学习中心。

圆相交函数的积分:在这个问题的接受答案中:01AutoMonkeyA JavaScript function that returns the x,y points of intersection between two circles?

function deg2rad(deg) {
  return deg * Math.PI / 180;
}

function rad2deg(rad) {
  return rad * 180 / Math.PI;
}

function lessThanEpsilon(x) {
  return (Math.abs(x) < 0.00000000001);
}

function angleBetween(point1, point2) {
  var x1 = point1.X(), y1 = point1.Y(), x2 = point2.X(), y2 = point2.Y();
  var dy = y2 - y1, dx = x2 - x1;
  var t = -Math.atan2(dx, dy); /* range (PI, -PI] */
  return rad2deg(t); /* range (180, -180] */
}

function circleIntersection(circle1, circle2) {
  var r1 = circle1.radius, cx1 = circle1.center.X(), cy1 = circle1.center.Y();
  var r2 = circle2.radius, cx2 = circle2.center.X(), cy2 = circle2.center.Y();

  var a, dx, dy, d, h, h2, rx, ry, x2, y2;

  /* dx and dy are the vertical and horizontal distances between the circle centers. */
  dx = cx2 - cx1;
  dy = cy2 - cy1;
  
  /* angle between circle centers */
  var theta = Math.atan2(dy,dx);

  /* vertical and horizontal components of the line connecting the circle centers */
  var xs1 = r1*Math.cos(theta), ys1 = r1*Math.sin(theta), xs2 = r2*Math.cos(theta), ys2 = r2*Math.sin(theta);
  
  /* intersection points of the line connecting the circle centers */
  var sxA = cx1 + xs1, syA = cy1 + ys1, sxL = cx2 - xs2, syL = cy2 - ys2;
  
  /* Determine the straight-line distance between the centers. */
  d = Math.sqrt((dy*dy) + (dx*dx));

  /* Check for solvability. */
  if (d > (r1 + r2)) {
    /* no solution. circles do not intersect. */
    return [[sxA,syA], [sxL,syL]];
  }

  thetaA = -Math.PI - Math.atan2(cx1,cy1); /* Swap X-Y and re-orient to -Y */
  xA = +r1*Math.sin(thetaA);
  yA = -r1*Math.cos(thetaA);
  ixA = cx1 - xA;
  iyA = cy1 - yA;

  thetaL = Math.atan(cx2/cy2);
  xL = -r2*Math.sin(thetaL);
  yL = -r2*Math.cos(thetaL);
  ixL = cx2 - xL;
  iyL = cy2 - yL;

  if(d === 0 && r1 === r2) {
    /* infinite solutions. circles are overlapping */
    return [[ixA,iyA], [ixL,iyL]];
  }
  
  if (d < Math.abs(r1 - r2)) {
    /* no solution. one circle is contained in the other */
   return [[ixA,iyA], [ixL,iyL]];
  }

  /* 'point 2' is the point where the line through the circle intersection points crosses the line between the circle centers. */

  /* Determine the distance from point 0 to point 2. */
  a = ((r1*r1) - (r2*r2) + (d*d)) / (2.0 * d);
  
  /* Determine the coordinates of point 2. */
  x2 = cx1 + (dx * a/d);
  y2 = cy1 + (dy * a/d);
  
  /* Determine the distance from point 2 to either of the intersection points. */
  h2 = r1*r1 - a*a;
  h = lessThanEpsilon(h2) ? 0 : Math.sqrt(h2);

  /* Now determine the offsets of the intersection points from point 2. */
  rx = -dy * (h/d);
  ry = +dx * (h/d);

  /* Determine the absolute intersection points. */
  var xi = x2 + rx, yi = y2 + ry;
  var xi_prime = x2 - rx, yi_prime = y2 - ry;

  return [[xi, yi], [xi_prime, yi_prime]];
}

function plot() {

  var cases = [
    {a: 1.1, l: 1.9, f: 0.3073},
    {a: 1.0, l: 1.7, f: 0.3229}
  ];

  var testCase = 1;
  
  var magA = cases[testCase].a, magL = cases[testCase].l;
  var maxS = Math.sqrt(magA*magA+magL*magL), magS1 = maxS * cases[testCase].f, magS2 = maxS - magS1;

  var origin = [0,0], board = JXG.JSXGraph.initBoard('jxgbox', {boundingbox: [-5.0, 5.0, 5.0, -5.0], axis: true});
  var drawAs = {dashed: {dash: 3, strokeWidth: 0.5, strokeColor: '#888888'} };

  board.suspendUpdate();

  var leftArm = board.create('slider', [[-4.5, 3], [-1.5, 3], [0, -64, -180]]);
  var leftLeg = board.create('slider', [[-4.5, 2], [-1.5, 2], [0, -12, -30]]);

  var rightArm = board.create('slider', [[0.5, 3], [3.5, 3], [0, 64, 180]]);
  var rightLeg = board.create('slider', [[0.5, 2], [3.5, 2], [0, 12, 30]]);

  var lh = board.create('point', [
    function() { return +magA * Math.sin(deg2rad(leftArm.Value())); },
    function() { return -magA * Math.cos(deg2rad(leftArm.Value())); }
  ], {size: 3, name: 'lh'});
  var LA = board.create('line', [origin, lh], {straightFirst: false, straightLast: false, lastArrow: true});
  var cLS1 = board.create('circle', [function() { return [lh.X(), lh.Y()]; }, function() { return magS1; }], drawAs.dashed);
  
  var lf = board.create('point', [
    function() { return +magL * Math.sin(deg2rad(leftLeg.Value())); },
    function() { return -magL * Math.cos(deg2rad(leftLeg.Value())); }
  ], {size: 3, name: 'lf'});
  var LL = board.create('line', [origin, lf], {straightFirst: false, straightLast: false, lastArrow: true});
  var cLS2 = board.create('circle', [function() { return [lf.X(), lf.Y()]; }, function() { return magS2; }], drawAs.dashed);

  var lx1 = board.create('point', [
    function() { return circleIntersection(cLS1, cLS2)[0][0]; },
    function() { return circleIntersection(cLS1, cLS2)[0][1]; }
  ], {size: 3, face:'x', name: 'lx1'});

  var lx2 = board.create('point', [
    function() { return circleIntersection(cLS1, cLS2)[1][0]; },
    function() { return circleIntersection(cLS1, cLS2)[1][1]; }
  ], {size: 3, face:'x', name: 'lx2'});

  /* Angle between lh, lx1 shall be between 0 and -180 */
  var angleLAJ = board.create('text', [-3.7, 0.5, function(){ return angleBetween(lh, lx1).toFixed(2); }]);
  /* Angle between lf, lx1 shall be between 0 and 180 */
  var angleLLJ = board.create('text', [-2.7, 0.5, function(){ return angleBetween(lf, lx1).toFixed(2); }]);
  
  var rh = board.create('point', [
    function() { return +magA * Math.sin(deg2rad(rightArm.Value())); },
    function() { return -magA * Math.cos(deg2rad(rightArm.Value())); }
  ], {size: 3, name: 'rh'});
  var RA = board.create('line', [origin, rh], {straightFirst: false, straightLast: false, lastArrow: true});
  var cRS1 = board.create('circle', [function() { return [rh.X(), rh.Y()]; }, function() { return magS1; }], drawAs.dashed);
  
  var rf = board.create('point', [
    function() { return +magL * Math.sin(deg2rad(rightLeg.Value())); },
    function() { return -magL * Math.cos(deg2rad(rightLeg.Value())); }
  ], {size: 3, name: 'rf'});
  var RL = board.create('line', [origin, rf], {straightFirst: false, straightLast: false, lastArrow: true});
  var cRS2 = board.create('circle', [function() { return [rf.X(), rf.Y()]; }, function() { return magS2; }], drawAs.dashed);

  var rx1 = board.create('point', [
    function() { return circleIntersection(cRS1, cRS2)[1][0]; },
    function() { return circleIntersection(cRS1, cRS2)[1][1]; }
  ], {size: 3, face:'x', name: 'rx1'});

  var rx2 = board.create('point', [
    function() { return circleIntersection(cRS1, cRS2)[0][0]; },
    function() { return circleIntersection(cRS1, cRS2)[0][1]; }
  ], {size: 3, face:'x', name: 'rx2'});
  
  var angleRAJ = board.create('text', [+1.3, 0.5, function(){ return angleBetween(rh, rx1).toFixed(2); }]);
  var angleRLJ = board.create('text', [+2.3, 0.5, function(){ return angleBetween(rf, rx1).toFixed(2); }]);

  board.unsuspendUpdate();

}

plot();
<!DOCTYPE html>
<html>

<head>
  <link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/jsxgraph/0.99.7/jsxgraph.css" />
  <link rel="stylesheet" href="style.css">
  <script type="text/javascript" charset="UTF-8" src="//cdnjs.cloudflare.com/ajax/libs/jsxgraph/0.99.7/jsxgraphcore.js"></script>
</head>

<body>
  <div id="jxgbox" class="jxgbox" style="width:580px; height:580px;"></div>
</body>

</html>

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-05-31 15:28:47

根据你的草图,E和G的坐标是:

E = (0, -magOE)
G = magOG * ( -sin(gamma), -cos(gamma) )

然后,计算H的位置是一个trilateration问题。实际上,这只是双边测量,因为你错过了第三个距离。因此,您将获得H的两个可能的位置。

首先,让我们定义一个新的坐标系,其中E位于原点,G位于x轴。在我们的原始坐标系中的x轴方向是:

x = (G - E) / ||G - E||

Y轴是:

y = ( x.y, -x.x )

E和G在这个新坐标系中的坐标是:

E* = (0, 0)
G* = (0, ||G - E||)

现在,我们可以很容易地在这个坐标系中找到H的坐标,直到前面提到的模糊性。我将缩写||G - E|| = d,就像维基百科文章中使用的符号一样:

H.x* = (magGH * magGH - magEH * magEH + d * d) / (2 * d)
H.y* = +- sqrt(magGH * magGH - H.x* * H.x*)

因此,我们对H.y有两种解决方案,一种是积极的,另一种是消极的。

最后,我们只需要将H转换回原来的坐标系:

H = x * H.x* + y * H.y* - (0, magOE)

给定H的坐标,计算角度非常简单:

alpha = arccos((H.x - G.x) / ||H - G||)
beta  = arccos((H.y - E.y) / ||H - E||)

示例

从您的示例中获取值

magOG = 3
magOE = 4
magGH = 3
magEH = 2
angleGamma = 82.74°

我们首先得到:

E = (0, -4)
G = 3 * ( -sin(82.74°), -cos(82.74°) )
  = (-2.976, -0.379)

我们的坐标系:

X= (-0.635,0.773) y=( 0.773,0.635)

在此坐标系中:

E* = (0, 0)
G* = (0, 4.687)

那么,H在我们的辅助坐标系中的坐标是:

H* = (2.877, +- 0.851)

我将只关注H*.y的正值,因为这是您在草图中标记的点。

变换回原始坐标系:

H = (-1.169, -1.237)

最后计算角度:

alpha = 25.41°
beta  = 22.94°

值的细微差异可能是由舍入误差引起的(在我的计算中或在您的计算中)。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50608788

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档