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