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 import Mat from '../math/math.js'; 36 37 /** 38 * Constructor for 3D polygons. 39 * @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. 40 * 41 * @augments JXG.GeometryElement3D 42 * @augments JXG.GeometryElement 43 * @param {View3D} view 44 * @param {Point3D|Array} point 45 * @param {Array} direction 46 * @param {Array} range 47 * @param {Object} attributes 48 * @see JXG.Board#generateName 49 */ 50 JXG.Polygon3D = function (view, vertices, attributes) { 51 var i; 52 53 this.constructor(view.board, attributes, Const.OBJECT_TYPE_POLYGON3D, Const.OBJECT_CLASS_3D); 54 this.constructor3D(view, 'polygon3d'); 55 56 this.board.finalizeAdding(this); 57 58 /** 59 * References to the points defining the polygon. 60 * Compared to the 2D {@link JXG.Polygon#vertices}, it contains one point less, i.e. for a quadrangle 61 * 'vertices' contains four points. In a 2D quadrangle, 'vertices' will contain five points, the last one being 62 * a copy of the first one. 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 updateZIndex: function() { 94 var i, 95 le = this.vertices.length, // - 1, 96 c3d = [1, 0, 0, 0]; 97 98 if (le <= 0) { 99 return [NaN, NaN, NaN, NaN]; 100 } 101 for (i = 0; i < le; i++) { 102 c3d[1] += this.vertices[i].coords[1]; 103 c3d[2] += this.vertices[i].coords[2]; 104 c3d[3] += this.vertices[i].coords[3]; 105 } 106 c3d[1] /= le; 107 c3d[2] /= le; 108 c3d[3] /= le; 109 110 this.zIndex = Mat.matVecMult(this.view.matrix3DRotShift, c3d)[3]; 111 112 return this; 113 } 114 } 115 ); 116 117 /** 118 * @class A polygon is a sequence of points connected by lines, with the last point 119 * connecting back to the first one. The points are given by: 120 * <ul> 121 * <li> a list of Point3D objects, 122 * <li> a list of coordinate arrays, or 123 * <li> a function returning a list of coordinate arrays. 124 * </ul> 125 * Each two consecutive points of the list define a line. 126 * <p> 127 * JSXGraph does not require and does not check planarity of the polygon. 128 * 129 * @pseudo 130 * @constructor 131 * @name Polygon3D 132 * @type JXG.Polygon3D 133 * @augments JXG.Polygon3D 134 * @throws {Exception} If the element cannot be constructed with the given parent objects an exception is thrown. 135 * @param {Array} vertices The polygon's vertices. 136 */ 137 JXG.createPolygon3D = function (board, parents, attributes) { 138 var view = parents[0], 139 el, i, le, obj, 140 points = [], 141 points2d = [], 142 attr, 143 attr_points, 144 is_transform = false; 145 146 attr = Type.copyAttributes(attributes, board.options, 'polygon3d'); 147 obj = board.select(parents[1]); 148 if (obj === null) { 149 // This is necessary if the original polygon is defined in another board. 150 obj = parents[1]; 151 } 152 // TODO: Number of points? Is the last point equal to the first point? 153 if ( 154 Type.isObject(obj) && 155 obj.type === Const.OBJECT_TYPE_POLYGON3D && 156 Type.isTransformationOrArray(parents[2]) 157 ) { 158 is_transform = true; 159 le = obj.vertices.length - 1; 160 attr_points = Type.copyAttributes(attributes, board.options, 'polygon3d', 'vertices'); 161 for (i = 0; i < le; i++) { 162 if (attr_points.withlabel) { 163 attr_points.name = 164 obj.vertices[i].name === '' ? '' : obj.vertices[i].name + "'"; 165 } 166 points.push(board.create('point3d', [obj.vertices[i], parents[2]], attr_points)); 167 } 168 } else { 169 points = Type.providePoints3D(view, parents.slice(1), attributes, 'polygon3d', ['vertices']); 170 if (points === false) { 171 throw new Error( 172 "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" 173 ); 174 } 175 } 176 177 el = new JXG.Polygon3D(view, points, attr); 178 el.isDraggable = true; 179 180 attr = el.setAttr2D(attr); 181 for (i = 0; i < points.length; i++) { 182 points2d.push(points[i].element2D); 183 } 184 el.element2D = board.create('polygon', points2d, attr); 185 el.element2D.view = view; 186 el.addChild(el.element2D); 187 el.inherits.push(el.element2D); 188 el.element2D.setParents(el); 189 190 // Put the points in their positions 191 if (is_transform) { 192 el.prepareUpdate().update().updateVisibility().updateRenderer(); 193 le = obj.vertices.length - 1; 194 for (i = 0; i < le; i++) { 195 points[i].prepareUpdate().update().updateVisibility().updateRenderer(); 196 } 197 } 198 199 return el; 200 }; 201 JXG.registerElement('polygon3d', JXG.createPolygon3D);