001: /*
002: * $RCSfile: PickCanvas.java,v $
003: *
004: * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * - Redistribution of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * - Redistribution in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * Neither the name of Sun Microsystems, Inc. or the names of
019: * contributors may be used to endorse or promote products derived
020: * from this software without specific prior written permission.
021: *
022: * This software is provided "AS IS," without a warranty of any
023: * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
024: * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
025: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
026: * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
027: * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
028: * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
029: * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
030: * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
031: * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
032: * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
033: * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
034: * POSSIBILITY OF SUCH DAMAGES.
035: *
036: * You acknowledge that this software is not designed, licensed or
037: * intended for use in the design, construction, operation or
038: * maintenance of any nuclear facility.
039: *
040: * $Revision: 1.5 $
041: * $Date: 2007/02/09 17:20:24 $
042: * $State: Exp $
043: */
044:
045: package com.sun.j3d.utils.pickfast;
046:
047: import java.awt.event.*;
048: import javax.vecmath.*;
049: import javax.media.j3d.*;
050: import com.sun.j3d.utils.geometry.*; // Cone, Cylinder
051:
052: /**
053: * A subclass of PickTool, simplifies picking using mouse events from a canvas.
054: * This class allows picking using canvas x,y locations by generating the
055: * appropriate pick shape.
056: * <p>
057: * The pick tolerance specifies the distance from the
058: * pick center to include in the pick shape. A tolerance of 0.0 may speedup
059: * picking slightly, but also make it very difficult to pick points and lines.
060: * <p>
061: * The pick canvas can be used to make a series of picks. For example, to
062: * initialize the pick canvas:
063: * <blockquote><pre>
064: * PickCanvas pickCanvas = new PickCanvas(canvas, scene);
065: * pickCanvas.setMode(PickInfo.PICK_GEOMETRY);
066: * pickCanvas.setFlags(PickInfo.NODE | PickInfo.CLOSEST_INTERSECTION_POINT);
067: * pickCanvas.setTolerance(4.0f);
068: * </pre></blockquote>
069: * <p>
070: * Then for each mouse event:
071: * <blockquote><pre>
072: * pickCanvas.setShapeLocation(mouseEvent);
073: * PickInfo[] pickInfos = pickCanvas.pickAll();
074: * </pre></blockquote>
075: * <p>
076: * NOTE: For the pickAllSorted or pickClosest methods, the picks will be sorted
077: * by the distance from the ViewPlatform to the intersection point.
078: * @see PickTool
079: */
080: public class PickCanvas extends PickTool {
081:
082: /* OPEN ISSUES:
083: -- Should restrict the pick shape to the front/back clip plane
084: */
085:
086: /** The canvas we are picking into */
087: Canvas3D canvas;
088:
089: /* the pick tolerance, default to 2.0 */
090: float tolerance = 2.0f;
091: int save_xpos;
092: int save_ypos;
093:
094: /** Constructor with Canvas3D for mouse events and BranchGroup to be picked.
095: */
096: public PickCanvas(Canvas3D c, BranchGroup b) {
097: super (b);
098: canvas = c;
099: }
100:
101: /** Constructor with Canvas3D for mouse events and Locale to be picked.
102: */
103: public PickCanvas(Canvas3D c, Locale l) {
104: super (l);
105: canvas = c;
106: }
107:
108: /** Inquire the canvas to be used for picking operations.
109: @return the canvas.
110: */
111: public Canvas3D getCanvas() {
112: return canvas;
113: }
114:
115: /** Set the picking tolerance. Objects within this distance
116: * (in pixels)
117: * to the mouse x,y location will be picked. The default tolerance is 2.0.
118: * @param t The tolerance
119: * @exception IllegalArgumentException if the tolerance is less than 0.
120: */
121: public void setTolerance(float t) {
122: if (t < 0.0f) {
123: throw new IllegalArgumentException();
124: }
125: tolerance = t;
126:
127: if ((pickShape != null) && (!userDefineShape)) {
128: // reset pickShape
129: pickShape = null;
130: setShapeLocation(save_xpos, save_ypos);
131: }
132: }
133:
134: /** Get the pick tolerance.
135: */
136: public float getTolerance() {
137: return tolerance;
138: }
139:
140: /** Set the pick location. Defines the location on the canvas where the
141: pick is to be performed.
142: @param mevent The MouseEvent for the picking point
143: */
144: public void setShapeLocation(MouseEvent mevent) {
145: setShapeLocation(mevent.getX(), mevent.getY());
146: }
147:
148: /** Set the pick location. Defines the location on the canvas where the
149: pick is to be performed (upper left corner of canvas is 0,0).
150: @param xpos the X position of the picking point
151: @param ypos the Y position of the picking point
152: */
153: public void setShapeLocation(int xpos, int ypos) {
154: Transform3D motion = new Transform3D();
155: Point3d eyePosn = new Point3d();
156: Point3d mousePosn = new Point3d();
157: Vector3d mouseVec = new Vector3d();
158: boolean isParallel = false;
159: double radius = 0.0;
160: double spreadAngle = 0.0;
161:
162: this .save_xpos = xpos;
163: this .save_ypos = ypos;
164: canvas.getCenterEyeInImagePlate(eyePosn);
165: canvas.getPixelLocationInImagePlate(xpos, ypos, mousePosn);
166:
167: if ((canvas.getView() != null)
168: && (canvas.getView().getProjectionPolicy() == View.PARALLEL_PROJECTION)) {
169: // Correct for the parallel projection: keep the eye's z
170: // coordinate, but make x,y be the same as the mouse, this
171: // simulates the eye being at "infinity"
172: eyePosn.x = mousePosn.x;
173: eyePosn.y = mousePosn.y;
174: isParallel = true;
175: }
176:
177: // Calculate radius for PickCylinderRay and spread angle for PickConeRay
178: Vector3d eyeToCanvas = new Vector3d();
179: eyeToCanvas.sub(mousePosn, eyePosn);
180: double distanceEyeToCanvas = eyeToCanvas.length();
181:
182: Point3d deltaImgPlate = new Point3d();
183: canvas.getPixelLocationInImagePlate(xpos + 1, ypos,
184: deltaImgPlate);
185:
186: Vector3d ptToDelta = new Vector3d();
187: ptToDelta.sub(mousePosn, deltaImgPlate);
188: double distancePtToDelta = ptToDelta.length();
189: distancePtToDelta *= tolerance;
190:
191: canvas.getImagePlateToVworld(motion);
192:
193: /*
194: System.out.println("mouse position " + xpos + " " + ypos);
195: System.out.println("before, mouse " + mousePosn + " eye " + eyePosn);
196: */
197:
198: motion.transform(eyePosn);
199: start = new Point3d(eyePosn); // store the eye position
200: motion.transform(mousePosn);
201: mouseVec.sub(mousePosn, eyePosn);
202: mouseVec.normalize();
203:
204: /*
205: System.out.println(motion + "\n");
206: System.out.println("after, mouse " + mousePosn + " eye " + eyePosn +
207: " mouseVec " + mouseVec);
208: */
209:
210: if (tolerance == 0.0) {
211: if ((pickShape != null) && (pickShape instanceof PickRay)) {
212: ((PickRay) pickShape).set(eyePosn, mouseVec);
213: } else {
214: pickShape = (PickShape) new PickRay(eyePosn, mouseVec);
215: }
216: // pickShape = (PickShape) new PickConeRay (eyePosn,
217: // mouseVec,1.0*Math.PI/180.0);
218: } else {
219: if (isParallel) {
220: // Parallel projection, use a PickCylinderRay
221: distancePtToDelta *= motion.getScale();
222: if ((pickShape != null)
223: && (pickShape instanceof PickCylinderRay)) {
224: ((PickCylinderRay) pickShape).set(eyePosn,
225: mouseVec, distancePtToDelta);
226: } else {
227: pickShape = (PickShape) new PickCylinderRay(
228: eyePosn, mouseVec, distancePtToDelta);
229: }
230: } else {
231: // Perspective projection, use a PickConeRay
232:
233: // Calculate spread angle
234: spreadAngle = Math.atan(distancePtToDelta
235: / distanceEyeToCanvas);
236:
237: if ((pickShape != null)
238: && (pickShape instanceof PickConeRay)) {
239: ((PickConeRay) pickShape).set(eyePosn, mouseVec,
240: spreadAngle);
241: } else {
242: pickShape = (PickShape) new PickConeRay(eyePosn,
243: mouseVec, spreadAngle);
244: }
245: }
246: }
247: }
248: } // PickCanvas
|