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 /** 57 * @ignore 58 */ 59 this.F = F; 60 61 /** 62 * Function which maps u to x; i.e. it defines the x-coordinate of the curve 63 * @function 64 * @returns Number 65 */ 66 this.X = X; 67 68 /** 69 * Function which maps u to y; i.e. it defines the y-coordinate of the curve 70 * @function 71 * @returns Number 72 */ 73 this.Y = Y; 74 75 /** 76 * Function which maps u to z; i.e. it defines the x-coordinate of the curve 77 * @function 78 * @returns Number 79 */ 80 this.Z = Z; 81 82 if (this.F !== null) { 83 this.X = function (u) { 84 return this.F(u)[0]; 85 }; 86 this.Y = function (u) { 87 return this.F(u)[1]; 88 }; 89 this.Z = function (u) { 90 return this.F(u)[2]; 91 }; 92 } 93 94 this.range = range; 95 96 this.methodMap = Type.deepCopy(this.methodMap, { 97 // TODO 98 }); 99 }; 100 JXG.Curve3D.prototype = new JXG.GeometryElement(); 101 Type.copyPrototypeMethods(JXG.Curve3D, JXG.GeometryElement3D, "constructor3D"); 102 103 JXG.extend( 104 JXG.Curve3D.prototype, 105 /** @lends JXG.Curve3D.prototype */ { 106 updateDataArray: function () { 107 var steps = Type.evaluate(this.visProp.numberpointshigh), 108 r, s, e, delta, c2d, u, dataX, dataY, 109 i, 110 p = [0, 0, 0]; 111 112 dataX = []; 113 dataY = []; 114 115 if (Type.isArray(this.X)) { 116 steps = this.X.length; 117 for (u = 0; u < steps; u++) { 118 p = [this.X[u], this.Y[u], this.Z[u]]; 119 c2d = this.view.project3DTo2D(p); 120 dataX.push(c2d[1]); 121 dataY.push(c2d[2]); 122 } 123 } else { 124 r = Type.evaluate(this.range); 125 s = Type.evaluate(r[0]); 126 e = Type.evaluate(r[1]); 127 delta = (e - s) / (steps - 1); 128 for (i = 0, u = s; i < steps && u <= e; i++, u += delta) { 129 if (this.F !== null) { 130 p = this.F(u); 131 } else { 132 p = [this.X(u), this.Y(u), this.Z(u)]; 133 } 134 c2d = this.view.project3DTo2D(p); 135 dataX.push(c2d[1]); 136 dataY.push(c2d[2]); 137 } 138 } 139 return { X: dataX, Y: dataY }; 140 }, 141 142 update: function () { 143 return this; 144 }, 145 146 updateRenderer: function () { 147 this.needsUpdate = false; 148 return this; 149 } 150 } 151 ); 152 153 /** 154 * @class This element creates a 3D parametric curves. 155 * @pseudo 156 * @description A 3D parametric curve is defined by a function 157 * <i>F: R<sup>1</sup> → R<sup>3</sup></i>. 158 * 159 * @name Curve3D 160 * @augments Curve 161 * @constructor 162 * @type Object 163 * @throws {Exception} If the element cannot be constructed with the given parent objects an exception is thrown. 164 * @param {Function_Function_Function_Array,Function} F<sub>X</sub>,F<sub>Y</sub>,F<sub>Z</sub>,range 165 * 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 166 * lower and upper bound for the range of the parameter u. range may also be a function returning an array of length two. 167 * @param {Function_Array,Function} F,range Alternatively: F<sub>[X,Y,Z]</sub>(u) a function returning an array [x,y,z] of 168 * numbers, range as above. 169 * @param {Array_Array_Array} X,Y,Z Three arrays containing the coordinate points which define the curve. 170 */ 171 JXG.createCurve3D = function (board, parents, attributes) { 172 var view = parents[0], 173 F, X, Y, Z, range, attr, el; 174 175 if (parents.length === 3) { 176 F = parents[1]; 177 range = parents[2]; 178 X = null; 179 Y = null; 180 Z = null; 181 } else { 182 X = parents[1]; 183 Y = parents[2]; 184 Z = parents[3]; 185 range = parents[4]; 186 F = null; 187 } 188 // TODO Throw error 189 190 attr = Type.copyAttributes(attributes, board.options, "curve3d"); 191 el = new JXG.Curve3D(view, F, X, Y, Z, range, attr); 192 193 attr = el.setAttr2D(attr); 194 el.element2D = view.create("curve", [[], []], attr); 195 /** 196 * @ignore 197 */ 198 el.element2D.updateDataArray = function () { 199 var ret = el.updateDataArray(); 200 this.dataX = ret.X; 201 this.dataY = ret.Y; 202 }; 203 el.addChild(el.element2D); 204 el.inherits.push(el.element2D); 205 el.element2D.setParents(el); 206 207 el.element2D.prepareUpdate().update(); 208 if (!board.isSuspendedUpdate) { 209 el.element2D.updateVisibility().updateRenderer(); 210 } 211 212 return el; 213 }; 214 JXG.registerElement("curve3d", JXG.createCurve3D); 215