user3815508
user3815508

Reputation: 399

How can I draw arc's in angles of an arbitrary triangle?

I have realized a javascript program, which can draw an arbitrary triangle, and calculate the angles and sides length. Here is a program, which I try to realize: https://www.mathsisfun.com/proof180deg.html
Sadly I can't draw the arc's in angles of triangle! enter image description here

Maybe by means of the HTML canvas arc() Method will be realized. E.g. like:

ctx.arc(x, y, 50, start , end);

The x-y position is known. I'm looking for "start" and "end" of angles.

Thanks in advance.

Upvotes: 2

Views: 794

Answers (1)

Blindman67
Blindman67

Reputation: 54128

Math.atan2

You can use Math.atan2 to get the direction of a line.

for example

  // line from x1,y1 to x2,y2
  var nx1 = x2 - x1;
  var ny1 = y2 - y1;
  var angle = Math.atan2(ny1,nx1); 

So the you get the angle of the two lines from a corner. The angles are in the range -Math.PI to Math.PI so you need to move the first angle ahead of the second if it is lower or it will take the long way around.

There is also the problem of the triangle orientation, it can be clockwise or anticlockwise. If the wrong way the angles will be on the outside. You can use the cross product of the two lines to find the directio. If the wrong way then just swap the two angles.

Demo function

Use the mouse to move one of the points.

const ctx = canvas.getContext("2d");


// 2 lines start at x1,y1, then join at x2,y2, and then out to x3,y3
function drawLinesAndAngle(x1,y1,x2,y2,x3,y3){
 
 
  // get vectors from x2,y2 to the other points
  var nx1 = x1 - x2;
  var ny1 = y1 - y2;
  var nx2 = x3 - x2;
  var ny2 = y3 - y2;

  var lineAngle1 = Math.atan2(ny1,nx1);
  var lineAngle2 = Math.atan2(ny2,nx2);

  // use cross product to find correct direction.
  if(nx1 * ny2 - ny1 * nx2 < 0){ // wrong way around swap direction
      const t = lineAngle2;
      lineAngle2 = lineAngle1;
      lineAngle1 = t;
  }
  
  // if angle 1 is behind then move ahead
  if(lineAngle1 < lineAngle2){
      lineAngle1 += Math.PI * 2;
  }

  
  // render the arc
  ctx.fillStyle = "red";
  ctx.beginPath();
  ctx.moveTo(x2,y2);
  ctx.arc(x2,y2,35,lineAngle1, lineAngle2);
  ctx.fill();

  // render outside  arc
  ctx.fillStyle = "blue";
  ctx.beginPath();
  ctx.moveTo(x2,y2);
  ctx.arc(x2,y2,7,lineAngle2, lineAngle1);
  ctx.fill();
  
  // get the mid point
  const mx = -Math.cos((lineAngle1 + lineAngle2) / 2) * 50 + x2;
  const my = -Math.sin((lineAngle1 + lineAngle2) / 2) * 50 + y2;


  
  // render the angle
  ctx.fillStyle = "black";
  ctx.font = "16px arial";
  ctx.textAlign = "center";
  ctx.textBaseline = "middle";
  ctx.fillText(
      (360-(lineAngle1 - lineAngle2) * (180 /Math.PI)).toFixed(0),  // convert to deg
      mx,  
      my,
   )

}



// short cut vars 
var w = canvas.width;
var h = canvas.height;
var cw = w / 2;  // center 
var ch = h / 2;

// main update function
function update(timer){
    ctx.setTransform(1,0,0,1,0,0); // reset transform
    ctx.globalAlpha = 1;           // reset alpha
    if(w !== innerWidth || h !== innerHeight){
        cw = (w = canvas.width = innerWidth) / 2;
        ch = (h = canvas.height = innerHeight) / 2;
    }else{
        ctx.clearRect(0,0,w,h);
    }	
    // start line
    const x = Math.cos(timer / 5000) * Math.min(cw,ch) * 0.95 + cw;
    const y = Math.sin(timer / 5000) * Math.min(cw,ch) * 0.95 + ch;

    // fill triangle
    ctx.fillStyle = "#FD8";
    ctx.beginPath();
    ctx.lineTo(x,y);
    ctx.lineTo(cw,ch);
    ctx.lineTo(mouse.x,mouse.y);
    ctx.closePath();
    ctx.fill();


    drawLinesAndAngle(x,y,cw,ch,mouse.x,mouse.y);
    drawLinesAndAngle(cw,ch,mouse.x,mouse.y,x,y);
    drawLinesAndAngle(mouse.x,mouse.y,x,y,cw,ch);
    
    
    // render the lines
    ctx.strokeStyle = "black";
    ctx.lineWidth = 3;
    ctx.lineJoin = "round";
    ctx.beginPath();
    ctx.lineTo(x,y);
    ctx.lineTo(cw,ch);
    ctx.lineTo(mouse.x,mouse.y);
    ctx.closePath();
    ctx.stroke();
    
    
    requestAnimationFrame(update);
}
requestAnimationFrame(update);






const mouse  = {x : 0, y : 0, button : false, drag : false, dragStart : false, dragEnd : false, dragStartX : 0, dragStartY : 0}
function mouseEvents(e){
	mouse.x = e.pageX;
	mouse.y = e.pageY;
	mouse.button = e.type === "mousedown" ? true : e.type === "mouseup" ? false : mouse.button;

}
["down","up","move"].forEach(name => document.addEventListener("mouse"+name,mouseEvents));
canvas { position : absolute; top : 0px; left : 0px; }
<canvas id="canvas"></canvas>

Upvotes: 5

Related Questions