Hi All,

I attached a simple program of picking multiple objects by dragging mouse to
draw a window on the screen. This program draws 2 polygons. If my window is near or 
enclosing the right common point of the 2 polygons, it works fine.
Otherwise, it can't get the right result.

The picking process is simple. I constructed a BoundingPolytope type bounds,
which consists of 5 planes. One plane is the backClipPlane, the other 4 planes are 
constructed by combining the 4 points of the picking window and
the eye point. Then, setPickShape to the PickBounds for a PickTool object.

BTW, it also works fine for certain other shapes. I don't know why it's not working 
for this case. Did I do sth wrong? or the Java3D picking utility
functions have some constraints?

Thanks a lot---white


/*
 * PickAllTest.java
 *
 * Created on July 23, 2002, 10:15 AM
 */

/**
 *
 * @author
 */
import javax.vecmath.*;
import javax.media.j3d.*;
import com.sun.j3d.utils.picking.PickTool;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.geometry.*;
import java.awt.*;

public class PickAllTest extends javax.swing.JFrame {

    /** Creates new form PickAllTest */
    public PickAllTest() {
        initComponents();
        initGraphics();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    private void initComponents() {

        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                exitForm(evt);
            }
        });

        pack();
        java.awt.Dimension screenSize = 
java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        setSize(new java.awt.Dimension(640, 480));
        setLocation((screenSize.width-640)/2,(screenSize.height-480)/2);
    }

    /** Exit the Application */
    private void exitForm(java.awt.event.WindowEvent evt) {
        System.exit(0);
    }

    private void initGraphics(){
        GraphicsConfiguration config =
            SimpleUniverse.getPreferredConfiguration();

        canvas = new Canvas3D(config);
        u = new SimpleUniverse(canvas);

        imagePanel = new javax.swing.JPanel(new java.awt.BorderLayout());
        getContentPane().add(imagePanel, java.awt.BorderLayout.CENTER);

        imagePanel.add(canvas, java.awt.BorderLayout.CENTER);

        BranchGroup scene = createSceneGraph();


        ViewingPlatform viewingPlatform = u.getViewingPlatform();
        Transform3D t = new Transform3D();
        Point3d cp = new Point3d();
        bounds.getCenter(cp);
        System.out.println("The bounding center is "+cp.x+", "+cp.y+", "+cp.z);

        t.set(new Vector3d(cp.x, cp.y, cp.z + 3.0*bounds.getRadius()));
        (viewingPlatform.getViewPlatformTransform()).setTransform(t);

        u.addBranchGraph(scene);


        imagePanel.updateUI();
    }

    private BranchGroup createSceneGraph(){
        /*
        double vertices[] = {0.0525,0,0.726,  -0.9779,0,0.397007,  -0.85,0.5263,0.4213,
                            -0.52633,0.732855,0.521687,  0.236547,0.76,0.699422,
                        0.253872,-0.753073,0.697205,  -0.5155,-0.74767,0.520049,
                        -0.849,-0.5263,0.4213};
        */

        double vertices[] = {0.236547,0.76,0.699422, -0.52633,0.732855,0.521687,
                    -0.85,0.5263,0.4213,  -0.9779,0,0.397007,  0.0525,0,0.726};

        double vertices1[] = {0.0525,0,0.726,  -0.9779,0,0.397007,
                              -0.849,-0.5263,0.4213, -0.5155,-0.74767,0.520049,
                               0.253872,-0.753073,0.697205};

        Shape3D part1 = new Shape3D();

        // Clockwise order
        //int []part1Index = {0, 1, 2, 3, 4};
        //int []part2Index = {5, 6, 7, 1, 0};

        // Counterclockwise order
        int []part1Index = {4, 3, 2, 1, 0};
        int []part2Index = {0, 1, 7, 6, 5};

        int []stripCounts1 = new int[1];
        int []stripCounts2 = new int[1];

        stripCounts1[0] = part1Index.length;

        GeometryInfo gi1 = new GeometryInfo(GeometryInfo.POLYGON_ARRAY);
        gi1.setCoordinates(vertices);
        //gi1.setCoordinateIndices(part1Index);
        gi1.setStripCounts(stripCounts1);

        //IndexedGeometryArray ga1 = gi1.getIndexedGeometryArray();
        GeometryArray ga1 = gi1.getGeometryArray();


        part1.setGeometry(ga1);

        Appearance myApp1 = new Appearance();
        ColoringAttributes colorAttr1 = new ColoringAttributes(0.5f, 0.4f, 0.0f,
                                              ColoringAttributes.SHADE_GOURAUD);

        myApp1.setColoringAttributes(colorAttr1);
        part1.setAppearance(myApp1);
        //part1.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
        PickTool.setCapabilities(part1, PickTool.INTERSECT_FULL);




        Shape3D part2 = new Shape3D();


        // Construct triangleArrays using GeometryInfo Class
        GeometryInfo gi2 = new GeometryInfo(GeometryInfo.POLYGON_ARRAY);
        gi2.setCoordinates(vertices1);
        //gi2.setCoordinates(vertices);
        //gi2.setCoordinateIndices(part2Index);
        stripCounts2[0] = part2Index.length;
        gi2.setStripCounts(stripCounts2);

        //IndexedGeometryArray ga2 = gi2.getIndexedGeometryArray();
        GeometryArray ga2 = gi2.getGeometryArray();



        part2.setGeometry(ga2);


        Appearance myApp2 = new Appearance();
        ColoringAttributes colorAttr2 = new ColoringAttributes(0.2f, 0.7f, 0.0f,
                                              ColoringAttributes.SHADE_GOURAUD);

        myApp2.setColoringAttributes(colorAttr2);
        part2.setAppearance(myApp2);
        //part2.setCapability(Shape3D.ALLOW_APPEARANCE_READ);
        //part2.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
        //part2.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
        PickTool.setCapabilities(part2, PickTool.INTERSECT_FULL);


        BranchGroup group = new BranchGroup();

        group.addChild(part1);
        group.addChild(part2);

        bounds = new BoundingSphere(group.getBounds());
        WindowPickBehavior pick = new WindowPickBehavior(group, canvas, bounds);
        pick.setEnable(true);
        group.addChild(pick);

        group.compile();

        return group;
    }


    public static void main(String args[]) {
        new PickAllTest().show();
    }


    // Variables declaration - do not modify
    // End of variables declaration

    private BoundingSphere bounds;
    private SimpleUniverse u;
    private Canvas3D canvas;
    private javax.swing.JPanel imagePanel;
}


/*
 * WindowPickBehavior.java
 *
 * Created on October 29, 2002, 2:09 PM
 */

/**
 *
 * @author
 */
import javax.media.j3d.*;
import java.awt.event.*;
import java.awt.*;
import javax.vecmath.*;
import javax.media.j3d.*;
import com.sun.j3d.utils.picking.*;


public class WindowPickBehavior extends javax.media.j3d.Behavior {
    private WakeupCriterion[] mouseEvents;
    private WakeupOr  mouseCriterion;

    private int orgX, orgY;
    private int oldX, oldY;
    private int newX, newY;

    private boolean activeOn;
    private boolean buttonPress;
    private Color rubberColor;
    private Graphics2D g2d;
    private Canvas3D canvas;
    private BranchGroup branchGroup;


    /** Creates a new instance of WindowPickBehavior */
    public WindowPickBehavior(BranchGroup group, Canvas3D canvas, Bounds bounds) {
        g2d = (Graphics2D)(canvas.getGraphics());
        activeOn = false;
        rubberColor = Color.white;

        this.canvas = canvas;
        branchGroup = group;

        oldX = oldY = -1;

        g2d.setXORMode(rubberColor);
        setSchedulingBounds(bounds);
    }

    public void setEnable(boolean flag) {
        activeOn = flag;
    }

    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(java.util.Enumeration criteria) {
        WakeupCriterion wakeup;
        AWTEvent[] evt = null;
        MouseEvent mevent = null;

        if (!activeOn) {
            wakeupOn(mouseCriterion);
            return;
        }

        while(criteria.hasMoreElements()) {
            wakeup = (WakeupCriterion)criteria.nextElement();
            if (wakeup instanceof WakeupOnAWTEvent)
                evt = ((WakeupOnAWTEvent)wakeup).getAWTEvent();
        }


        if (evt[evt.length-1] instanceof MouseEvent){
            mevent = (MouseEvent) evt[evt.length-1];

            processMouseEvent(mevent);
            newX = mevent.getPoint().x;
            newY = mevent.getPoint().y;
        }


        if (buttonPress){
            updateScene();
        }
       wakeupOn(mouseCriterion);
    }

    /*
     * Handles mouse events
     */
    public void processMouseEvent(AWTEvent evt) {
        if (evt.getID()==MouseEvent.MOUSE_PRESSED) {
            buttonPress = true;
            orgX = ((MouseEvent)evt).getPoint().x;
            orgY = ((MouseEvent)evt).getPoint().y;
            return;
        }
        else if (evt.getID()==MouseEvent.MOUSE_RELEASED) {
            buttonPress = false;
            //activeOn = false;

            oldX = -1;
            oldY = -1;

            int wd = Math.abs(newX - orgX);
            int ht = Math.abs(newY - orgY);

            if (wd > 0 || ht > 0) {
                g2d.drawRect(orgX, orgY, wd, ht);
                // call the function to pick objects
                pickObjects();
            }
        }
        else if (evt.getID() == MouseEvent.MOUSE_MOVED) {
            // Process mouse move event
        }
    }

    /**
     * Draw the rubber wand
     */
    private void updateScene() {

        int width = 0, height = 0;

        /* Before use the new position to draw the rectangle, make the following
         * calls using the old position, which in fact erases the old rectangle
        */
        if(oldX >= 0 && oldY >= 0) {
            width = Math.abs(oldX - orgX);
            height = Math.abs(oldY - orgY);

            if (width > 0 || height > 0)
                g2d.drawRect(orgX, orgY, width, height);

        }

        width = Math.abs(newX - orgX);
        height = Math.abs(newY - orgY);

        if (width > 0 || height > 0)
            g2d.drawRect(orgX, orgY, width, height);

        /*
        System.out.println("The org point: ("+ orgX + ", " + orgY + "), old point: ("
            + oldX + ", " + oldY + "), new point: (" + newX + ", " + newY + ")");
         */

        oldX = newX;
        oldY = newY;
    }

    /**
     * Compute the plane function, return it
     *
     * @param p1  The 1rst point
     * @param p2  The 2nd point
     * @param p3  The 3rd point
     *
     * @return An object of Vector4d, which represents a plane function
     */
    private Vector4d getPlaneFunc(Point3d p1, Point3d p2, Point3d p3) {
        Point3d pt = new Point3d();

        pt.sub(p1, p2);
        Vector3d v1 = new Vector3d(pt);
        pt.sub(p3, p2);
        Vector3d v2 = new Vector3d(pt);

        Vector3d planeVec = new Vector3d();
        planeVec.cross(v2, v1);
        planeVec.normalize();

        //double d0 = -planeVec.dot(new Vector3d(p1));
        double d1 = -planeVec.dot(new Vector3d(p2));

        return new Vector4d(planeVec.x, planeVec.y, planeVec.z, d1);
    }

    /**
     * Function to construct the pickBounds for multiple object picking
     */
    private void pickObjects() {
        Point3d []pyramVertex = new Point3d[6];
        Point2d []rectPoint = new Point2d[5];

        for (int ii=0; ii<pyramVertex.length; ii++)
            pyramVertex[ii] = new Point3d();

        rectPoint[0] = new Point2d(orgX, orgY);
        rectPoint[1] = new Point2d(orgX, newY);
        rectPoint[2] = new Point2d(newX, newY);
        rectPoint[3] = new Point2d(newX, orgY);

        java.awt.Dimension dim = canvas.getSize();
        rectPoint[4] = new Point2d(dim.width/2.0, dim.height/2.0);
        //rectPoint[4] = new Point2d(orgX + (newX - orgX)/2.0,
          //                         orgY + (newY - orgY)/2.0);

        for (int ii=0; ii<rectPoint.length; ii++)
          canvas.getPixelLocationInImagePlate(rectPoint[ii], pyramVertex[ii]);

        canvas.getCenterEyeInImagePlate(pyramVertex[5]);

        Transform3D trans = new Transform3D();
        canvas.getImagePlateToVworld(trans);

        for (int ii=0; ii<pyramVertex.length; ii++)
           trans.transform(pyramVertex[ii], pyramVertex[ii]);

        //Compute the plane function of the bottom face of the pyramid bounds
        double farClipLength = canvas.getView().getBackClipDistance();

        Vector3d farClipVect = new Vector3d();
        farClipVect.sub(pyramVertex[4], pyramVertex[5]);
        farClipVect.normalize();
        Vector3d farClipPt = new Vector3d();
        farClipPt.scale(farClipLength, farClipVect);
        double d0 = -farClipVect.dot(farClipPt);

        //Define an array of Vector4d for all the planes of the pickBounds
        Vector4d []planeFunc = new Vector4d[5];
        planeFunc[0] = new Vector4d(farClipVect.x, farClipVect.y, farClipVect.z, d0);

        planeFunc[1] = getPlaneFunc(pyramVertex[0], pyramVertex[1], pyramVertex[5]);
        planeFunc[2] = getPlaneFunc(pyramVertex[1], pyramVertex[2], pyramVertex[5]);
        planeFunc[3] = getPlaneFunc(pyramVertex[2], pyramVertex[3], pyramVertex[5]);
        planeFunc[4] = getPlaneFunc(pyramVertex[3], pyramVertex[0], pyramVertex[5]);

        //Define the BoundingPolytope bounds object for picking
        BoundingPolytope bounds = new BoundingPolytope(planeFunc);
        //PickBounds pickBounds = new PickBounds(bounds);

        PickTool pickTool = new PickTool(branchGroup);
        pickTool.setMode(PickTool.GEOMETRY);
        //pickTool.setShape(pickBounds, pyramVertex[4]);
        pickTool.setShapeBounds(bounds, pyramVertex[4]);

        PickResult []pr = pickTool.pickAllSorted();

        if (pr == null)
            return;
        else
            System.out.println("The number of geometries picked is " + pr.length);

    }
}

===========================================================================
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".

Reply via email to