I have two vectors, the Y-aligned is fixed whereby the X-aligned is allowed to rotate. These vectors are connected together through two fixed-length segments. Given the angle between the two vectors (82.74) and the length of all segments, how can I get the angle of the two jointed segments (24.62 and 22.61)?
What is given: the magnitude of the vectors, and the angle between the X-axis and OG:
var magOG = 3,
magOE = 4,
magGH = 3,
magEH = 2,
angleGamma = 90;
This is my starting point: angleGamma = 90
- then, I will have following vectors:
var vOG = new vec2(-3,0),
vOE = new vec2(0,-4);
From here on, I am trying to get angleAlpha
and angleBeta
for values of angleGamma
less than 90 degrees.
MAGNITUDE OF THE CONSTRAINED SEGMENTS:
Segments HG and HE must meet following conditions:
/
| OG*OG+ OE*OE = (HG + HE)*(HG + HE)
>
| OG - HG = OE - HE
\
which will lead to following two solutions (as pointed out in the accepted answer - bilateration):
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:
Here is a playground with the complete solution. The visualization library used here is the great JSXGraph. Thanks to the Center for Mobile Learning with Digital Technology of the Bayreuth University.
Credits for the circle intersection function: 01AutoMonkey in the accepted answer to this question: A 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>