package grapher3D.controller;
import expressionConsole.CommandExecutingMenuItem;
import expressionConsole.ExpressionConsoleModel;
import grapher3D.Grapher3DConstants;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import javax.swing.ButtonGroup;
import javax.swing.JMenu;
import logEnabledComponents.LogEnabledJRadioButtonMenuItem;
import parser.RecursiveDescentParser;
import valueTypes.StringValue;
import variables.Variable;
/**
* A panel which contains radio buttons for selecting the coordinate space to
* use.
*
* @author Curran Kelleher
*
*/
public class CoordinateSystemSelectorMenu extends JMenu {
private static final long serialVersionUID = -893328529774054453L;
/**
* the CoordinateSystemTranslator which the radio buttons will control.
*/
CoordinateSystemTranslator translator;
/**
* The current CoordinateSystem being used. Whenever a radio button is
* clicked, the state of this CoordinateSystem is saved, then it is swapped
* out for the new one.
*/
CoordinateSystem currentCoordinateSystem = null;
/**
* Creates a CoordinateSystemSelectorPanel bound to the specified
* CoordinateSystemTranslator.
*
* @param translator
* the CoordinateSystemTranslator which the radio buttons will
* control.
*/
public CoordinateSystemSelectorMenu(CoordinateSystemTranslator translator) {
super("Coordinate System");
setMnemonic('C');
this.translator = translator;
// create the buttons and add them to the panel
ButtonGroup radioButtons = new ButtonGroup();
for (Iterator<CoordinateSystem> i = createCoordinateSystems()
.iterator(); i.hasNext();) {
CoordinateSystem currentCoordinateSystem = i.next();
CoordinateSystemButton currentButton = new CoordinateSystemButton(
currentCoordinateSystem);
radioButtons.add(currentButton);
add(currentButton);
add(new CommandExecutingMenuItem("Edit Range", 'e',
currentCoordinateSystem.editRangeCommand));
addSeparator();
}
// select the first one initially
radioButtons.getElements().nextElement().doClick(0);
}
/**
* Creates the CoordinateSystems.
*/
private List<CoordinateSystem> createCoordinateSystems() {
RecursiveDescentParser parser = ExpressionConsoleModel.getInstance()
.getParser();
List<CoordinateSystem> coordinateSystems = new LinkedList<CoordinateSystem>();
coordinateSystems
.add(new CoordinateSystem(
"Cartesian z = f(x,y)",
'c',
"executeFunction({x=u*(xMax-xMin)+xMin;y=v*(yMax-yMin)+yMin;#;x=(x-xMin)/(xMax-xMin)*20-10;y=(y-yMin)/(yMax-yMin)*20-10})",
"z = sin((x^2+y^2)*((sin(t)+1)/20)+t/2)",
"CartesianCoordinateSystem",
"edit(xMax,xMin,yMax,yMin)"));
parser.parse("executeFunction({xMin=-10;xMax=10;yMin=-10;yMax=10})")
.evaluate();
coordinateSystems
.add(new CoordinateSystem(
"Cylindrical z = f(r,theta)",
'y',
"executeFunction({r=u*(rMax-rMin)+rMin;theta=v*(thetaMax-thetaMin)+thetaMin;#;x=r*cos(theta);y=r*sin(theta)})",
"z = -(r^2/10)+5+sin(r^2/10-t+theta)",
"CylindricalCoordinateSystem_r_dependent",
"edit(rMax,rMin,thetaMax,thetaMin)"));
parser.parse(
"executeFunction({rMin=0;rMax=10;thetaMin=0;thetaMax=2*pi})")
.evaluate();
coordinateSystems
.add(new CoordinateSystem(
"Cylindrical r = f(z,theta)",
'r',
"executeFunction({z=u*(zMax-zMin)+zMin;theta=v*(thetaMax-thetaMin)+thetaMin;#;x=r*cos(theta);y=r*sin(theta)})",
"r = 5+sin(z+t)+sin(theta*4)+sin(z/5+t)*3",
"CylindricalCoordinateSystem_z_dependent",
"edit(zMax,zMin,thetaMax,thetaMin)"));
parser.parse(
"executeFunction({zMin=-10;zMax=10;thetaMin=0;thetaMax=2*pi})")
.evaluate();
coordinateSystems
.add(new CoordinateSystem(
"Spherical rho = f(phi,theta)",
's',
"executeFunction({phi=u*(phiMax-phiMin)+phiMin;theta=v*(thetaMax-thetaMin)+thetaMin;#;r = rho*sin(phi);x=r*cos(theta);y=r*sin(theta);z = rho*cos(phi)})",
"rho = 9+sin((10*sin(t/5)+2)*phi+t)",
"SphericalCoordinateSystem",
"edit(phiMax,phiMin,thetaMax,thetaMin)"));
parser.parse("executeFunction({phiMin=0;phiMax=pi})").evaluate();
coordinateSystems
.add(new CoordinateSystem(
"Parametric Surface (x,y,z) = f(u,v)",
'p',
"executeFunction({u=u*(uMax-uMin)+uMin;v=v*(vMax-vMin)+vMin;#})",
"a=2.7*(1-cos(u)/2); x= 2.7*cos(u)*(1+sin(u))+a*cos(v)*(u<pi?cos(u):-1); y=7.2*sin(u)+(u<pi?a*cos(v)*sin(u):0); z=a*sin(v)",
"ParametricSurfaceCoordinateSystem",
"edit(uMax,uMin,vMax,vMin)"));
parser.parse("executeFunction({uMax=2*pi;uMin=0;vMax=2*pi;vMin=0})")
.evaluate();
coordinateSystems
.add(new CoordinateSystem(
"Color color = f(x,y)",
'o',
"executeFunction({x=u*(colorXMax-colorXMin)+colorXMin;y=v*(colorYMax-colorYMin)+colorYMin;#;x=(x-colorXMin)/(colorXMax-colorXMin)*20-10;y=(y-colorYMin)/(colorYMax-colorYMin)*20-10;color=(color-colorMin)/(colorMax-colorMin)})",
"color = sin(x*y/10+t)/2+.5",
"ColorCoordinateSystem",
"edit(colorMax,colorMin,colorXMax,colorXMin,colorYMax,colorYMin)",
Grapher3DConstants.DrawGraphsIn3D + "=false",
Grapher3DConstants.DrawGraphsIn3D + "=true"));
parser
.parse(
"executeFunction({colorMin=0;colorMax=1;colorXMin=-10;colorXMax=10;colorYMin=-10;colorYMax=10})")
.evaluate();
/*
coordinateSystems
.add(new CoordinateSystem(
"2D Cartesian y = f(x)",
'a',
"executeFunction({x=u*(xMax-xMin)+xMin;#;x=(x-xMin)/(xMax-xMin)*20-10;y=(y-yMin)/(yMax-yMin)*20-10})",
"y = sin(x+t)", "Cartesian2DCoordinateSystem",
"edit(xMax,xMin,yMax,yMin)",
Grapher3DConstants.DrawGraphsIn3D
+ "=false; graphUResolutionOutsideCartesian2DCoordinateSystem = "
+ Grapher3DConstants.GraphResolution_U+";"+ Grapher3DConstants.GraphResolution_U+"=1",
Grapher3DConstants.DrawGraphsIn3D + "=true;"+Grapher3DConstants.GraphResolution_U+"=graphUResolutionOutsideCartesian2DCoordinateSystem"));
parser.parse("executeFunction({xMin=-10;xMax=10;yMin=-10;yMax=10})").evaluate();
*/
// the AWESOME LOOKING klein bottle
// xBottom = (2.5+1.5*cos(2*v))*cos(u);
// yBottom=(2.5+1.5*cos(2*v))*sin(u);zBottom = -2.5*sin(2*v); x =
// v<pi/2?xBottom:0; y= v<pi/2?yBottom:0; z= v<pi/2?zBottom:0
// xHandle=2-2*cos(v*2-pi)+sin(u); yHandle=cos(u); zHandle= 3*(v*2-pi);
// x = v<pi?xHandle:0; y= v<pi?yHandle:0; z= v<pi? zHandle:0
// xTop=2+(2+cos(u))*cos(2*v-2*pi); yTop=sin(u); zTop=
// 3*pi+(2+cos(u))*sin(2*v-2*pi) ; x = xTop; y=yTop; z=zTop
// xMid=(2.5+1.5*cos(-v*2+4*pi))*cos(u); yMid=
// (2.5+1.5*cos(-v*2+4*pi))*sin(u); zMid=3*(-v*2+4*pi); x =xMid; y=yMid;
// z=zMid
// scale=.4;r=1.5; u=u+d;a=4*r*(1-cos(u)/2); x=
// scale*6*cos(u)*(1+sin(u))+scale*a*cos(v)*(u<pi?cos(u):-1);
// y=16*sin(u)*scale+scale*(u<pi?1:0)*a*sin(u)*cos(v); z=a*sin(v)*scale
// "scale=.45;r=1.5; a=4*r*(1-cos(u)/2); x=
// scale*(6*cos(u)*(1+sin(u))+a*cos(v)*(u<pi?cos(u):-1));
// y=scale*(16*sin(u)+(u<pi?1:0)*a*sin(u)*cos(v)); z=a*sin(v)*scale",
return coordinateSystems;
}
class CoordinateSystemButton extends LogEnabledJRadioButtonMenuItem {
private static final long serialVersionUID = 3887583792612139407L;
/**
* The coordinate system associated with this button
*/
final CoordinateSystem thisSystem;
public CoordinateSystemButton(CoordinateSystem system) {
super(system.title, system.alphaNumericName);
this.setMnemonic(system.mnemonic);
thisSystem = system;
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// save the state of the current system, and swap it out for
// the new one
if (currentCoordinateSystem != null) {
// save the state of the current one
currentCoordinateSystem.saveState();
// execute the exiting command for the new coordinate
if (currentCoordinateSystem.initializingCommand != null)
ExpressionConsoleModel
.getInstance().executeFunction(currentCoordinateSystem.exitingCommand);
}
// currentCoordinateSystem is only used for saving states,
// nothing more
currentCoordinateSystem = thisSystem;
// set the actual translator to the new one
translator.currentTranslator = thisSystem.translationSpecification;
// execute the initializing command for the new coordinate
if (thisSystem.initializingCommand != null)
ExpressionConsoleModel
.getInstance().executeFunction(currentCoordinateSystem.initializingCommand);
// set the external (in the text field) function string to
// the one which is stored in this coordinate system.
Variable
.getVariable(
Grapher3DConstants.Grapher3DFunctionString_external)
.set(new StringValue(thisSystem.functionString));
}
});
}
}
}