Home | Math Display Experiments | JSXGraph Internal Angles of a Triangle
Page by Murray Bourne, IntMath.com. Last updated: 07 Jul 2019JSXGraph Internal Angles of a Triangle
Last updated: 07 July 2019.
In the following interactive graph, we want all our angles to show as internal angles of the triangle.
However, by default, JSXGraph displays angle sizes based on the order of the points defining each angle.
In the following triangle, JSXGraph reads ∠ABC as the external reflex angle 284.6°. If we want the internal angle, we need to reverse the first and third points: ∠CBA = 75.4°
When we drag the points, as soon as one of the angles is more than 180° (e.g. drag point C beyond line AB), all will "snap" to show the external angle.
The Problem: External angles
Drag any of the angle points through the opposite side of the triangle. You'll see reflex angles.
Here's the code used:
board = JXG.JSXGraph.initBoard('jxgbox0', {axis:false,boundingbox:[-5.9,8,5.9,-5.9], keepaspectratio:true,showCopyright:false, showNavigation:false}); var qr = [], arc2,isInDragMode; qr[1] = board.create('point', [0,0], {style:5,fillColor:'#ff00ff'}); qr[2] = board.create('point', [5,0], {style:5,fillColor:'#ff00ff'}); qr[3] = board.create('point', [3.85,4.4], {style:5,fillColor:'#ff00ff'}); var triArr1 = [qr[3],qr[2],qr[1]]; var tri = board.createElement('polygon',triArr1, {strokeWidth:2, strokeColor:'#dd00dd',highlight:false}); var arc1 = board.create('angle',triArr1,{radius:1,name:'θ2'}); var triArr2 = [qr[2],qr[1],qr[3]]; var arc2 = board.create('angle',triArr2,{radius:1,name:'θ1'}); var triArr3 = [qr[1],qr[3],qr[2]]; var arc3 = board.create('angle',triArr3,{radius:1,name:'θ3'}); board.create('text', [-5, 3, function () { return '<p>θ_1 = ' + (arc2.Value() * 180 / Math.PI).toFixed(1) + '°</p>' +'<p>θ_2 = ' + (arc1.Value() * 180 / Math.PI).toFixed(1) + '°</p>' +'<p>θ_3 = ' + (arc3.Value() * 180 / Math.PI).toFixed(1) + '°</p>'; }],{highlight:false,fixed:true});
A workaround
The following code swaps the angle point order when any angle becomes reflex.
board = JXG.JSXGraph.initBoard('jxgbox1', {axis:false,boundingbox:[-5.9,8,5.9,-5.9], keepaspectratio:true,showCopyright:false, showNavigation:false}); var qr = [], arc2,isInDragMode; qr[1] = board.create('point', [0,0], {style:5,fillColor:'#ff00ff'}); qr[2] = board.create('point', [5,0], {style:5,fillColor:'#ff00ff'}); qr[3] = board.create('point', [3.85,4.4], {style:5,fillColor:'#ff00ff'}); var triArr1 = [qr[3],qr[2],qr[1]]; var tri = board.createElement('polygon',triArr1, {strokeWidth:2, strokeColor:'#dd00dd',highlight:false}); var arc1 = board.create('angle',triArr1,{radius:1,name:'θ2'}); var triArr2 = [qr[2],qr[1],qr[3]]; var arc2 = board.create('angle',triArr2,{radius:1,name:'θ1'}); var triArr3 = [qr[1],qr[3],qr[2]]; var arc3 = board.create('angle',triArr3,{radius:1,name:'θ3'}); var updateG = function() { board.suspendUpdate(); if( arc1.Value() > Math.PI) { board.removeObject(arc1); triArr1 = [triArr1[2], triArr1[1], triArr1[0]]; arc1 = board.create('angle',triArr1,{radius:1,name:'θ2'}); board.removeObject(arc2); triArr2 = [triArr2[2], triArr2[1], triArr2[0]]; arc2 = board.create('angle',triArr2,{radius:1,name:'θ1'}); board.removeObject(arc3); triArr3 = [triArr3[2], triArr3[1], triArr3[0]]; arc3 = board.create('angle',triArr3,{radius:1,name:'θ3'}); } board.unsuspendUpdate(); } qr[1].on('drag',function(){ updateG(); }); qr[2].on('drag',function(){ updateG(); }); qr[3].on('drag',function(){ updateG(); }); board.create('text', [-5, 3, function () { return '<p>θ_1 = ' + (arc2.Value() * 180 / Math.PI).toFixed(1) + '°</p>'+ '<p>θ_2 = ' + (arc1.Value() * 180 / Math.PI).toFixed(1) + '°</p>'+ '<p>θ_3 = ' + (arc3.Value() * 180 / Math.PI).toFixed(1) + '°</p>'+ '<p>θ_1 + θ_2 + θ_3 = 180°</p>'; }],{highlight:false,fixed:true});
Easier Alternative?
Since version 0.99.2, it has been possible to create angles as "nonreflex" using board.create('nonreflexangle'...
, as follows.
However, while the indicated angle is now internal, the magnitude of the angle given by arc1.Value()
remains the reflex angle.
board2 = JXG.JSXGraph.initBoard('jxgbox2', {axis:false,boundingbox:[-5.9,8,5.9,-5.9], keepaspectratio:true,showCopyright:false, showNavigation:false}); var qr = [], arc2,isInDragMode; qr[1] = board2.create('point', [0,0], {style:5,fillColor:'#ff00ff'}); qr[2] = board2.create('point', [5,0], {style:5,fillColor:'#ff00ff'}); qr[3] = board2.create('point', [3.85,4.4], {style:5,fillColor:'#ff00ff'}); var triArr1 = [qr[3],qr[2],qr[1]]; var tri = board2.createElement('polygon',triArr1, {strokeWidth:2, strokeColor:'#dd00dd',highlight:false}); var arc1 = board2.create('nonreflexangle',triArr1, {radius:1,name:'θ2'}); var triArr2 = [qr[2],qr[1],qr[3]]; var arc2 = board2.create('nonreflexangle',triArr2, {radius:1,name:'θ1'}); var triArr3 = [qr[1],qr[3],qr[2]]; var arc3 = board2.create('nonreflexangle',triArr3, {radius:1,name:'θ3'}); board2.create('text', [-5, 3, function () { return '<p>θ_1 = ' + (arc2.Value() * 180 / Math.PI).toFixed(1) + '°</p>'+ '<p>θ_2 = ' + (arc1.Value() * 180 / Math.PI).toFixed(1) + '°</p>'+ '<p>θ_3 = ' + (arc3.Value() * 180 / Math.PI).toFixed(1) + '°</p>'; }],{highlight:false,fixed:true});
A fix for reflex angle magnitudes
In this version, we test if the angle is greater than 180°, and if so, output the magnitude of the triangle's associated internal angle.
board2 = JXG.JSXGraph.initBoard('jxgbox3', {axis:false,boundingbox:[-5.9,8,5.9,-5.9], keepaspectratio:true,showCopyright:false, showNavigation:false}); var qr = [], arc2,isInDragMode; qr[1] = board2.create('point', [0,0], {style:5,fillColor:'#ff00ff'}); qr[2] = board2.create('point', [5,0], {style:5,fillColor:'#ff00ff'}); qr[3] = board2.create('point', [3.85,4.4], {style:5,fillColor:'#ff00ff'}); var triArr1 = [qr[3],qr[2],qr[1]]; var tri = board2.createElement('polygon',triArr1, {strokeWidth:2, strokeColor:'#dd00dd',highlight:false}); var arc1 = board2.create('nonreflexangle',triArr1, {radius:1,name:'θ2'}); var triArr2 = [qr[2],qr[1],qr[3]]; var arc2 = board2.create('nonreflexangle',triArr2, {radius:1,name:'θ1'}); var triArr3 = [qr[1],qr[3],qr[2]]; var arc3 = board2.create('nonreflexangle',triArr3, {radius:1,name:'θ3'}); board2.create('text', [-5, 3, function () { if(arc2.Value() > Math.PI) { ang2 = (360 - arc2.Value() * 180 / Math.PI).toFixed(1); ang1 = (360 - arc1.Value() * 180 / Math.PI).toFixed(1); ang3 = (360 - arc3.Value() * 180 / Math.PI).toFixed(1); } else { ang2 = (arc2.Value() * 180 / Math.PI).toFixed(1); ang1 = (arc1.Value() * 180 / Math.PI).toFixed(1); ang3 = (arc3.Value() * 180 / Math.PI).toFixed(1); } return '<p>θ_1 = ' + ang2 + '°</p>'+ '<p>θ_2 = ' + ang1 + '°</p>'+ '<p>θ_3 = ' + ang3 + '°</p>'+ '<p>θ_1 + θ_2 + θ_3 = 180°</p>'; }],{highlight:false,fixed:true});
Any questions or comments on these examples, please add them here.