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