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  * @param {string} elType
 39  */
 40 JXG.GeometryElement3D = function (view, elType) {
 41     this.elType = elType;
 42     this.id = this.board.setId(this, elType);
 43 
 44     /**
 45      * Pointer to the view3D in which the element is constructed
 46      * @type JXG.View3D
 47      * @private
 48      */
 49     this.view = view;
 50 
 51     /**
 52      * Link to the 2D element(s) used to visualize the 3D element
 53      * in a view. In case, there are several 2D elements, it is an array.
 54      *
 55      * @type Array
 56      * @description JXG.GeometryElement,Array
 57      * @private
 58      *
 59      * @example
 60      *   p.element2D;
 61      */
 62     this.element2D = null;
 63 
 64     /**
 65      * If this property exists (and is true) the element is a 3D element.
 66      *
 67      * @type Boolean
 68      * @private
 69      */
 70     this.is3D = true;
 71 
 72     this.view.objects[this.id] = this;
 73 
 74     if (this.name !== "") {
 75         this.view.elementsByName[this.name] = this;
 76     }
 77 };
 78 
 79 JXG.extend(JXG.GeometryElement3D.prototype, {
 80 
 81     setAttr2D: function(attr3D) {
 82         var attr2D = attr3D;
 83 
 84         attr2D.name = this.name;
 85         attr2D.element3d = this;
 86 
 87         return attr2D;
 88     },
 89 
 90     // Documented in element.js
 91     setAttribute: function(attr) {
 92         var i, key, value, arg, pair,
 93         attributes = {};
 94 
 95         // Normalize the user input
 96         for (i = 0; i < arguments.length; i++) {
 97             arg = arguments[i];
 98             if (Type.isString(arg)) {
 99                 // pairRaw is string of the form 'key:value'
100                 pair = arg.split(":");
101                 attributes[Type.trim(pair[0])] = Type.trim(pair[1]);
102             } else if (!Type.isArray(arg)) {
103                 // pairRaw consists of objects of the form {key1:value1,key2:value2,...}
104                 JXG.extend(attributes, arg);
105             } else {
106                 // pairRaw consists of array [key,value]
107                 attributes[arg[0]] = arg[1];
108             }
109         }
110 
111         for (i in attributes) {
112             if (attributes.hasOwnProperty(i)) {
113                 key = i.replace(/\s+/g, "").toLowerCase();
114                 value = attributes[i];
115                 switch (key) {
116                     case "numberpointshigh":
117                     case "stepsu":
118                     case "stepsv":
119                         if (Type.exists(this.visProp[key]) &&
120                         (!JXG.Validator[key] ||
121                             (JXG.Validator[key] && JXG.Validator[key](value)) ||
122                             (JXG.Validator[key] &&
123                                 Type.isFunction(value) &&
124                                 JXG.Validator[key](value())))
125                         ) {
126                             value =
127                                 value.toLowerCase && value.toLowerCase() === "false"
128                                     ? false
129                                     : value;
130                             this._set(key, value);
131                         }
132                     break;
133                     default:
134                         if (Type.exists(this.element2D)) {
135                             this.element2D.setAttribute(attributes);
136                         }
137                 }
138             }
139         }
140     },
141 
142     // Documented in element.js
143     getAttribute: function(key) {
144         var result;
145         key = key.toLowerCase();
146 
147         switch (key) {
148             case "numberpointshigh":
149             case "stepsu":
150             case "stepsv":
151                 result = this.visProp[key];
152                 break;
153             default:
154                 if (Type.exists(this.element2D)) {
155                     result = this.element2D.getAttribute(key);
156                 }
157                 break;
158         }
159 
160         return result;
161     },
162 
163     // Documented in element.js
164     getAttributes: function() {
165         var attr = {},
166             i, key,
167             attr3D = ['numberpointshigh', 'stepsu', 'stepsv'],
168             le = attr3D.length;
169 
170         if (Type.exists(this.element2D)) {
171             attr = Type.merge(this.element2D.getAttributes());
172         }
173 
174         for (i = 0; i < le; i++) {
175             key = attr3D[i];
176             if (Type.exists(this.visProp[key])) {
177                 attr[key] = this.visProp[key];
178             }
179         }
180 
181         return attr;
182     },
183 
184     /**
185      * Set position of the 2D element. This is a
186      * callback function, executed in {@link JXG.GeometryElement#setPosition}.
187      * @param {JXG.Transform} t transformation
188      * @private
189      * @see JXG.GeometryElement#setPosition
190      */
191     setPosition2D: function(t) {
192         /* stub */
193     },
194 
195     remove: function() {}
196 
197 });
198 
199 export default JXG.GeometryElement3D;
200