Hi, I have problems picking multiple points from a PointArray.
The scenario is as follows: The scene graph has a PointArray inside a Shape3D. The user needs to "draw" a rectangle on the screen by clicking on the starting point, dragging through a region and clicking on the final point. After this, I need to find all the points in the PointArray which lies in this rectangular region. |---------------------| | 1 * 4 * | | | |---------------------| 2 * 3 * As depicted above, the PointArray has four points and the dotted line is the rectangle that the user draws on the screen. Under this scenario points 1 and 4 need to be selected. I have been able to pick individual points using PickRays and PickConeRays. But I am at a loss to understand how to pick ALL the points that fall in the bounds of the rectangle. Any ideas on how to get this working? Have attached two files with code that i have been trying out with. For picking a single point, use of PickRay seems a bit random. However a PickConeRay seems to perform very well. I have cheated in forming the PickConeRay object though. I have no idea of how to use the PickBounds pickshape to pick all the points in the bound. After compilation, the code can be run using java Content <RAY/CONERAY> The argument is to tell whether to use PickRay or PickConeRay for single point selection. You can just click on the window for single point selection and you can "draw" a rectangle on the screen to generate arguments for the PickBounds object. Thanks, Anand. =========================================================================== To unsubscribe, send email to [EMAIL PROTECTED] and include in the body of the message "signoff JAVA3D-INTEREST". For general help, send email to [EMAIL PROTECTED] and include in the body of the message "help".
import java.awt.*; import java.awt.event.*; import java.util.Enumeration; import javax.vecmath.*; import javax.media.j3d.*; import com.sun.j3d.utils.picking.*; public class PickPointsBehavior extends Behavior { private Canvas3D canvas; private BranchGroup objRoot; private BranchGroup quadBranch; private String pointPickType; private WakeupCriterion[] mouseEvents; private WakeupOr mouseCriterion; private Point3d initialPoint, finalPoint; private boolean mousePressed = false; private boolean mouseDragged = false; private PickCanvas pickCanvas; private int x,y; public PickPointsBehavior (Canvas3D canvas, BranchGroup objRoot, String pointPickType) { this.canvas = canvas; this.objRoot = objRoot; this.pointPickType = pointPickType; if (Content.coneRay.equals(pointPickType)) { pickCanvas = new PickCanvas(canvas, objRoot); pickCanvas.setMode(PickTool.GEOMETRY_INTERSECT_INFO); pickCanvas.setTolerance(.5f); } } public void initialize() { mouseEvents = new WakeupCriterion[3]; mouseEvents[0] = new WakeupOnAWTEvent(MouseEvent.MOUSE_DRAGGED); mouseEvents[1] = new WakeupOnAWTEvent(MouseEvent.MOUSE_PRESSED); mouseEvents[2] = new WakeupOnAWTEvent(MouseEvent.MOUSE_RELEASED); mouseCriterion = new WakeupOr(mouseEvents); wakeupOn (mouseCriterion); } public void processStimulus (Enumeration criteria) { WakeupCriterion wakeup; AWTEvent[] event; int id; while (criteria.hasMoreElements()) { wakeup = (WakeupCriterion) criteria.nextElement(); if (wakeup instanceof WakeupOnAWTEvent) { event = ((WakeupOnAWTEvent)wakeup).getAWTEvent(); for (int i=0; i<event.length; i++) { id = event[i].getID(); if (id == MouseEvent.MOUSE_DRAGGED) { if (!mousePressed) continue; mouseDragged = true; } else if (id == MouseEvent.MOUSE_PRESSED) { mousePressed = true; x = ((MouseEvent)event[i]).getX(); y = ((MouseEvent)event[i]).getY(); initialPoint = new Point3d(); canvas.getPixelLocationInImagePlate(x, y, initialPoint); Transform3D transform3D = new Transform3D(); canvas.getImagePlateToVworld(transform3D); transform3D.transform (initialPoint); } else if (id == MouseEvent.MOUSE_RELEASED) { if (!mouseDragged) { mousePressed = false; mouseDragged = false; if (Content.coneRay.equals(pointPickType)) performConeRayPicking(); if (Content.ray.equals(pointPickType)) performRayPicking(); } else { mousePressed = false; mouseDragged = false; x = ((MouseEvent)event[i]).getX(); y = ((MouseEvent)event[i]).getY(); finalPoint = new Point3d(); canvas.getPixelLocationInImagePlate(x, y, finalPoint); Transform3D transform3D = new Transform3D(); canvas.getImagePlateToVworld(transform3D); transform3D.transform (finalPoint); performBoundsPicking(); } } } } } wakeupOn (mouseCriterion); } /** * 0. Remove any previously drawn quadrilaterals. * 1. If mouse has been just clicked, then use the initialPoint * saved to generate a pickRay and perform single point picking. */ private void performRayPicking() { System.out.println ("BEGIN - Use PickRay to pick A point."); if (quadBranch != null) { objRoot.removeChild (quadBranch); quadBranch = null; } // make the origin of the ray at z=1 since the poitns are all at z=0 // XXX HOW TO GET THE Z COORDINATE FOR THE ORIGIN OF THE RAY?? initialPoint.z = 1; Vector3d direction = new Vector3d (0, 0, -1); PickShape pickRay = new PickRay (initialPoint, direction); SceneGraphPath[] sgp = objRoot.pickAll (pickRay); if (sgp != null) { for (int i=0; i<sgp.length; i++) { PickResult pickResult = new PickResult (sgp[i], pickRay); System.out.println ("pickResult["+i+"]="+pickResult); // XXX WHY IS numIntersections ZERO ?? System.out.println ("numIntersections="+pickResult.numIntersections()); } } else { System.out.println ("Nothing picked"); } System.out.println ("END - Use PickRay to pick A point."); } /** * 0. Remove any previously drawn quadrilaterals. * 1. Draw a quadrilateral with endoints at initalPoint and finalPoint * 2. Try picking using a BoundingBox to get all points in this range */ private void performBoundsPicking() { System.out.println ("BEGIN - Use PickBounds to pick points."); // Remove any previously drawn quadrilaterals. if (quadBranch != null) { objRoot.removeChild (quadBranch); quadBranch = null; } // Draw a quadrilateral with endoints at initalPoint and finalPoint QuadArray qa = new QuadArray (4, QuadArray.COORDINATES); qa.setCoordinate (0, initialPoint); qa.setCoordinate (1, new Point3d (initialPoint.x, finalPoint.y, 0)); qa.setCoordinate (2, finalPoint); qa.setCoordinate (3, new Point3d (finalPoint.x, initialPoint.y, 0)); Appearance appearance = new Appearance(); PolygonAttributes pa = new PolygonAttributes (); pa.setPolygonMode (PolygonAttributes.POLYGON_LINE); appearance.setPolygonAttributes (pa); LineAttributes la = new LineAttributes(); la.setLinePattern (LineAttributes.PATTERN_DASH); la.setLineAntialiasingEnable (true); appearance.setLineAttributes (la); ColoringAttributes ca = new ColoringAttributes (); ca.setColor (new Color3f (Content.black)); appearance.setColoringAttributes (ca); Shape3D s = new Shape3D (qa, appearance); quadBranch = new BranchGroup (); quadBranch.setCapability (BranchGroup.ALLOW_DETACH); quadBranch.addChild (s); objRoot.addChild (quadBranch); // Try picking using a BoundingBox to get all points in this range PickBounds pickBounds = new PickBounds (new BoundingBox (initialPoint, finalPoint)); SceneGraphPath[] sgp = objRoot.pickAll (pickBounds); if (sgp != null) { for (int i=0; i<sgp.length; i++) { PickResult pickResult = new PickResult (sgp[i], pickBounds); System.out.println ("pickResult["+i+"]="+pickResult); System.out.println ("numIntersections="+pickResult.numIntersections()); } } else { System.out.println ("Nothing picked"); } System.out.println ("END - Use PickBounds to pick points."); } /** * 0. Remove any previously drawn quadrilaterals. * 1. If mouse has been just clicked, then use the initialPoint * saved to generate a pickConeRay and perform single point picking. * 2. CHEAT while generating the pickConeRay. Use pickCanvas to do a pseudo picking, * and use the parameters of the PickConeRay therein. Just change the spreadAngle * to a bigger value. */ private void performConeRayPicking() { System.out.println ("BEGIN - Use PickConeRay to pick points."); if (quadBranch != null) { objRoot.removeChild (quadBranch); quadBranch = null; } PickResult pickResult = null; pickCanvas.setShapeLocation(x, y); pickResult = pickCanvas.pickClosest(); PickConeRay p = (PickConeRay) pickCanvas.getPickShape(); Point3d origin = new Point3d(); p.getOrigin (origin); Vector3d v = new Vector3d(); p.getDirection (v); p = new PickConeRay (origin, v, 0.05f); pickCanvas.setShape (p, origin); pickResult = pickCanvas.pickClosest(); if (pickResult != null) { Shape3D shape = (Shape3D) pickResult.getNode(PickResult.SHAPE3D); int numIntersections = pickResult.numIntersections(); System.out.println ("numIntersections = "+numIntersections); for (int i=0; i<numIntersections; i++) { System.out.println ("\tIntersection number "+i); PickIntersection intersection = pickResult.getIntersection(i); javax.media.j3d.GeometryArray ga = intersection.getGeometryArray(); int[] primitiveVertexIndices = intersection.getPrimitiveVertexIndices(); if (primitiveVertexIndices != null) { for (int j=0; j<primitiveVertexIndices.length; j++) { Point3f point = new Point3f(); ga.getCoordinate (primitiveVertexIndices[j], point); System.out.println ("\t\t\tindex="+primitiveVertexIndices[j]+", point="+point); } } } } else { System.out.println ("Nothing picked"); } System.out.println ("END - Use PickConeRay to pick points."); } }
import java.awt.*; import java.applet.Applet; import javax.vecmath.*; import javax.media.j3d.*; import com.sun.j3d.utils.universe.*; import com.sun.j3d.utils.applet.MainFrame; public class Content extends Applet { private static final BoundingSphere bounds = new BoundingSphere(new Point3d(0.0d, 0.0d, 0.0d), 2); public static final Color3f black = new Color3f (0.f, 0.f, 0.f); public static final String ray = "RAY"; public static final String coneRay = "CONERAY"; private Canvas3D canvas; private String pointPickType; public Content (String s) { pointPickType = s; } public void init() { setLayout(new BorderLayout()); GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration(); canvas = new Canvas3D(config); add("Center", canvas); SimpleUniverse simpleUniverse = new SimpleUniverse (canvas); simpleUniverse.getViewingPlatform().setNominalViewingTransform(); BranchGroup scene = createSceneGraph(); scene.compile(); simpleUniverse.addBranchGraph(scene); } private BranchGroup createSceneGraph () { BranchGroup objRoot = new BranchGroup(); objRoot.setCapability (BranchGroup.ALLOW_CHILDREN_EXTEND); objRoot.setCapability (BranchGroup.ALLOW_CHILDREN_WRITE); objRoot.setCapability (BranchGroup.ALLOW_LOCAL_TO_VWORLD_READ); Background background = new Background (1.0f, 1.0f, 1.0f); background.setApplicationBounds (bounds); objRoot.addChild (background); PointArray array = new PointArray (4, PointArray.COORDINATES); array.setCapability (PointArray.ALLOW_FORMAT_READ); array.setCapability (PointArray.ALLOW_COUNT_READ); array.setCapability (PointArray.ALLOW_COORDINATE_READ); array.setCoordinate (0, new Point3f (-0.2f, 0.2f, -0.f)); array.setCoordinate (1, new Point3f (-0.2f, -0.2f, -0.f)); array.setCoordinate (2, new Point3f (0.2f, -0.2f, -0.f)); array.setCoordinate (3, new Point3f (0.2f, 0.2f, -0.f)); Appearance app = new Appearance(); PointAttributes pa = new PointAttributes (); pa.setPointSize(5.0f); app.setPointAttributes (pa); ColoringAttributes ca = new ColoringAttributes (); ca.setColor (black); app.setColoringAttributes (ca); Shape3D shape = new Shape3D(array, app); shape.setCapability (Shape3D.ALLOW_LOCAL_TO_VWORLD_READ); shape.setCapability (Shape3D.ALLOW_GEOMETRY_READ); objRoot.addChild (shape); PickPointsBehavior behavior = new PickPointsBehavior (canvas, objRoot, pointPickType); behavior.setSchedulingBounds (bounds); objRoot.addChild (behavior); return objRoot; } public static void main(String[] args) { if (args.length != 1) { System.out.println("Usage: java Content <RAY/CONERAY>"); System.exit(0); } else { String s = args[0]; if (!ray.equals (s) && !coneRay.equals (s)) { System.out.println("Usage: java Content <RAY/CONERAY>"); System.exit(0); } new MainFrame (new Content(s), 700, 500); } } }