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