jsxgraph 1.4.4 → 1.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +24 -0
  2. package/build/Readme.md +17 -0
  3. package/build/bin/jsxcompressor.js +1 -0
  4. package/build/bin/jsxgraphcore-min.js +7 -0
  5. package/build/bin/jsxgraphcore.js +83017 -0
  6. package/build/bin/jsxgraphcore.min.js +67 -0
  7. package/build/compressor.build.json +14 -0
  8. package/build/compressor.deps.js +8 -0
  9. package/build/core-amd.build.json +14 -0
  10. package/build/core-amd.deps.js +81 -0
  11. package/build/core.build.json +14 -0
  12. package/build/core.deps.js +102 -0
  13. package/build/plot.build.json +15 -0
  14. package/distrib/README.md +24 -0
  15. package/distrib/geogebra.min.js +1 -1
  16. package/distrib/geonext.min.js +1 -1
  17. package/distrib/index.d.ts +28 -7
  18. package/distrib/intergeo.min.js +1 -1
  19. package/distrib/jsxgraph.css +6 -0
  20. package/distrib/jsxgraphcore.js +3 -3
  21. package/distrib/jsxgraphsrc.js +3558 -1857
  22. package/distrib/sketch.min.js +1 -1
  23. package/package.json +1 -1
  24. package/src/3d/box3d.js +43 -38
  25. package/src/3d/curve3d.js +157 -53
  26. package/src/3d/element3d.js +84 -0
  27. package/src/3d/linspace3d.js +427 -146
  28. package/src/3d/point3d.js +360 -123
  29. package/src/3d/surface3d.js +140 -42
  30. package/src/3d/view3d.js +319 -164
  31. package/src/base/board.js +163 -78
  32. package/src/base/constants.js +8 -1
  33. package/src/base/curve.js +51 -9
  34. package/src/base/polygon.js +111 -69
  35. package/src/base/text.js +122 -19
  36. package/src/base/ticks.js +12 -3
  37. package/src/element/button.js +7 -3
  38. package/src/element/checkbox.js +8 -4
  39. package/src/element/composition.js +7 -1
  40. package/src/element/conic.js +2 -2
  41. package/src/element/input.js +9 -5
  42. package/src/jsxgraph.js +4 -1
  43. package/src/loadjsxgraph.js +13 -8
  44. package/src/math/clip.js +34 -134
  45. package/src/math/geometry.js +204 -3
  46. package/src/math/math.js +1 -2
  47. package/src/math/nlp.js +865 -774
  48. package/src/options.js +185 -12
  49. package/src/options3d.js +24 -7
  50. package/src/parser/jessiecode.js +9 -3
  51. package/src/renderer/abstract.js +26 -15
  52. package/src/renderer/canvas.js +2 -2
  53. package/src/renderer/svg.js +15 -2
  54. package/src/utils/env.js +36 -53
  55. package/src/utils/type.js +75 -2
  56. package/src/3d/threed.js +0 -38
package/src/3d/point3d.js CHANGED
@@ -28,173 +28,410 @@
28
28
  */
29
29
  /*global JXG:true, define: true*/
30
30
 
31
- define(['jxg', 'base/constants', 'math/math', 'math/geometry', 'utils/type', '3d/view3d'
32
- ], function (JXG, Const, Mat, Geometry, Type, ThreeD) {
31
+ define(['jxg', 'base/constants', 'math/math', 'math/geometry', 'utils/type' //, '3d/element3d'
32
+ ], function (JXG, Const, Mat, Geometry, Type) { //, GeometryElement3D) {
33
33
  "use strict";
34
34
 
35
35
  /**
36
- * @class This element is used to provide a constructor for a 3D Point.
37
- * @pseudo
38
- * @description There are two possibilities to create a Line3D object.
39
- * <p>
40
- * First: the line in 3D is defined by two points in 3D (Point3D).
41
- * The points can be either existing points or coordinate arrays of
42
- * the form [x, y, z].
43
- * <p>Second: the line in 3D is defined by a point (or coordinate array [x, y, z])
44
- * a direction given as array [x, y, z] and an optional range
45
- * given as array [s, e]. The default value for the range is [-Infinity, Infinity].
46
- * <p>
47
- * All numbers can also be provided as functions returning a number.
48
- *
49
- * @name Point3D
50
- * @augments JXG.Point
51
- * @constructor
52
- * @type JXG.Point
53
- * @throws {Exception} If the element cannot be constructed with the given parent
54
- * objects an exception is thrown.
55
- * @param {JXG.Point_number,JXG.Point,JXG.Line,JXG.Circle} center,radius The center must be given as a {@link JXG.Point}, see {@link JXG.providePoints}, but the radius can be given
56
- * as a number (which will create a circle with a fixed radius), another {@link JXG.Point}, a {@link JXG.Line} (the distance of start and end point of the
57
- * line will determine the radius), or another {@link JXG.Circle}.
58
- *
36
+ * A 3D point is the basic geometric element.
37
+ * @class Creates a new 3D point object. Do not use this constructor to create a 3D point. Use {@link JXG.Board#create} with
38
+ * type {@link Point3D} instead.
39
+ * @augments JXG.GeometryElement3D
40
+ * @augments JXG.GeometryElement
41
+ * @param {JXG.View3D} view The 3D view the point is drawn on.
42
+ * @param {Function,Array} F Array of numbers, array of functions or function returning an array with defines the user coordinates of the point.
43
+ * @parame {JXG.GeometryElement3D} slide Object the 3D point should be bound to. If null, the point is a free point.
44
+ * @param {Object} attributes An object containing visual properties like in {@link JXG.Options#point3d} and
45
+ * {@link JXG.Options#elements}, and optional a name and an id.
46
+ * @see JXG.Board#generateName
59
47
  */
60
- ThreeD.createPoint = function (board, parents, attributes) {
61
- var view = parents[0],
62
- attr, update2D, D3,
63
- i, c2d,
64
- el;
48
+ JXG.Point3D = function (view, F, slide, attributes) {
49
+ this.constructor(view.board, attributes, Const.OBJECT_TYPE_POINT3D, Const.OBJECT_CLASS_3D);
50
+ this.constructor3D(view, 'point3d');
65
51
 
66
- attr = Type.copyAttributes(attributes, board.options, 'point3d');
52
+ this.id = this.view.board.setId(this, 'P3D');
53
+ this.board.finalizeAdding(this);
67
54
 
68
- D3 = {
69
- elType: 'point3d',
70
- coords: [1, 0, 0, 0],
71
- X: function () { return this.coords[1]; },
72
- Y: function () { return this.coords[2]; },
73
- Z: function () { return this.coords[3]; }
74
- };
75
-
76
- // If the last element of partents is a 3D object, the point is a glider
77
- // on that element.
78
- if (parents.length > 2 && Type.exists(parents[parents.length - 1].D3)) {
79
- D3.slide = parents.pop();
80
- } else {
81
- D3.slide = null;
82
- }
55
+ /**
56
+ * Homogeneous coordinates of a Point3D, i.e. array of length 4: [w, x, y, z]. Usually, w=1 for finite points and w=0 for points
57
+ * which are infinitely far.
58
+ *
59
+ * @example
60
+ * p.coords;
61
+ *
62
+ * @name Point3D#coords
63
+ * @type Array
64
+ * @private
65
+ */
66
+ this.coords = [0, 0, 0, 0];
83
67
 
84
- if (parents.length === 2) {
85
- D3.F = parents[1]; // (Array [x, y, z] | function) returning [x, y, z]
86
- D3.coords = [1].concat(Type.evaluate(D3.F));
87
- } else if (parents.length === 4) {
88
- D3.F = parents.slice(1); // 3 numbers | functions
89
- for (i = 0; i < 3; i++) {
90
- D3.coords[i + 1] = Type.evaluate(D3.F[i]);
91
- }
92
- } else {
93
- // Throw error
94
- }
68
+ /**
69
+ * Function or array of functions or array of numbers defining the coordinates of the point, used in {@link updateCoords}.
70
+ *
71
+ * @name F
72
+ * @memberOf Point3D
73
+ * @function
74
+ * @private
75
+ *
76
+ * @see updateCoords
77
+ */
78
+ this.F = F;
79
+
80
+ /**
81
+ * Optional slide element, i.e. element the Point3D lives on.
82
+ *
83
+ * @example
84
+ * p.slide;
85
+ *
86
+ * @name Point3D#slide
87
+ * @type JXG.GeometryElement3D
88
+ * @default null
89
+ * @private
90
+ *
91
+ */
92
+ this.slide = slide;
93
+
94
+ /**
95
+ * Get x-coordinate of a 3D point.
96
+ *
97
+ * @name X
98
+ * @memberOf Point3D
99
+ * @function
100
+ * @returns {Number}
101
+ *
102
+ * @example
103
+ * p.X();
104
+ */
105
+ this.X = function () { return this.coords[1]; };
95
106
 
96
107
  /**
97
- * Update the 4D coords array
98
- * @returns Object
108
+ * Get y-coordinate of a 3D point.
109
+ *
110
+ * @name Y
111
+ * @memberOf Point3D
112
+ * @function
113
+ * @returns Number
114
+ *
115
+ * @example
116
+ * p.Y();
99
117
  */
100
- D3.updateCoords = function () {
101
- var res, i;
118
+ this.Y = function () { return this.coords[2]; };
119
+
120
+ /**
121
+ * Get z-coordinate of a 3D point.
122
+ *
123
+ * @name Z
124
+ * @memberOf Point3D
125
+ * @function
126
+ * @returns Number
127
+ *
128
+ * @example
129
+ * p.Z();
130
+ */
131
+ this.Z = function () { return this.coords[3]; };
132
+
133
+ /**
134
+ * Store the last position of the 2D point for the optimizer.
135
+ *
136
+ * @type Array
137
+ * @private
138
+ */
139
+ this._params = null;
140
+
141
+ this._c2d = null;
142
+
143
+ this.methodMap = Type.deepCopy(this.methodMap, {
144
+ // TODO
145
+ });
146
+ };
147
+ JXG.Point3D.prototype = new JXG.GeometryElement();
148
+ Type.copyPrototypeMethods(JXG.Point3D, JXG.GeometryElement3D, 'constructor3D');
149
+
150
+ JXG.extend(JXG.Point3D.prototype, /** @lends JXG.Point3D.prototype */ {
151
+ /**
152
+ * Update the the homogeneous coords array.
153
+ *
154
+ * @name updateCoords
155
+ * @memberOf Point3D
156
+ * @function
157
+ * @returns {Object} Reference to the Point3D object
158
+ * @private
159
+ * @example
160
+ * p.updateCoords();
161
+ */
162
+ updateCoords: function () {
163
+ var i;
164
+
102
165
  if (Type.isFunction(this.F)) {
103
- res = Type.evaluate(this.F);
104
- this.coords = [1, res[0], res[1], res[2]];
166
+ this.coords = [1].concat(Type.evaluate(this.F));
105
167
  } else {
106
168
  this.coords[0] = 1;
107
169
  for (i = 0; i < 3; i++) {
170
+ // Attention: if F is array of numbers, coords are not updated.
171
+ // Otherwise, dragging will not work anymore.
108
172
  if (Type.isFunction(this.F[i])) {
109
173
  this.coords[i + 1] = Type.evaluate(this.F[i]);
110
174
  }
111
175
  }
112
176
  }
113
177
  return this;
114
- };
115
- D3.updateCoords();
178
+ },
116
179
 
117
- c2d = view.project3DTo2D(D3.coords);
118
- el = board.create('point', c2d, attr);
119
- el.D3 = D3;
120
- el.D3.c2d = el.coords.usrCoords.slice(); // Copy of the coordinates to detect dragging
121
- update2D = el.update;
180
+ /**
181
+ * Initialize the coords array.
182
+ *
183
+ * @private
184
+ * @returns {Object} Reference to the Point3D object
185
+ */
186
+ initCoords: function () {
187
+ var i;
122
188
 
123
- if (el.D3.slide) {
124
- el._minFunc = function (n, m, x, con) {
125
- var surface = el.D3.slide.D3,
126
- c3d = [1, surface.X(x[0], x[1]), surface.Y(x[0], x[1]), surface.Z(x[0], x[1])],
127
- c2d = view.project3DTo2D(c3d);
189
+ if (Type.isFunction(this.F)) {
190
+ this.coords = [1].concat(Type.evaluate(this.F));
191
+ } else {
192
+ this.coords[0] = 1;
193
+ for (i = 0; i < 3; i++) {
194
+ this.coords[i + 1] = Type.evaluate(this.F[i]);
195
+ }
196
+ }
197
+ return this;
198
+ },
128
199
 
129
- con[0] = el.X() - c2d[1];
130
- con[1] = el.Y() - c2d[2];
200
+ /**
201
+ * Normalize homogeneous coordinates such the the first coordinate (the w-coordinate is equal to 1 or 0)-
202
+ *
203
+ * @name normalizeCoords
204
+ * @memberOf Point3D
205
+ * @function
206
+ * @returns {Object} Reference to the Point3D object
207
+ * @private
208
+ * @example
209
+ * p.normalizeCoords();
210
+ */
211
+ normalizeCoords: function () {
212
+ if (Math.abs(this.coords[0]) > Mat.eps) {
213
+ this.coords[1] /= this.coords[0];
214
+ this.coords[2] /= this.coords[0];
215
+ this.coords[3] /= this.coords[0];
216
+ this.coords[0] = 1.0;
217
+ }
218
+ return this;
219
+ },
131
220
 
132
- return con[0] * con[0] + con[1] * con[1];
133
- };
221
+ /**
222
+ * Set the position of a 3D point.
223
+ *
224
+ * @name setPosition
225
+ * @memberOf Point3D
226
+ * @function
227
+ * @param {Array} coords 3D coordinates. Either of the form [x,y,z] (Euclidean) or [w,x,y,z] (homogeneous).
228
+ * @param {Boolean} [noevent] If true, no events are triggered.
229
+ * @returns {Object} Reference to the Point3D object
230
+ *
231
+ * @example
232
+ * p.setPosition([1, 3, 4]);
233
+ */
234
+ setPosition: function (coords, noevent) {
235
+ var c = this.coords,
236
+ oc = this.coords.slice(); // Copy of original values
134
237
 
135
- el.projectCoords2Surface = function () {
136
- var n = 2, // # of variables
137
- m = 2, // number of constraints
138
- x = [0, 0],
139
- // Various Cobyla constants, see Cobyla docs in Cobyja.js
140
- rhobeg = 5.0,
141
- rhoend = 1.0e-6,
142
- iprint = 0,
143
- maxfun = 200,
144
- surface = this.D3.slide.D3,
145
- r, c3d, c2d;
146
-
147
- if (Type.exists(this.D3.params)) {
148
- x = this.D3.params.slice();
149
- }
150
- r = Mat.Nlp.FindMinimum(this._minFunc, n, m, x, rhobeg, rhoend, iprint, maxfun);
151
-
152
- c3d = [1, surface.X(x[0], x[1]), surface.Y(x[0], x[1]), surface.Z(x[0], x[1])];
153
- c2d = view.project3DTo2D(c3d);
154
- this.D3.params = x;
155
- this.D3.coords = c3d;
156
- this.coords.setCoordinates(Const.COORDS_BY_USER, c2d);
157
- this.D3.c2d = c2d;
158
- };
159
- }
238
+ if (coords.length === 3) { // Euclidean coordinates
239
+ c[0] = 1.0;
240
+ c[1] = coords[0];
241
+ c[2] = coords[1];
242
+ c[3] = coords[2];
243
+ } else { // Homogeneous coordinates (normalized)
244
+ c[0] = coords[0];
245
+ c[1] = coords[1];
246
+ c[2] = coords[2];
247
+ c[3] = coords[2];
248
+ this.normalizeCoords();
249
+ }
250
+
251
+ // console.log(el.emitter, !noevent, oc[0] !== c[0] || oc[1] !== c[1] || oc[2] !== c[2] || oc[3] !== c[3]);
252
+ // Not yet working
253
+ // if (el.emitter && !noevent &&
254
+ // (oc[0] !== c[0] || oc[1] !== c[1] || oc[2] !== c[2] || oc[3] !== c[3])) {
255
+ // this.triggerEventHandlers(['update3D'], [oc]);
256
+ // }
257
+ return this;
258
+ },
160
259
 
161
- el.update = function (drag) {
260
+ update: function (drag) {
162
261
  var c3d, foot;
163
- if (!this.needsUpdate) {
164
- return this;
165
- }
166
262
 
167
- // Update is called in from two methods:
168
- // Once in setToPositionDirectly and
263
+ // Update is called from two methods:
264
+ // Once in setToPosition and
169
265
  // once in the subsequent board.update
170
- if (this.draggable() &&
171
- Geometry.distance(this.D3.c2d, this.coords.usrCoords) !== 0) {
266
+ if (this.element2D.draggable() &&
267
+ Geometry.distance(this._c2d, this.element2D.coords.usrCoords) !== 0) {
172
268
 
173
- if (this.D3.slide) {
269
+ if (this.slide) {
174
270
  this.projectCoords2Surface();
175
271
  } else {
176
272
  // Drag the point in its xy plane
177
- foot = [1, 0, 0, this.D3.coords[3]];
178
- c3d = view.project2DTo3DPlane(el, [1, 0, 0, 1], foot);
273
+ foot = [1, 0, 0, this.coords[3]];
274
+ c3d = this.view.project2DTo3DPlane(this.element2D, [1, 0, 0, 1], foot);
179
275
  if (c3d[0] !== 0) {
180
- this.D3.coords = view.project3DToCube(c3d);
276
+ this.coords = this.view.project3DToCube(c3d);
181
277
  }
182
278
  }
183
279
  } else {
184
- this.D3.updateCoords();
280
+ this.updateCoords();
185
281
  // Update 2D point from its 3D view
186
- el.coords.setCoordinates(Const.COORDS_BY_USER,
187
- view.project3DTo2D([1, this.D3.X(), this.D3.Y(), this.D3.Z()])
282
+ this.element2D.coords.setCoordinates(Const.COORDS_BY_USER,
283
+ this.view.project3DTo2D([1, this.X(), this.Y(), this.Z()])
188
284
  );
189
285
  }
190
- this.D3.c2d = el.coords.usrCoords.slice();
286
+ this._c2d = this.element2D.coords.usrCoords.slice();
287
+
288
+ return this;
289
+ },
191
290
 
192
- update2D.apply(this, [drag]);
291
+ updateRenderer: function() {
292
+ this.needsUpdate = false;
193
293
  return this;
194
- };
294
+ },
295
+
296
+ projectCoords2Surface: function () {
297
+ var n = 2, // # of variables
298
+ m = 2, // number of constraints
299
+ x = [0, 0],
300
+
301
+ // Various Cobyla constants, see Cobyla docs in Cobyja.js
302
+ rhobeg = 5.0,
303
+ rhoend = 1.0e-6,
304
+ iprint = 0,
305
+ maxfun = 200,
306
+
307
+ surface = this.slide,
308
+ that = this,
309
+ r, c3d, c2d,
310
+ _minFunc;
311
+
312
+ if (surface === null) {
313
+ return;
314
+ }
315
+
316
+ _minFunc = function (n, m, x, con) {
317
+ var c3d = [1, surface.X(x[0], x[1]), surface.Y(x[0], x[1]), surface.Z(x[0], x[1])],
318
+ c2d = that.view.project3DTo2D(c3d);
319
+
320
+ con[0] = that.element2D.X() - c2d[1];
321
+ con[1] = that.element2D.Y() - c2d[2];
322
+
323
+ return con[0] * con[0] + con[1] * con[1];
324
+ };
325
+ if (Type.exists(this._params)) {
326
+ x = this._params.slice();
327
+ }
328
+ r = Mat.Nlp.FindMinimum(_minFunc, n, m, x, rhobeg, rhoend, iprint, maxfun);
329
+
330
+ c3d = [1, surface.X(x[0], x[1]), surface.Y(x[0], x[1]), surface.Z(x[0], x[1])];
331
+ c2d = this.view.project3DTo2D(c3d);
332
+ this._params = x;
333
+ this.coords = c3d;
334
+ this.element2D.coords.setCoordinates(Const.COORDS_BY_USER, c2d);
335
+ this._c2d = c2d;
336
+ },
337
+
338
+ // Not yet working
339
+ __evt__update3D: function (oc) { }
340
+
341
+ });
342
+
343
+ /**
344
+ * @class This element is used to provide a constructor for a 3D Point.
345
+ * @pseudo
346
+ * @description A Point3D object is defined by 3 coordinates [x,y,z].
347
+ * <p>
348
+ * All numbers can also be provided as functions returning a number.
349
+ *
350
+ * @name Point3D
351
+ * @augments JXG.Point3D
352
+ * @constructor
353
+ * @throws {Exception} If the element cannot be constructed with the given parent
354
+ * objects an exception is thrown.
355
+ * @param {number,function_number,function_number,function} x,y,z The coordinates are given as x, y, z consisting of numbers of functions.
356
+ * @param {array,function} F Alternatively, the coordinates can be supplied as
357
+ * <ul>
358
+ * <li>array arr=[x,y,z] of length 3 consisting of numbers or
359
+ * <li>function returning an array [x,y,z] of length 3 of numbers.
360
+ * </ul>
361
+ *
362
+ * @example
363
+ * var bound = [-5, 5];
364
+ * var view = board.create('view3d',
365
+ * [[-6, -3], [8, 8],
366
+ * [bound, bound, bound]],
367
+ * {});
368
+ * var p = view.create('point3d', [1, 2, 2], { name:'A', size: 5 });
369
+ * var q = view.create('point3d', function() { return [p.X(), p.Y(), p.Z() - 3]; }, { name:'B', size: 5, fixed: true });
370
+ *
371
+ * </pre><div id="JXGb9ee8f9f-3d2b-4f73-8221-4f82c09933f1" class="jxgbox" style="width: 300px; height: 300px;"></div>
372
+ * <script type="text/javascript">
373
+ * (function() {
374
+ * var board = JXG.JSXGraph.initBoard('JXGb9ee8f9f-3d2b-4f73-8221-4f82c09933f1',
375
+ * {boundingbox: [-8, 8, 8,-8], axis: false, showcopyright: false, shownavigation: false});
376
+ * var bound = [-5, 5];
377
+ * var view = board.create('view3d',
378
+ * [[-6, -3], [8, 8],
379
+ * [bound, bound, bound]],
380
+ * {});
381
+ * var p = view.create('point3d', [1, 2, 2], { name:'A', size: 5 });
382
+ * var q = view.create('point3d', function() { return [p.X(), p.Y(), p.Z() - 3]; }, { name:'B', size: 5 });
383
+ * })();
384
+ *
385
+ * </script><pre>
386
+ *
387
+ */
388
+ JXG.createPoint3D = function (board, parents, attributes) {
389
+ // parents[0]: view
390
+ // followed by
391
+ // parents[1]: function or array
392
+ // or
393
+ // parents[1..3]: coordinates
394
+
395
+ var view = parents[0],
396
+ attr, F, slide,
397
+ c2d, el;
398
+
399
+ // If the last element of parents is a 3D object,
400
+ // the point is a glider on that element.
401
+ if (parents.length > 2 && Type.exists(parents[parents.length - 1].is3D)) {
402
+ slide = parents.pop();
403
+ } else {
404
+ slide = null;
405
+ }
406
+
407
+ if (parents.length === 2) { // [view, array|fun] (Array [x, y, z] | function) returning [x, y, z]
408
+ F = parents[1];
409
+ } else if (parents.length === 4) { // [view, x, y, z], (3 numbers | functions)
410
+ F = parents.slice(1);
411
+ } else {
412
+ throw new Error("JSXGraph: Can't create point3d with parent types '" +
413
+ (typeof parents[0]) + "' and '" + (typeof parents[1]) + "'." +
414
+ "\nPossible parent types: [[x,y,z]], [x,y,z]");
415
+ // "\nPossible parent types: [[x,y,z]], [x,y,z], [element,transformation]"); // TODO
416
+ }
417
+
418
+ attr = Type.copyAttributes(attributes, board.options, 'point3d');
419
+ el = new JXG.Point3D(view, F, slide, attr);
420
+ el.initCoords();
421
+
422
+ c2d = view.project3DTo2D(el.coords);
423
+
424
+ attr.name = el.name;
425
+ el.element2D = view.create('point', c2d, attr);
426
+ el.addChild(el.element2D);
427
+ el.inherits.push(el.element2D);
428
+ el.element2D.setParents(el);
429
+
430
+ el._c2d = el.element2D.coords.usrCoords.slice(); // Store a copy of the coordinates to detect dragging
195
431
 
196
432
  return el;
197
433
  };
198
- JXG.registerElement('point3d', ThreeD.createPoint);
434
+
435
+ JXG.registerElement('point3d', JXG.createPoint3D);
199
436
 
200
437
  });