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/view3d.js CHANGED
@@ -28,74 +28,117 @@
28
28
  */
29
29
  /*global JXG:true, define: true*/
30
30
 
31
- define(['jxg', 'options', 'base/constants', 'utils/type', 'math/math', 'base/element', '3d/threed',
32
- ], function (JXG, Options, Const, Type, Mat, GeometryElement, ThreeD) {
31
+ define(['jxg', 'options', 'base/constants', 'utils/type', 'math/math', 'base/element','base/composition'],
32
+ function (JXG, Options, Const, Type, Mat, GeometryElement, Composition) {
33
33
  "use strict";
34
34
 
35
- ThreeD.View3D = function (board, parents, attributes) {
36
- var bbox3d, coords, size;
37
- this.constructor(board, attributes, Const.OBJECT_TYPE_VIEW3D, Const.OBJECT_CLASS_CURVE);
38
-
39
- bbox3d = parents[2]; // [[x1, x2], [y1,y2], [z1,z2]]
40
- coords = parents[0]; // llft corner
41
- size = parents[1]; // [w, h]
42
-
43
- /**
44
- * "Namespace" for all 3D handling
45
- */
46
- this.D3 = {};
35
+ /**
36
+ * 3D view inside of a JXGraph board.
37
+ *
38
+ * @class Creates a new 3D view. Do not use this constructor to create a 3D view. Use {@link JXG.Board#create} with
39
+ * type {@link View3D} instead.
40
+ *
41
+ * @augments JXG.GeometryElement
42
+ * @param {Array} parents Array consisting of lower left corner [x, y] of the view inside the board, [width, height] of the view
43
+ * and box size [[x1, x2], [y1,y2], [z1,z2]]. If the view's azimuth=0 and elevation=0, the 3D view will cover a rectangle with lower left corner
44
+ * [x,y] and side lengths [w, h] of the board.
45
+ */
46
+ JXG.View3D = function (board, parents, attributes) {
47
+ this.constructor(board, attributes, Const.OBJECT_TYPE_VIEW3D, Const.OBJECT_CLASS_3D);
47
48
 
48
49
  /**
49
50
  * An associative array containing all geometric objects belonging to the view.
50
51
  * Key is the id of the object and value is a reference to the object.
51
52
  * @type Object
53
+ * @private
52
54
  */
53
- this.D3.objects = {};
55
+ this.objects = {};
54
56
 
55
57
  /**
56
58
  * An array containing all geometric objects in this view in the order of construction.
57
59
  * @type Array
60
+ * @private
58
61
  */
59
- this.D3.objectsList = [];
62
+ this.objectsList = [];
60
63
 
61
64
  /**
62
- * @type {Object} contains the axes of the view or null
65
+ * An associative array / dictionary to store the objects of the board by name. The name of the object is the key and value is a reference to the object.
66
+ * @type Object
67
+ * @private
68
+ */
69
+ this.elementsByName = {};
70
+
71
+ /**
72
+ * Default axes of the 3D view, contains the axes of the view or null.
73
+ *
74
+ * @type {Object}
63
75
  * @default null
64
76
  */
65
- this.D3.defaultAxes = null;
77
+ this.defaultAxes = null;
66
78
 
67
79
  /**
68
80
  * 3D-to-2D transformation matrix
69
- * @type {Array} 3 x 4 mattrix
81
+ * @type {Array} 3 x 4 matrix
82
+ * @private
70
83
  */
71
- this.D3.matrix = [
84
+ this.matrix3D = [
72
85
  [1, 0, 0, 0],
73
86
  [0, 1, 0, 0],
74
87
  [0, 0, 1, 0]
75
88
  ];
76
89
 
77
- // Bounding box (cube) [[x1, x2], [y1,y2], [z1,z2]]:
78
- this.D3.bbox3d = bbox3d;
79
- this.D3.coords = coords;
80
- this.D3.size = size;
90
+ /**
91
+ * Lower left corner [x, y] of the 3D view if elevation and azimuth are set to 0.
92
+ * @type array
93
+ * @private
94
+ */
95
+ this.llftCorner = parents[0];
96
+
97
+ /**
98
+ * Width and height [w, h] of the 3D view if elevation and azimuth are set to 0.
99
+ * @type array
100
+ * @private
101
+ */
102
+ this.size = parents[1];
103
+
104
+ /**
105
+ * Bounding box (cube) [[x1, x2], [y1,y2], [z1,z2]] of the 3D view
106
+ * @type array
107
+ */
108
+ this.bbox3D = parents[2];
81
109
 
82
110
  /**
83
111
  * Distance of the view to the origin. In other words, its
84
- * the radius of the sphere where the camera sits.
112
+ * the radius of the sphere where the camera sits.view.board.update
113
+ * @type Number
85
114
  */
86
- this.D3.r = -1;
115
+ this.r = -1;
87
116
 
88
117
  this.timeoutAzimuth = null;
89
118
 
90
119
  this.id = this.board.setId(this, 'V');
91
120
  this.board.finalizeAdding(this);
92
121
  this.elType = 'view3d';
122
+
93
123
  this.methodMap = Type.deepCopy(this.methodMap, {
124
+ // TODO
94
125
  });
95
126
  };
96
- ThreeD.View3D.prototype = new GeometryElement();
127
+ JXG.View3D.prototype = new GeometryElement();
128
+
129
+ JXG.extend(JXG.View3D.prototype, /** @lends JXG.View3D.prototype */ {
97
130
 
98
- JXG.extend(ThreeD.View3D.prototype, /** @lends ThreeD.View3D.prototype */ {
131
+ /**
132
+ * Creates a new 3D element of type elementType.
133
+ * @param {String} elementType Type of the element to be constructed given as a string e.g. 'point3d' or 'surface3d'.
134
+ * @param {Array} parents Array of parent elements needed to construct the element e.g. coordinates for a 3D point or two
135
+ * 3D points to construct a line. This highly depends on the elementType that is constructed. See the corresponding JXG.create*
136
+ * methods for a list of possible parameters.
137
+ * @param {Object} [attributes] An object containing the attributes to be set. This also depends on the elementType.
138
+ * Common attributes are name, visible, strokeColor.
139
+ * @returns {Object} Reference to the created element. This is usually a GeometryElement3D, but can be an array containing
140
+ * two or more elements.
141
+ */
99
142
  create: function (elementType, parents, attributes) {
100
143
  var prefix = [],
101
144
  is3D = false,
@@ -106,59 +149,117 @@ define(['jxg', 'options', 'base/constants', 'utils/type', 'math/math', 'base/ele
106
149
  prefix.push(this);
107
150
  }
108
151
  el = this.board.create(elementType, prefix.concat(parents), attributes);
109
- if (true || is3D) {
110
- this.add(el);
111
- }
112
- return el;
113
- },
114
152
 
115
- add: function (el) {
116
- this.D3.objects[el.id] = el;
117
- this.D3.objectsList.push(el);
153
+ return el;
118
154
  },
119
155
 
120
156
  /**
121
- * Update 3D-to-2D transformation matrix with the actual
122
- * elevation and azimuth angles.
157
+ * Select a single or multiple elements at once.
158
+ * @param {String|Object|function} str The name, id or a reference to a JSXGraph 3D element in the 3D view. An object will
159
+ * be used as a filter to return multiple elements at once filtered by the properties of the object.
160
+ * @param {Boolean} onlyByIdOrName If true (default:false) elements are only filtered by their id, name or groupId.
161
+ * The advanced filters consisting of objects or functions are ignored.
162
+ * @returns {JXG.GeometryElement3D|JXG.Composition}
163
+ * @example
164
+ * // select the element with name A
165
+ * view.select('A');
123
166
  *
124
- * @private
167
+ * // select all elements with strokecolor set to 'red' (but not '#ff0000')
168
+ * view.select({
169
+ * strokeColor: 'red'
170
+ * });
171
+ *
172
+ * // select all points on or below the x/y plane and make them black.
173
+ * view.select({
174
+ * elType: 'point3d',
175
+ * Z: function (v) {
176
+ * return v <= 0;
177
+ * }
178
+ * }).setAttribute({color: 'black'});
179
+ *
180
+ * // select all elements
181
+ * view.select(function (el) {
182
+ * return true;
183
+ * });
125
184
  */
185
+ select: function (str, onlyByIdOrName) {
186
+ var flist, olist, i, l,
187
+ s = str;
188
+
189
+ if (s === null) {
190
+ return s;
191
+ }
192
+
193
+ // It's a string, most likely an id or a name.
194
+ if (Type.isString(s) && s !== '') {
195
+ // Search by ID
196
+ if (Type.exists(this.objects[s])) {
197
+ s = this.objects[s];
198
+ // Search by name
199
+ } else if (Type.exists(this.elementsByName[s])) {
200
+ s = this.elementsByName[s];
201
+ // // Search by group ID
202
+ // } else if (Type.exists(this.groups[s])) {
203
+ // s = this.groups[s];
204
+ }
205
+
206
+ // It's a function or an object, but not an element
207
+ } else if (!onlyByIdOrName &&
208
+ (Type.isFunction(s) ||
209
+ (Type.isObject(s) && !Type.isFunction(s.setAttribute))
210
+ )) {
211
+ flist = Type.filterElements(this.objectsList, s);
212
+
213
+ olist = {};
214
+ l = flist.length;
215
+ for (i = 0; i < l; i++) {
216
+ olist[flist[i].id] = flist[i];
217
+ }
218
+ s = new Composition(olist);
219
+
220
+ // It's an element which has been deleted (and still hangs around, e.g. in an attractor list
221
+ } else if (Type.isObject(s) && Type.exists(s.id) && !Type.exists(this.objects[s.id])) {
222
+ s = null;
223
+ }
224
+
225
+ return s;
226
+ },
227
+
126
228
  update: function () {
127
- var D3 = this.D3,
128
- e, r, a, f, mat;
229
+ // Update 3D-to-2D transformation matrix with the actual
230
+ // elevation and azimuth angles.
129
231
 
130
- if (!Type.exists(D3.el_slide) ||
131
- !Type.exists(D3.az_slide) ||
232
+ var e, r, a, f, mat;
233
+
234
+ if (!Type.exists(this.el_slide) ||
235
+ !Type.exists(this.az_slide) ||
132
236
  !this.needsUpdate) {
133
237
  return this;
134
238
  }
135
239
 
136
- e = D3.el_slide.Value();
137
- r = D3.r;
138
- a = D3.az_slide.Value();
240
+ e = this.el_slide.Value();
241
+ r = this.r;
242
+ a = this.az_slide.Value();
139
243
  f = r * Math.sin(e);
140
244
  mat = [[1, 0, 0,], [0, 1, 0], [0, 0, 1]];
141
245
 
142
- D3.matrix = [
246
+ this.matrix3D = [
143
247
  [1, 0, 0, 0],
144
248
  [0, 1, 0, 0],
145
249
  [0, 0, 1, 0]
146
250
  ];
147
251
 
148
- D3.matrix[1][1] = r * Math.cos(a);
149
- D3.matrix[1][2] = -r * Math.sin(a);
150
- D3.matrix[2][1] = f * Math.sin(a);
151
- D3.matrix[2][2] = f * Math.cos(a);
152
- D3.matrix[2][3] = Math.cos(e);
153
-
154
- if (true) {
155
- mat[1][1] = D3.size[0] / (D3.bbox3d[0][1] - D3.bbox3d[0][0]); // w / d_x
156
- mat[2][2] = D3.size[1] / (D3.bbox3d[1][1] - D3.bbox3d[1][0]); // h / d_y
157
- mat[1][0] = D3.coords[0] - mat[1][1] * D3.bbox3d[0][0]; // llft_x
158
- mat[2][0] = D3.coords[1] - mat[2][2] * D3.bbox3d[1][0]; // llft_y
252
+ this.matrix3D[1][1] = r * Math.cos(a);
253
+ this.matrix3D[1][2] = -r * Math.sin(a);
254
+ this.matrix3D[2][1] = f * Math.sin(a);
255
+ this.matrix3D[2][2] = f * Math.cos(a);
256
+ this.matrix3D[2][3] = Math.cos(e);
159
257
 
160
- D3.matrix = Mat.matMatMult(mat, D3.matrix);
161
- }
258
+ mat[1][1] = this.size[0] / (this.bbox3D[0][1] - this.bbox3D[0][0]); // w / d_x
259
+ mat[2][2] = this.size[1] / (this.bbox3D[1][1] - this.bbox3D[1][0]); // h / d_y
260
+ mat[1][0] = this.llftCorner[0] - mat[1][1] * this.bbox3D[0][0]; // llft_x
261
+ mat[2][0] = this.llftCorner[1] - mat[2][2] * this.bbox3D[1][0]; // llft_y
262
+ this.matrix3D = Mat.matMatMult(mat, this.matrix3D);
162
263
 
163
264
  return this;
164
265
  },
@@ -190,19 +291,20 @@ define(['jxg', 'options', 'base/constants', 'utils/type', 'math/math', 'base/ele
190
291
  vec = x;
191
292
  }
192
293
  }
193
- return Mat.matVecMult(this.D3.matrix, vec);
294
+ return Mat.matVecMult(this.matrix3D, vec);
194
295
  },
195
296
 
196
297
  /**
197
- * Project a 2D coordinate to the plane through the origin
198
- * defined by its normal vector `normal`.
298
+ * Project a 2D coordinate to the plane defined by the point foot
299
+ * and the normal vector `normal`.
199
300
  *
200
301
  * @param {JXG.Point} point
201
302
  * @param {Array} normal
202
- * @returns Array of length 4 containing the projected
303
+ * @param {Array} foot
304
+ * @returns {Array} of length 4 containing the projected
203
305
  * point in homogeneous coordinates.
204
306
  */
205
- project2DTo3DPlane: function (point, normal, foot) {
307
+ project2DTo3DPlane: function (point2d, normal, foot) {
206
308
  var mat, rhs, d, le,
207
309
  n = normal.slice(1),
208
310
  sol = [1, 0, 0, 0];
@@ -211,11 +313,11 @@ define(['jxg', 'options', 'base/constants', 'utils/type', 'math/math', 'base/ele
211
313
  le = Mat.norm(n, 3);
212
314
  d = Mat.innerProduct(foot.slice(1), n, 3) / le;
213
315
 
214
- mat = this.D3.matrix.slice(0, 3); // True copy
316
+ mat = this.matrix3D.slice(0, 3); // True copy
215
317
  mat.push([0].concat(n));
216
318
 
217
319
  // 2D coordinates of point:
218
- rhs = point.coords.usrCoords.concat([d]);
320
+ rhs = point2d.coords.usrCoords.concat([d]);
219
321
  try {
220
322
  // Prevent singularity in case elevation angle is zero
221
323
  if (mat[2][3] === 1.0) {
@@ -229,8 +331,14 @@ define(['jxg', 'options', 'base/constants', 'utils/type', 'math/math', 'base/ele
229
331
  return sol;
230
332
  },
231
333
 
334
+ /**
335
+ * Limit 3D coordinates to the bounding cube.
336
+ *
337
+ * @param {Array} c3d 3D coordinates [x,y,z]
338
+ * @returns Array with updated 3D coordinates.
339
+ */
232
340
  project3DToCube: function (c3d) {
233
- var cube = this.D3.bbox3d;
341
+ var cube = this.bbox3D;
234
342
  if (c3d[1] < cube[0][0]) { c3d[1] = cube[0][0]; }
235
343
  if (c3d[1] > cube[0][1]) { c3d[1] = cube[0][1]; }
236
344
  if (c3d[2] < cube[1][0]) { c3d[2] = cube[1][0]; }
@@ -241,14 +349,21 @@ define(['jxg', 'options', 'base/constants', 'utils/type', 'math/math', 'base/ele
241
349
  return c3d;
242
350
  },
243
351
 
352
+ /**
353
+ * Intersect a ray with the bounding cube of the 3D view.
354
+ * @param {Array} p 3D coordinates [x,y,z]
355
+ * @param {Array} d 3D direction vector of the line (array of length 3)
356
+ * @param {Number} r direction of the ray (positive if r > 0, negative if r < 0).
357
+ * @returns Affine ratio of the intersection of the line with the cube.
358
+ */
244
359
  intersectionLineCube: function (p, d, r) {
245
360
  var rnew, i, r0, r1;
246
361
 
247
362
  rnew = r;
248
363
  for (i = 0; i < 3; i++) {
249
364
  if (d[i] !== 0) {
250
- r0 = (this.D3.bbox3d[i][0] - p[i]) / d[i];
251
- r1 = (this.D3.bbox3d[i][1] - p[i]) / d[i];
365
+ r0 = (this.bbox3D[i][0] - p[i]) / d[i];
366
+ r1 = (this.bbox3D[i][1] - p[i]) / d[i];
252
367
  if (r < 0) {
253
368
  rnew = Math.max(rnew, Math.min(r0, r1));
254
369
  } else {
@@ -259,29 +374,35 @@ define(['jxg', 'options', 'base/constants', 'utils/type', 'math/math', 'base/ele
259
374
  return rnew;
260
375
  },
261
376
 
377
+ /**
378
+ * Test if coordinates are inside of the bounding cube.
379
+ * @param {array} q 3D coordinates [x,y,z] of a point.
380
+ * @returns Boolean
381
+ */
262
382
  isInCube: function (q) {
263
- return q[0] > this.D3.bbox3d[0][0] - Mat.eps && q[0] < this.D3.bbox3d[0][1] + Mat.eps &&
264
- q[1] > this.D3.bbox3d[1][0] - Mat.eps && q[1] < this.D3.bbox3d[1][1] + Mat.eps &&
265
- q[2] > this.D3.bbox3d[2][0] - Mat.eps && q[2] < this.D3.bbox3d[2][1] + Mat.eps;
383
+ return q[0] > this.bbox3D[0][0] - Mat.eps && q[0] < this.bbox3D[0][1] + Mat.eps &&
384
+ q[1] > this.bbox3D[1][0] - Mat.eps && q[1] < this.bbox3D[1][1] + Mat.eps &&
385
+ q[2] > this.bbox3D[2][0] - Mat.eps && q[2] < this.bbox3D[2][1] + Mat.eps;
266
386
  },
267
387
 
268
388
  /**
269
389
  *
270
- * @param {*} plane1
271
- * @param {*} plane2
272
- * @param {*} d
273
- * @returns Array of length 2 containing the coordinates of the defining points of
390
+ * @param {JXG.Plane3D} plane1
391
+ * @param {JXG.Plane3D} plane2
392
+ * @param {JXG.Plane3D} d
393
+ * @returns {Array} of length 2 containing the coordinates of the defining points of
274
394
  * of the intersection segment.
275
395
  */
276
396
  intersectionPlanePlane: function(plane1, plane2, d) {
277
397
  var ret = [[], []],
278
398
  p, dir, r, q;
279
399
 
280
- d = d || plane2.D3.d;
400
+ d = d || plane2.d;
281
401
 
282
- p = Mat.Geometry.meet3Planes(plane1.D3.normal, plane1.D3.d, plane2.D3.normal, d,
283
- Mat.crossProduct(plane1.D3.normal, plane2.D3.normal), 0);
284
- dir = Mat.Geometry.meetPlanePlane(plane1.D3.dir1, plane1.D3.dir2, plane2.D3.dir1, plane2.D3.dir2);
402
+ p = Mat.Geometry.meet3Planes(
403
+ plane1.normal, plane1.d, plane2.normal, d, Mat.crossProduct(plane1.normal, plane2.normal
404
+ ), 0);
405
+ dir = Mat.Geometry.meetPlanePlane(plane1.vec1, plane1.vec2, plane2.vec1, plane2.vec2);
285
406
  r = this.intersectionLineCube(p, dir, Infinity);
286
407
  q = Mat.axpy(r, dir, p);
287
408
  if (this.isInCube(q)) {
@@ -295,7 +416,39 @@ define(['jxg', 'options', 'base/constants', 'utils/type', 'math/math', 'base/ele
295
416
  return ret;
296
417
  },
297
418
 
298
- getMesh: function (X, Y, Z, interval_u, interval_v) {
419
+ /**
420
+ * Generate mesh for a surface / plane.
421
+ * Returns array [dataX, dataY] for a JSXGraph curve's updateDataArray function.
422
+ * @param {Array,Function} func
423
+ * @param {Array} interval_u
424
+ * @param {Array} interval_v
425
+ * @returns Array
426
+ * @private
427
+ *
428
+ * @example
429
+ * var el = view.create('curve', [[], []]);
430
+ * el.updateDataArray = function () {
431
+ * var steps_u = Type.evaluate(this.visProp.stepsu),
432
+ * steps_v = Type.evaluate(this.visProp.stepsv),
433
+ * r_u = Type.evaluate(this.range_u),
434
+ * r_v = Type.evaluate(this.range_v),
435
+ * func, ret;
436
+ *
437
+ * if (this.F !== null) {
438
+ * func = this.F;
439
+ * } else {
440
+ * func = [this.X, this.Y, this.Z];
441
+ * }
442
+ * ret = this.view.getMesh(func,
443
+ * r_u.concat([steps_u]),
444
+ * r_v.concat([steps_v]));
445
+ *
446
+ * this.dataX = ret[0];
447
+ * this.dataY = ret[1];
448
+ * };
449
+ *
450
+ */
451
+ getMesh: function (func, interval_u, interval_v) {
299
452
  var i_u, i_v, u, v, c2d,
300
453
  delta_u, delta_v,
301
454
  p = [0, 0, 0],
@@ -312,9 +465,11 @@ define(['jxg', 'options', 'base/constants', 'utils/type', 'math/math', 'base/ele
312
465
  u = interval_u[0] + delta_u * i_u;
313
466
  for (i_v = 0; i_v <= steps_v; i_v++) {
314
467
  v = interval_v[0] + delta_v * i_v;
315
- p[0] = X(u, v);
316
- p[1] = Y(u, v);
317
- p[2] = Z(u, v);
468
+ if (Type.isFunction(func)) {
469
+ p = func(u, v);
470
+ } else {
471
+ p = [func[0](u, v), func[1](u, v), func[2](u, v)];
472
+ }
318
473
  c2d = this.project3DTo2D(p);
319
474
  dataX.push(c2d[1]);
320
475
  dataY.push(c2d[2]);
@@ -327,9 +482,11 @@ define(['jxg', 'options', 'base/constants', 'utils/type', 'math/math', 'base/ele
327
482
  v = interval_v[0] + delta_v * i_v;
328
483
  for (i_u = 0; i_u <= steps_u; i_u++) {
329
484
  u = interval_u[0] + delta_u * i_u;
330
- p[0] = X(u, v);
331
- p[1] = Y(u, v);
332
- p[2] = Z(u, v);
485
+ if (Type.isFunction(func)) {
486
+ p = func(u, v);
487
+ } else {
488
+ p = [func[0](u, v), func[1](u, v), func[2](u, v)];
489
+ }
333
490
  c2d = this.project3DTo2D(p);
334
491
  dataX.push(c2d[1]);
335
492
  dataY.push(c2d[2]);
@@ -341,21 +498,27 @@ define(['jxg', 'options', 'base/constants', 'utils/type', 'math/math', 'base/ele
341
498
  return [dataX, dataY];
342
499
  },
343
500
 
501
+ /**
502
+ *
503
+ */
344
504
  animateAzimuth: function () {
345
- var s = this.D3.az_slide._smin,
346
- e = this.D3.az_slide._smax,
505
+ var s = this.az_slide._smin,
506
+ e = this.az_slide._smax,
347
507
  sdiff = e - s,
348
- newVal = this.D3.az_slide.Value() + 0.1;
508
+ newVal = this.az_slide.Value() + 0.1;
349
509
 
350
- this.D3.az_slide.position = ((newVal - s) / sdiff);
351
- if (this.D3.az_slide.position > 1) {
352
- this.D3.az_slide.position = 0.0;
510
+ this.az_slide.position = ((newVal - s) / sdiff);
511
+ if (this.az_slide.position > 1) {
512
+ this.az_slide.position = 0.0;
353
513
  }
354
514
  this.board.update();
355
515
 
356
516
  this.timeoutAzimuth = setTimeout(function () { this.animateAzimuth(); }.bind(this), 200);
357
517
  },
358
518
 
519
+ /**
520
+ *
521
+ */
359
522
  stopAzimuth: function () {
360
523
  clearTimeout(this.timeoutAzimuth);
361
524
  this.timeoutAzimuth = null;
@@ -375,8 +538,9 @@ define(['jxg', 'options', 'base/constants', 'utils/type', 'math/math', 'base/ele
375
538
  * @param {Array_Array_Array} lower,dim,cube Here, lower is an array of the form [x, y] and
376
539
  * dim is an array of the form [w, h].
377
540
  * The arrays [x, y] and [w, h] define the 2D frame into which the 3D cube is
378
- * (roughly) projected.
379
- * cube is an array of the form [[x1, x2], [y1, y2], [z1, z2]]
541
+ * (roughly) projected. If the view's azimuth=0 and elevation=0, the 3D view will cover a rectangle with lower left corner
542
+ * [x,y] and side lengths [w, h] of the board.
543
+ * The array 'cube' is of the form [[x1, x2], [y1, y2], [z1, z2]]
380
544
  * which determines the coordinate ranges of the 3D cube.
381
545
  *
382
546
  * @example
@@ -410,43 +574,38 @@ define(['jxg', 'options', 'base/constants', 'utils/type', 'math/math', 'base/ele
410
574
  * (function() {
411
575
  * var board = JXG.JSXGraph.initBoard('JXGdd06d90e-be5d-4531-8f0b-65fc30b1a7c7',
412
576
  * {boundingbox: [-8, 8, 8,-8], axis: false, showcopyright: false, shownavigation: false});
413
- * var bound = [-5, 5];
414
- * var view = board.create('view3d',
415
- * [[-6, -3], [8, 8],
416
- * [bound, bound, bound]],
417
- * {
418
- * // Main axes
419
- * axesPosition: 'center',
420
- * xAxis: { strokeColor: 'blue', strokeWidth: 3},
421
- *
422
- * // Planes
423
- * xPlaneRear: { fillColor: 'yellow', mesh3d: {visible: false}},
424
- * yPlaneFront: { visible: true, fillColor: 'blue'},
425
- *
426
- * // Axes on planes
427
- * xPlaneRearYAxis: {strokeColor: 'red'},
428
- * xPlaneRearZAxis: {strokeColor: 'red'},
429
- *
430
- * yPlaneFrontXAxis: {strokeColor: 'blue'},
431
- * yPlaneFrontZAxis: {strokeColor: 'blue'},
432
- *
433
- * zPlaneFrontXAxis: {visible: false},
434
- * zPlaneFrontYAxis: {visible: false}
435
- * });
436
- *
577
+ * var bound = [-5, 5];
578
+ * var view = board.create('view3d',
579
+ * [[-6, -3], [8, 8],
580
+ * [bound, bound, bound]],
581
+ * {
582
+ * // Main axes
583
+ * axesPosition: 'center',
584
+ * xAxis: { strokeColor: 'blue', strokeWidth: 3},
585
+ * // Planes
586
+ * xPlaneRear: { fillColor: 'yellow', mesh3d: {visible: false}},
587
+ * yPlaneFront: { visible: true, fillColor: 'blue'},
588
+ * // Axes on planes
589
+ * xPlaneRearYAxis: {strokeColor: 'red'},
590
+ * xPlaneRearZAxis: {strokeColor: 'red'},
591
+ * yPlaneFrontXAxis: {strokeColor: 'blue'},
592
+ * yPlaneFrontZAxis: {strokeColor: 'blue'},
593
+ * zPlaneFrontXAxis: {visible: false},
594
+ * zPlaneFrontYAxis: {visible: false}
595
+ * });
437
596
  * })();
438
597
  *
439
598
  * </script><pre>
440
599
  *
441
600
  */
442
- ThreeD.createView3D = function (board, parents, attributes) {
443
- var view, frame, attr,
601
+ JXG.createView3D = function (board, parents, attributes) {
602
+ var view, attr,
444
603
  x, y, w, h,
445
604
  coords = parents[0], // llft corner
446
605
  size = parents[1]; // [w, h]
447
606
 
448
607
  attr = Type.copyAttributes(attributes, board.options, 'view3d');
449
- view = new ThreeD.View3D(board, parents, attr);
608
+ view = new JXG.View3D(board, parents, attr);
450
609
  view.defaultAxes = view.create('axes3d', parents, attributes);
451
610
 
452
611
  x = coords[0];
@@ -454,37 +613,12 @@ define(['jxg', 'options', 'base/constants', 'utils/type', 'math/math', 'base/ele
454
613
  w = size[0];
455
614
  h = size[1];
456
615
 
457
- /**
458
- * Frame around the view object
459
- */
460
- if (false) {
461
- frame = board.create('polygon', [
462
- [coords[0], coords[1] + size[1]], // ulft
463
- [coords[0], coords[1]], // llft
464
- [coords[0] + size[0], coords[1]], // lrt
465
- [coords[0] + size[0], coords[1] + size[1]], // urt
466
- ], {
467
- fillColor: 'none',
468
- highlightFillColor: 'none',
469
- highlight: false,
470
- vertices: {
471
- fixed: true,
472
- visible: false
473
- },
474
- borders: {
475
- strokeColor: 'black',
476
- highlight: false,
477
- strokeWidth: 0.5,
478
- dash: 4
479
- }
480
- });
481
- //view.add(frame);
482
- }
483
-
484
616
  /**
485
617
  * Slider to adapt azimuth angle
618
+ * @name JXG.View3D#az_slide
619
+ * @type {Slider}
486
620
  */
487
- view.D3.az_slide = board.create('slider', [[x - 1, y - 2], [x + w + 1, y - 2], [0, 1.0, 2 * Math.PI]], {
621
+ view.az_slide = board.create('slider', [[x - 1, y - 2], [x + w + 1, y - 2], [0, 1.0, 2 * Math.PI]], {
488
622
  style: 6, name: 'az',
489
623
  point1: { frozen: true },
490
624
  point2: { frozen: true }
@@ -492,38 +626,59 @@ define(['jxg', 'options', 'base/constants', 'utils/type', 'math/math', 'base/ele
492
626
 
493
627
  /**
494
628
  * Slider to adapt elevation angle
629
+ *
630
+ * @name JXG.View3D#el_slide
631
+ * @type {Slider}
495
632
  */
496
- view.D3.el_slide = board.create('slider', [[x - 1, y], [x - 1, y + h], [0, 0.30, Math.PI / 2]], {
633
+ view.el_slide = board.create('slider', [[x - 1, y], [x - 1, y + h], [0, 0.30, Math.PI / 2]], {
497
634
  style: 6, name: 'el',
498
635
  point1: { frozen: true },
499
636
  point2: { frozen: true }
500
637
  });
501
638
 
502
639
  view.board.highlightInfobox = function (x, y, el) {
503
- var d;
504
-
505
- if (Type.exists(el.D3)) {
506
- d = Type.evaluate(el.visProp.infoboxdigits);
640
+ var d, i,
641
+ c3d, foot,
642
+ brd = el.board,
643
+ p = null;
644
+
645
+ // Search 3D parent
646
+ for (i = 0; i < el.parents.length; i++) {
647
+ p = brd.objects[el.parents[i]];
648
+ if (p.is3D) {
649
+ break;
650
+ }
651
+ }
652
+ if (p) {
653
+ foot = [1, 0, 0, p.coords[3]];
654
+ c3d = view.project2DTo3DPlane(p.element2D, [1, 0, 0, 1], foot);
655
+ if (!view.isInCube(c3d)) {
656
+ view.board.highlightCustomInfobox('', p);
657
+ return;
658
+ }
659
+ d = Type.evaluate(p.visProp.infoboxdigits);
507
660
  if (d === 'auto') {
508
661
  view.board.highlightCustomInfobox('(' +
509
- Type.autoDigits(el.D3.X()) + ' | ' +
510
- Type.autoDigits(el.D3.Y()) + ' | ' +
511
- Type.autoDigits(el.D3.Z()) + ')', el);
662
+ Type.autoDigits(p.X()) + ' | ' +
663
+ Type.autoDigits(p.Y()) + ' | ' +
664
+ Type.autoDigits(p.Z()) + ')', p);
512
665
  } else {
513
666
  view.board.highlightCustomInfobox('(' +
514
- Type.toFixed(el.D3.X(), d) + ' | ' +
515
- Type.toFixed(el.D3.Y(), d) + ' | ' +
516
- Type.toFixed(el.D3.Z(), d) + ')', el);
667
+ Type.toFixed(p.X(), d) + ' | ' +
668
+ Type.toFixed(p.Y(), d) + ' | ' +
669
+ Type.toFixed(p.Z(), d) + ')', p);
517
670
  }
518
671
  } else {
519
672
  view.board.highlightCustomInfobox('(' + x + ', ' + y + ')', el);
520
673
  }
521
674
  };
522
675
 
676
+ view.board.update();
677
+
523
678
  return view;
524
679
  };
525
- JXG.registerElement('view3d', ThreeD.createView3D);
680
+ JXG.registerElement('view3d', JXG.createView3D);
526
681
 
527
- return ThreeD.View3D;
682
+ return JXG.View3D;
528
683
  });
529
684