View Javadoc
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