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