title: How to calculate the rotation angle of two constrained segments?
body: <p>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)?</p>
  
  <p><a href="https://i.stack.imgur.com/sLpj6.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/sLpj6.png" alt="enter image description here"></a></p>
  
  <p>What is given: the magnitude of the vectors, and the angle between the X-axis and OG:</p>
  
  <pre><code>var magOG = 3,
      magOE = 4,
      magGH = 3,
      magEH = 2,
      angleGamma = 90;
  </code></pre>
  
  <p>This is my starting point: <code>angleGamma = 90</code> - then, I will have following vectors:</p>
  
  <pre><code>var vOG = new vec2(-3,0),
      vOE = new vec2(0,-4);
  </code></pre>
  
  <p>From here on, I am trying to get <code>angleAlpha</code>and <code>angleBeta</code> for values of <code>angleGamma</code> less than 90 degrees. </p>
  
  <p><strong>MAGNITUDE OF THE CONSTRAINED SEGMENTS:</strong></p>
  
  <p>Segments HG and HE must meet following conditions:</p>
  
  <pre><code>/
  |  OG*OG+ OE*OE = (HG + HE)*(HG + HE)
  &gt;
  |  OG - HG = OE - HE
  \
  </code></pre>
  
  <p>which will lead to following two solutions (as pointed out in the accepted answer - bilateration):</p>
  
  <pre><code>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)
  </code></pre>
  
  <hr>
  
  <p><strong>SCRATCHPAD:</strong></p>
  
  <p>Here is a playground with the complete solution. The visualization library used here is the great <a href="https://jsxgraph.uni-bayreuth.de/wp/index.html" rel="nofollow noreferrer">JSXGraph</a>. Thanks to the Center for Mobile Learning with Digital Technology of the Bayreuth University.</p>
  
  <p>Credits for the circle intersection function: <a href="https://stackoverflow.com/users/473368/01automonkey">01AutoMonkey</a> in the accepted answer to this question: <a href="https://stackoverflow.com/a/12221389/4845566">A JavaScript function that returns the x,y points of intersection between two circles?</a></p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>function deg2rad(deg) {
    return deg * Math.PI / 180;
  }
  
  function rad2deg(rad) {
    return rad * 180 / Math.PI;
  }
  
  function lessThanEpsilon(x) {
    return (Math.abs(x) &lt; 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 &gt; (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 &amp;&amp; r1 === r2) {
      /* infinite solutions. circles are overlapping */
      return [[ixA,iyA], [ixL,iyL]];
    }
    
    if (d &lt; 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();</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;!DOCTYPE html&gt;
  &lt;html&gt;
  
  &lt;head&gt;
    &lt;link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/jsxgraph/0.99.7/jsxgraph.css" /&gt;
    &lt;link rel="stylesheet" href="style.css"&gt;
    &lt;script type="text/javascript" charset="UTF-8" src="//cdnjs.cloudflare.com/ajax/libs/jsxgraph/0.99.7/jsxgraphcore.js"&gt;&lt;/script&gt;
  &lt;/head&gt;
  
  &lt;body&gt;
    &lt;div id="jxgbox" class="jxgbox" style="width:580px; height:580px;"&gt;&lt;/div&gt;
  &lt;/body&gt;
  
  &lt;/html&gt;</code></pre>
  </div>
  </div>
  </p>