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