      1 /*
      2     Copyright 2008-2025
      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 In this file the geometry object Arc is defined. Arc stores all
     37  * style and functional properties that are required to draw an arc on a board.
     38  */
     39
     40 import JXG from "../jxg.js";
     41 import Geometry from "../math/geometry.js";
     42 import Mat from "../math/math.js";
     43 import Coords from "../base/coords.js";
     44 import Circle from "../base/circle.js";
     45 import Type from "../utils/type.js";
     46 import Const from "../base/constants.js";
     47
     48 /**
     49  * @class An arc is a partial circumference line of a circle.
     50  * It is defined by a center, one point that
     51  * defines the radius, and a third point that defines the angle of the arc.
     52  * <p>
     53  * As a curve the arc has curve length 6.
     54  * @pseudo
     55  * @name Arc
     56  * @augments Curve
     57  * @constructor
     58  * @type JXG.Curve
     59  * @throws {Error} If the element cannot be constructed with the given parent objects an exception is thrown.
     60  * @param {JXG.Point_JXG.Point_JXG.Point} p1,p2,p3 The result will be an arc of a circle around p1 through p2. The arc is drawn
     61  * counter-clockwise from p2 to p3.
     62  * @example
     63  * // Create an arc out of three free points
     64  * var p1 = board.create('point', [2.0, 2.0]);
     65  * var p2 = board.create('point', [1.0, 0.5]);
     66  * var p3 = board.create('point', [3.5, 1.0]);
     67  *
     68  * var a = board.create('arc', [p1, p2, p3]);
     69  * board.create('text',[1,6,function(){return 'arclength: '+Math.round(a.Value()*100)/100}])
     70  * </pre><div class="jxgbox" id="JXG114ef584-4a5e-4686-8392-c97501befb5b" style="width: 300px; height: 300px;"></div>
     71  * <script type="text/javascript">
     72  * (function () {
     73  *   var board = JXG.JSXGraph.initBoard('JXG114ef584-4a5e-4686-8392-c97501befb5b', {boundingbox: [-1, 7, 7, -1], axis: true, showcopyright: false, shownavigation: false}),
     74  *       p1 = board.create('point', [2.0, 2.0]),
     75  *       p2 = board.create('point', [1.0, 0.5]),
     76  *       p3 = board.create('point', [3.5, 1.0]),
     77  *
     78  *       a = board.create('arc', [p1, p2, p3]);
     79  *       board.create('text',[1,6,function(){return 'arclength: '+Math.round(a.Value()*100)/100}])
     80  * })();
     81  * </script><pre>
     82  *
     83  * @example
     84  * var t = board.create('transform', [2, 1.5], {type: 'scale'});
     85  * var a1 = board.create('arc', [[1, 1], [0, 1], [1, 0]], {strokeColor: 'red'});
     86  * var a2 = board.create('curve', [a1, t], {strokeColor: 'red'});
     87  *
     88  * </pre><div id="JXG1949da46-6339-11e8-9fb9-901b0e1b8723" class="jxgbox" style="width: 300px; height: 300px;"></div>
     89  * <script type="text/javascript">
     90  *     (function() {
     91  *         var board = JXG.JSXGraph.initBoard('JXG1949da46-6339-11e8-9fb9-901b0e1b8723',
     92  *             {boundingbox: [-8, 8, 8,-8], axis: true, showcopyright: false, shownavigation: false});
     93  *     var t = board.create('transform', [2, 1.5], {type: 'scale'});
     94  *     var a1 = board.create('arc', [[1, 1], [0, 1], [1, 0]], {strokeColor: 'red'});
     95  *     var a2 = board.create('curve', [a1, t], {strokeColor: 'red'});
     96  *
     97  *     })();
     98  *
     99  * </script><pre>
    100  *
    101  */
    102 JXG.createArc = function (board, parents, attributes) {
    103     var el, attr, points;
    104
    105     // attributes.radiusPoint = {visible: false};
    106     points = Type.providePoints(board, parents, attributes, "arc", [
    107         "center",
    108         "radiuspoint",
    109         "anglepoint"
    110     ]);
    111     if (points === false || points.length < 3) {
    112         throw new Error(
    113             "JSXGraph: Can't create Arc with parent types '" +
    114                 typeof parents[0] +
    115                 "' and '" +
    116                 typeof parents[1] +
    117                 "' and '" +
    118                 typeof parents[2] +
    119                 "'." +
    120                 "\nPossible parent types: [point,point,point], [arc, transformation]"
    121         );
    122     }
    123
    124     attr = Type.copyAttributes(attributes, board.options, "arc");
    125     el = board.create("curve", [[0], [0], 0, 4], attr);
    126
    127     el.elType = "arc";
    128     el.setParents(points);
    129
    130     /**
    131      * documented in JXG.GeometryElement
    132      * @ignore
    133      */
    134     el.type = Const.OBJECT_TYPE_ARC;
    135
    136     /**
    137      * Center of the arc.
    138      * @memberOf Arc.prototype
    139      * @name center
    140      * @type JXG.Point
    141      */
    142     el.center = points[0];
    143
    144     /**
    145      * Point defining the arc's radius.
    146      * @memberOf Arc.prototype
    147      * @name radiuspoint
    148      * @type JXG.Point
    149      */
    150     el.radiuspoint = points[1];
    151     el.point2 = el.radiuspoint;
    152
    153     /**
    154      * The point defining the arc's angle.
    155      * @memberOf Arc.prototype
    156      * @name anglepoint
    157      * @type JXG.Point
    158      */
    159     el.anglepoint = points[2];
    160     el.point3 = el.anglepoint;
    161
    162     // Add arc as child to defining points
    163     // or vice versa if the points are provided as coordinates
    164     if (Type.exists(el.center._is_new)) {
    165         el.addChild(el.center);
    166         delete el.center._is_new;
    167     } else {
    168         el.center.addChild(el);
    169     }
    170     if (Type.exists(el.radiuspoint._is_new)) {
    171         el.addChild(el.radiuspoint);
    172         delete el.radiuspoint._is_new;
    173     } else {
    174         el.radiuspoint.addChild(el);
    175     }
    176     if (Type.exists(el.anglepoint._is_new)) {
    177         el.addChild(el.anglepoint);
    178         delete el.anglepoint._is_new;
    179     } else {
    180         el.anglepoint.addChild(el);
    181     }
    182
    183     // This attribute is necessary for circumCircleArcs
    184     el.useDirection = attr.usedirection; // This makes the attribute immutable
    185
    186     // documented in JXG.Curve
    187     /**
    188      * @class
    189      * @ignore
    190      */
    191     el.updateDataArray = function () {
    192         var ar, phi, det,
    193             p0c, p1c, p2c,
    194             sgn = 1,
    195             A = this.radiuspoint,
    196             B = this.center,
    197             C = this.anglepoint,
    198             ev_s = this.evalVisProp('selection');
    199
    200         phi = Geometry.rad(A, B, C);
    201         if ((ev_s === "minor" && phi > Math.PI) || (ev_s === "major" && phi < Math.PI)) {
    202             sgn = -1;
    203         }
    204
    205         // This is true for circumCircleArcs. In that case there is
    206         // a fourth parent element: [center, point1, point3, point2]
    207         if (this.useDirection) {
    208             p0c = points[1].coords.usrCoords;
    209             p1c = points[3].coords.usrCoords;
    210             p2c = points[2].coords.usrCoords;
    211             det = (p0c[1] - p2c[1]) * (p0c[2] - p1c[2]) - (p0c[2] - p2c[2]) * (p0c[1] - p1c[1]);
    212
    213             if (det < 0) {
    214                 this.radiuspoint = points[1];
    215                 this.anglepoint = points[2];
    216             } else {
    217                 this.radiuspoint = points[2];
    218                 this.anglepoint = points[1];
    219             }
    220         }
    221
    222         A = A.coords.usrCoords;
    223         B = B.coords.usrCoords;
    224         C = C.coords.usrCoords;
    225
    226         ar = Geometry.bezierArc(A, B, C, false, sgn);
    227
    228         this.dataX = ar[0];
    229         this.dataY = ar[1];
    230
    231         this.bezierDegree = 3;
    232
    233         this.updateStdform();
    234         this.updateQuadraticform();
    235     };
    236
    237     /**
    238      * Determines the arc's current radius. I.e. the distance between {@link Arc#center} and {@link Arc#radiuspoint}.
    239      * @memberOf Arc.prototype
    240      * @name Radius
    241      * @function
    242      * @returns {Number} The arc's radius
    243      */
    244     el.Radius = function () {
    245         return this.radiuspoint.Dist(this.center);
    246     };
    247
    248     /**
    249      * @deprecated Use {@link Arc#Radius}
    250      * @memberOf Arc.prototype
    251      * @name getRadius
    252      * @function
    253      * @returns {Number}
    254      */
    255     el.getRadius = function () {
    256         JXG.deprecated("Arc.getRadius()", "Arc.Radius()");
    257         return this.Radius();
    258     };
    259
    260     /**
    261      * Returns the length of the arc or the value of the angle spanned by the arc.
    262      * @memberOf Arc.prototype
    263      * @name Value
    264      * @function
    265      * @param {String} [unit='length'] Unit of the returned values. Possible units are
    266      * <ul>
    267      * <li> 'length' (default): length of the arc line
    268      * <li> 'radians': angle spanned by the arc in radians
    269      * <li> 'degrees': angle spanned by the arc in degrees
    270      * <li> 'semicircle': angle spanned by the arc in radians as a multiple of π, e.g. if the angle is 1.5π, 1.5 will be returned.
    271      * <li> 'circle': angle spanned by the arc in radians as a multiple of 2π
    272      * </ul>
    273      * It is sufficient to supply the first three characters of the unit, e.g. 'len'.
    274      * @param {Number} [rad=undefined] Value of angle which can be used instead of the generic one.
    275      * @returns {Number} The arc length or the angle value in various units.
    276      */
    277     el.Value = function (unit, rad) {
    278         var val;
    279
    280         rad = rad || Geometry.rad(this.radiuspoint, this.center, this.anglepoint);
    281
    282         unit = unit || 'length';
    283         unit = unit.toLocaleLowerCase();
    284         if (unit === '' || unit.indexOf('len') === 0) {
    285             val = rad * this.Radius();
    286         } else if (unit.indexOf('rad') === 0) {
    287             val = rad;
    288         } else if (unit.indexOf('deg') === 0) {
    289             val = rad * 180 / Math.PI;
    290         } else if (unit.indexOf('sem') === 0) {
    291             val = rad / Math.PI;
    292         } else if (unit.indexOf('cir') === 0) {
    293             val = rad * 0.5 / Math.PI;
    294         }
    295
    296         return val;
    297     };
    298
    299     /**
    300      * Arc length.
    301      * @memberOf Arc.prototype
    302      * @name L
    303      * @returns {Number} Length of the arc.
    304      * @see Arc#Value
    305      */
    306     el.L = function() {
    307         return this.Value('length');
    308     };
    309
    310     // documented in geometry element
    311     el.hasPoint = function (x, y) {
    312         var dist,
    313             checkPoint,
    314             has,
    315             invMat,
    316             c,
    317             prec,
    318             type,
    319             r = this.Radius();
    320
    321         if (this.evalVisProp('hasinnerpoints')) {
    322             return this.hasPointSector(x, y);
    323         }
    324
    325         if (Type.isObject(this.evalVisProp('precision'))) {
    326             type = this.board._inputDevice;
    327             prec = this.evalVisProp('precision.' + type);
    328         } else {
    329             // 'inherit'
    330             prec = this.board.options.precision.hasPoint;
    331         }
    332         prec /= Math.min(Math.abs(this.board.unitX), Math.abs(this.board.unitY));
    333         checkPoint = new Coords(Const.COORDS_BY_SCREEN, [x, y], this.board);
    334
    335         if (this.transformations.length > 0) {
    336             // Transform the mouse/touch coordinates
    337             // back to the original position of the curve.
    338             this.updateTransformMatrix();
    339             invMat = Mat.inverse(this.transformMat);
    340             c = Mat.matVecMult(invMat, checkPoint.usrCoords);
    341             checkPoint = new Coords(Const.COORDS_BY_USER, c, this.board);
    342         }
    343
    344         dist = this.center.coords.distance(Const.COORDS_BY_USER, checkPoint);
    345         has = Math.abs(dist - r) < prec;
    346
    347         /**
    348          * At that point we know that the user has touched the circle line.
    349          * Now, we have to check, if the user has hit the arc path.
    350          */
    351         if (has) {
    352             has = Geometry.coordsOnArc(this, checkPoint);
    353         }
    354         return has;
    355     };
    356
    357     /**
    358      * Checks whether (x,y) is within the sector defined by the arc.
    359      * @memberOf Arc.prototype
    360      * @name hasPointSector
    361      * @function
    362      * @param {Number} x Coordinate in x direction, screen coordinates.
    363      * @param {Number} y Coordinate in y direction, screen coordinates.
    364      * @returns {Boolean} True if (x,y) is within the sector defined by the arc, False otherwise.
    365      */
    366     el.hasPointSector = function (x, y) {
    367         var checkPoint = new Coords(Const.COORDS_BY_SCREEN, [x, y], this.board),
    368             r = this.Radius(),
    369             dist = this.center.coords.distance(Const.COORDS_BY_USER, checkPoint),
    370             has = dist < r;
    371
    372         if (has) {
    373             has = Geometry.coordsOnArc(this, checkPoint);
    374         }
    375         return has;
    376     };
    377
    378     // documented in geometry element
    379     el.getTextAnchor = function () {
    380         return this.center.coords;
    381     };
    382
    383     // documented in geometry element
    384     /**
    385      * @class
    386      * @ignore
    387      */
    388     el.getLabelAnchor = function () {
    389         var coords,
    390             vec, vecx, vecy,
    391             len,
    392             pos = this.label.evalVisProp('position'),
    393             angle = Geometry.rad(this.radiuspoint, this.center, this.anglepoint),
    394             dx = 10 / this.board.unitX,
    395             dy = 10 / this.board.unitY,
    396             p2c = this.point2.coords.usrCoords,
    397             pmc = this.center.coords.usrCoords,
    398             bxminusax = p2c[1] - pmc[1],
    399             byminusay = p2c[2] - pmc[2],
    400             ev_s = this.evalVisProp('selection'),
    401             l_vp = this.label ? this.label.visProp : this.visProp.label;
    402
    403         // If this is uncommented, the angle label can not be dragged
    404         //if (Type.exists(this.label)) {
    405         //    this.label.relativeCoords = new Coords(Const.COORDS_BY_SCREEN, [0, 0], this.board);
    406         //}
    407
    408         if (
    409             !Type.isString(pos) ||
    410             (pos.indexOf('right') < 0 && pos.indexOf('left') < 0)
    411         ) {
    412
    413             if ((ev_s === "minor" && angle > Math.PI) || (ev_s === "major" && angle < Math.PI)) {
    414                 angle = -(2 * Math.PI - angle);
    415             }
    416
    417             coords = new Coords(
    418                 Const.COORDS_BY_USER,
    419                 [
    420                     pmc[1] + Math.cos(angle * 0.5) * bxminusax - Math.sin(angle * 0.5) * byminusay,
    421                     pmc[2] + Math.sin(angle * 0.5) * bxminusax + Math.cos(angle * 0.5) * byminusay
    422                 ],
    423                 this.board
    424             );
    425
    426             vecx = coords.usrCoords[1] - pmc[1];
    427             vecy = coords.usrCoords[2] - pmc[2];
    428
    429             len = Mat.hypot(vecx, vecy);
    430             vecx = (vecx * (len + dx)) / len;
    431             vecy = (vecy * (len + dy)) / len;
    432             vec = [pmc[1] + vecx, pmc[2] + vecy];
    433
    434             l_vp.position = Geometry.calcLabelQuadrant(Geometry.rad([1, 0], [0, 0], vec));
    435
    436             return new Coords(Const.COORDS_BY_USER, vec, this.board);
    437         } else {
    438             return this.getLabelPosition(pos, this.label.evalVisProp('distance'));
    439         }
    440
    441     };
    442
    443     // documentation in jxg.circle
    444     el.updateQuadraticform = Circle.prototype.updateQuadraticform;
    445
    446     // documentation in jxg.circle
    447     el.updateStdform = Circle.prototype.updateStdform;
    448
    449     el.methodMap = JXG.deepCopy(el.methodMap, {
    450         getRadius: "getRadius",
    451         radius: "Radius",
    452         Radius: "Radius",
    453         center: "center",
    454         radiuspoint: "radiuspoint",
    455         anglepoint: "anglepoint",
    456         Value: "Value",
    457         L: "L"
    458     });
    459
    460     el.prepareUpdate().update();
    461     return el;
    462 };
    463
    464 JXG.registerElement("arc", JXG.createArc);
    465
    466 /**
    467  * @class A semicircle is a special arc defined by two points. The arc hits both points.
    468  * @pseudo
    469  * @name Semicircle
    470  * @augments Arc
    471  * @constructor
    472  * @type Arc
    473  * @throws {Error} If the element cannot be constructed with the given parent objects an exception is thrown.
    474  * @param {JXG.Point_JXG.Point} p1,p2 The result will be a composition of an arc drawn clockwise from <tt>p1</tt> and
    475  * <tt>p2</tt> and the midpoint of <tt>p1</tt> and <tt>p2</tt>.
    476  * @example
    477  * // Create an arc out of three free points
    478  * var p1 = board.create('point', [4.5, 2.0]);
    479  * var p2 = board.create('point', [1.0, 0.5]);
    480  *
    481  * var a = board.create('semicircle', [p1, p2]);
    482  * </pre><div class="jxgbox" id="JXG5385d349-75d7-4078-b732-9ae808db1b0e" style="width: 300px; height: 300px;"></div>
    483  * <script type="text/javascript">
    484  * (function () {
    485  *   var board = JXG.JSXGraph.initBoard('JXG5385d349-75d7-4078-b732-9ae808db1b0e', {boundingbox: [-1, 7, 7, -1], axis: true, showcopyright: false, shownavigation: false}),
    486  *       p1 = board.create('point', [4.5, 2.0]),
    487  *       p2 = board.create('point', [1.0, 0.5]),
    488  *
    489  *       sc = board.create('semicircle', [p1, p2]);
    490  * })();
    491  * </script><pre>
    492  */
    493 JXG.createSemicircle = function (board, parents, attributes) {
    494     var el, mp, attr, points;
    495
    496     // we need 2 points
    497     points = Type.providePoints(board, parents, attributes, "point");
    498     if (points === false || points.length !== 2) {
    499         throw new Error(
    500             "JSXGraph: Can't create Semicircle with parent types '" +
    501                 typeof parents[0] +
    502                 "' and '" +
    503                 typeof parents[1] +
    504                 "'." +
    505                 "\nPossible parent types: [point,point]"
    506         );
    507     }
    508
    509     attr = Type.copyAttributes(attributes, board.options, "semicircle", "center");
    510     mp = board.create("midpoint", points, attr);
    511     mp.dump = false;
    512
    513     attr = Type.copyAttributes(attributes, board.options, "semicircle");
    514     el = board.create("arc", [mp, points[1], points[0]], attr);
    515     el.elType = "semicircle";
    516     el.setParents([points[0].id, points[1].id]);
    517     el.subs = {
    518         midpoint: mp
    519     };
    520     el.inherits.push(mp);
    521
    522     /**
    523      * The midpoint of the two defining points.
    524      * @memberOf Semicircle.prototype
    525      * @name midpoint
    526      * @type Midpoint
    527      */
    528     el.midpoint = el.center = mp;
    529
    530     return el;
    531 };
    532
    533 JXG.registerElement("semicircle", JXG.createSemicircle);
    534
    535 /**
    536  * @class A partial circum circle through three points.
    537  * @pseudo
    538  * @name CircumcircleArc
    539  * @augments Arc
    540  * @constructor
    541  * @type Arc
    542  * @throws {Error} If the element cannot be constructed with the given parent objects an exception is thrown.
    543  * @param {JXG.Point_JXG.Point_JXG.Point} p1,p2,p3 The result will be a composition of an arc of the circumcircle of
    544  * <tt>p1</tt>, <tt>p2</tt>, and <tt>p3</tt> and the midpoint of the circumcircle of the three points. The arc is drawn
    545  * counter-clockwise from <tt>p1</tt> over <tt>p2</tt> to <tt>p3</tt>.
    546  * @example
    547  * // Create a circum circle arc out of three free points
    548  * var p1 = board.create('point', [2.0, 2.0]);
    549  * var p2 = board.create('point', [1.0, 0.5]);
    550  * var p3 = board.create('point', [3.5, 1.0]);
    551  *
    552  * var a = board.create('circumcirclearc', [p1, p2, p3]);
    553  * </pre><div class="jxgbox" id="JXG87125fd4-823a-41c1-88ef-d1a1369504e3" style="width: 300px; height: 300px;"></div>
    554  * <script type="text/javascript">
    555  * (function () {
    556  *   var board = JXG.JSXGraph.initBoard('JXG87125fd4-823a-41c1-88ef-d1a1369504e3', {boundingbox: [-1, 7, 7, -1], axis: true, showcopyright: false, shownavigation: false}),
    557  *       p1 = board.create('point', [2.0, 2.0]),
    558  *       p2 = board.create('point', [1.0, 0.5]),
    559  *       p3 = board.create('point', [3.5, 1.0]),
    560  *
    561  *       cca = board.create('circumcirclearc', [p1, p2, p3]);
    562  * })();
    563  * </script><pre>
    564  */
    565 JXG.createCircumcircleArc = function (board, parents, attributes) {
    566     var el, mp, attr, points;
    567
    568     // We need three points
    569     points = Type.providePoints(board, parents, attributes, "point");
    570     if (points === false || points.length !== 3) {
    571         throw new Error(
    572             "JSXGraph: create Circumcircle Arc with parent types '" +
    573                 typeof parents[0] +
    574                 "' and '" +
    575                 typeof parents[1] +
    576                 "' and '" +
    577                 typeof parents[2] +
    578                 "'." +
    579                 "\nPossible parent types: [point,point,point]"
    580         );
    581     }
    582
    583     attr = Type.copyAttributes(attributes, board.options, "circumcirclearc", "center");
    584     mp = board.create("circumcenter", points, attr);
    585     mp.dump = false;
    586
    587     attr = Type.copyAttributes(attributes, board.options, "circumcirclearc");
    588     attr.usedirection = true;
    589     el = board.create("arc", [mp, points[0], points[2], points[1]], attr);
    590
    591     el.elType = "circumcirclearc";
    592     el.setParents([points[0].id, points[1].id, points[2].id]);
    593     el.subs = {
    594         center: mp
    595     };
    596     el.inherits.push(mp);
    597
    598     /**
    599      * The midpoint of the circumcircle of the three points defining the circumcircle arc.
    600      * @memberOf CircumcircleArc.prototype
    601      * @name center
    602      * @type Circumcenter
    603      */
    604     el.center = mp;
    605
    606     return el;
    607 };
    608
    609 JXG.registerElement("circumcirclearc", JXG.createCircumcircleArc);
    610
    611 /**
    612  * @class A minor arc given by three points is that part of the circumference of a circle having
    613  * measure at most 180 degrees (pi radians). It is defined by a center, one point that
    614  * defines the radius, and a third point that defines the angle of the arc.
    615  * @pseudo
    616  * @name MinorArc
    617  * @augments Curve
    618  * @constructor
    619  * @type JXG.Curve
    620  * @throws {Error} If the element cannot be constructed with the given parent objects an exception is thrown.
    621  * @param {JXG.Point_JXG.Point_JXG.Point} p1,p2,p3 . Minor arc is an arc of a circle around p1 having measure less than or equal to
    622  * 180 degrees (pi radians) and starts at p2. The radius is determined by p2, the angle by p3.
    623  * @example
    624  * // Create an arc out of three free points
    625  * var p1 = board.create('point', [2.0, 2.0]);
    626  * var p2 = board.create('point', [1.0, 0.5]);
    627  * var p3 = board.create('point', [3.5, 1.0]);
    628  *
    629  * var a = board.create('arc', [p1, p2, p3]);
    630  * </pre><div class="jxgbox" id="JXG64ba7ca2-8728-45f3-96e5-3c7a4414de2f" style="width: 300px; height: 300px;"></div>
    631  * <script type="text/javascript">
    632  * (function () {
    633  *   var board = JXG.JSXGraph.initBoard('JXG64ba7ca2-8728-45f3-96e5-3c7a4414de2f', {boundingbox: [-1, 7, 7, -1], axis: true, showcopyright: false, shownavigation: false}),
    634  *       p1 = board.create('point', [2.0, 2.0]),
    635  *       p2 = board.create('point', [1.0, 0.5]),
    636  *       p3 = board.create('point', [3.5, 1.0]),
    637  *
    638  *       a = board.create('minorarc', [p1, p2, p3]);
    639  * })();
    640  * </script><pre>
    641  */
    642
    643 JXG.createMinorArc = function (board, parents, attributes) {
    644     attributes.selection = "minor";
    645     return JXG.createArc(board, parents, attributes);
    646 };
    647
    648 JXG.registerElement("minorarc", JXG.createMinorArc);
    649
    650 /**
    651  * @class A major arc given by three points is that part of the circumference of a circle having
    652  * measure at least 180 degrees (pi radians). It is defined by a center, one point that
    653  * defines the radius, and a third point that defines the angle of the arc.
    654  * @pseudo
    655  * @name MajorArc
    656  * @augments Curve
    657  * @constructor
    658  * @type JXG.Curve
    659  * @throws {Error} If the element cannot be constructed with the given parent objects an exception is thrown.
    660  * @param {JXG.Point_JXG.Point_JXG.Point} p1,p2,p3 . Major arc is an arc of a circle around p1 having measure greater than or equal to
    661  * 180 degrees (pi radians) and starts at p2. The radius is determined by p2, the angle by p3.
    662  * @example
    663  * // Create an arc out of three free points
    664  * var p1 = board.create('point', [2.0, 2.0]);
    665  * var p2 = board.create('point', [1.0, 0.5]);
    666  * var p3 = board.create('point', [3.5, 1.0]);
    667  *
    668  * var a = board.create('majorarc', [p1, p2, p3]);
    669  * </pre><div class="jxgbox" id="JXG17a10d38-5629-40a4-b150-f41806edee9f" style="width: 300px; height: 300px;"></div>
    670  * <script type="text/javascript">
    671  * (function () {
    672  *   var board = JXG.JSXGraph.initBoard('JXG17a10d38-5629-40a4-b150-f41806edee9f', {boundingbox: [-1, 7, 7, -1], axis: true, showcopyright: false, shownavigation: false}),
    673  *       p1 = board.create('point', [2.0, 2.0]),
    674  *       p2 = board.create('point', [1.0, 0.5]),
    675  *       p3 = board.create('point', [3.5, 1.0]),
    676  *
    677  *       a = board.create('majorarc', [p1, p2, p3]);
    678  * })();
    679  * </script><pre>
    680  */
    681 JXG.createMajorArc = function (board, parents, attributes) {
    682     attributes.selection = "major";
    683     return JXG.createArc(board, parents, attributes);
    684 };
    685
    686 JXG.registerElement("majorarc", JXG.createMajorArc);
    687