1 /***
2 * Virtual Mockup for Machine Vision Copyright (C) 2001-2003 Fabio R. de
3 * Miranda, João E. Kogler Jr., Carlos S. Santos. Virtual Mockup for Machine
4 * Vision Project funded by SENAC-SP Permission is granted to redistribute
5 * and/or modify this software under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either version 2.1 of
7 * the License, or (at your option) any later version. This software is
8 * distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
10 * PARTICULAR PURPOSE. See the GNU Lesser General Public License
11 * (http://www.gnu.org/copyleft/lesser.html) for more details.
12 */
13
14 package camera3d;
15 import camera3d.event.*;
16 import com.sun.j3d.utils.picking.PickIntersection;
17 import com.sun.j3d.utils.picking.PickResult;
18 import com.sun.j3d.utils.picking.PickTool;
19
20 import javax.media.j3d.BranchGroup;
21 import javax.media.j3d.Geometry;
22 import javax.media.j3d.Group;
23 import javax.media.j3d.Node;
24 import javax.media.j3d.PickRay;
25 import javax.media.j3d.Shape3D;
26 import javax.media.j3d.TransformGroup;
27 import javax.swing.Icon;
28 import javax.swing.ImageIcon;
29 import javax.vecmath.Point3d;
30 import javax.vecmath.Vector3d;
31
32 /***
33 * Object used to measure distances in the virtual world. A DistanceMeasurer is
34 * composed of two main parts: the origin point and the target.
35 *
36 *@author Fábio Roberto de Miranda, Carlos da Silva dos Santos
37 *@created October 22, 2003
38 */
39 public class DistanceMeasurer extends VcHelper {
40
41 private static int instanceCounter;
42
43 private Icon measurerIcon = new ImageIcon(this.getClass().getResource("icons/measurer_item.gif"));
44
45 private boolean debugflag = true;
46
47 /***
48 * Tells whether the target is bound to the origin point.
49 */
50 private boolean bound = false;
51
52 /*
53 * Most important class to the picking action.
54 */
55 private PickTool pickTool;
56 /*
57 * Geometry used to tell which objects were picked. Objects which intersect
58 * pickRay are picked.
59 */
60 private PickRay pickRay;
61
62 /*
63 * Para fins de resultado - informação sobre onde ocorreu o picking
64 */
65 private PickIntersection pickIntersection;
66 /*
67 * Holds results from the picking operation.
68 */
69 private PickResult[] pickResult;
70
71 /*
72 * Holds direction of picking operation.
73 */
74 private Vector3d direction = new Vector3d();
75
76 /*
77 * Origin point of picking ray
78 */
79 private Point3d origin = new Point3d();
80
81 /*
82 *
83 */
84 private Point3d pickedPoint;
85
86 /***
87 * BranchGroup used to determine which objects can be picked
88 */
89 private BranchGroup contentBG;
90
91 /***
92 * Used to retrieve a reference to the BranchGroup which determines the
93 * scope of picking.
94 */
95 private J3DBase base;
96
97 private double distance;
98
99 /*
100 * to avoid multiple allocations
101 */
102 private Point3d tempP3d = new Point3d();
103
104 /*
105 * a gizmo shown at the origin point position.
106 */
107 private Cursor3D cursor3d = new Cursor3D();
108
109 /*
110 *
111 */
112 private VcHelperPoint target = new VcHelperPoint();
113
114 /*
115 * gizmo shown at the target point position
116 */
117 private Node targetNode;
118
119 /***
120 * Flag that signals whether the target cursor has already been added to
121 * the scenegraph. Used to prevent double addition, which would cause an
122 * exception
123 */
124 private boolean addedTargetCursor = false;
125
126 /*
127 * Objects used for placement of the target.
128 */
129 private BranchGroup targetBG = new BranchGroup();
130 private TransformGroup targetTG = new TransformGroup();
131
132
133 /***
134 * Constructor for the DistanceMeasurer object
135 */
136 public DistanceMeasurer() {
137 super();
138 this.setLabel("distance" + (DistanceMeasurer.instanceCounter++));
139
140 pickRay = new PickRay();
141 /*
142 * Making bg pickable is desirable because it will allow DistanceMeasurer to
143 * be selected with the mouse. On the other hand, that creates the problem of
144 * the origin point being picked during measurement operations.
145 */
146 //this.bg.setPickable(false);
147 this.bg.setPickable(true);
148 //this.bg.clearCapability(Node.ENABLE_PICK_REPORTING);
149 this.bg.setCapability(Node.ENABLE_PICK_REPORTING);
150
151 this.addNode(cursor3d);
152
153 targetTG.setCapability(Group.ALLOW_CHILDREN_READ);
154 targetTG.setCapability(Group.ALLOW_CHILDREN_EXTEND);
155 targetTG.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
156 targetTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
157
158 Cursor3D tempCursor = new Cursor3D();
159 tempCursor.setColor((byte) 255, (byte) 0, (byte) 0);
160 tempCursor.setLineWidth(1.0f);
161 tempCursor.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
162 tempCursor.setCapability(Shape3D.ALLOW_PICKABLE_READ);
163 tempCursor.setCapability(Shape3D.ALLOW_PICKABLE_WRITE);
164 tempCursor.setCapability(Shape3D.ENABLE_PICK_REPORTING);
165 tempCursor.getGeometry().setCapability(Geometry.ALLOW_INTERSECT);
166
167 target.addNode(tempCursor);
168 target.bg.setPickable(false);
169 targetNode = (Node) tempCursor;
170 // target is unbound
171 this.bg.addChild(target.getBranchGroup());
172 cursor3d.setLineWidth(2.0f);
173 cursor3d.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
174 cursor3d.setCapability(Shape3D.ALLOW_PICKABLE_READ);
175 cursor3d.setCapability(Shape3D.ALLOW_PICKABLE_WRITE);
176 cursor3d.setCapability(Shape3D.ENABLE_PICK_REPORTING);
177 cursor3d.getGeometry().setCapability(Geometry.ALLOW_INTERSECT);
178
179 }
180
181
182 /***
183 * Returns the number of objects instatiated so far.
184 *
185 *@return The instanceCounter value
186 */
187 public static int getInstanceCounter() {
188 return instanceCounter;
189 }
190
191
192 /***
193 * The main program for the DistanceMeasurer class
194 *
195 *@param args The command line arguments
196 */
197 public static void main(String[] args) {
198 DistanceMeasurer distanceMeasurer1 = new DistanceMeasurer();
199 }
200
201
202 // Talvez no futuro implementar um método que o posiciona perto de um objeto a
203 // uma certa distancia de seus Bounding Points, etc
204
205 /***
206 * Sets the j3DBase attribute of the DistanceMeasurer object
207 *
208 *@param base The new j3DBase value
209 */
210 public final void setJ3DBase(J3DBase base) {
211 this.base = base;
212 this.setBranchGroup(base.getJ3DRootBranchGroup());
213 }
214
215
216 /***
217 * Sets BranchGroup which determines the scope of picking. Only objects
218 * that are under bg can be picked during the measurement process.
219 *
220 *@param bg The new branchGroup value
221 */
222 public void setBranchGroup(BranchGroup bg) {
223 this.contentBG = bg;
224 pickTool = new PickTool(bg);
225 }
226
227
228 /***
229 * Sets the direction for measurement.
230 *
231 *@param direction The new direction value
232 */
233 public void setDirection(Vector3d direction) {
234 this.direction.set(direction);
235 }
236
237
238 /***
239 * Sets the direction for measurement so it corresponds to the current
240 * position of the target object.
241 */
242 public void setToTarget() {
243 // gets translation component from target
244 //target.pivotTG.getChild(0).getLocalToVworld(tempT3D);
245 targetNode.getLocalToVworld(tempT3D);
246 tempT3D.get(tempVec3d);
247 // sets direction to target traslation
248 this.direction.set(tempVec3d);
249 // gets translation component from measurer's base
250 cursor3d.getLocalToVworld(tempT3D);
251 tempT3D.get(tempVec3d);
252 // subtracts measurer's translation from target's
253 this.direction.sub(tempVec3d);
254 this.direction.normalize();
255 }
256
257
258 /*
259 * Os próximos métodos apontam a direção do picking para alguma direção canonica
260 */
261 /***
262 * Sets the negativeZ attribute of the DistanceMeasurer object
263 */
264 public void setNegativeZ() {
265 this.direction.set(0.0, 0.0, -1.0);
266 setTargetPositionRelative(new Point3d(0.0, 0.0, -1.0));
267 //this.setToTarget();
268 debugln("Direction set to -Z");
269 }
270
271
272 /***
273 * Sets the positiveZ attribute of the DistanceMeasurer object
274 */
275 public void setPositiveZ() {
276 this.direction.set(0.0, 0.0, 1.0);
277 setTargetPositionRelative(new Point3d(0.0, 0.0, 1.0));
278 //this.setToTarget();
279 debugln("Direction set to Z");
280 }
281
282
283 /***
284 * Sets the positiveX attribute of the DistanceMeasurer object
285 */
286 public void setPositiveX() {
287 this.direction.set(1.0, 0.0, 0.0);
288 setTargetPositionRelative(new Point3d(1.0, 0.0, 0.0));
289 //this.setToTarget();
290 debugln("Direction set to X");
291 }
292
293
294 /***
295 * Sets the negativeX attribute of the DistanceMeasurer object
296 */
297 public void setNegativeX() {
298 this.direction.set(-1.0, 0.0, 0.0);
299 setTargetPositionRelative(new Point3d(-1.0, 0.0, 0.0));
300 //this.setToTarget();
301 debugln("Direction set to -X");
302 }
303
304
305 /***
306 * Sets the positiveY attribute of the DistanceMeasurer object
307 */
308 public void setPositiveY() {
309 this.direction.set(0.0, 1.0, 0.0);
310 setTargetPositionRelative(new Point3d(0.0, 1.0, 0.0));
311 //this.setToTarget();
312 debugln("Direction set to Y");
313 }
314
315
316 /***
317 * Sets the negativeY attribute of the DistanceMeasurer object
318 */
319 public void setNegativeY() {
320 this.direction.set(0.0, -1.0, 0.0);
321 setTargetPositionRelative(new Point3d(0.0, -1.0, 0.0));
322 //this.setToTarget();
323 debugln("Direction set to -Y");
324 }
325
326
327
328 /***
329 * O ponto de origem (em coordenadas de VWorld) é obtido Simplesmente
330 * convertendo as coordenadas do ponto (0,0,0), que está no mesmo
331 * referencial que o gizmo que indica a origem do medidor para coordenadas
332 * de VWorld
333 */
334 protected void setOrigin() {
335 tempP3d.x = 0.0;
336 tempP3d.y = 0.0;
337 tempP3d.z = 0.0;
338 // Atenção para o método getTransformS
339 // ^
340
341 this.getTransforms(tempT3D);
342 tempT3D.transform(tempP3d);
343 debugln("Origin point is " + tempP3d.x + "," + tempP3d.y + "," + tempP3d.z);
344 origin.set(tempP3d);
345 }
346
347
348 /***
349 * Sets whether the target object should move in companion to the origin
350 * point.
351 *
352 *@param bound The new bound value
353 */
354 public void setBound(boolean bound) {
355 // VWtoTarget = VWtoOrigin*localTransform
356 if(bound && !this.bound) {
357 // bind: target becomes a VcChild
358 // localTransform = inv(VWtoOrigin)*VWtoTarget
359 //VWtoOrigin
360 cursor3d.getLocalToVworld(tempT3D);
361 //inv(VWtoOrigin)
362 tempT3D.invert();
363 // VWtoTarget
364 target.getTransforms(auxT3D);
365 // inv(VWtoOrigin)*VWtoTarget
366 tempT3D.mul(auxT3D);
367 target.detach();
368 target.setTransform(tempT3D);
369 this.parentRotScaleTG.addChild(target.getBranchGroup());
370 //this.childTG.addChild(target.getBranchGroup());
371 }
372 if(!bound && this.bound) {
373 // unbind: target becomes child of this.bg
374 // VWtoTarget = VWtoOrigin*localTransform
375 // VWtoOrigin
376 cursor3d.getLocalToVworld(tempT3D);
377 // localTransform
378 target.getTransforms(auxT3D);
379 // VWtoOrigin*localTransform
380 tempT3D.mul(auxT3D);
381 target.detach();
382 target.setTransform(tempT3D);
383 this.bg.addChild(target.getBranchGroup());
384 }
385 this.bound = bound;
386 target.notifyChangeListeners();
387 }
388
389
390 /***
391 * Sets the targetPosition attribute of the DistanceMeasurer object
392 *
393 *@param point The new targetPosition value
394 */
395 protected void setTargetPosition(Point3d point) {
396
397 }
398
399
400 /***
401 * Sets the targetPositionRelative attribute of the DistanceMeasurer object
402 *
403 *@param point The new targetPositionRelative value
404 */
405 protected void setTargetPositionRelative(Point3d point) {
406 Point3d pointOut = new Point3d();
407 if(!this.bound) {
408 this.getTransforms(tempT3D);
409 tempT3D.transform(point, pointOut);
410 tempVec3d.set(pointOut);
411
412 } else {
413 tempVec3d.set(point);
414 }
415 tempT3D.set(tempVec3d);
416 target.setTransform(tempT3D);
417 debugln("setTargetPositionRelative: notifyChangeListeners");
418 target.notifyChangeListeners();
419 }
420
421
422 /***
423 * Sets measurement mode.
424 *
425 *@param direction If positive, measurement will be
426 * performed in positive direction of axis. If negative, measurement
427 * will be performed in negative direction of axis.
428 *@param axis Axis that defines direction of
429 * measurement.
430 *@throws IllegalArgumentException if axis is not really an axis (X,Y or
431 * Z).
432 */
433 public void setMode(int direction, TransformScope axis) {
434 if(!axis.isAxis()) {
435 throw new IllegalArgumentException("Transform scope is not an axis.");
436 }
437 if(axis == TransformScope.X) {
438 if(direction > 0) {
439 setPositiveX();
440 } else {
441 setNegativeX();
442 }
443 }
444 if(axis == TransformScope.Y) {
445 if(direction > 0) {
446 setPositiveY();
447 } else {
448 setNegativeY();
449 }
450 }
451 if(axis == TransformScope.Z) {
452 if(direction > 0) {
453 setPositiveZ();
454 } else {
455 setNegativeZ();
456 }
457 }
458 }
459
460
461 /***
462 * Sets the Icon associated with DistanceMeasurer.
463 *
464 *@param measurerIcon The new icon value
465 */
466 public void setIcon(Icon measurerIcon) {
467 this.measurerIcon = measurerIcon;
468 }
469
470
471 /***
472 * Gets the target attribute of the DistanceMeasurer object
473 *
474 *@return The target value
475 */
476 public VcHelperPoint getTarget() {
477 return this.target;
478 }
479
480
481 /***
482 * Gets the distance attribute of the DistanceMeasurer object
483 *
484 *@return The distance value
485 */
486 public double getDistance() {
487 //measureDistance();
488 return this.distance;
489 }
490
491
492 /***
493 * Returns a flag indicating whether the target movement is bound to the
494 * origin object.
495 *
496 *@return The bound value
497 */
498 public boolean isBound() {
499 return this.bound;
500 }
501
502
503 /***
504 * Returns the Icon associated with DistanceMeasurer.
505 *
506 *@return The icon value
507 */
508 public Icon getIcon() {
509 return this.measurerIcon;
510 }
511
512
513 /***
514 * Makes the measurement. The target object is placed on the hitting place.
515 * The value of the distance can then be retrieved by calling getDistance.
516 */
517 public void measureDistance() {
518 //boolean oldBound = this.bound;
519 //setBound(false);
520 setToTarget();
521 // Faz o picking
522 setOrigin();
523 pickRay.set(origin, direction);
524 pickTool.setShape(pickRay, origin);
525 pickTool.setMode(PickTool.GEOMETRY);
526 /*
527 * O critério de sorting do pickAllSorted é distância
528 */
529 pickResult = pickTool.pickAllSorted();
530 if(pickResult != null) {
531 debugln(pickResult.length + " objects picked");
532
533 // Descobre o objeto
534 if(pickResult.length > 0) {
535
536 PickResult hitResult = this.checkResults(pickResult);
537 if(hitResult == null) {
538 distance = -1.0;
539 return;
540 }
541 // Descobre qual é o ponto mais próximo da origem deste pickRay
542 pickIntersection = hitResult.getClosestIntersection(origin);
543 pickedPoint = pickIntersection.getPointCoordinatesVW();
544 showPicked(pickedPoint);
545 // Calcula a distância. A origin deve estar em coordenadas do
546 // virtual world
547 distance = origin.distance(pickedPoint);
548 debugln("new computed distance is:" + distance);
549 } else {
550 debugln("Length of pickResults vector was zero");
551 }
552 // Avisa interessados na distância ou a retorna?
553
554 // Desenha uma linha para mostrar a operação executada?
555 } else {
556 debugln("Null returned as result of picking.");
557 }
558 //setBound(oldBound);
559 this.currentEvent = this.genericEvent;
560 genericEvent.setType(VcObjectEvent.DISTANCE_MEASURER_CHANGED);
561 notifyChangeListeners();
562 }
563
564
565 /***
566 * Checks a PickResult vector to see if this measurer picked itself.
567 * Returns the first object from prVec that is different from this
568 * measurer's origin point or its target; returns null if just the origin
569 * point or the target were picked.
570 *
571 *@param prVec Description of the Parameter
572 *@return Description of the Return Value
573 */
574 PickResult checkResults(PickResult[] prVec) {
575 //if(prVec.length<1) return null;
576 BranchGroup bGroup;
577 Object obj;
578 VcObject vc;
579 for(int i = 0; i < prVec.length; i++) {
580 bGroup = (BranchGroup) (prVec[i]).getNode(PickResult.BRANCH_GROUP);
581 obj = (Object) bGroup.getUserData();
582 if(obj instanceof VcObject) {
583 if(!((obj == this) || (obj == this.target))) {
584 return prVec[i];
585 }
586 } else {
587 return prVec[i];
588 }
589 }
590 return null;
591 }
592
593
594 /***
595 * Coloca um gizmo no ponto especificado (que deve ser onde o raio de
596 * picking bateu)
597 *
598 *@param point Description of the Parameter
599 */
600 protected void showPicked(Point3d point) {
601 tempT3D.setIdentity();
602 /*
603 * Coloca as coordenadas do ponto num vetor, que passará a apontar
604 * da origem para o ponto
605 */
606 tempVec3d.set(point);
607 /*
608 * Ajusta a translação da transformada para um valor igual ao do vetor
609 */
610 tempT3D.set(tempVec3d);
611 if(!this.bound) {
612 target.setTransform(tempT3D);
613 } else {
614 cursor3d.getLocalToVworld(auxT3D);
615 auxT3D.invert();
616 auxT3D.mul(tempT3D);
617 target.setTransform(auxT3D);
618 }
619 target.notifyChangeListeners();
620 debugln("showPicked: notifyChangeListeners");
621 }
622
623 }
This page was automatically generated by Maven