      1 /*
      2  Copyright 2008-2014
      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 class="jxgbox" 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 && Type.isPoint(parents[0])) {
    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.setParents([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 });
    181