Andriy B
Andriy B

Reputation: 724

How to calculate internal angles of a closed polygon path with Paper.js?

Having a closed filled polygon defined as a set of points, question is how to get a list of internal angles between each 2 connecting segment lines that make up this polygon.

Upvotes: 0

Views: 580

Answers (1)

Andriy B
Andriy B

Reputation: 724

Paper.js allows to get angle between 2 vectors by calling getDirectedAngle (See class Point). So we can get angles between all segments, just we still need a way to decide which angle value is internal.

After spending some time i solved the task using this method.

First, i calculate angle between 2 connecting segments A and B. Next, i evaluate median vector M for A and B starting from the connecting point C where segments A and B meet. Finally i test whether point that lies on median between A and B is inside of polygon or outside of it and based on that i decide if this angle is internal or external.

Solution is below.

function checkPolygonAngle(path) {
  if (path.curves.length<=1) {
    return;
  } 

  const angleText = function(point, angle) {
    const text = new paper.PointText(point);
    text.justification = 'center';
    text.fillColor = 'black';
    text.content = ""+(Math.round(angle*100)/100);
    return text;
  }
  for (let i=1;i<=path.curves.length;i++) {
    console.log(i);
    const curve1 = path.curves[i-1];
    const curve2 = i==path.curves.length ? path.curves[0] : path.curves[i];
    const v1 = curve1.segment1.point.subtract(curve1.segment2.point);
    const v2 = curve2.segment2.point.subtract(curve2.segment1.point);
    const point = curve1.segment2.point;
    (new paper.Path.Circle(point,3)).fillColor='red';

    const angle = v1.getDirectedAngle(v2);

    const medianAngle = angle/2;
    const medianPoint = curve1.segment1.point.rotate(medianAngle, point);
    const medianVector = medianPoint.subtract(point);
    medianVector.length=30;

    const pointOnMedian = point.add(medianVector);
    (new paper.Path.Line(point,pointOnMedian)).strokeColor='green';
    let insideAngle = null;
    if (path.contains(pointOnMedian)) {
      insideAngle = Math.abs(angle);
      (new paper.Path.Circle(pointOnMedian,3)).fillColor='magenta';
      angleText(pointOnMedian, insideAngle);
    }

    const oppositeMedianVector = medianVector.multiply(-1);
    const pointOnOppositeMedian = point.add(oppositeMedianVector);
    (new paper.Path.Line(point,pointOnOppositeMedian)).strokeColor='blue';
    if (path.contains(pointOnOppositeMedian)) {
      insideAngle = (360 - Math.abs(angle));
      (new paper.Path.Circle(pointOnOppositeMedian,3)).fillColor='magenta';
      angleText(pointOnOppositeMedian, insideAngle);
    }

    console.log(i+":", v1, v2, 'angle: ', insideAngle);
  }
}

Sample of polygon with internal angles

Upvotes: 1

Related Questions