1 /* 2 Copyright 2008-2022 3 Matthias Ehmann, 4 Carsten Miller, 5 Andreas Walter, 6 Alfred Wassermann 7 8 This file is part of JSXGraph. 9 10 JSXGraph is free software dual licensed under the GNU LGPL or MIT License. 11 12 You can redistribute it and/or modify it under the terms of the 13 14 * GNU Lesser General Public License as published by 15 the Free Software Foundation, either version 3 of the License, or 16 (at your option) any later version 17 OR 18 * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT 19 20 JSXGraph is distributed in the hope that it will be useful, 21 but WITHOUT ANY WARRANTY; without even the implied warranty of 22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 GNU Lesser General Public License for more details. 24 25 You should have received a copy of the GNU Lesser General Public License and 26 the MIT License along with JSXGraph. If not, see <http://www.gnu.org/licenses/> 27 and <http://opensource.org/licenses/MIT/>. 28 */ 29 /*global JXG:true, define: true*/ 30 31 define(['jxg', 'base/constants', 'utils/type'], function (JXG, Const, Type) { 32 "use strict"; 33 34 /** 35 * Constructor for 3D curves. 36 * @class Creates a new 3D curve object. Do not use this constructor to create a 3D curve. Use {@link JXG.Board#create} with type {@link Curve3D} instead. 37 * 38 * @augments JXG.GeometryElement3D 39 * @augments JXG.GeometryElement 40 * @param {View3D} view 41 * @param {Function} F 42 * @param {Function} X 43 * @param {Function} Y 44 * @param {Function} Z 45 * @param {Array} range 46 * @param {Object} attributes 47 * @see JXG.Board#generateName 48 */ 49 JXG.Curve3D = function (view, F, X, Y, Z, range, attributes) { 50 this.constructor(view.board, attributes, Const.OBJECT_TYPE_CURVE3D, Const.OBJECT_CLASS_3D); 51 this.constructor3D(view, 'surface3d'); 52 53 this.id = this.view.board.setId(this, 'S3D'); 54 this.board.finalizeAdding(this); 55 56 this.F = F; 57 58 /** 59 * Function which maps u to x; i.e. it defines the x-coordinate of the curve 60 * @function 61 * @returns Number 62 */ 63 this.X = X; 64 65 /** 66 * Function which maps u to y; i.e. it defines the y-coordinate of the curve 67 * @function 68 * @returns Number 69 */ 70 this.Y = Y; 71 72 /** 73 * Function which maps u to z; i.e. it defines the x-coordinate of the curve 74 * @function 75 * @returns Number 76 */ 77 this.Z = Z; 78 79 if (this.F !== null) { 80 this.X = function(u) { return this.F(u)[0]; }; 81 this.Y = function(u) { return this.F(u)[1]; }; 82 this.Z = function(u) { return this.F(u)[2]; }; 83 } 84 85 this.range = range; 86 87 this.methodMap = Type.deepCopy(this.methodMap, { 88 // TODO 89 }); 90 }; 91 JXG.Curve3D.prototype = new JXG.GeometryElement(); 92 Type.copyPrototypeMethods(JXG.Curve3D, JXG.GeometryElement3D, 'constructor3D'); 93 94 JXG.extend(JXG.Curve3D.prototype, /** @lends JXG.Curve3D.prototype */ { 95 96 updateDataArray: function () { 97 var steps = Type.evaluate(this.visProp.numberpointshigh), 98 r, s, e, delta, 99 c2d, u, 100 dataX, dataY, 101 p = [0, 0, 0]; 102 103 dataX = []; 104 dataY = []; 105 106 if (Type.isArray(this.X)) { 107 steps = this.X.length; 108 for (u = 0; u < steps; u++) { 109 p = [this.X[u], this.Y[u], this.Z[u]]; 110 c2d = this.view.project3DTo2D(p); 111 dataX.push(c2d[1]); 112 dataY.push(c2d[2]); 113 } 114 } else { 115 r = Type.evaluate(this.range); 116 s = r[0]; 117 e = r[1]; 118 delta = (e - s) / (steps - 1); 119 for (u = s; u <= e; u += delta) { 120 if (this.F !== null){ 121 p = this.F(u); 122 } else { 123 p = [this.X(u), this.Y(u), this.Z(u)]; 124 } 125 c2d = this.view.project3DTo2D(p); 126 dataX.push(c2d[1]); 127 dataY.push(c2d[2]); 128 } 129 } 130 return {'X': dataX, 'Y': dataY}; 131 }, 132 133 update: function () { return this; }, 134 135 updateRenderer: function () { 136 this.needsUpdate = false; 137 return this; 138 } 139 }); 140 141 /** 142 * @class This element creates a 3D parametric curves. 143 * @pseudo 144 * @description A 3D parametric curve is defined by a function 145 * <i>F: R<sup>1</sup> → R<sup>3</sup></i>. 146 * 147 * @name Curve3D 148 * @augments Curve 149 * @constructor 150 * @type Object 151 * @throws {Exception} If the element cannot be constructed with the given parent objects an exception is thrown. 152 * @param {Function_Function_Function_Array,Function} F<sub>X</sub>,F<sub>Y</sub>,F<sub>Z</sub>,range 153 * F<sub>X</sub>(u), F<sub>Y</sub>(u), F<sub>Z</sub>(u) are functions returning a number, range is the array containing 154 * lower and upper bound for the range of the parameter u. range may also be a function returning an array of length two. 155 * @param {Function_Array,Function} F,range Alternatively: F<sub>[X,Y,Z]</sub>(u) a function returning an array [x,y,z] of 156 * numbers, range as above. 157 * @param {Array_Array_Array} X,Y,Z Three arrays containing the coordinate points which define the curve. 158 */ 159 JXG.createCurve3D = function (board, parents, attributes) { 160 var view = parents[0], 161 F, X, Y, Z, range, 162 attr, el; 163 164 if (parents.length === 3) { 165 F = parents[1]; 166 range = parents[2]; 167 X = null; 168 Y = null; 169 Z = null; 170 } else { 171 X = parents[1]; 172 Y = parents[2]; 173 Z = parents[3]; 174 range = parents[4]; 175 F = null; 176 } 177 // TODO Throw error 178 179 attr = Type.copyAttributes(attributes, board.options, 'curve3d'); 180 el = new JXG.Curve3D(view, F, X, Y, Z, range, attr); 181 182 el.element2D = board.create('curve', [[], []], attr); 183 el.element2D.updateDataArray = function() { 184 var ret = el.updateDataArray(); 185 this.dataX = ret.X; 186 this.dataY = ret.Y; 187 }; 188 el.addChild(el.element2D); 189 el.inherits.push(el.element2D); 190 el.element2D.setParents(el); 191 192 el.element2D.prepareUpdate().update(); 193 if (!board.isSuspendedUpdate) { 194 el.element2D.updateVisibility().updateRenderer(); 195 } 196 197 return el; 198 }; 199 JXG.registerElement('curve3d', JXG.createCurve3D); 200 201 });