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