1 /* 2 Copyright 2008-2023 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 <https://www.gnu.org/licenses/> 27 and <https://opensource.org/licenses/MIT/>. 28 */ 29 /*global JXG:true, define: true*/ 30 31 import JXG from "../jxg"; 32 import Const from "../base/constants"; 33 import Type from "../utils/type"; 34 35 /** 36 * Constructor for 3D curves. 37 * @class Creates a new 3D curve object. Do not use this constructor to create a 3D curve. Use {@link JXG.View3D#create} with type {@link Curve3D} instead. 38 * 39 * @augments JXG.GeometryElement3D 40 * @augments JXG.GeometryElement 41 * @param {View3D} view 42 * @param {Function} F 43 * @param {Function} X 44 * @param {Function} Y 45 * @param {Function} Z 46 * @param {Array} range 47 * @param {Object} attributes 48 * @see JXG.Board#generateName 49 */ 50 JXG.Curve3D = function (view, F, X, Y, Z, range, attributes) { 51 this.constructor(view.board, attributes, Const.OBJECT_TYPE_CURVE3D, Const.OBJECT_CLASS_3D); 52 this.constructor3D(view, "curve3d"); 53 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) { 81 return this.F(u)[0]; 82 }; 83 this.Y = function (u) { 84 return this.F(u)[1]; 85 }; 86 this.Z = function (u) { 87 return this.F(u)[2]; 88 }; 89 } 90 91 this.range = range; 92 93 this.methodMap = Type.deepCopy(this.methodMap, { 94 // TODO 95 }); 96 }; 97 JXG.Curve3D.prototype = new JXG.GeometryElement(); 98 Type.copyPrototypeMethods(JXG.Curve3D, JXG.GeometryElement3D, "constructor3D"); 99 100 JXG.extend( 101 JXG.Curve3D.prototype, 102 /** @lends JXG.Curve3D.prototype */ { 103 updateDataArray: function () { 104 var steps = Type.evaluate(this.visProp.numberpointshigh), 105 r, s, e, delta, c2d, u, dataX, dataY, 106 i, 107 p = [0, 0, 0]; 108 109 dataX = []; 110 dataY = []; 111 112 if (Type.isArray(this.X)) { 113 steps = this.X.length; 114 for (u = 0; u < steps; u++) { 115 p = [this.X[u], this.Y[u], this.Z[u]]; 116 c2d = this.view.project3DTo2D(p); 117 dataX.push(c2d[1]); 118 dataY.push(c2d[2]); 119 } 120 } else { 121 r = Type.evaluate(this.range); 122 s = Type.evaluate(r[0]); 123 e = Type.evaluate(r[1]); 124 delta = (e - s) / (steps - 1); 125 for (i = 0, u = s; i < steps && u <= e; i++, u += delta) { 126 if (this.F !== null) { 127 p = this.F(u); 128 } else { 129 p = [this.X(u), this.Y(u), this.Z(u)]; 130 } 131 c2d = this.view.project3DTo2D(p); 132 dataX.push(c2d[1]); 133 dataY.push(c2d[2]); 134 } 135 } 136 return { X: dataX, Y: dataY }; 137 }, 138 139 update: function () { 140 return this; 141 }, 142 143 updateRenderer: function () { 144 this.needsUpdate = false; 145 return this; 146 } 147 } 148 ); 149 150 /** 151 * @class This element creates a 3D parametric curves. 152 * @pseudo 153 * @description A 3D parametric curve is defined by a function 154 * <i>F: R<sup>1</sup> → R<sup>3</sup></i>. 155 * 156 * @name Curve3D 157 * @augments Curve 158 * @constructor 159 * @type Object 160 * @throws {Exception} If the element cannot be constructed with the given parent objects an exception is thrown. 161 * @param {Function_Function_Function_Array,Function} F<sub>X</sub>,F<sub>Y</sub>,F<sub>Z</sub>,range 162 * 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 163 * lower and upper bound for the range of the parameter u. range may also be a function returning an array of length two. 164 * @param {Function_Array,Function} F,range Alternatively: F<sub>[X,Y,Z]</sub>(u) a function returning an array [x,y,z] of 165 * numbers, range as above. 166 * @param {Array_Array_Array} X,Y,Z Three arrays containing the coordinate points which define the curve. 167 */ 168 JXG.createCurve3D = function (board, parents, attributes) { 169 var view = parents[0], 170 F, X, Y, Z, range, attr, el; 171 172 if (parents.length === 3) { 173 F = parents[1]; 174 range = parents[2]; 175 X = null; 176 Y = null; 177 Z = null; 178 } else { 179 X = parents[1]; 180 Y = parents[2]; 181 Z = parents[3]; 182 range = parents[4]; 183 F = null; 184 } 185 // TODO Throw error 186 187 attr = Type.copyAttributes(attributes, board.options, "curve3d"); 188 el = new JXG.Curve3D(view, F, X, Y, Z, range, attr); 189 190 attr = el.setAttr2D(attr); 191 el.element2D = view.create("curve", [[], []], attr); 192 /** 193 * @ignore 194 */ 195 el.element2D.updateDataArray = function () { 196 var ret = el.updateDataArray(); 197 this.dataX = ret.X; 198 this.dataY = ret.Y; 199 }; 200 el.addChild(el.element2D); 201 el.inherits.push(el.element2D); 202 el.element2D.setParents(el); 203 204 el.element2D.prepareUpdate().update(); 205 if (!board.isSuspendedUpdate) { 206 el.element2D.updateVisibility().updateRenderer(); 207 } 208 209 return el; 210 }; 211 JXG.registerElement("curve3d", JXG.createCurve3D); 212