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 
 86         return attr2D;
 87     },
 88 
 89     // Documented in element.js
 90     setAttribute: function(attr) {
 91         var i, key, value, arg, pair,
 92         attributes = {};
 93 
 94         // Normalize the user input
 95         for (i = 0; i < arguments.length; i++) {
 96             arg = arguments[i];
 97             if (Type.isString(arg)) {
 98                 // pairRaw is string of the form 'key:value'
 99                 pair = arg.split(":");
100                 attributes[Type.trim(pair[0])] = Type.trim(pair[1]);
101             } else if (!Type.isArray(arg)) {
102                 // pairRaw consists of objects of the form {key1:value1,key2:value2,...}
103                 JXG.extend(attributes, arg);
104             } else {
105                 // pairRaw consists of array [key,value]
106                 attributes[arg[0]] = arg[1];
107             }
108         }
109 
110         for (i in attributes) {
111             if (attributes.hasOwnProperty(i)) {
112                 key = i.replace(/\s+/g, "").toLowerCase();
113                 value = attributes[i];
114                 switch (key) {
115                     case "numberpointshigh":
116                     case "stepsu":
117                     case "stepsv":
118                         if (Type.exists(this.visProp[key]) &&
119                         (!JXG.Validator[key] ||
120                             (JXG.Validator[key] && JXG.Validator[key](value)) ||
121                             (JXG.Validator[key] &&
122                                 Type.isFunction(value) &&
123                                 JXG.Validator[key](value())))
124                         ) {
125                             value =
126                                 value.toLowerCase && value.toLowerCase() === "false"
127                                     ? false
128                                     : value;
129                             this._set(key, value);
130                         }
131                     break;
132                     default:
133                         if (Type.exists(this.element2D)) {
134                             this.element2D.setAttribute(attributes);
135                         }
136                 }
137             }
138         }
139     },
140 
141     // Documented in element.js
142     getAttribute: function(key) {
143         var result;
144         key = key.toLowerCase();
145 
146         switch (key) {
147             case "numberpointshigh":
148             case "stepsu":
149             case "stepsv":
150                 result = this.visProp[key];
151                 break;
152             default:
153                 if (Type.exists(this.element2D)) {
154                     result = this.element2D.getAttribute(key);
155                 }
156                 break;
157         }
158 
159         return result;
160     },
161 
162     // Documented in element.js
163     getAttributes: function() {
164         var attr = {},
165             i, key,
166             attr3D = ['numberpointshigh', 'stepsu', 'stepsv'],
167             le = attr3D.length;
168 
169         if (Type.exists(this.element2D)) {
170             attr = Type.merge(this.element2D.getAttributes());
171         }
172 
173         for (i = 0; i < le; i++) {
174             key = attr3D[i];
175             if (Type.exists(this.visProp[key])) {
176                 attr[key] = this.visProp[key];
177             }
178         }
179 
180         return attr;
181     },
182 
183     /**
184      * Set position of the 2D element. This is a
185      * callback function, executed in {@link JXG.GeometryElement#setPosition}.
186      * @param {JXG.Transform} t transformation
187      * @private
188      * @see JXG.GeometryElement#setPosition
189      */
190     setPosition2D: function(t) {
191         /* stub */
192     },
193 
194     remove: function() {}
195 
196 });
197 
198 export default JXG.GeometryElement3D;
199