View Javadoc
1 /***************************************************************************** 2 * Virtual Mockup for Machine Vision 3 * Copyright (C) 2001-2003 Fabio R. de Miranda, João E. Kogler Jr., 4 * Carlos S. Santos. 5 * Virtual Mockup for Machine Vision Project funded by SENAC-SP 6 * 7 * Permission is granted to redistribute and/or modify this 8 * software under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This software is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License (http://www.gnu.org/copyleft/lesser.html) 16 * for more details. 17 * 18 *****************************************************************************/ 19 20 package camera3d; 21 22 /*** 23 * Title: Câmera Virtual - LIVES 24 * Description: Câmera Virtual para Controle via LabVIEW 25 * Copyright: Copyright (c) 2001 26 * Company: Centro de Educação em Informática - SENAC - SP 27 */ 28 29 import javax.media.j3d.*; 30 import javax.vecmath.*; 31 import java.util.Enumeration; 32 33 /*** 34 * Utility class for computing BoundingBox dimensions and geometry of VcObjects.<p> 35 * The methods provided here for computing bounding box dimensions are quite particular 36 * to VcObjects and are not garanteed to work with other kind of objects (even though 37 * from the method signatures one could suppose that they ara more general).<br> 38 * 39 * @author Fábio Roberto de Miranda, Carlos da Silva dos Santos 40 * @version 1.0 41 */ 42 class GeometryUtility { 43 44 /* 45 The methods that compute bounding boxes's coordinates rely heavily in the way 46 that VcContent objects are currently created (as of 22/07/2003). 47 48 When a VcContent object is created from some VRML file, the branch graph that 49 contains the shapes may also contain TransformGroups. Therefore, in order to 50 generate the correct coordinates of the bounding box these additional 51 transformations must be taken into account. Thus we demand the input nodes (whose 52 bounding box will be computed) to be live, so we can retrieve their local to vworld 53 transformation and apply it to the geometry vertex coordinate. The caveat is that 54 local to vworld transform also includes the VcContent's internal graph transforms: 55 parentTransTG, parentRotScaleTG and pivotTG. The bounding box will be subsequently 56 attached under parentRotScaleTG-- which means that the internal transformations 57 will affect twice the calculated bounding box. 58 The methods here work because (currently) at the time a VcContent object is added to 59 the application, its internal transforms are always equal to identity. 60 61 A more general scheme would be traversing the scene graph and keeping track of the 62 transforms (probably inside a stack structure) till a Shape3D is found. Then the 63 bounding box could be calculated for each geometry and tranformed by the accumulated 64 transforms. 65 66 */ 67 private static boolean firstMesh = true; 68 private static Point3d lowerP3d = new Point3d(); 69 private static Point3d upperP3d = new Point3d(); 70 private static Transform3D tempT3D = new Transform3D(); 71 72 public GeometryUtility() { 73 74 } 75 76 /*** 77 * Computes dimensions of a BoundingBox that contains all Geometries owned by 78 * a certain Shape3D. The input shape must be live, as the method utilizes the 79 * Shape3D.getLocalToVWorld method. 80 * @param shape Shape3D the BoundingBox will be computed for. 81 * @param box BoundingBox which will receive computed dimensions. 82 * @throws IllegalArgumentException if shape is not live. 83 */ 84 public static void computeBoundingBox(Shape3D shape, BoundingBox box){ 85 if(!shape.isLive()){ 86 throw new IllegalArgumentException("Cannot compute BoundingBox for non-live Shape3D"); 87 //System.out.println("Cannot compute BoundingBox for non-live Shape3D"); 88 //return; 89 } 90 firstMesh = true; 91 lowerP3d.set(0.0,0.0,0.0); 92 upperP3d.set(1.0,1.0,1.0); 93 recursivelyComputeBoundingBox((Node)shape); 94 if(box!=null){ 95 box.setLower(lowerP3d); 96 box.setUpper(upperP3d); 97 } 98 } 99 100 /*** 101 * Computes dimensions of a BoundingBox that contains all Geometries owned by 102 * a certain Group. The input group must be live, as the method utilizes the 103 * Group.getLocalToVWorld method. 104 * @param group Group object the BoundingBox will be computed for. 105 * @param box BoundingBox which will receive computed dimensions. 106 * @throws IllegalArgumentException if group is not live. 107 */ 108 public static void computeBoundingBox(Group group, BoundingBox box){ 109 if(!group.isLive()){ 110 throw new IllegalArgumentException("Cannot compute BoundingBox for non-live Group"); 111 //System.out.println("Cannot compute BoundingBox for non-live Group"); 112 //return; 113 } 114 Enumeration enum = null; 115 try { 116 enum = group.getAllChildren(); 117 } catch (CapabilityNotSetException cns){ 118 System.out.println("Capability error at group"); 119 cns.printStackTrace(); 120 } 121 firstMesh=true; 122 lowerP3d.set(0.0,0.0,0.0); 123 upperP3d.set(1.0,1.0,1.0); 124 125 while (enum.hasMoreElements()){ 126 recursivelyComputeBoundingBox((Node)enum.nextElement()); 127 } 128 129 box.setLower(lowerP3d); 130 box.setUpper(upperP3d); 131 } 132 133 /*** 134 * Creates a Shape3D containing geometry that represents a BoundingBox. 135 * @param box BoundingBox whose dimensions will be used to define Geoemtry. 136 * @param boxShape Shape3D that will receive Box Geometry 137 * @param color Color to be used by Geometry 138 */ 139 public static void createBoxGeometry(BoundingBox box, Shape3D boxShape, Color3f color){ 140 box.getLower(lowerP3d); 141 box.getUpper(upperP3d); 142 143 double[][] coordinates = new double[][]{ 144 {lowerP3d.x, lowerP3d.y, lowerP3d.z}, //0-1 145 {lowerP3d.x, lowerP3d.y, upperP3d.z}, 146 {lowerP3d.x, lowerP3d.y, lowerP3d.z}, //0-2 147 {lowerP3d.x, upperP3d.y, lowerP3d.z}, 148 {lowerP3d.x, lowerP3d.y, lowerP3d.z}, //0-3 149 {upperP3d.x, lowerP3d.y, lowerP3d.z}, 150 {upperP3d.x, upperP3d.y, upperP3d.z}, //4-5 151 {upperP3d.x, upperP3d.y, lowerP3d.z}, 152 {upperP3d.x, upperP3d.y, upperP3d.z}, //4-6 153 {upperP3d.x, lowerP3d.y, upperP3d.z}, 154 {upperP3d.x, upperP3d.y, upperP3d.z}, //4-7 155 {lowerP3d.x, upperP3d.y, upperP3d.z}, 156 {lowerP3d.x, upperP3d.y, lowerP3d.z}, //2-5 157 {upperP3d.x, upperP3d.y, lowerP3d.z}, 158 {lowerP3d.x, lowerP3d.y, upperP3d.z}, //1-7 159 {lowerP3d.x, upperP3d.y, upperP3d.z}, 160 {upperP3d.x, lowerP3d.y, upperP3d.z}, //6-3 161 {upperP3d.x, lowerP3d.y, lowerP3d.z}, 162 {upperP3d.x, lowerP3d.y, upperP3d.z}, //6-1 163 {lowerP3d.x, lowerP3d.y, upperP3d.z}, 164 {upperP3d.x, upperP3d.y, lowerP3d.z}, //5-3 165 {upperP3d.x, lowerP3d.y, lowerP3d.z}, 166 {lowerP3d.x, upperP3d.y, upperP3d.z}, //7-2 167 {lowerP3d.x, upperP3d.y, lowerP3d.z}, 168 }; 169 170 LineArray lineArray = new LineArray( 24, LineArray.COORDINATES| LineArray.COLOR_3); 171 172 for (int i=0; i<coordinates.length; i++){ 173 lineArray.setCoordinate(i, coordinates[i]); 174 lineArray.setColor(i, color); 175 } 176 lineArray.setCapability(Geometry.ALLOW_INTERSECT); 177 boxShape.setGeometry(lineArray); 178 Appearance boxAppearance = new Appearance(); 179 PolygonAttributes polygonAttributes = new PolygonAttributes(PolygonAttributes.POLYGON_LINE, PolygonAttributes.CULL_NONE, 0.0f); 180 boxAppearance.setPolygonAttributes(polygonAttributes); 181 boxShape.setAppearance(boxAppearance); 182 } 183 184 185 186 private static void recursivelyComputeBoundingBox(Node node){ 187 //debugln("VcObject:recursing to compute BB"); 188 Point3d tempP3d = new Point3d(); 189 if (node instanceof Group ) { 190 Enumeration enum = null; 191 try { 192 enum = ((Group)node).getAllChildren(); 193 } catch (CapabilityNotSetException cns){ 194 System.out.println("Capability error at Node"); 195 cns.printStackTrace(); 196 } 197 while (enum.hasMoreElements()){ 198 recursivelyComputeBoundingBox((Node)enum.nextElement()); 199 } 200 } else if (node instanceof Link){ 201 // this will not work as shared graphs cannot call getLocalToVworld 202 // recursivelyComputeBoundingBox(((Link)node).getSharedGroup()); 203 } else if (node instanceof Shape3D) { 204 // Extract Geometry information from Shape3D 205 Shape3D shape = (Shape3D)node; 206 Geometry geom = shape.getGeometry(); 207 if (geom!=null){ 208 shape.getLocalToVworld(tempT3D); 209 if (geom instanceof GeometryArray) { 210 GeometryArray gArray = (GeometryArray)geom; 211 int vertexCount = gArray.getVertexCount(); 212 //rVertexCount += vertexCount; 213 /* the "coordinates" array must hold 3 times every geometryArray coordinates 214 * if it's not capable of doing that, it must then be resized, here it's resized 215 * to the double of known needed size (6* vertexCount instead of 3*vertexCount) 216 * to avoid resizing it more very often 217 */ 218 219 for ( int i=0; i< vertexCount; i++ ) { 220 gArray.getCoordinate(i, tempP3d); 221 tempT3D.transform(tempP3d); 222 if ((i==0)&&(firstMesh)){ 223 lowerP3d.set(tempP3d); 224 upperP3d.set(tempP3d); 225 firstMesh = false; 226 } 227 compareAndSet(lowerP3d, upperP3d, tempP3d); 228 } 229 } 230 231 } 232 } 233 } 234 235 /* 236 * 237 */ 238 private static void compareAndSet(Point3d lower, Point3d upper, Point3d point){ 239 if (point.x < lower.x){ 240 lower.x = point.x; 241 } else if (point.x > upper.x) { 242 upper.x = point.x; 243 } 244 245 if (point.y < lower.y) { 246 lower.y = point.y; 247 } else if (point.y > upper.y) { 248 upper.y = point.y; 249 } 250 251 if (point.z < lower.z) { 252 lower.z = point.z; 253 } else if ( point.z > upper.z) { 254 upper.z = point.z; 255 } 256 } 257 258 259 260 public static void main(String[] args) { 261 GeometryUtility geometryUtility1 = new GeometryUtility(); 262 } 263 264 }

This page was automatically generated by Maven