/src/org/mt4j/components/clusters/Cluster.java
Java | 340 lines | 179 code | 58 blank | 103 comment | 33 complexity | eaadee8e975324d5f6de8e0e88a6b5d2 MD5 | raw file
1/*********************************************************************** 2 * mt4j Copyright (c) 2008 - 2009, C.Ruff, Fraunhofer-Gesellschaft All rights reserved. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 * 17 ***********************************************************************/ 18package org.mt4j.components.clusters; 19 20 21import java.util.ArrayList; 22import java.util.Arrays; 23 24import org.mt4j.components.MTComponent; 25import org.mt4j.components.TransformSpace; 26import org.mt4j.components.bounds.BoundsArbitraryPlanarPolygon; 27import org.mt4j.components.bounds.BoundsZPlaneRectangle; 28import org.mt4j.components.visibleComponents.shapes.AbstractShape; 29import org.mt4j.components.visibleComponents.shapes.MTPolygon; 30import org.mt4j.util.math.ConvexQuickHull2D; 31import org.mt4j.util.math.Matrix; 32import org.mt4j.util.math.Vector3D; 33import org.mt4j.util.math.Vertex; 34 35import processing.core.PApplet; 36 37/** 38 * The Class Cluster. 39 * @author Christopher Ruff 40 */ 41public class Cluster extends MTComponent { //extends MTComponent/implements IMTComponent3D? 42 /** The selection polygon. */ 43 private MTPolygon selectionPolygon; 44 45 //FIXME THIS WHOLE CLASS SHOULD BE RE-WORKED! 46 47 //Disadvantages of the cluster: 48 //each of the children are transformed, not only the cluster parent -> performance.. 49 //hardwired into mtcanvas -> should be removed.. 50 //could be replaced with a composite component -> but then we have the problem of picking child components of the group 51 52 /** 53 * Instantiates a new cluster. 54 * 55 * @param pApplet the applet 56 * @param selectionPolygon the selection polygon 57 */ 58 public Cluster(PApplet pApplet,MTPolygon selectionPolygon) { 59 this(pApplet, new MTComponent[]{}, selectionPolygon); 60 } 61 62 /** 63 * Info: Cluster can only hold instances of MTBaseComponent!. 64 * 65 * @param pApplet the applet 66 * @param components the components 67 * @param selectionPolygon the selection polygon 68 */ 69 public Cluster(PApplet pApplet, MTComponent[] components, MTPolygon selectionPolygon) { 70 super(pApplet); 71 72 this.selectionPolygon = selectionPolygon; 73 if (selectionPolygon != null){ 74 this.addChild(selectionPolygon); 75 } 76 77 for (MTComponent component3D : components) { 78 this.addChild(component3D); 79 } 80 81 this.setName("unnamed Cluster"); 82 } 83 84 85 86 /** 87 * Gets the cluster polygon. 88 * 89 * @return the cluster polygon 90 */ 91 public MTPolygon getClusterPolygon() { 92 return selectionPolygon; 93 } 94 95 /** 96 * Calculates the convex hull of all its children. 97 * Then changes the cluster-polygon to represent that convex hull 98 * and adds it as a child. 99 */ 100 public void packClusterPolygon(){ 101 ArrayList<Vector3D> allClusteredVerts = new ArrayList<Vector3D>(); 102 int shapes = 0; 103 104 //Remove the old clusterpoly 105 MTPolygon clusterPoly = getClusterPolygon(); 106 this.removeChild(clusterPoly); 107 108 MTComponent[] children = this.getChildren(); 109 for (MTComponent component : children) { 110 //Get vertices for convex hull of all selected components 111 if (component instanceof AbstractShape) { 112 shapes++; 113 AbstractShape shape = (AbstractShape) component; 114// Vertex[] verts = shape.getVerticesPickingWorld(); 115 Vector3D[] verts = null; 116 117// if (shape.isBoundingShapeSet()){ 118// verts = shape.getBoundingShape().getVectorsGlobal(); 119// }else{ 120// verts = shape.getVerticesGlobal(); 121// } 122 123 if (shape.hasBounds()) { 124 if (shape.getBounds() instanceof BoundsZPlaneRectangle || shape.getBounds() instanceof BoundsArbitraryPlanarPolygon) { 125 verts = shape.getBounds().getVectorsGlobal(); 126 } else { 127 BoundsZPlaneRectangle b = new BoundsZPlaneRectangle(shape); 128 verts = b.getVectorsGlobal(); 129 } 130 } else { 131 BoundsZPlaneRectangle b = new BoundsZPlaneRectangle(shape); 132 verts = b.getVectorsGlobal(); 133// verts = shape.getVerticesGlobal(); 134 } 135 136 allClusteredVerts.addAll(Arrays.asList(verts)); 137 //for (Vector3D v : verts){ 138 // allClusteredVerts.add(v); 139 //} 140 } 141 } 142 143 if (shapes != 0 && shapes == children.length){ //If all children are of type abstractShape 144 145 ArrayList<Vector3D> hull = ConvexQuickHull2D.getConvexHull2D(allClusteredVerts); 146 if (hull.size() > 0){ 147 //Correctly close polygon with 1.st vertex again 148 hull.add(hull.get(0).getCopy()); 149 150 Vertex[] newVerts = new Vertex[hull.size()]; 151 for (int i = 0; i < hull.size(); i++) { 152 Vector3D vec = hull.get(i); 153 newVerts[i] = new Vertex(vec); 154 } 155 156// Vertex[] newVerts = (Vertex[])hull.toArray(new Vertex[hull.size()]); 157// System.out.println("Hull vertices: "); 158 for (Vertex v : newVerts){ 159 v.setRGBA(100,150,250, 50); 160 } 161 162 clusterPoly.setVertices(newVerts); 163 164 clusterPoly.setBoundsBehaviour(AbstractShape.BOUNDS_DONT_USE); 165// clusterPoly.setBoundingShape(new BoundsArbitraryPlanarPolygon(clusterPoly, clusterPoly.getVerticesLocal())); 166 167 //Reset matrix of the clusterpoly because the new vertices are set at the global location 168 clusterPoly.setLocalMatrix(new Matrix()); 169 170 //FIXME center are is negative if verts are in counterclockwise order? 171// Vector3D clusterCenter = clusterPoly.getCenterPointGlobal(); 172// clusterPoly.scaleGlobal(1.1f, 1.1f, 1, new Vector3D(-1* clusterCenter.x, -1 * clusterCenter.y, clusterCenter.z)); 173 clusterPoly.scale(1.1f, 1.1f, 1, clusterPoly.getCenterPointLocal(), TransformSpace.LOCAL); 174 this.addChild(clusterPoly); 175 }else{ 176 System.err.println("Couldnt pack polygon."); 177 } 178 } 179 } 180 181 /** 182 * overridden to only put the cluster polygon last 183 * in its parent list. 184 */ 185 @Override 186 public void sendToFront() { 187 if (this.getClusterPolygon() != null){ 188 this.getClusterPolygon().sendToFront(); 189 } 190 191 for (int i = 0; i < this.getChildren().length; i++) { 192 MTComponent childComp = this.getChildren()[i]; 193 if (!childComp.equals(this.getClusterPolygon())) 194 childComp.sendToFront(); 195 } 196 } 197 198 @Override 199 public void addChild(int i, MTComponent tangibleComp) { 200 //Overridden, so the component keeps it original parent 201 this.getChildList().add(i, tangibleComp); 202 } 203 204 @Override 205 public void addChild(MTComponent tangibleComp) { 206 this.getChildList().add(tangibleComp); 207 } 208 209 @Override 210 public void addChildren(MTComponent[] tangibleComps) { 211 for (MTComponent object : tangibleComps) { 212 //Add direct objects 213 this.getChildList().add(object); 214 } 215 } 216 217 @Override 218 public void removeAllChildren() { 219 this.getChildList().clear(); 220 } 221 222 @Override 223 public void removeChild(int i) { 224 this.getChildList().remove(i); 225 } 226 227 @Override 228 public void removeChild(MTComponent comp) { 229 this.getChildList().remove(comp); 230 } 231 232 233 //TODO GANZE CLUSTERING ÜBERARBEITEN 234 //SO GIBTS PROBLEME WENN GECLUSTERTE OBJECTE IN VERSCHIEDENEN PARENTS SIND 235 // => DANN WERDEN SIE VERSCHIEDEN TRANSFORMIERT 236 // aM BESTEN ALLE ALS KINDER DES CLUSTERPOLYS MACHEN UND DAS AUF COMPOSITE=TRUE MACHEN 237 // ABER WOHIN GEHEN SIE WENN SIE AUS DEM CLUSTER GELÖST WERDEN? VIELLEICHT GIBTS DIE ALTE GRUPPE NICHT MEHR? 238 // DANN AUF DEN WORLD CANVAS SETZEN; => ABER AN GLEICHER STELLE! 239 240 241 /** 242 * Transforms the shapes local coordinate space by the given matrix. 243 * 244 * @param transformMatrix the transform matrix 245 */ 246 public void transform(Matrix transformMatrix) { 247 for (MTComponent c : this.getChildList()){ 248 c.transform(transformMatrix); 249 } 250 } 251 252 253 public void translateGlobal(Vector3D dirVect) { 254 for (MTComponent c : this.getChildList()){ 255 c.translateGlobal(dirVect); 256 } 257 } 258 259 public void translate(Vector3D dirVect) { 260 for (MTComponent c : this.getChildList()){ 261 c.translate(dirVect); 262 } 263 } 264 265 266 public void rotateXGlobal(Vector3D rotationPoint, float degree) { 267 for (MTComponent c : this.getChildList()){ 268 c.rotateXGlobal(rotationPoint, degree); 269 } 270 } 271 272 public void rotateX(Vector3D rotationPoint, float degree) { 273 for (MTComponent c : this.getChildList()){ 274 c.rotateX(rotationPoint, degree); 275 } 276 } 277 278 279 public void rotateYGlobal(Vector3D rotationPoint, float degree) { 280 for (MTComponent c : this.getChildList()){ 281 c.rotateYGlobal(rotationPoint, degree); 282 } 283 } 284 285 public void rotateY(Vector3D rotationPoint, float degree) { 286 for (MTComponent c : this.getChildList()){ 287 c.rotateY(rotationPoint, degree); 288 } 289 } 290 291 public void rotateZGlobal(Vector3D rotationPoint, float degree) { 292 for (MTComponent c : this.getChildList()){ 293 c.rotateZGlobal(rotationPoint, degree); 294 } 295 } 296 297 298 public void rotateZ(Vector3D rotationPoint, float degree) { 299 for (MTComponent c : this.getChildList()){ 300 c.rotateZ(rotationPoint, degree); 301 } 302 } 303 304 public void scaleGlobal(float factor, Vector3D scaleReferencePoint) { 305 this.scaleGlobal(factor, factor, factor, scaleReferencePoint); 306 } 307 308 /** 309 * scales the polygon around the scalingPoint, currently dosent support scaling around the Z axis. 310 * 311 * @param X the x 312 * @param Y the y 313 * @param Z the z 314 * @param scalingPoint the scaling point 315 */ 316 public void scaleGlobal(float X, float Y, float Z, Vector3D scalingPoint) { 317 for (MTComponent c : this.getChildList()){ 318 c.scaleGlobal(X, Y, Z, scalingPoint); 319 } 320 } 321 322 323 public void scale(float factor, Vector3D scaleReferencePoint) { 324 this.scale(factor, factor, factor, scaleReferencePoint); 325 } 326 327 /** 328 * scales the polygon around the scalingPoint, currently dosent support scaling around the Z axis. 329 * 330 * @param X the x 331 * @param Y the y 332 * @param Z the z 333 * @param scalingPoint the scaling point 334 */ 335 public void scale(float X, float Y, float Z, Vector3D scalingPoint) { 336 for (MTComponent c : this.getChildList()){ 337 c.scale(X, Y, Z, scalingPoint); 338 } 339 } 340}