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