1 /* 2 Copyright 2008-2024 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.js"; 32 import Type from "../utils/type.js"; 33 34 /** 35 * Constructs a new GeometryElement3D object. 36 * @class This is the basic class for 3D geometry elements like Point3D and Line3D. 37 * @constructor 38 * @augments JXG.GeometryElement 39 * 40 * @param {string} elType 41 */ 42 JXG.GeometryElement3D = function (view, elType) { 43 this.elType = elType; 44 45 /** 46 * Pointer to the view3D in which the element is constructed 47 * @type JXG.View3D 48 * @private 49 */ 50 this.view = view; 51 52 this.id = this.view.board.setId(this, elType); 53 54 /** 55 * Link to the 2D element(s) used to visualize the 3D element 56 * in a view. In case, there are several 2D elements, it is an array. 57 * 58 * @type Array 59 * @description JXG.GeometryElement,Array 60 * @private 61 * 62 * @example 63 * p.element2D; 64 */ 65 this.element2D = null; 66 67 /** 68 * If this property exists (and is true) the element is a 3D element. 69 * 70 * @type Boolean 71 * @private 72 */ 73 this.is3D = true; 74 75 this.zIndex = 0.0; 76 77 this.view.objects[this.id] = this; 78 79 if (this.name !== "") { 80 this.view.elementsByName[this.name] = this; 81 } 82 }; 83 84 JXG.extend(JXG.GeometryElement3D.prototype, { 85 86 setAttr2D: function(attr3D) { 87 var attr2D = attr3D; 88 89 attr2D.name = this.name; 90 attr2D.element3d = this; 91 attr2D.id = null; // The 2D element's id may not be controlled by the user. 92 93 return attr2D; 94 }, 95 96 // Documented in element.js 97 setAttribute: function(attr) { 98 var i, key, value, arg, pair, 99 attributes = {}; 100 101 // Normalize the user input 102 for (i = 0; i < arguments.length; i++) { 103 arg = arguments[i]; 104 if (Type.isString(arg)) { 105 // pairRaw is string of the form 'key:value' 106 pair = arg.split(":"); 107 attributes[Type.trim(pair[0])] = Type.trim(pair[1]); 108 } else if (!Type.isArray(arg)) { 109 // pairRaw consists of objects of the form {key1:value1,key2:value2,...} 110 JXG.extend(attributes, arg); 111 } else { 112 // pairRaw consists of array [key,value] 113 attributes[arg[0]] = arg[1]; 114 } 115 } 116 117 for (i in attributes) { 118 if (attributes.hasOwnProperty(i)) { 119 key = i.replace(/\s+/g, "").toLowerCase(); 120 value = attributes[i]; 121 switch (key) { 122 case "numberpointshigh": 123 case "stepsu": 124 case "stepsv": 125 if (Type.exists(this.visProp[key]) && 126 (!JXG.Validator[key] || 127 (JXG.Validator[key] && JXG.Validator[key](value)) || 128 (JXG.Validator[key] && 129 Type.isFunction(value) && 130 JXG.Validator[key](value()))) 131 ) { 132 value = 133 value.toLowerCase && value.toLowerCase() === "false" 134 ? false 135 : value; 136 this._set(key, value); 137 } 138 break; 139 default: 140 if (Type.exists(this.element2D)) { 141 this.element2D.setAttribute(attributes); 142 } 143 } 144 } 145 } 146 }, 147 148 // Documented in element.js 149 getAttribute: function(key) { 150 var result; 151 key = key.toLowerCase(); 152 153 switch (key) { 154 case "numberpointshigh": 155 case "stepsu": 156 case "stepsv": 157 result = this.visProp[key]; 158 break; 159 default: 160 if (Type.exists(this.element2D)) { 161 result = this.element2D.getAttribute(key); 162 } 163 break; 164 } 165 166 return result; 167 }, 168 169 // Documented in element.js 170 getAttributes: function() { 171 var attr = {}, 172 i, key, 173 attr3D = ['numberpointshigh', 'stepsu', 'stepsv'], 174 le = attr3D.length; 175 176 if (Type.exists(this.element2D)) { 177 attr = Type.merge(this.element2D.getAttributes()); 178 } 179 180 for (i = 0; i < le; i++) { 181 key = attr3D[i]; 182 if (Type.exists(this.visProp[key])) { 183 attr[key] = this.visProp[key]; 184 } 185 } 186 187 return attr; 188 }, 189 190 // /** 191 // * Add transformations to this element. 192 // * @param {JXG.GeometryElement} el 193 // * @param {JXG.Transformation|Array} transform Either one {@link JXG.Transformation} 194 // * or an array of {@link JXG.Transformation}s. 195 // * @returns {JXG.CoordsElement} Reference to itself. 196 // */ 197 addTransformGeneric: function (el, transform) { 198 var i, 199 list = Type.isArray(transform) ? transform : [transform], 200 len = list.length; 201 202 // There is only one baseElement possible 203 if (this.transformations.length === 0) { 204 this.baseElement = el; 205 } 206 207 for (i = 0; i < len; i++) { 208 this.transformations.push(list[i]); 209 } 210 211 return this; 212 }, 213 214 /** 215 * Set position of the 2D element. This is a 216 * callback function, executed in {@link JXG.GeometryElement#setPosition}. 217 * @param {JXG.Transform} t transformation 218 * @private 219 * @see JXG.GeometryElement#setPosition 220 */ 221 setPosition2D: function(t) { 222 /* stub */ 223 }, 224 225 /** 226 * Project a 3D point to this element and update point.position. 227 * @param {Array} p 3D position of the point (array of length 3) 228 * @param {Array} params Changed in place to the new of the point in terms of the elements functions X, Y, Z. 229 * For example for a surface, params will contain values (u,v) such that the new 3D position 230 * p = [X(u, v), Z(u, v), Z(u, v)]. 231 * @returns {Array} 3D coordinates of the projected point with homogeneous coordinates of the form [1, x, y, z]. 232 */ 233 projectCoords: function(p, params) { 234 /* stub */ 235 }, 236 237 // Documented in element.js 238 remove: function() {} 239 240 }); 241 242 export default JXG.GeometryElement3D; 243