PageRenderTime 37ms CodeModel.GetById 8ms app.highlight 24ms RepoModel.GetById 1ms app.codeStats 0ms

/src/org/mt4j/components/clusters/Cluster.java

http://mt4j.googlecode.com/
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}