Picking an object is basically clicking on the screen and
getting back the serial number of that object. If the object is a solid then pick should apply to solids, if face
then to faces and so on. We will show how to
pick solids in a scene. The pick
method should apply to the MyGroup class (since it has to search the group). We
should provide the xmouse and ymouse coordinates of the screen when the mouse
is clicked. The pick algorithm should return
back an integer number, which is the serial number of the picked object.
Therefore, the pick method should be in the mouseDown and should look like
this:
public boolean mouseDown(Event e, int x, int y){
xf = x;
yf = y;
group.pick(x,
y);
repaint();
return true;
}
This means that MyGgroup should have a method called pick. MyGroup.pick()
will transfer its jurisdiction to the solids[i].pick() one level below and expect
back a boolean
true or false indicating that a solid was or was not picked:
public boolean pick(int xmouse, int ymouse){
boolean in =
false;
for(int i=0;
i<numSolids; i++)
if(solids[i].pick(xmouse, ymouse) ==
true){
in = true;
break;
}
return in;
}
The if(in==true) break; statement indicates that if an object was found
there is no need to continue.
At this point object transfers its jurisdiction one level
below asking the MyFace to find whether a face was selected.
public boolean pick(int xmouse, int ymouse){
boolean in
= false;
for(int
i=0; i<numFaces; i++)
if(faces[i].pick(xmouse, ymouse) == true){
in = true;
setColor(Color.red);
break;
}
return in;
}
At the MyFace level the pick method is as follows:
public boolean
pick(int xmouse, int ymouse){
Polygon poly = new Polygon();
for(int i=0; i<numPoints; i++){
MyPoint p = points[i].setPerspective();
poly.addPoint((int)p.x+200, (int)p.y+200);
}
return
poly.contains(xmouse, ymouse);
}
The face is projected on the screen through axo or
perspective projection and now the problem has been deduced to simply finding
whether a 2D point (xmouse, ymouse) is within a 2D polygon poly area.
This can be dome manually or we can use the contains() method of polygon. If poly.contains()
is true, face was indeed selected else not.
In this example, we have managed to pick a solid on the screen. This is a significant task. Objects suddenly can become active. The user will be able to select solids and do things to them such as move, rotate, scale, erase, etc. This is the first step to interactivity on the MySolid level.
The result is:

In this example, we simulate a menu bar using choice
buttons. The reason is that real menu bars need detached windows to exist, and
we would like to use the existing applet window. So choice buttons are sticked
to frame window that can be moved anywhere in the scene. Here is the code for a
simple menu bar:
import java.applet.*;
import java.awt.*;
public class MyControl extends Frame{
public final int MOVE
= 0;
public final int
ROTATE = 1;
public final int
DEFORM = 2;
public int
transform_type = ROTATE;
public static final
int AXONOMETRIC = 0;
public static final
int PERSPECTIVE = 1;
public static final
int HYPERBOLIC = 2;
public static int
projection_type = PERSPECTIVE;
public final int POINTS = 0;
public final int LINES = 1;
public int display_type = POINTS;
Choice transform;
Choice projection;
Choice display;
public MyControl() {
//*** Choice
setup
transform = new
Choice();
transform.addItem("Transform");
transform.addItem("Move");
transform.addItem("Rotate");
transform.addItem("Deform");
transform.setLocation(0, 20);
transform.setSize(100, 20);
//*** Choice
setup
projection = new
Choice();
projection.addItem("Projection");
projection.addItem("Axonometric");
projection.addItem("Perspective");
projection.addItem("Hyperbolic");
projection.setLocation(100, 20);
projection.setSize(100, 20);
//*** Choice
setup
display = new
Choice();
display.addItem("Display");
display.addItem("Points");
display.addItem("Lines");
display.setLocation(200, 20);
display.setSize(100, 20);
setSize(400, 60);
setLocation(20, 20);
setLayout(null);
add(transform);
add(projection);
add(display);
show();
}
//******************************************
public boolean
action(Event e, Object o){
if(e.target instanceof
Choice){
if(o.equals("Move"))
transform_type = MOVE;
else
if(o.equals("Rotate"))
transform_type = ROTATE;
else
if(o.equals("Axonometric"))
projection_type = AXONOMETRIC;
else
if(o.equals("Deform"))
projection_type = DEFORM;
else
if(o.equals("Perspective"))
projection_type = PERSPECTIVE;
else
if(o.equals("Hyperbolic"))
projection_type = HYPERBOLIC;
else
if(o.equals("Points"))
display_type = POINTS;
else
if(o.equals("Lines"))
display_type = LINES;
}
return true;
}
}
A frame is created first. This is like a window coming out
of the applet screen. Then a choice
button is defined and attached to the frame. A set of Choice buttons called transform,
projection, and display are defined. The
action method sets the variables to whatever value is assigned.
if(e.target instanceof
Choice){
if(o.equals("Move"))
transform_type = MOVE;
else
if(o.equals("Rotate"))
transform_type = ROTATE;
. . . (etc.)
Once a choice is selected a flag called transform_type,
or display_type
or projection_type
is set to MOVE or ROTATE, etc. The flag is a static variable and that is how
the main program knows about their changes:
//************************************************
public boolean
mouseDrag(Event e, int x, int y){
int xoff = x - xf;
int yoff = y - yf;
switch(control.transform_type){
case 0: //move
group.setMove(xoff, yoff, 0.);
break;
case
1: // rotate
group.setRotatex(xoff*Math.PI/180);
group.setRotatey(yoff*Math.PI/180);
break;
}
repaint();
xf = x;
yf = y;
return true;
}
The result is:

A variation of the Choice button can be found in the following code. Here we create a Frame and we draw predefined images. We then check for the mouse location and if it is clicked on top of an image we replace it with its inverted image and send execute the command. Here is the code:
import
java.awt.*;
import
java.applet.*;
public
class MyToolbar extends Frame
{
Image
icons[];
int flag;
int sf =
1;
Frame
parent;
//
public toolbar(Frame parentframe, Image Images[])
public MyToolbar(Applet app)
{
super ();
setSize (72,344);
setResizable(false);
icons = new Image[8];
//for (int i=0; i<Images.length;
i++) {
icons[0] =
app.getImage(app.getDocumentBase(),"res/1i.gif");
icons[1] =
app.getImage(app.getDocumentBase(),"res/2i.gif");
icons[2] =
app.getImage(app.getDocumentBase(),"res/3i.gif");
icons[3] =
app.getImage(app.getDocumentBase(),"res/4i.gif");
icons[4] =
app.getImage(app.getDocumentBase(),"res/1.gif");
icons[5] =
app.getImage(app.getDocumentBase(),"res/2.gif");
icons[6] =
app.getImage(app.getDocumentBase(),"res/3.gif");
icons[7] =
app.getImage(app.getDocumentBase(),"res/4.gif");
//}
setForeground(Color.black);
setBackground (Color.black);
Dimension
screenSize=getToolkit().getScreenSize();
Dimension dialogSize=size();
setLocation(10, 100);
show();
}
public void paint(Graphics g) {
for (int i=0; i< 4; i++){
g.drawImage
(icons[i],4,79*i+25,this);
}
if (flag == 1) g.drawImage
(icons[4],4, 79*0+25, this);
else if (flag == 2) g.drawImage
(icons[5],4,79*1+25, this);
else if (flag == 3) g.drawImage
(icons[6],4,79*2+25, this);
else if (flag == 4) g.drawImage
(icons[7],4,79*3+25, this);
}
public boolean mouseDown (Event evt, int x,
int y) {
if (y >= 79*0+25 && y <=
79*1+25) {
//progWindow.current_transform =
progWindow.ZOOM;
//app.setCursor(Cursor.N_RESIZE_CURSOR);
flag = 1;
}
else if (y >= 79*1+25 && y
<= 79*2+25) {
//progWindow.current_transform =
progWindow.SLIDE;
//parent.setCursor(Cursor.MOVE_CURSOR);
flag = 2;
}
else if (y >= 79*2+25 && y
<= 79*3+25) {
//progWindow.current_transform =
progWindow.ROTATE;
//parent.setCursor(Cursor.HAND_CURSOR);
flag = 3;
}
else if (y >= 79*3+25 && y
<= 79*4+25) {
//progWindow.current_transform =
progWindow.MORPH;
//parent.setCursor(Cursor.W_RESIZE_CURSOR);
flag = 4;
}
repaint();
return true;
}
}
The result is:
