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