      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