1 /* 2 Copyright 2008-2023 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 import JXG from "../jxg"; 36 import Symbolic from "../math/symbolic"; 37 import Type from "../utils/type"; 38 39 /** 40 * @class This element is used to visualize the locus of a given dependent point. 41 * @pseudo 42 * @description The locus element is used to visualize the curve a given point describes. 43 * @constructor 44 * @name Locus 45 * @type JXG.Curve 46 * @augments JXG.Curve 47 * @throws {Error} If the element cannot be constructed with the given parent objects an exception is thrown. 48 * @param {JXG.Point} p The constructed curve is the geometric locus of the given point. 49 * @example 50 * // This examples needs JXG.Server up and running, otherwise it won't work. 51 * p1 = board.create('point', [0, 0]); 52 * p2 = board.create('point', [6, -1]); 53 * c1 = board.create('circle', [p1, 2]); 54 * c2 = board.create('circle', [p2, 1.5]); 55 * g1 = board.create('glider', [6, 3, c1]); 56 * c3 = board.create('circle', [g1, 4]); 57 * g2 = board.create('intersection', [c2,c3,0]); 58 * m1 = board.create('midpoint', [g1,g2]); 59 * loc = board.create('locus', [m1], {strokeColor: 'red'}); 60 * </pre><div class="jxgbox" id="JXGd45d7188-6624-4d6e-bebb-1efa2a305c8a" style="width: 400px; height: 400px;"></div> 61 * <script type="text/javascript"> 62 * lcex_board = JXG.JSXGraph.initBoard('JXGd45d7188-6624-4d6e-bebb-1efa2a305c8a', {boundingbox:[-4, 6, 10, -6], axis: true, grid: false, keepaspectratio: true}); 63 * lcex_p1 = lcex_board.create('point', [0, 0]); 64 * lcex_p2 = lcex_board.create('point', [6, -1]); 65 * lcex_c1 = lcex_board.create('circle', [lcex_p1, 2]); 66 * lcex_c2 = lcex_board.create('circle', [lcex_p2, 1.5]); 67 * lcex_g1 = lcex_board.create('glider', [6, 3, lcex_c1]); 68 * lcex_c3 = lcex_board.create('circle', [lcex_g1, 4]); 69 * lcex_g2 = lcex_board.create('intersection', [lcex_c2,lcex_c3,0]); 70 * lcex_m1 = lcex_board.create('midpoint', [lcex_g1,lcex_g2]); 71 * lcex_loc = board.create('locus', [lcex_m1], {strokeColor: 'red'}); 72 * </script><pre> 73 */ 74 JXG.createLocus = function (board, parents, attributes) { 75 var c, p; 76 77 if (Type.isArray(parents) && parents.length === 1 && Type.isPoint(parents[0])) { 78 p = parents[0]; 79 } else { 80 throw new Error( 81 "JSXGraph: Can't create locus with parent of type other than point." + 82 "\nPossible parent types: [point]" 83 ); 84 } 85 86 c = board.create("curve", [[null], [null]], attributes); 87 c.dontCallServer = false; 88 89 c.elType = "locus"; 90 c.setParents([p.id]); 91 92 /** 93 * Should be documented in JXG.Curve 94 * @ignore 95 */ 96 c.updateDataArray = function () { 97 var spe, cb, data; 98 99 if (c.board.mode > 0) { 100 return; 101 } 102 103 spe = Symbolic.generatePolynomials(board, p, true).join("|"); 104 if (spe === c.spe) { 105 return; 106 } 107 108 c.spe = spe; 109 110 cb = function (x, y, eq, t) { 111 c.dataX = x; 112 c.dataY = y; 113 114 /** 115 * The implicit definition of the locus. 116 * @memberOf Locus.prototype 117 * @name eq 118 * @type String 119 */ 120 c.eq = eq; 121 122 /** 123 * The time it took to calculate the locus 124 * @memberOf Locus.prototype 125 * @name ctime 126 * @type Number 127 */ 128 c.ctime = t; 129 130 // convert equation and use it to build a generatePolynomial-method 131 c.generatePolynomial = (function (equations) { 132 return function (point) { 133 var i, 134 x = "(" + point.symbolic.x + ")", 135 y = "(" + point.symbolic.y + ")", 136 res = []; 137 138 for (i = 0; i < equations.length; i++) { 139 res[i] = equations[i] 140 .replace(/\*\*/g, "^") 141 .replace(/x/g, x) 142 .replace(/y/g, y); 143 } 144 145 return res; 146 }; 147 })(eq); 148 }; 149 data = Symbolic.geometricLocusByGroebnerBase(board, p, cb); 150 151 cb(data.datax, data.datay, data.polynomial, data.exectime); 152 }; 153 return c; 154 }; 155 156 JXG.registerElement("locus", JXG.createLocus); 157 158 // export default { 159 // createLocus: JXG.createLocus 160 // }; 161