1 /* 2 Copyright 2008-2024 3 Matthias Ehmann, 4 Michael Gerhaeuser, 5 Carsten Miller, 6 Bianca Valentin, 7 Alfred Wassermann, 8 Peter Wilfahrt 9 10 This file is part of JSXGraph. 11 12 JSXGraph is free software dual licensed under the GNU LGPL or MIT License. 13 14 You can redistribute it and/or modify it under the terms of the 15 16 * GNU Lesser General Public License as published by 17 the Free Software Foundation, either version 3 of the License, or 18 (at your option) any later version 19 OR 20 * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT 21 22 JSXGraph is distributed in the hope that it will be useful, 23 but WITHOUT ANY WARRANTY; without even the implied warranty of 24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 GNU Lesser General Public License for more details. 26 27 You should have received a copy of the GNU Lesser General Public License and 28 the MIT License along with JSXGraph. If not, see <https://www.gnu.org/licenses/> 29 and <https://opensource.org/licenses/MIT/>. 30 */ 31 32 /*global JXG: true, define: true*/ 33 /*jslint nomen: true, plusplus: true*/ 34 35 /** 36 * @fileoverview Example file for a triangle implemented as a extension to JSXGraph. 37 */ 38 39 import JXG from "../jxg.js"; 40 import Type from "../utils/type.js"; 41 import Const from "../base/constants.js"; 42 import Polygon from "../base/polygon.js"; 43 44 var priv = { 45 removeSlopeTriangle: function () { 46 Polygon.prototype.remove.call(this); 47 48 this.board.removeObject(this.toppoint); 49 this.board.removeObject(this.glider); 50 51 this.board.removeObject(this.baseline); 52 this.board.removeObject(this.basepoint); 53 54 this.board.removeObject(this.label); 55 56 if (this._isPrivateTangent) { 57 this.board.removeObject(this.tangent); 58 } 59 }, 60 Value: function () { 61 return this.tangent.getSlope(); 62 }, 63 Direction: function() { 64 return this.tangent.Direction(); 65 } 66 }; 67 68 /** 69 * @class Slope triangle for a point on a line. 70 * @pseudo 71 * @name Slopetriangle 72 * @augments JXG.Line 73 * @constructor 74 * @type JXG.Polygon 75 * @throws {Error} If the element cannot be constructed with the given parent objects an exception is thrown. 76 * Parameter options: 77 * @param {JXG.Line} t A tangent based on a glider on some object, e.g. curve, circle, line or turtle. 78 * @param {JXG.Line_JXG.Point} li, p A line and a point on that line. 79 * The user has to take care that the point is a member of the line. 80 * @example 81 * // Create a slopetriangle on a tangent 82 * var f = board.create('plot', ['sin(x)']), 83 * g = board.create('glider', [1, 2, f]), 84 * t = board.create('tangent', [g]), 85 * 86 * st = board.create('slopetriangle', [t]); 87 * 88 * </pre><div class="jxgbox" id="JXG951ccb6a-52bc-4dc2-80e9-43db064f0f1b" style="width: 300px; height: 300px;"></div> 89 * <script type="text/javascript"> 90 * (function () { 91 * var board = JXG.JSXGraph.initBoard('JXG951ccb6a-52bc-4dc2-80e9-43db064f0f1b', {boundingbox: [-5, 5, 5, -5], axis: true, showcopyright: false, shownavigation: false}), 92 * f = board.create('plot', ['sin(x)']), 93 * g = board.create('glider', [1, 2, f]), 94 * t = board.create('tangent', [g]), 95 * 96 * st = board.create('slopetriangle', [t]); 97 * })(); 98 * </script><pre> 99 * 100 * @example 101 * // Create a on a line and a point on that line 102 * var p1 = board.create('point', [-2, 3]), 103 * p2 = board.create('point', [2, -3]), 104 * li = board.create('line', [p1, p2]), 105 * p = board.create('glider', [0, 0, li]), 106 * 107 * st = board.create('slopetriangle', [li, p]); 108 * 109 * </pre><div class="jxgbox" id="JXGb52f451c-22cf-4677-852a-0bb9d764ee95" style="width: 300px; height: 300px;"></div> 110 * <script type="text/javascript"> 111 * (function () { 112 * var board = JXG.JSXGraph.initBoard('JXGb52f451c-22cf-4677-852a-0bb9d764ee95', {boundingbox: [-5, 5, 5, -5], axis: true, showcopyright: false, shownavigation: false}), 113 * p1 = board.create('point', [-2, 3]), 114 * p2 = board.create('point', [2, -3]), 115 * li = board.create('line', [p1, p2]), 116 * p = board.create('glider', [0, 0, li]), 117 * 118 * st = board.create('slopetriangle', [li, p]); 119 * })(); 120 * </script><pre> 121 */ 122 JXG.createSlopeTriangle = function (board, parents, attributes) { 123 var el, tangent, tglide, glider, 124 toppoint, baseline, basepoint, 125 label, attr, 126 isPrivateTangent = false; 127 128 if (parents.length === 1 && parents[0].type === Const.OBJECT_TYPE_TANGENT) { 129 tangent = parents[0]; 130 tglide = tangent.glider; 131 } else if (parents.length === 1 && parents[0].type === Const.OBJECT_TYPE_GLIDER) { 132 tglide = parents[0]; 133 attr = Type.copyAttributes(attributes, board.options, "slopetriangle", "tangent"); 134 tangent = board.create("tangent", [tglide], attr); 135 isPrivateTangent = true; 136 } else if ( 137 parents.length === 2 && 138 parents[0].elementClass === Const.OBJECT_CLASS_LINE && 139 Type.isPoint(parents[1]) 140 ) { 141 tangent = parents[0]; 142 tglide = parents[1]; 143 } else { 144 throw new Error( 145 "JSXGraph: Can't create slope triangle with parent types '" + 146 typeof parents[0] + 147 "'." 148 ); 149 } 150 151 attr = Type.copyAttributes(attributes, board.options, "slopetriangle", "basepoint"); 152 basepoint = board.create( 153 "point", 154 [ 155 function () { 156 return [tglide.X() + 1, tglide.Y()]; 157 } 158 ], 159 attr 160 ); 161 162 attr = Type.copyAttributes(attributes, board.options, "slopetriangle", "baseline"); 163 baseline = board.create("line", [tglide, basepoint], attr); 164 165 attr = Type.copyAttributes(attributes, board.options, "slopetriangle", "glider"); 166 glider = board.create("glider", [tglide.X() + 1, tglide.Y(), baseline], attr); 167 168 attr = Type.copyAttributes(attributes, board.options, "slopetriangle", "toppoint"); 169 toppoint = board.create( 170 "point", 171 [ 172 function () { 173 return [ 174 glider.X(), 175 glider.Y() + (glider.X() - tglide.X()) * tangent.getSlope() 176 ]; 177 } 178 ], 179 attr 180 ); 181 182 attr = Type.copyAttributes(attributes, board.options, "slopetriangle"); 183 // attr.borders = Type.copyAttributes(attr.borders, board.options, "slopetriangle", "borders"); 184 el = board.create("polygon", [tglide, glider, toppoint], attr); 185 186 /** 187 * Returns the value of the slope triangle, that is the slope of the tangent. 188 * @name Value 189 * @memberOf Slopetriangle.prototype 190 * @function 191 * @returns {Number} slope of the tangent. 192 */ 193 el.Value = priv.Value; 194 195 /** 196 * Returns the direction of the slope triangle, that is the direction of the tangent. 197 * @name Direction 198 * @memberOf Slopetriangle.prototype 199 * @see Line#Direction 200 * @function 201 * @returns {Number} slope of the tangent. 202 */ 203 el.Direction = priv.Direction; 204 el.tangent = tangent; 205 el._isPrivateTangent = isPrivateTangent; 206 207 //el.borders[0].setArrow(false, {type: 2, size: 10}); 208 //el.borders[1].setArrow(false, {type: 2, size: 10}); 209 el.borders[2].setArrow(false, false); 210 211 attr = Type.copyAttributes(attributes, board.options, "slopetriangle", "label"); 212 //label = board.create("text", [ 213 // function () { 214 // return glider.X() + 0.1; 215 // }, 216 // function () { 217 // return (glider.Y() + toppoint.Y()) * 0.5; 218 // }, 219 // function () { 220 // return ""; 221 // } 222 // ], 223 // attr 224 // ); 225 226 attr = Type.copyAttributes(attr, board.options, "label"); 227 // Add label to vertical polygon edge 228 attr.isLabel = true; 229 attr.anchor = el.borders[1]; 230 attr.priv = el.borders[1].visProp.priv; 231 attr.id = el.borders[1].id + "Label"; 232 233 label = board.create("text", [0, 0, function () { return ""; }], attr); 234 label.needsUpdate = true; 235 label.dump = false; 236 el.borders[1].label = label; 237 el.borders[1].hasLabel = true; 238 el.borders[1].visProp.withlabel = true; 239 240 label._setText(function () { 241 var digits = Type.evaluate(label.visProp.digits); 242 243 if (label.useLocale()) { 244 return label.formatNumberLocale(el.Value(), digits); 245 } 246 return Type.toFixed(el.Value(), digits); 247 }); 248 label.fullUpdate(); 249 250 el.glider = glider; 251 el.basepoint = basepoint; 252 el.baseline = baseline; 253 el.toppoint = toppoint; 254 el.label = label; 255 256 el.subs = { 257 glider: glider, 258 basePoint: basepoint, 259 baseLine: baseline, 260 topPoint: toppoint, 261 label: label 262 }; 263 el.inherits.push(glider, basepoint, baseline, toppoint, label); 264 265 el.methodMap = JXG.deepCopy(el.methodMap, { 266 tangent: "tangent", 267 glider: "glider", 268 basepoint: "basepoint", 269 baseline: "baseline", 270 toppoint: "toppoint", 271 label: "label", 272 Value: "Value", 273 V: "Value", 274 Direction: "Direction" 275 }); 276 277 el.remove = priv.removeSlopeTriangle; 278 279 return el; 280 }; 281 282 JXG.registerElement("slopetriangle", JXG.createSlopeTriangle); 283 284 // export default { 285 // createSlopeTriangle: JXG.createSlopeTriangle 286 // }; 287