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