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