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', 'utils/type', '3d/view3d' 32 ], function (JXG, Type, ThreeD) { 33 "use strict"; 34 35 36 /** 37 * @class This element creates a 3D parametric surface. 38 * @pseudo 39 * @description A 3D parametric surface is defined by a function 40 * <i>F: R<sup>2</sup> → R<sup>3</sup></i>. 41 * 42 * @name ParametricSurface3D 43 * @augments Curve 44 * @constructor 45 * @type Object 46 * @throws {Exception} If the element cannot be constructed with the given parent objects an exception is thrown. 47 * @param {Function_Function_Function_Array_Array} F<sub>X</sub>,F<sub>Y</sub>,F<sub>Z</sub>,rangeX,rangeY 48 * F<sub>X</sub>(u,v), F<sub>Y</sub>(u,v), F<sub>Z</sub>(u,v) are functions returning a number, rangeU is the array containing 49 * lower and upper bound for the range of parameter u, rangeV is the array containing 50 * lower and upper bound for the range of parameter v. rangeU and rangeV may also be functions returning an array of length two. 51 * @example 52 * var view = board.create('view3d', 53 * [[-6, -3], [8, 8], 54 * [[-5, 5], [-5, 5], [-5, 5]]]); 55 * 56 * // Sphere 57 * var c = view.create('parametricsurface3d', [ 58 * (u, v) => 2 * Math.sin(u) * Math.cos(v), 59 * (u, v) => 2 * Math.sin(u) * Math.sin(v), 60 * (u, v) => 2 * Math.cos(u), 61 * [0, 2 * Math.PI], 62 * [0, Math.PI] 63 * ], { 64 * strokeColor: '#ff0000', 65 * stepsU: 30, 66 * stepsV: 30 67 * }); 68 * 69 * </pre><div id="JXG52da0ecc-1ba9-4d41-850c-36e5120025a5" class="jxgbox" style="width: 500px; height: 500px;"></div> 70 * <script type="text/javascript"> 71 * (function() { 72 * var board = JXG.JSXGraph.initBoard('JXG52da0ecc-1ba9-4d41-850c-36e5120025a5', 73 * {boundingbox: [-8, 8, 8,-8], axis: false, showcopyright: false, shownavigation: false}); 74 * var view = board.create('view3d', 75 * [[-6, -3], [8, 8], 76 * [[-5, 5], [-5, 5], [-5, 5]]]); 77 * 78 * // Sphere 79 * var c = view.create('parametricsurface3d', [ 80 * (u, v) => 2 * Math.sin(u) * Math.cos(v), 81 * (u, v) => 2 * Math.sin(u) * Math.sin(v), 82 * (u, v) => 2 * Math.cos(u), 83 * [0, 2 * Math.PI], 84 * [0, Math.PI] 85 * ], { 86 * strokeColor: '#ff0000', 87 * stepsU: 20, 88 * stepsV: 20 89 * }); 90 * 91 * })(); 92 * 93 * </script><pre> 94 * 95 */ 96 ThreeD.createParametricSurface = function (board, parents, attributes) { 97 var view = parents[0], 98 attr, 99 X = parents[1], 100 Y = parents[2], 101 Z = parents[3], 102 range_u = parents[4], 103 range_v = parents[5], 104 D3, el; 105 106 D3 = { 107 elType: 'surface3d', 108 X: X, 109 Y: Y, 110 Z: Z, 111 range_u: range_u, 112 range_v: range_v 113 }; 114 attr = Type.copyAttributes(attributes, board.options, 'surface3d'); 115 el = board.create('curve', [[], []], attr); 116 el.updateDataArray = function () { 117 var steps_u = Type.evaluate(this.visProp.stepsu), 118 steps_v = Type.evaluate(this.visProp.stepsv), 119 r_u = Type.evaluate(this.D3.range_u), // Type.evaluate(range_u), 120 r_v = Type.evaluate(this.D3.range_v), // Type.evaluate(range_v), 121 res = view.getMesh(this.D3.X, this.D3.Y, this.D3.Z, 122 r_u.concat([steps_u]), 123 r_v.concat([steps_v])); 124 this.dataX = res[0]; 125 this.dataY = res[1]; 126 }; 127 el.D3 = D3; 128 129 return el; 130 }; 131 JXG.registerElement('parametricsurface3d', ThreeD.createParametricSurface); 132 133 /** 134 * @class This element creates a 3D function graph. 135 * @pseudo 136 * @description A 3D function graph is defined by a function 137 * <i>F: R<sup>2</sup> → R</i>. 138 * 139 * @name Functiongraph3D 140 * @augments ParametricSurface3D 141 * @constructor 142 * @type Object 143 * @throws {Exception} If the element cannot be constructed with the given parent objects an exception is thrown. 144 * @param {Function_Array_Array} F,rangeX,rangeY F(x,y) is a function returning a number, rangeX is the array containing 145 * lower and upper bound for the range of x, rangeY is the array containing 146 * lower and upper bound for the range of y. 147 * @example 148 * var box = [-5, 5]; 149 * var view = board.create('view3d', 150 * [ 151 * [-6, -3], [8, 8], 152 * [box, box, box] 153 * ], 154 * { 155 * xPlaneRear: {visible: false}, 156 * yPlaneRear: {visible: false}, 157 * }); 158 * 159 * // Function F to be plotted 160 * var F = (x, y) => Math.sin(x * y / 4); 161 * 162 * // 3D surface 163 * var c = view.create('functiongraph3d', [ 164 * F, 165 * box, // () => [-s.Value()*5, s.Value() * 5], 166 * box, // () => [-s.Value()*5, s.Value() * 5], 167 * ], { 168 * strokeWidth: 0.5, 169 * stepsU: 70, 170 * stepsV: 70 171 * }); 172 * 173 * </pre><div id="JXG87646dd4-9fe5-4c21-8734-089abc612515" class="jxgbox" style="width: 500px; height: 500px;"></div> 174 * <script type="text/javascript"> 175 * (function() { 176 * var board = JXG.JSXGraph.initBoard('JXG87646dd4-9fe5-4c21-8734-089abc612515', 177 * {boundingbox: [-8, 8, 8,-8], axis: false, showcopyright: false, shownavigation: false}); 178 * var box = [-5, 5]; 179 * var view = board.create('view3d', 180 * [ 181 * [-6, -3], [8, 8], 182 * [box, box, box] 183 * ], 184 * { 185 * xPlaneRear: {visible: false}, 186 * yPlaneRear: {visible: false}, 187 * }); 188 * 189 * // Function F to be plotted 190 * var F = (x, y) => Math.sin(x * y / 4); 191 * 192 * // 3D surface 193 * var c = view.create('functiongraph3d', [ 194 * F, 195 * box, // () => [-s.Value()*5, s.Value() * 5], 196 * box, // () => [-s.Value()*5, s.Value() * 5], 197 * ], { 198 * strokeWidth: 0.5, 199 * stepsU: 70, 200 * stepsV: 70 201 * }); 202 * 203 * })(); 204 * 205 * </script><pre> 206 * 207 */ 208 ThreeD.createFunctiongraph = function (board, parents, attributes) { 209 var view = parents[0], 210 X = function(u, v) { return u; }, 211 Y = function(u, v) { return v; }, 212 Z = parents[1], 213 range_u = parents[2], 214 range_v = parents[3]; 215 216 return view.create('parametricsurface3d', [X, Y, Z, range_u, range_v], attributes); 217 }; 218 JXG.registerElement('functiongraph3d', ThreeD.createFunctiongraph); 219 220 }); 221