      1 /*
      2     Copyright 2008-2024
      3         Matthias Ehmann,
      4         Aaron Fenyes,
      5         Carsten Miller,
      6         Andreas Walter,
      7         Alfred Wassermann
      8
      9     This file is part of JSXGraph.
     10
     11     JSXGraph is free software dual licensed under the GNU LGPL or MIT License.
     12
     13     You can redistribute it and/or modify it under the terms of the
     14
     15       * GNU Lesser General Public License as published by
     16         the Free Software Foundation, either version 3 of the License, or
     17         (at your option) any later version
     18       OR
     19       * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT
     20
     21     JSXGraph is distributed in the hope that it will be useful,
     22     but WITHOUT ANY WARRANTY; without even the implied warranty of
     23     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     24     GNU Lesser General Public License for more details.
     25
     26     You should have received a copy of the GNU Lesser General Public License and
     27     the MIT License along with JSXGraph. If not, see <https://www.gnu.org/licenses/>
     28     and <https://opensource.org/licenses/MIT/>.
     29  */
     30 /*global JXG:true, define: true*/
     31
     32 import JXG from '../jxg.js';
     33 import Const from '../base/constants.js';
     34 import Type from '../utils/type.js';
     35
     36 // -----------------------
     37 //  Lines
     38 // -----------------------
     39
     40 /**
     41  * Constructor for 3D polygons.
     42  * @class Creates a new 3D polygon object. Do not use this constructor to create a 3D polygon. Use {@link JXG.View3D#create} with type {@link Polygon3D} instead.
     43  *
     44  * @augments JXG.GeometryElement3D
     45  * @augments JXG.GeometryElement
     46  * @param {View3D} view
     47  * @param {Point3D|Array} point
     48  * @param {Array} direction
     49  * @param {Array} range
     50  * @param {Object} attributes
     51  * @see JXG.Board#generateName
     52  */
     53 JXG.Polygon3D = function (view, vertices, attributes) {
     54     var i;
     55
     56     this.constructor(view.board, attributes, Const.OBJECT_TYPE_POLYGON3D, Const.OBJECT_CLASS_3D);
     57     this.constructor3D(view, 'polygon3d');
     58
     59     this.board.finalizeAdding(this);
     60
     61     /**
     62      * References to the points defining the polygon. The last vertex is the same as the first vertex.
     63      * @type Array
     64      */
     65     this.vertices = [];
     66     for (i = 0; i < vertices.length; i++) {
     67         this.vertices[i] = this.board.select(vertices[i]);
     68
     69         // The _is_new flag is replaced by _is_new_pol.
     70         // Otherwise, the polygon would disappear if the last border element
     71         // is removed (and the point has been provided by coordinates)
     72         if (this.vertices[i]._is_new) {
     73             delete this.vertices[i]._is_new;
     74             this.vertices[i]._is_new_pol = true;
     75         }
     76     }
     77 };
     78 JXG.Polygon3D.prototype = new JXG.GeometryElement();
     79 Type.copyPrototypeMethods(JXG.Polygon3D, JXG.GeometryElement3D, 'constructor3D');
     80
     81 JXG.extend(
     82     JXG.Polygon3D.prototype,
     83     /** @lends JXG.Polygon3D.prototype */ {
     84         update: function () {
     85             return this;
     86         },
     87
     88         updateRenderer: function () {
     89             this.needsUpdate = false;
     90             return this;
     91         }
     92     }
     93 );
     94
     95 /**
     96  * @class A polygon is a sequence of points connected by lines, with the last point
     97  * connecting back to the first one. The points are given by:
     98  * <ul>
     99  *    <li> a list of Point3D objects,
    100  *    <li> a list of coordinate arrays, or
    101  *    <li> a function returning a list of coordinate arrays.
    102  * </ul>
    103  * Each two consecutive points of the list define a line.
    104  * @pseudo
    105  * @constructor
    106  * @name Polygon
    107  * @type JXG.Polygon
    108  * @augments JXG.Polygon
    109  * @throws {Exception} If the element cannot be constructed with the given parent objects an exception is thrown.
    110  * @param {Array} vertices The polygon's vertices. If the first and the last vertex don't match the first one will be
    111  * added to the array by the creator. Here, two points match if they have the same 'id' attribute.
    112  */
    113 JXG.createPolygon3D = function (board, parents, attributes) {
    114     var view = parents[0],
    115         el, i, le, obj,
    116         points = [],
    117         points2d = [],
    118         attr,
    119         attr_points,
    120         is_transform = false;
    121
    122     attr = Type.copyAttributes(attributes, board.options, 'polygon3d');
    123     obj = board.select(parents[1]);
    124     if (obj === null) {
    125         // This is necessary if the original polygon is defined in another board.
    126         obj = parents[1];
    127     }
    128     if (
    129         Type.isObject(obj) &&
    130         obj.type === Const.OBJECT_TYPE_POLYGON3D &&
    131         Type.isTransformationOrArray(parents[2])
    132     ) {
    133         is_transform = true;
    134         le = obj.vertices.length - 1;
    135         attr_points = Type.copyAttributes(attributes, board.options, 'polygon3d', 'vertices');
    136         for (i = 0; i < le; i++) {
    137             if (attr_points.withlabel) {
    138                 attr_points.name =
    139                     obj.vertices[i].name === '' ? '' : obj.vertices[i].name + "'";
    140             }
    141             points.push(board.create('point3d', [obj.vertices[i], parents[2]], attr_points));
    142         }
    143     } else {
    144         points = Type.providePoints3D(view, parents.slice(1), attributes, 'polygon3d', ['vertices']);
    145         if (points === false) {
    146             throw new Error(
    147                 "JSXGraph: Can't create polygon3d with parent types other than 'point' and 'coordinate arrays' or a function returning an array of coordinates. Alternatively, a polygon3d and a transformation can be supplied"
    148             );
    149         }
    150     }
    151
    152     el = new JXG.Polygon3D(view, points, attr);
    153     el.isDraggable = true;
    154
    155     attr = el.setAttr2D(attr);
    156     for (i = 0; i < points.length; i++) {
    157         points2d.push(points[i].element2D);
    158     }
    159     el.element2D = board.create('polygon', points2d, attr);
    160     el.element2D.view = view;
    161     el.addChild(el.element2D);
    162     el.inherits.push(el.element2D);
    163     el.element2D.setParents(el);
    164
    165     // Put the points in their positions
    166     if (is_transform) {
    167       el.prepareUpdate().update().updateVisibility().updateRenderer();
    168       le = obj.vertices.length - 1;
    169       for (i = 0; i < le; i++) {
    170           points[i].prepareUpdate().update().updateVisibility().updateRenderer();
    171       }
    172     }
    173
    174     return el;
    175 };
    176 JXG.registerElement('polygon3d', JXG.createPolygon3D);