25

I know, of course, how to draw a triangle in the plane given the vertices:

Graphics[Polygon[{{1, 0}, {0, Sqrt[3]}, {-1, 0}}]]

But I'm not sure how to simply draw a triangle if all I care about is the length of the sides. (I'm happy to place one of the vertices at the origin and place one of the sides on the non-negative side of the x-axis, but that doesn't really matter.) Is there a straightforward way?

This raises the additional question, "how do I draw a triangle in Mathematica, given three angles?" (Say I want to it to reside somewhere in the unit circle.)

J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
DavidC
  • 16,724
  • 1
  • 42
  • 94

6 Answers6

22

In version 10, use SSSTriangle which stands for side-side-side triangle.

Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263
16

To answer your first question: when in doubt, fall back to basic construction geometry. Fix two points arbitrarily, and "construct" the third by finding the point of intersection of two circles with these points as centers and radii as the sides. Example:

sideAB = 4;sideBC = 5;sideCA = 6;
ptA = {0, 0};ptB = ptA + {sideAB, 0};
ptC = {x, y} /. Last@Solve[x^2 + y^2 - sideCA^2 == 0 && 
     y^2 + (x - sideAB)^2 - sideBC^2 == 0, {x, y}]

Graphics[{FaceForm[], EdgeForm[{Thick, Black}], Polygon[{ptA, ptB, ptC}]}]

rm -rf
  • 88,781
  • 21
  • 293
  • 472
  • 2
    That makes perfect sense. Funny, I used this method recently playing with GeoGebra but didn't think to transfer it to Mathematica. Once the side is on the x-axis you just use your compass. – DavidC Feb 08 '12 at 02:15
15

I'm not sure how to draw a triangle if all I care about is the length of the sides. (I'm happy to place one of the vertices at the origin and place one of the sides on the nonnegative side of the $x$-axis, but that doesn't really matter.) Is there a straightforward way?

Given a triangle with side lengths $p \leq q \leq r$ (assuming the lengths satisfy the triangle inequality, of course), with hypotenuse on the positive $x$-axis, and the origin as one endpoint, you can solve a system of equations to get the third point, apart from $(0,0)$ and $(r,0)$:

FullSimplify[{x, y} /. 
             Last[Solve[{x^2 + y^2 == p^2, (x - r)^2 + y^2 == q^2}, {x, y}]]]
{(p^2 - q^2 + r^2)/(2 r),
 Sqrt[-(p - q - r) (p + q - r) (p - q + r) (p + q + r)]/(2 r)}

and thus, either of

Graphics[Line[{{0, 0}, {r, 0}, {(p^2 - q^2 + r^2)/(2 r),
         Sqrt[-(p - q - r) (p + q - r) (p - q + r) (p + q + r)]/(2 r)}, {0, 0}}]]

or

Graphics[Polygon[{{0, 0}, {r, 0}, {(p^2 - q^2 + r^2)/(2 r),
         Sqrt[-(p - q - r) (p + q - r) (p - q + r) (p + q + r)]/(2 r)}}]]

does the job.

Verify the triangle:

FullSimplify[
 Norm /@ Differences[{{0, 0}, {r, 0}, {(p^2 - q^2 + r^2)/(2 r), 
     Sqrt[-(p - q - r) (p + q - r) (p - q + r) (p + q + 
          r)]/(2 r)}, {0, 0}}], 0 <= p <= q <= r && p + q >= r]
{r, q, p}

This raises the additional question, "how do I draw a triangle in Mathematica, given three angles?". (Say I want to it to reside somewhere in the unit circle.)

The law of sines saves your bacon here (the ratio of a side length and the sine of the opposite angle gives the diameter of the triangle's circumcircle). Skipping details, here's how to inscribe a triangle with specified angles into the unit circle:

parts = IntegerPartitions[180, {3}];

(* generate corresponding sides from randomly chosen angles *)
angles = parts[[RandomInteger[{1, Length[parts]}]]];
{r, q, p} = 2 Sin[angles Degree];

Graphics[{Line[{{1, 0}, {1 - p^2/2, p Sqrt[1 - p^2/4]},
                {1 - q^2/2, -q Sqrt[1 - q^2/4]}, {1, 0}}], 
          Circle[{0, 0}, 1]}]

You can use the next two snippets to verify that the triangle generated fits the specifications:

(* check side lengths *)
Norm /@ RotateLeft[Differences[
     N[{{1, 0}, {1 - p^2/2, p Sqrt[1 - p^2/4]},
        {1 - q^2/2, -q Sqrt[1 - q^2/4]}, {1, 0}}]]] - {r, q, p} // Chop

(* check angles *)
(Apply[VectorAngle, Map[Function[pt, pt - First[#]], Rest[#]]]/Degree) & /@ 
   NestList[RotateLeft, N[{{1, 0}, {1 - p^2/2, p Sqrt[1 - p^2/4]},
       {1 - q^2/2, -q Sqrt[1 - q^2/4]}}], 2] - angles // Chop

Both snippets should return {0, 0, 0} if all goes well.

J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
10

Brute forcing it:

triangle[a_?NumericQ, b_?NumericQ, c_?NumericQ] := 
 Block[{x, y, pt, sqr},
  sqr = #.# &;
  pt[a1_, b1_, c1_] := 
   Reduce[sqr[{x, y}] == b1^2 && sqr[{x, y} - {a1, 0}] == c1^2 && 
     y > 0, {x, y}];
  Polygon[{{0, 0}, {a, 0}, {x, y} /. ToRules[pt[a, b, c]]}]
  ]

Graphics[{EdgeForm[Thick], FaceForm[None], triangle[1, 1, 1/2]}]

Mathematica graphics

EDIT

Brute forcing it even more:

triangle[x_, y_, z_] := Block[{x1, y1, x2, y2, x3, y3},
  With[{a = {x1, y1}, b = {x2, y2}, 
    c = {x3, y3}}, {{x1, y1}, {x2, y2}, {x3, y3}} /. 
    First@FindInstance[
      Norm[a - b] == x && Norm[b - c] == y && Norm[c - a] == z, {x1, 
       y1, x2, y2, x3, y3}, Reals]
   ]
  ]
Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263
10

Here's a variation that labels the lengths of the sides. It is based on @Szabolcs' first solution.

triangle[a_?NumericQ,b_?NumericQ,c_?NumericQ]:=
  Block[{x,y,pt,sqr},
    sqr=#.#&;
    pt[a1_,b1_,c1_]:=
    Reduce[sqr[{x,y}]==b1^2&&sqr[{x,y}-{a1,0}]==c1^2&&y>0,{x,y}];
    {(Polygon[{{0,0},{a,0},{x,y}}]),
      Text[Style[Framed[a,Background-> LightYellow],11],{a/2,0}],
      Text[Style[Framed[b,Background-> LightYellow],11],{x/2,y/2}],
      Text[Style[Framed[c,Background-> LightYellow],11], 
         {(a+x)/2,y/2}]}/.ToRules[pt[a,b,c]]]

 g[{s1_,s2_,s3_}]:=
    Graphics[{EdgeForm[Thick],FaceForm[None],triangle[s1,s2,s3]},
              ImagePadding->20,ImageSize->{200,200}]

Some examples:

GraphicsGrid[{
  {g[{2, 1, Sqrt[5]}], g[{1, 2, Sqrt[5]}],
   g[{Sqrt[5], 1, 2}], g[{Sqrt[5], 2, 1}]},
  {g[{2, 2, Sqrt[8]}], g[{Sqrt[8], 2, 2}],
   g[{2, Sqrt[8], 2}],
   g[{Sqrt[2], Sqrt[2], 2}]}}]

labeled triangles

rm -rf
  • 88,781
  • 21
  • 293
  • 472
DavidC
  • 16,724
  • 1
  • 42
  • 94
1

I just realized that there is a another straightforward approach using circles. Let's assume that two of the vertices lie at {0,0} and {1.5, 0}, as suggested by Szabolcs' example from Jun' 28, '14.

The third vertex will lie at either of the two points given by Solve. Those points are 2 units from the origin and 1 unit from the vertex at (1.5, 0).

Solve[{x, y} \[Element] Circle[{0, 0}, 2] && {x, y} \[Element]Circle[{1.5, 0}, 1], {x, y}]

{{x -> 1.75, y -> -0.968246}, {x -> 1.75, y -> 0.968246}}

Let's take the point that lies in quadrant I as the solution:

Graphics[{{Red, PointSize[Large], Point[{0, 0}], Point[{0, 0}], Point[{3/2, 0}], Point[{1.75`, 0.9682458365518543`}]}, 
Circle[{0, 0}, 2], Circle[{3/2, 0}, 1], 
Triangle[{{0, 0}, {1.5, 0}, {1.75`, 0.9682458365518543`}}]}, 
AxesOrigin -> {0, 0}, Axes -> True, Frame -> True]

triangle

DavidC
  • 16,724
  • 1
  • 42
  • 94