      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  see define call
     38  */
     39
     40 /**
     41  * @fileoverview Example file for a triangle implemented as a extension to JSXGraph.
     42  */
     43
     44 define([
     45     'jxg', 'options', 'utils/type', 'base/constants', 'base/line', 'base/polygon', 'base/point', 'base/element'
     46 ], function (JXG, Options, Type, Const, Line, Polygon, Point, GeometryElement) {
     47
     48     "use strict";
     49
     50     var priv = {
     51             removeSlopeTriangle: function () {
     52                 Polygon.Polygon.prototype.remove.call(this);
     53
     54                 this.board.removeObject(this.toppoint);
     55                 this.board.removeObject(this.glider);
     56
     57                 this.board.removeObject(this.baseline);
     58                 this.board.removeObject(this.basepoint);
     59
     60                 this.board.removeObject(this.label);
     61
     62                 if (this._isPrivateTangent) {
     63                     this.board.removeObject(this.tangent);
     64                 }
     65             },
     66             Value: function () {
     67                 return this.tangent.getSlope();
     68             }
     69         };
     70
     71     /**
     72      * @class Slope triangle for a point on a line.
     73      * @pseudo
     74      * @name Slopetriangle
     75      * @augments JXG.Line
     76      * @constructor
     77      * @type JXG.Polygon
     78      * @throws {Error} If the element cannot be constructed with the given parent objects an exception is thrown.
     79      * Parameter options:
     80      * @param {JXG.Line} t A tangent based on a glider on some object, e.g. curve, circle, line or turtle.
     81      * @param {JXG.Line_JXG.Point} li, p A line and a point on that line.
     82      *  The user has to take care that the point is a member of the line.
     83      * @example
     84      * // Create a slopetriangle on a tangent
     85      * var f = board.create('plot', ['sin(x)']),
     86      *     g = board.create('glider', [1, 2, f]),
     87      *     t = board.create('tangent', [g]),
     88      *
     89      *     st = board.create('slopetriangle', [t]);
     90      *
     91      * </pre><div class="jxgbox" id="951ccb6a-52bc-4dc2-80e9-43db064f0f1b" style="width: 300px; height: 300px;"></div>
     92      * <script type="text/javascript">
     93      * (function () {
     94      *   var board = JXG.JSXGraph.initBoard('951ccb6a-52bc-4dc2-80e9-43db064f0f1b', {boundingbox: [-5, 5, 5, -5], axis: true, showcopyright: false, shownavigation: false}),
     95      *     f = board.create('plot', ['sin(x)']),
     96      *     g = board.create('glider', [1, 2, f]),
     97      *     t = board.create('tangent', [g]),
     98      *
     99      *     st = board.create('slopetriangle', [t]);
    100      * })();
    101      * </script><pre>
    102      *
    103      * @example
    104      * // Create a on a line and a point on that line
    105      * var p1 = board.create('point', [-2, 3]),
    106      *     p2 = board.create('point', [2, -3]),
    107      *     li = board.create('line', [p1, p2]),
    108      *     p = board.create('glider', [0, 0, li]),
    109      *
    110      *     st = board.create('slopetriangle', [li, p]);
    111      *
    112      * </pre><div class="jxgbox" id="b52f451c-22cf-4677-852a-0bb9d764ee95" style="width: 300px; height: 300px;"></div>
    113      * <script type="text/javascript">
    114      * (function () {
    115      *   var board = JXG.JSXGraph.initBoard('b52f451c-22cf-4677-852a-0bb9d764ee95', {boundingbox: [-5, 5, 5, -5], axis: true, showcopyright: false, shownavigation: false}),
    116      *     p1 = board.create('point', [-2, 3]),
    117      *     p2 = board.create('point', [2, -3]),
    118      *     li = board.create('line', [p1, p2]),
    119      *     p = board.create('glider', [0, 0, li]),
    120      *
    121      *     st = board.create('slopetriangle', [li, p]);
    122      * })();
    123      * </script><pre>
    124      */
    125     JXG.createSlopeTriangle = function (board, parents, attributes) {
    126         var el, tangent, tglide, glider, toppoint, baseline, basepoint, label, attr,
    127             isPrivateTangent = false;
    128
    129         if (parents.length === 1 && parents[0].type === Const.OBJECT_TYPE_TANGENT) {
    130             tangent = parents[0];
    131             tglide = tangent.glider;
    132         } else if (parents.length === 1 && parents[0].type === Const.OBJECT_TYPE_GLIDER) {
    133             tglide = parents[0];
    134             attr = Type.copyAttributes(attributes, board.options,  'slopetriangle', 'tangent');
    135             tangent = board.create('tangent', [tglide], attr);
    136             isPrivateTangent = true;
    137         } else if (parents.length === 2 &&
    138                 parents[0].elementClass === Const.OBJECT_CLASS_LINE && Type.isPoint(parents[1])) {
    139             tangent = parents[0];
    140             tglide = parents[1];
    141         } else {
    142             throw new Error("JSXGraph: Can't create slope triangle with parent types '" + (typeof parents[0]) + "'.");
    143         }
    144
    145         attr = Type.copyAttributes(attributes, board.options, 'slopetriangle', 'basepoint');
    146         basepoint = board.create('point', [function () {
    147             return [tglide.X() + 1,  tglide.Y()];
    148         }], attr);
    149
    150         attr = Type.copyAttributes(attributes, board.options, 'slopetriangle', 'baseline');
    151         baseline = board.create('line', [tglide, basepoint], attr);
    152
    153         attr = Type.copyAttributes(attributes, board.options, 'slopetriangle', 'glider');
    154         glider = board.create('glider', [tglide.X() + 1, tglide.Y(), baseline], attr);
    155
    156         attr = Type.copyAttributes(attributes, board.options, 'slopetriangle', 'toppoint');
    157         toppoint = board.create('point', [function () {
    158             return [glider.X(), glider.Y() + (glider.X() - tglide.X()) * tangent.getSlope()];
    159         }], attr);
    160
    161         attr = Type.copyAttributes(attributes, board.options, 'slopetriangle');
    162         attr.borders = Type.copyAttributes(attr.borders, board.options, 'slopetriangle', 'borders');
    163         el = board.create('polygon', [tglide, glider, toppoint], attr);
    164
    165         el.Value = priv.Value;
    166         el.tangent = tangent;
    167         el._isPrivateTangent = isPrivateTangent;
    168
    169         //el.borders[0].setArrow(false, {type: 2, size: 10});
    170         //el.borders[1].setArrow(false, {type: 2, size: 10});
    171         el.borders[2].setArrow(false, false);
    172
    173         attr = Type.copyAttributes(attributes, board.options, 'slopetriangle', 'label');
    174         label = board.create('text', [
    175             function () { return glider.X() + 0.1; },
    176             function () { return (glider.Y() + toppoint.Y()) * 0.5; },
    177             function () { return ''; }
    178         ], attr);
    179
    180         label._setText(function () {
    181             return Type.toFixed(el.Value(), Type.evaluate(label.visProp.digits));
    182         });
    183         label.fullUpdate();
    184
    185         el.glider = glider;
    186         el.basepoint = basepoint;
    187         el.baseline = baseline;
    188         el.toppoint = toppoint;
    189         el.label = label;
    190
    191         el.subs = {
    192             glider: glider,
    193             basePoint: basepoint,
    194             baseLine: baseline,
    195             topPoint: toppoint,
    196             label: label
    197         };
    198         el.inherits.push(glider, basepoint, baseline, toppoint, label);
    199
    200         el.methodMap = JXG.deepCopy(el.methodMap, {
    201             tangent: 'tangent',
    202             glider: 'glider',
    203             basepoint: 'basepoint',
    204             baseline: 'baseline',
    205             toppoint: 'toppoint',
    206             label: 'label',
    207             Value: 'Value',
    208             V: 'Value'
    209         });
    210
    211         el.remove = priv.removeSlopeTriangle;
    212
    213         return el;
    214     };
    215
    216     JXG.registerElement('slopetriangle', JXG.createSlopeTriangle);
    217
    218     return {
    219         createSlopeTriangle: JXG.createSlopeTriangle
    220     };
    221 });
    222