Home > Back-end >  convert length to point in svg (polygon) dynamically
convert length to point in svg (polygon) dynamically

Time:02-11

I am doing a small assignment to find out the type of the triangle whether is equilateral, isosceles, or scalene based on the values a,b,c.

my problem is that I couldn't manage to convert the a,b,c values in order to draw the shape by using SVG (polygon) since it takes points and I have only values

function triangle(a, b, c) {
  if (a === b && a === c && b === c) return "equilateral";
  if (a === b && a === c) return "isosceles";
  else {
    return "scalene";
  }
}
 <div>
        <svg className="traingle" height="400" width="400">
          <polygon points={`200 ${b}, 200 ${a}, 0 ${c}`} />
        </svg>
      </div>

enter image description here

CodePudding user response:

This question probably belongs in Maths StackExchange, but anyway.

Firstly, you need to first check whether it is possible for the combination of side lengths to form a triangle.

The way to do that is with the Triangle Inequality Theorem. It states that each of the side lengths must be less than the sum of the other two.

So in your example, the lengths [5,200,300] cannot form a triangle because 300 is not less than (5 200).

Also, none of the lengths should be <= 0.

So let's work with three valid side lengths: [150, 200, 300].

The way to get the three points is to start with one side, and draw that first. So we will start with the side that is 150.

You can draw that side anywhere, but let's make the line go from (0,0) to (150,0).

To get the third point we need to find where the other two sides would meet. Imagine two circles centred at each end of that first line. Each circle has a radius corresponding to the remaining two side lengths. The way to calculate the third point is to find the instersection point(s) of those two circles.

svg {
  background-color: linen;
  width: 500px;
}

line {
  stroke: black;
  stroke-width: 2;
}

.c300 {
  fill: none;
  stroke: blue;
  stroke-width: 2;
}

.c200 {
  fill: none;
  stroke: green;
  stroke-width: 2;
}

line.la {
  stroke: blue;
  stroke-dasharray: 4 6;
}

.lb {
  stroke: green;
  stroke-dasharray: 4 6;
}
<svg viewBox="-350 -350 750 700">

  <line  x1="0" y1="0" x2="150" y2="0"/>
  
  <circle  cx="0" cy="0" r="300"/>
  <circle  cx="150" cy="0" r="200"/>

  <line  x1="0" y1="0" x2="241.667" y2="-177.756"/>
  <line  x1="150" y1="0" x2="241.667" y2="-177.756"/>

</svg>  

If we use Wolfram Alpha's version of the formula then we get the following:

     d^2 - r^2   R^2
x = -----------------
          2 * d;

and

     sqrt( 4 * d^2 * R^2 - ( d^2 - r^2   R^2 )^2 )
y = -----------------------------------------------
                       2 * d

where d is the length of that first side, and r and R are the lengths of the other two sides.

So for our example:

R = 300
r = 200
d^2 - r^2   R^2 = 150^2 - 300^2   200^2
                = 72500

x = 72500 / 300
  = 241.667

y = sqrt( 4 * 22500 * 90000 - 72500^2) / 300
  = sqrt( 2843750000 ) / 300 
  = 53326.823 / 300
  = 177.756

And you can see these values for x and y in the example SVG above.

Note that the circles intersect both above and below the first line. So 177.756 and -177.656 are both valid solutions for y.

CodePudding user response:

Let's assume point A is always at 0,0, and point B has the same y coordinate. You can calculate position of C using the law of cosines:

const calculateTriangle = (a, b, c) => {
  const ax = 0;
  const ay = 0;
  const bx = ax   c;
  const by = ay;
  const cosAlpha = (a * a - b * b - c * c) / (b * c * 2);
  const alpha = Math.acos(cosAlpha);
  const cx = ax - b * cosAlpha;
  const cy = ay   b * Math.sin(alpha);
  return {ax, ay, bx, by, cx, cy};
};

CodePudding user response:

Here is a working snippet with calculateTriangle. Please note that the side length numbers should be valid

const calculateTriangle = (a, b, c) => {
  const ax = 0;
  const ay = 0;
  const bx = ax   c;
  const by = ay;
  const cosAlpha = (a * a - b * b - c * c) / (b * c * 2);
  const alpha = Math.acos(cosAlpha);
  const cx = ax - b * cosAlpha;
  const cy = ay   b * Math.sin(alpha);
  return {ax, ay, bx, by, cx, cy};
};

const onDraw = () => {
    const a = d3.select('#side-a').node().value;
    const b = d3.select('#side-b').node().value;
    const c = d3.select('#side-c').node().value;
  const {ax, ay, bx, by, cx, cy} = calculateTriangle(parseInt(a), parseInt(b), parseInt(c));
  d3.select('polygon').attr('points', `${ax},${ay} ${bx},${by} ${cx},${cy}`)
  console.log('T: ', t);
}

d3.select('button').on('click', onDraw);
#wrapper {
  display: flex;
  flex-direction: row;
}

#container {
  font-family: Ubuntu;
  font-size: 16px;
  display: flex:
  flex-direction: column;
}

#container > div {
  display: flex;
  flex-direction: row;
  margin: 10px 0 0 20px;
}

#container > div > span {
  width: 10px;
}

#container > div > input {
  margin-left: 20px;
  width: 50px;
}

#container button {
  margin-left: 30px;
  width: 60px;
}

svg {
  border: 1px solid grey;
  margin: 10px 0 0 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id='wrapper'>
  <div id='container'>
    <div>
      <span>A: </span><input type="number" id="side-a" value="50"/>
    </div>
    <div>
      <span>B: </span><input type="number" id="side-b" value="40"/>
    </div>
    <div>
      <span>C: </span><input type="number" id="side-c" value="30"/>
    </div> 
    <div>
      <button>DRAW</button>
    </div>
  </div>
  <svg width="110" height="110">
    <polygon transform="translate(10,10)" />
  </svg>
</div>

  • Related