Does Java have a class for complex numbers?
There's an Apache Commons one called Complex. I don't believe the JDK has one.
No, the JDK does not have one but here is an implementation I have written.
Here is the GITHUB project.
/**
* <code>ComplexNumber</code> is a class which implements complex numbers in Java.
* It includes basic operations that can be performed on complex numbers such as,
* addition, subtraction, multiplication, conjugate, modulus and squaring.
* The data type for Complex Numbers.
* <br /><br />
* The features of this library include:<br />
* <ul>
* <li>Arithmetic Operations (addition, subtraction, multiplication, division)</li>
* <li>Complex Specific Operations - Conjugate, Inverse, Absolute/Magnitude, Argument/Phase</li>
* <li>Trigonometric Operations - sin, cos, tan, cot, sec, cosec</li>
* <li>Mathematical Functions - exp</li>
* <li>Complex Parsing of type x+yi</li>
* </ul>
*
* #author Abdul Fatir
* #version 1.1
*
*/
public class ComplexNumber
{
/**
* Used in <code>format(int)</code> to format the complex number as x+yi
*/
public static final int XY = 0;
/**
* Used in <code>format(int)</code> to format the complex number as R.cis(theta), where theta is arg(z)
*/
public static final int RCIS = 1;
/**
* The real, Re(z), part of the <code>ComplexNumber</code>.
*/
private double real;
/**
* The imaginary, Im(z), part of the <code>ComplexNumber</code>.
*/
private double imaginary;
/**
* Constructs a new <code>ComplexNumber</code> object with both real and imaginary parts 0 (z = 0 + 0i).
*/
public ComplexNumber()
{
real = 0.0;
imaginary = 0.0;
}
/**
* Constructs a new <code>ComplexNumber</code> object.
* #param real the real part, Re(z), of the complex number
* #param imaginary the imaginary part, Im(z), of the complex number
*/
public ComplexNumber(double real, double imaginary)
{
this.real = real;
this.imaginary = imaginary;
}
/**
* Adds another <code>ComplexNumber</code> to the current complex number.
* #param z the complex number to be added to the current complex number
*/
public void add(ComplexNumber z)
{
set(add(this,z));
}
/**
* Subtracts another <code>ComplexNumber</code> from the current complex number.
* #param z the complex number to be subtracted from the current complex number
*/
public void subtract(ComplexNumber z)
{
set(subtract(this,z));
}
/**
* Multiplies another <code>ComplexNumber</code> to the current complex number.
* #param z the complex number to be multiplied to the current complex number
*/
public void multiply(ComplexNumber z)
{
set(multiply(this,z));
}
/**
* Divides the current <code>ComplexNumber</code> by another <code>ComplexNumber</code>.
* #param z the divisor
*/
public void divide(ComplexNumber z)
{
set(divide(this,z));
}
/**
* Sets the value of current complex number to the passed complex number.
* #param z the complex number
*/
public void set(ComplexNumber z)
{
this.real = z.real;
this.imaginary = z.imaginary;
}
/**
* Adds two <code>ComplexNumber</code>.
* #param z1 the first <code>ComplexNumber</code>.
* #param z2 the second <code>ComplexNumber</code>.
* #return the resultant <code>ComplexNumber</code> (z1 + z2).
*/
public static ComplexNumber add(ComplexNumber z1, ComplexNumber z2)
{
return new ComplexNumber(z1.real + z2.real, z1.imaginary + z2.imaginary);
}
/**
* Subtracts one <code>ComplexNumber</code> from another.
* #param z1 the first <code>ComplexNumber</code>.
* #param z2 the second <code>ComplexNumber</code>.
* #return the resultant <code>ComplexNumber</code> (z1 - z2).
*/
public static ComplexNumber subtract(ComplexNumber z1, ComplexNumber z2)
{
return new ComplexNumber(z1.real - z2.real, z1.imaginary - z2.imaginary);
}
/**
* Multiplies one <code>ComplexNumber</code> to another.
* #param z1 the first <code>ComplexNumber</code>.
* #param z2 the second <code>ComplexNumber</code>.
* #return the resultant <code>ComplexNumber</code> (z1 * z2).
*/
public static ComplexNumber multiply(ComplexNumber z1, ComplexNumber z2)
{
double _real = z1.real*z2.real - z1.imaginary*z2.imaginary;
double _imaginary = z1.real*z2.imaginary + z1.imaginary*z2.real;
return new ComplexNumber(_real,_imaginary);
}
/**
* Divides one <code>ComplexNumber</code> by another.
* #param z1 the first <code>ComplexNumber</code>.
* #param z2 the second <code>ComplexNumber</code>.
* #return the resultant <code>ComplexNumber</code> (z1 / z2).
*/
public static ComplexNumber divide(ComplexNumber z1, ComplexNumber z2)
{
ComplexNumber output = multiply(z1,z2.conjugate());
double div = Math.pow(z2.mod(),2);
return new ComplexNumber(output.real/div,output.imaginary/div);
}
/**
* The complex conjugate of the current complex number.
* #return a <code>ComplexNumber</code> object which is the conjugate of the current complex number
*/
public ComplexNumber conjugate()
{
return new ComplexNumber(this.real,-this.imaginary);
}
/**
* The modulus, magnitude or the absolute value of current complex number.
* #return the magnitude or modulus of current complex number
*/
public double mod()
{
return Math.sqrt(Math.pow(this.real,2) + Math.pow(this.imaginary,2));
}
/**
* The square of the current complex number.
* #return a <code>ComplexNumber</code> which is the square of the current complex number.
*/
public ComplexNumber square()
{
double _real = this.real*this.real - this.imaginary*this.imaginary;
double _imaginary = 2*this.real*this.imaginary;
return new ComplexNumber(_real,_imaginary);
}
/**
* #return the complex number in x + yi format
*/
#Override
public String toString()
{
String re = this.real+"";
String im = "";
if(this.imaginary < 0)
im = this.imaginary+"i";
else
im = "+"+this.imaginary+"i";
return re+im;
}
/**
* Calculates the exponential of the <code>ComplexNumber</code>
* #param z The input complex number
* #return a <code>ComplexNumber</code> which is e^(input z)
*/
public static ComplexNumber exp(ComplexNumber z)
{
double a = z.real;
double b = z.imaginary;
double r = Math.exp(a);
a = r*Math.cos(b);
b = r*Math.sin(b);
return new ComplexNumber(a,b);
}
/**
* Calculates the <code>ComplexNumber</code> to the passed integer power.
* #param z The input complex number
* #param power The power.
* #return a <code>ComplexNumber</code> which is (z)^power
*/
public static ComplexNumber pow(ComplexNumber z, int power)
{
ComplexNumber output = new ComplexNumber(z.getRe(),z.getIm());
for(int i = 1; i < power; i++)
{
double _real = output.real*z.real - output.imaginary*z.imaginary;
double _imaginary = output.real*z.imaginary + output.imaginary*z.real;
output = new ComplexNumber(_real,_imaginary);
}
return output;
}
/**
* Calculates the sine of the <code>ComplexNumber</code>
* #param z the input complex number
* #return a <code>ComplexNumber</code> which is the sine of z.
*/
public static ComplexNumber sin(ComplexNumber z)
{
double x = Math.exp(z.imaginary);
double x_inv = 1/x;
double r = Math.sin(z.real) * (x + x_inv)/2;
double i = Math.cos(z.real) * (x - x_inv)/2;
return new ComplexNumber(r,i);
}
/**
* Calculates the cosine of the <code>ComplexNumber</code>
* #param z the input complex number
* #return a <code>ComplexNumber</code> which is the cosine of z.
*/
public static ComplexNumber cos(ComplexNumber z)
{
double x = Math.exp(z.imaginary);
double x_inv = 1/x;
double r = Math.cos(z.real) * (x + x_inv)/2;
double i = -Math.sin(z.real) * (x - x_inv)/2;
return new ComplexNumber(r,i);
}
/**
* Calculates the tangent of the <code>ComplexNumber</code>
* #param z the input complex number
* #return a <code>ComplexNumber</code> which is the tangent of z.
*/
public static ComplexNumber tan(ComplexNumber z)
{
return divide(sin(z),cos(z));
}
/**
* Calculates the co-tangent of the <code>ComplexNumber</code>
* #param z the input complex number
* #return a <code>ComplexNumber</code> which is the co-tangent of z.
*/
public static ComplexNumber cot(ComplexNumber z)
{
return divide(new ComplexNumber(1,0),tan(z));
}
/**
* Calculates the secant of the <code>ComplexNumber</code>
* #param z the input complex number
* #return a <code>ComplexNumber</code> which is the secant of z.
*/
public static ComplexNumber sec(ComplexNumber z)
{
return divide(new ComplexNumber(1,0),cos(z));
}
/**
* Calculates the co-secant of the <code>ComplexNumber</code>
* #param z the input complex number
* #return a <code>ComplexNumber</code> which is the co-secant of z.
*/
public static ComplexNumber cosec(ComplexNumber z)
{
return divide(new ComplexNumber(1,0),sin(z));
}
/**
* The real part of <code>ComplexNumber</code>
* #return the real part of the complex number
*/
public double getRe()
{
return this.real;
}
/**
* The imaginary part of <code>ComplexNumber</code>
* #return the imaginary part of the complex number
*/
public double getIm()
{
return this.imaginary;
}
/**
* The argument/phase of the current complex number.
* #return arg(z) - the argument of current complex number
*/
public double getArg()
{
return Math.atan2(imaginary,real);
}
/**
* Parses the <code>String</code> as a <code>ComplexNumber</code> of type x+yi.
* #param s the input complex number as string
* #return a <code>ComplexNumber</code> which is represented by the string.
*/
public static ComplexNumber parseComplex(String s)
{
s = s.replaceAll(" ","");
ComplexNumber parsed = null;
if(s.contains(String.valueOf("+")) || (s.contains(String.valueOf("-")) && s.lastIndexOf('-') > 0))
{
String re = "";
String im = "";
s = s.replaceAll("i","");
s = s.replaceAll("I","");
if(s.indexOf('+') > 0)
{
re = s.substring(0,s.indexOf('+'));
im = s.substring(s.indexOf('+')+1,s.length());
parsed = new ComplexNumber(Double.parseDouble(re),Double.parseDouble(im));
}
else if(s.lastIndexOf('-') > 0)
{
re = s.substring(0,s.lastIndexOf('-'));
im = s.substring(s.lastIndexOf('-')+1,s.length());
parsed = new ComplexNumber(Double.parseDouble(re),-Double.parseDouble(im));
}
}
else
{
// Pure imaginary number
if(s.endsWith("i") || s.endsWith("I"))
{
s = s.replaceAll("i","");
s = s.replaceAll("I","");
parsed = new ComplexNumber(0, Double.parseDouble(s));
}
// Pure real number
else
{
parsed = new ComplexNumber(Double.parseDouble(s),0);
}
}
return parsed;
}
/**
* Checks if the passed <code>ComplexNumber</code> is equal to the current.
* #param z the complex number to be checked
* #return true if they are equal, false otherwise
*/
#Override
public final boolean equals(Object z)
{
if (!(z instanceof ComplexNumber))
return false;
ComplexNumber a = (ComplexNumber) z;
return (real == a.real) && (imaginary == a.imaginary);
}
/**
* The inverse/reciprocal of the complex number.
* #return the reciprocal of current complex number.
*/
public ComplexNumber inverse()
{
return divide(new ComplexNumber(1,0),this);
}
/**
* Formats the Complex number as x+yi or r.cis(theta)
* #param format_id the format ID <code>ComplexNumber.XY</code> or <code>ComplexNumber.RCIS</code>.
* #return a string representation of the complex number
* #throws IllegalArgumentException if the format_id does not match.
*/
public String format(int format_id) throws IllegalArgumentException
{
String out = "";
if(format_id == XY)
out = toString();
else if(format_id == RCIS)
{
out = mod()+" cis("+getArg()+")";
}
else
{
throw new IllegalArgumentException("Unknown Complex Number format.");
}
return out;
}
}
The JDK doesn't current have any classes for complex numbers, unfortunately.
You could have a look at:
http://www.java2s.com/Code/Java/Data-Type/Thisclassrepresentscomplexnumbersanddefinesmethodsforperformingarithmeticoncomplexnumbers.htm
which provides an implementation you may find useful.
Related
import java.util.Scanner;
/**
* Calculates the amount of fuel needed.
*
* #param distance The distance of the trip.
* #param milesPerLiter Total distance that could be achieved with 1 liter of fuel.
* #return Total fuel needed.
*/
public static double calcFuelNeeded(double distance, double milesPerLiter) {
double fuelNeeded = distance / milesPerLiter;
return (fuelNeeded);
//FILL IN THE BODY
}
/**
* Calculates the total number of gallons needed.
*
* #param fuelNeeded Total fuel needed.
* #param litersPerGallon The volume of each gallon.
* #return Total number of gallons needed.
*/
public static int calcGallonsFuelNeeded(double fuelNeeded, double litersPerGallon) {
double gallonsFuel = Math.ceil(fuelNeeded / litersPerGallon);
return (int) gallonsFuel;//FILL IN THE BODY
}
/**
* Calculates the total cost needed.
*
* #param gallonsFuel Total number of gallons needed.
* #param costPerGallon The cost of each gallon.
* #return The total cost of the trip.
*/
public static double calcCostNeeded(int gallonsFuel, double costPerGallon) {
double costNeeded = gallonsFuel * costPerGallon;
return costNeeded;//FILL IN THE BODY
}
public static void main(String[] args) {
Scanner scnr = new Scanner(System.in);
System.out.println("Enter the distance to be covered (miles):");
double distance;
distance = scnr.nextDouble();
double milesPerLiter = 13.7;
double litersPerGallon = 3.785;
double costPerGallon = 2.629;
scnr.close();
System.out.println("Fuel Needed: " + calcFuelNeeded(distance, milesPerLiter) + " liter(s)");
System.out.println("Gallons needed: " + calcGallonsFuelNeeded( calcFuelNeeded(distance, milesPerLiter), litersPerGallon) + " gallon(s)");
System.out.println("Cost needed: " +calcCostNeeded( calcGallonsFuelNeeded( calcFuelNeeded(distance, milesPerLiter), litersPerGallon), costPerGallon) + " $" );
}
Could someone please tell me what is wrong with this program, since there is always error appear like
You need to put the contents within a class
Example:
package com.example.demo;
import java.util.Scanner;
public class Demo {
/**
* Calculates the amount of fuel needed. * * #param distance The distance of the trip. * #param milesPerLiter Total distance that could be achieved with 1 liter of fuel. * #return Total fuel needed. */ public static double calcFuelNeeded(double distance, double milesPerLiter) {
double fuelNeeded = distance / milesPerLiter;
return (fuelNeeded);
//FILL IN THE BODY
}
/**
* Calculates the total number of gallons needed. * * #param fuelNeeded Total fuel needed. * #param litersPerGallon The volume of each gallon. * #return Total number of gallons needed. */ public static int calcGallonsFuelNeeded(double fuelNeeded, double litersPerGallon) {
double gallonsFuel = Math.ceil(fuelNeeded / litersPerGallon);
return (int) gallonsFuel;//FILL IN THE BODY
}
/**
* Calculates the total cost needed. * * #param gallonsFuel Total number of gallons needed. * #param costPerGallon The cost of each gallon. * #return The total cost of the trip. */ public static double calcCostNeeded(int gallonsFuel, double costPerGallon) { double costNeeded = gallonsFuel * costPerGallon;
return costNeeded;//FILL IN THE BODY
}
public static void main(String[] args) {
Scanner scnr = new Scanner(System.in);
System.out.println("Enter the distance to be covered (miles):");
double distance;
distance = scnr.nextDouble();
double milesPerLiter = 13.7;
double litersPerGallon = 3.785;
double costPerGallon = 2.629;
scnr.close();
System.out.println("Fuel Needed: " + calcFuelNeeded(distance, milesPerLiter) + " liter(s)");
System.out.println("Gallons needed: " + calcGallonsFuelNeeded( calcFuelNeeded(distance, milesPerLiter), litersPerGallon) + " gallon(s)");
System.out.println("Cost needed: " +calcCostNeeded( calcGallonsFuelNeeded( calcFuelNeeded(distance, milesPerLiter), litersPerGallon), costPerGallon) + " $" );
}
}
I am developing a floodFill game using the Model-view-controller method. Now I am stuck building a stack that can store the clones of my gameModel objects.
public class GameModel implements Cloneable {
/**
* predefined values to capture the color of a DotInfo
*/
public static final int COLOR_0 = 0;
public static final int COLOR_1 = 1;
public static final int COLOR_2 = 2;
public static final int COLOR_3 = 3;
public static final int COLOR_4 = 4;
public static final int COLOR_5 = 5;
public static final int NUMBER_OF_COLORS = 6;
/**
* The current selection color
*/
private int currentSelectedColor;
/**
* The size of the game.
*/
private int sizeOfGame;
/**
* A 2 dimentionnal array of sizeOfGame*sizeOfGame recording the state of each dot
*/
private DotInfo[][] model;
/**
* The number of steps played since the last reset
*/
private int numberOfSteps;
/**
* The number of captered dots
*/
private int numberCaptured;
/**
* Random generator
*/
private Random generator;
/**
* Constructor to initialize the model to a given size of board.
*
* #param size
* the size of the board
*/
public GameModel(int size) {
generator = new Random();
sizeOfGame = size;
reset();
}
/**
* Resets the model to (re)start a game. The previous game (if there is one)
* is cleared up .
*/
public void reset(){
model = new DotInfo[sizeOfGame][sizeOfGame];
for(int i = 0; i < sizeOfGame; i++){
for(int j = 0; j < sizeOfGame; j++){
model[i][j] = new DotInfo(i,j,generator.nextInt(NUMBER_OF_COLORS));
}
}
numberOfSteps =0;
}
/**
* Getter method for the size of the game
*
* #return the value of the attribute sizeOfGame
*/
public int getSize(){
return sizeOfGame;
}
/**
* returns the color of a given dot in the game
*
* #param i
* the x coordinate of the dot
* #param j
* the y coordinate of the dot
* #return the status of the dot at location (i,j)
*/
public int getColor(int i, int j){
return isCaptured(i, j) ? currentSelectedColor : model[i][j].getColor();
}
/**
* returns true is the dot is captured, false otherwise
*
* #param i
* the x coordinate of the dot
* #param j
* the y coordinate of the dot
* #return the status of the dot at location (i,j)
*/
public boolean isCaptured(int i, int j){
return model[i][j].isCaptured();
}
/**
* Sets the status of the dot at coordinate (i,j) to captured
*
* #param i
* the x coordinate of the dot
* #param j
* the y coordinate of the dot
*/
public void capture(int i, int j){
model[i][j].setCaptured(true);
numberCaptured++;
}
/**
* Getter method for the current number of steps
*
* #return the current number of steps
*/
public int getNumberOfSteps(){
return numberOfSteps;
}
/**
* Setter method for currentSelectedColor
*
* #param val
* the new value for currentSelectedColor
*/
public void setCurrentSelectedColor(int val) {
currentSelectedColor = val;
}
/**
* Getter method for currentSelectedColor
*
* #return currentSelectedColor
*/
public int getCurrentSelectedColor() {
return currentSelectedColor ;
}
/**
* Getter method for the model's dotInfo reference
* at location (i,j)
*
* #param i
* the x coordinate of the dot
* #param j
* the y coordinate of the dot
*
* #return model[i][j]
*/
public DotInfo get(int i, int j) {
return model[i][j];
}
/**
* The metod <b>step</b> updates the number of steps. It must be called
* once the model has been updated after the payer selected a new color.
*/
public void step(){
numberOfSteps++;
}
/**
* The metod <b>isFinished</b> returns true iff the game is finished, that
* is, all the dats are captured.
*
* #return true if the game is finished, false otherwise
*/
public boolean isFinished(){
return numberCaptured == sizeOfGame*sizeOfGame;
}
public GameModel clone(){
try {
return (GameModel)super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
/**
* Builds a String representation of the model
*
* #return String representation of the model
*/
public String toString(){
StringBuffer b = new StringBuffer();
for(int i = 0; i < sizeOfGame; i++){
for(int j = 0; j < sizeOfGame; j++){
b.append(getColor(i, j) + " ");
}
b.append("\n");
}
return b.toString();
}
}
As you can see I have implemented cloneable and defined overriden the clone method the abstract class.
I am trying to clone the model so that the controller can use the function in its actionPerformed undo method.
public class GameController implements ActionListener{
/**
* Reference to the view of the board
*/
private GameView gameView;
/**
* Reference to the model of the game
*/
private GameModel gameModel;
private GameModel oldMove;
private int size;
private int i;
private int j;
private Stack<DotInfo> stack;
private boolean setting1;
private boolean setting2;
Stack<GameModel> steps;
/**
* Constructor used for initializing the controller. It creates the game's view
* and the game's model instances
*
* #param size
* the size of the board on which the game will be played
*/
public GameController(int size) {
gameModel = new GameModel(size);
gameView = new GameView(gameModel, this);
reset();
}
/**
* resets the game
*/
public void reset(){
steps= new GenericLinkedStack<GameModel>();
gameModel.reset();
flood();
gameView.update();
setting1 = false;
setting2 = false;
}
/**
* Callback used when the user clicks a button (reset or quit)
*
* #param e
* the ActionEvent
*/
public void actionPerformed(ActionEvent e) {
if (e.getSource() instanceof DotButton) {
if(gameModel.getNumberOfSteps()==0){
int row = ((DotButton)(e.getSource())).getRow();
int column = ((DotButton)(e.getSource())).getColumn();
gameModel.capture(row,column);
}
selectColor(((DotButton)(e.getSource())).getColor());
} else if (e.getSource() instanceof JButton) {
JButton clicked = (JButton)(e.getSource());
if (clicked.getText().equals("Quit")) {
System.exit(0);
} else if (clicked.getText().equals("Reset")){
reset();
} else if (clicked.getText().equals("Redo")) {
} else if (clicked.getText().equals("Undo")) {
steps.pop();
gameView.update();
} else if (clicked.getText().equals("Settings")) {
gameView.settingsMenu();
}
} else if (e.getSource() instanceof JRadioButton) {
JRadioButton clickedR = (JRadioButton)(e.getSource());
if (clickedR.getText().equals("Torus")) {
setting1 = true;
}
if (clickedR.getText().equals("Diagonal")) {
setting2 = true;
}
}
}
/**
* <b>selectColor</b> is the method called when the user selects a new color.
* If that color is not the currently selected one, then it applies the logic
* of the game to capture possible locations. It then checks if the game
* is finished, and if so, congratulates the player, showing the number of
* moves, and gives to options: start a new game, or exit
* #param color
* the newly selected color
*/
public void selectColor(int color){
steps.push(gameModel.clone());
if(color != gameModel.getCurrentSelectedColor()) {
gameModel.setCurrentSelectedColor(color);
flood();
gameModel.step();
gameView.update();
finished();
}
}
/**
* <b>flood</b> is the method that computes which new dots should be ``captured''
* when a new color has been selected. The Model is updated accordingly
*/
private void flood() {
size = gameModel.getSize()-1;
stack = new GenericLinkedStack<DotInfo>();
for(int i =0; i < gameModel.getSize(); i++) {
for(int j =0; j < gameModel.getSize(); j++) {
if(gameModel.isCaptured(i,j)) {
stack.push(gameModel.get(i,j));
}
}
}
DotInfo dotInfo;
while(!stack.isEmpty()){
dotInfo = stack.pop();
i = dotInfo.getX();
j = dotInfo.getY();
orthogonal();
if (setting1 == true) {
torus();
}
if (setting2 == true) {
diagonal();
}
}
}
/**
* <b>shouldBeCaptured</b> is a helper method that decides if the dot
* located at position (i,j), which is next to a captured dot, should
* itself be captured
* #param i
* row of the dot
* #param j
* column of the dot
*/
private boolean shouldBeCaptured(int x, int y) {
return (!gameModel.isCaptured(x, y) && (gameModel.getColor(x,y) == gameModel.getCurrentSelectedColor())) ? true : false;
}
private void captureAndStack(int x, int y) {
gameModel.capture(x, y);
stack.push(gameModel.get(x,y));
}
private void finished() {
if(gameModel.isFinished()) {
if (gameView.finishedMenu() == 0) {
reset();
} else {
System.exit(0);
}
}
}
I am using a stack to hold the states of the game but I am not sure how i can update the view using the past state. I dont think you need to see the view class of my game.
Can someone lead me on the right path of which methods i should implement and where.
I'm looking to convert OS Grid Reference to longitude and latitude, I'm using the jcoord library in Android studio, http://www.jstott.me.uk/jcoord/
I'm interested how I would connect this to a button that on on activity you can type in a grid reference on a edit text, and click convert (Which will do the magic formula) and will show the longitude and latitude below?
Basically I want to make a user interface, with being able to test this on my phone
I believe the formula will be done in the OSRef.java, with the code being the following:
public class OSRef extends Activity implements View.OnClickListener {
EditText osGridNumber;
View convertButton;
TextView latLongBox;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
convertButton = findViewById(R.id.cmdConvert);
convertButton.setOnClickListener(this);
osGridNumber = (EditText) findViewById(R.id.edtOS);
latLongBox = (TextView) findViewById(R.id.txtLngLat);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.cmdConvert:
break;
}
}
/**
* Easting
*/
private double easting;
/**
* Northing
*/
private double northing;
/**
* Create a new Ordnance Survey grid reference.
*
* #param easting the easting in metres
* #param northing the northing in metres
* #since 1.0
*/
public OSRef(double easting, double northing) {
this.easting = easting;
this.northing = northing;
}
/**
* Take a string formatted as a six-figure OS grid reference (e.g. "TG514131")
* and create a new OSRef object that represents that grid reference. The
* first character must be H, N, S, O or T. The second character can be any
* uppercase character from A through Z excluding I.
*
* #param ref a String representing a six-figure Ordnance Survey grid reference
* in the form XY123456
* #throws IllegalArgumentException if ref is not of the form XY123456
* #since 1.0
*/
public OSRef(String ref) throws IllegalArgumentException {
// if (ref.matches(""))
char char1 = ref.charAt(0);
char char2 = ref.charAt(1);
// Thanks to Nick Holloway for pointing out the radix bug here
int east = Integer.parseInt(ref.substring(2, 5)) * 100;
int north = Integer.parseInt(ref.substring(5, 8)) * 100;
if (char1 == 'H') {
north += 1000000;
} else if (char1 == 'N') {
north += 500000;
} else if (char1 == 'O') {
north += 500000;
east += 500000;
} else if (char1 == 'T') {
east += 500000;
}
int char2ord = char2;
if (char2ord > 73)
char2ord--; // Adjust for no I
double nx = ((char2ord - 65) % 5) * 100000;
double ny = (4 - Math.floor((char2ord - 65) / 5)) * 100000;
easting = east + nx;
northing = north + ny;
}
/**
* Return a String representation of this OSGB grid reference showing the
* easting and northing.
*
* #return a String represenation of this OSGB grid reference
* #since 1.0
*/
public String toString() {
return "(" + easting + ", " + northing + ")";
}
/**
* Return a String representation of this OSGB grid reference using the
* six-figure notation in the form XY123456
*
* #return a String representing this OSGB grid reference in six-figure
* notation
* #since 1.0
*/
public String toSixFigureString() {
int hundredkmE = (int) Math.floor(easting / 100000);
int hundredkmN = (int) Math.floor(northing / 100000);
String firstLetter;
if (hundredkmN < 5) {
if (hundredkmE < 5) {
firstLetter = "S";
} else {
firstLetter = "T";
}
} else if (hundredkmN < 10) {
if (hundredkmE < 5) {
firstLetter = "N";
} else {
firstLetter = "O";
}
} else {
firstLetter = "H";
}
int index = 65 + ((4 - (hundredkmN % 5)) * 5) + (hundredkmE % 5);
// int ti = index;
if (index >= 73)
index++;
String secondLetter = Character.toString((char) index);
int e = (int) Math.floor((easting - (100000 * hundredkmE)) / 100);
int n = (int) Math.floor((northing - (100000 * hundredkmN)) / 100);
String es = "" + e;
if (e < 100)
es = "0" + es;
if (e < 10)
es = "0" + es;
String ns = "" + n;
if (n < 100)
ns = "0" + ns;
if (n < 10)
ns = "0" + ns;
return firstLetter + secondLetter + es + ns;
}
/**
* Convert this OSGB grid reference to a latitude/longitude pair using the
* OSGB36 datum. Note that, the LatLng object may need to be converted to the
* WGS84 datum depending on the application.
*
* #return a LatLng object representing this OSGB grid reference using the
* OSGB36 datum
* #since 1.0
*/
public LatLng toLatLng() {
double OSGB_F0 = 0.9996012717;
double N0 = -100000.0;
double E0 = 400000.0;
double phi0 = Math.toRadians(49.0);
double lambda0 = Math.toRadians(-2.0);
double a = RefEll.AIRY_1830.getMaj();
double b = RefEll.AIRY_1830.getMin();
double eSquared = RefEll.AIRY_1830.getEcc();
double phi = 0.0;
double lambda = 0.0;
double E = this.easting;
double N = this.northing;
double n = (a - b) / (a + b);
double M = 0.0;
double phiPrime = ((N - N0) / (a * OSGB_F0)) + phi0;
do {
M =
(b * OSGB_F0)
* (((1 + n + ((5.0 / 4.0) * n * n) + ((5.0 / 4.0) * n * n * n)) * (phiPrime - phi0))
- (((3 * n) + (3 * n * n) + ((21.0 / 8.0) * n * n * n))
* Math.sin(phiPrime - phi0) * Math.cos(phiPrime + phi0))
+ ((((15.0 / 8.0) * n * n) + ((15.0 / 8.0) * n * n * n))
* Math.sin(2.0 * (phiPrime - phi0)) * Math
.cos(2.0 * (phiPrime + phi0))) - (((35.0 / 24.0) * n * n * n)
* Math.sin(3.0 * (phiPrime - phi0)) * Math
.cos(3.0 * (phiPrime + phi0))));
phiPrime += (N - N0 - M) / (a * OSGB_F0);
} while ((N - N0 - M) >= 0.001);
double v =
a * OSGB_F0
* Math.pow(1.0 - eSquared * Util.sinSquared(phiPrime), -0.5);
double rho =
a * OSGB_F0 * (1.0 - eSquared)
* Math.pow(1.0 - eSquared * Util.sinSquared(phiPrime), -1.5);
double etaSquared = (v / rho) - 1.0;
double VII = Math.tan(phiPrime) / (2 * rho * v);
double VIII =
(Math.tan(phiPrime) / (24.0 * rho * Math.pow(v, 3.0)))
* (5.0 + (3.0 * Util.tanSquared(phiPrime)) + etaSquared - (9.0 * Util
.tanSquared(phiPrime) * etaSquared));
double IX =
(Math.tan(phiPrime) / (720.0 * rho * Math.pow(v, 5.0)))
* (61.0 + (90.0 * Util.tanSquared(phiPrime)) + (45.0 * Util
.tanSquared(phiPrime) * Util.tanSquared(phiPrime)));
double X = Util.sec(phiPrime) / v;
double XI =
(Util.sec(phiPrime) / (6.0 * v * v * v))
* ((v / rho) + (2 * Util.tanSquared(phiPrime)));
double XII =
(Util.sec(phiPrime) / (120.0 * Math.pow(v, 5.0)))
* (5.0 + (28.0 * Util.tanSquared(phiPrime)) + (24.0 * Util
.tanSquared(phiPrime) * Util.tanSquared(phiPrime)));
double XIIA =
(Util.sec(phiPrime) / (5040.0 * Math.pow(v, 7.0)))
* (61.0
+ (662.0 * Util.tanSquared(phiPrime))
+ (1320.0 * Util.tanSquared(phiPrime) * Util
.tanSquared(phiPrime)) + (720.0 * Util.tanSquared(phiPrime)
* Util.tanSquared(phiPrime) * Util.tanSquared(phiPrime)));
phi =
phiPrime - (VII * Math.pow(E - E0, 2.0))
+ (VIII * Math.pow(E - E0, 4.0)) - (IX * Math.pow(E - E0, 6.0));
lambda =
lambda0 + (X * (E - E0)) - (XI * Math.pow(E - E0, 3.0))
+ (XII * Math.pow(E - E0, 5.0)) - (XIIA * Math.pow(E - E0, 7.0));
return new LatLng(Math.toDegrees(phi), Math.toDegrees(lambda));
}
/**
* Get the easting.
*
* #return the easting in metres
* #since 1.0
*/
public double getEasting() {
return easting;
}
/**
* Get the northing.
*
* #return the northing in metres
* #since 1.0
*/
public double getNorthing() {
return northing;
}
}
Thanks in advance
I wrote the following Java code to find zeroes for the Riemann-Siegel Z(t) function. I am wondering if I can optimize the code so that it doesn't take 36 hours to evaluate 0 < t < 1000000 (might not be possible though).
Through the findRoots() method inside the code sample below, can I adjust
double i = 0;
while (i < 1000000) {
i+= 0.001;
if(sign(func.value(i)) != sign(func.value(i+0.001))) {
set.add(f.solve(1000, func, i, i+0.001));
}
}
to do something faster? I am looking to increase i by 0.001 due to my investigation of the zeta function. Could I change this part so that the code doesn't take 36 hours to evaluate 0 < t < 1000000 while keeping i = 0.001?
The full program is pasted below. I am looking to change the part highlighted above.
Note: I am using a LinkedHashSet because I would like the output of the zeroes to be ordered when they are printed.
/**************************************************************************
**
** Apply Riemann-Siegel Formula for Lehmer's Phenomenon
**
**************************************************************************
** Axion004
** 09/30/2015
**************************************************************************/
import java.util.Iterator;
import java.util.LinkedHashSet;
//These two imports are from the Apache Commons Math library
import org.apache.commons.math3.analysis.UnivariateFunction;
import org.apache.commons.math3.analysis.solvers.BracketingNthOrderBrentSolver;
public class RiemannSiegel{
public static void main(String[] args){
SiegelMain();
}
// Main method
public static void SiegelMain() {
System.out.println("RS- Zeroes inside the critical line for " +
"Zeta(1/2 + it). The t values are referenced below.");
System.out.println();
findRoots();
}
/**
* The sign of a calculated double value.
* #param x - the double value.
* #return the sign in -1, 1, or 0 format.
*/
private static int sign(double x) {
if (x < 0.0)
return -1;
else if (x > 0.0)
return 1;
else
return 0;
}
/**
* Finds the roots of a specified function through the
* BracketingNthOrderBrentSolver from the Apache Commons Math library.
* See http://commons.apache.org/proper/commons-math/apidocs/org/
* apache/commons/math3/analysis/solvers/BracketingNthOrderBrentSolver
* .html
* The zeroes inside the interval of 0 < t < 10000 are printed from
* a LinkedHashSet.
*/
public static void findRoots() {
BracketingNthOrderBrentSolver f = new
BracketingNthOrderBrentSolver(1e-10, 10);
UnivariateFunction func = new UnivariateFunction() {
public double value(double x) {
return RiemennZ(x, 4);
}
};
LinkedHashSet<Double> set = new LinkedHashSet<>();
// Adjust values to see different zeroes
// Test adjusting values to understand the code
double i = 0;
while (i < 1000000) {
i+= 0.001;
if(sign(func.value(i)) != sign(func.value(i+0.001))) {
set.add(f.solve(1000, func, i, i+0.001));
}
}
for(Double s: set)
System.out.println(s);
}
/**
* Riemann-Siegel theta function using the approximation by the
* Stirling series.
* #param t - the value of t inside the Z(t) function.
* #return Stirling's approximation for theta(t).
*/
public static double theta (double t) {
return (t/2.0 * Math.log(t/(2.0*Math.PI)) - t/2.0 - Math.PI/8.0
+ 1.0/(48.0*Math.pow(t, 1)) + 7.0/(5760*Math.pow(t, 3)));
}
/**
* Computes Math.Floor of the absolute value term passed in as t.
* #param t - the value of t inside the Z(t) function.
* #return Math.floor of the absolute value of t.
*/
public static double fAbs(double t) {
return Math.floor(Math.abs(t));
}
/**
* Riemann-Siegel Z(t) function implemented per the Riemenn Siegel
* formula. See http://mathworld.wolfram.com/Riemann-SiegelFormula.html
* for details
* #param t - the value of t inside the Z(t) function.
* #param r - referenced for calculating the remainder terms by the
* Taylor series approximations.
* #return the approximate value of Z(t) through the Riemann-Siegel
* formula
*/
public static double RiemennZ(double t, int r) {
double twopi = Math.PI * 2.0;
double val = Math.sqrt(t/twopi);
double n = fAbs(val);
double sum = 0.0;
for (int i = 1; i <= n; i++) {
sum += (Math.cos(theta(t) - t * Math.log(i))) / Math.sqrt(i);
}
sum = 2.0 * sum;
double remainder;
double frac = val - n;
int k = 0;
double R = 0.0;
// Necessary to individually calculate each remainder term by using
// Taylor Series co-efficients. These coefficients are defined below.
while (k <= r) {
R = R + C(k, 2.0*frac-1.0) * Math.pow(t / twopi,
((double) k) * -0.5);
k++;
}
remainder = Math.pow(-1, (int)n-1) * Math.pow(t / twopi, -0.25) * R;
return sum + remainder;
}
/**
* C terms for the Riemann-Siegel formula. See
* https://web.viu.ca/pughg/thesis.d/masters.thesis.pdf for details.
* Calculates the Taylor Series coefficients for C0, C1, C2, C3,
* and C4.
* #param n - the number of coefficient terms to use.
* #param z - referenced per the Taylor series calculations.
* #return the Taylor series approximation of the remainder terms.
*/
public static double C (int n, double z) {
if (n==0)
return(.38268343236508977173 * Math.pow(z, 0.0)
+.43724046807752044936 * Math.pow(z, 2.0)
+.13237657548034352332 * Math.pow(z, 4.0)
-.01360502604767418865 * Math.pow(z, 6.0)
-.01356762197010358089 * Math.pow(z, 8.0)
-.00162372532314446528 * Math.pow(z,10.0)
+.00029705353733379691 * Math.pow(z,12.0)
+.00007943300879521470 * Math.pow(z,14.0)
+.00000046556124614505 * Math.pow(z,16.0)
-.00000143272516309551 * Math.pow(z,18.0)
-.00000010354847112313 * Math.pow(z,20.0)
+.00000001235792708386 * Math.pow(z,22.0)
+.00000000178810838580 * Math.pow(z,24.0)
-.00000000003391414390 * Math.pow(z,26.0)
-.00000000001632663390 * Math.pow(z,28.0)
-.00000000000037851093 * Math.pow(z,30.0)
+.00000000000009327423 * Math.pow(z,32.0)
+.00000000000000522184 * Math.pow(z,34.0)
-.00000000000000033507 * Math.pow(z,36.0)
-.00000000000000003412 * Math.pow(z,38.0)
+.00000000000000000058 * Math.pow(z,40.0)
+.00000000000000000015 * Math.pow(z,42.0));
else if (n==1)
return(-.02682510262837534703 * Math.pow(z, 1.0)
+.01378477342635185305 * Math.pow(z, 3.0)
+.03849125048223508223 * Math.pow(z, 5.0)
+.00987106629906207647 * Math.pow(z, 7.0)
-.00331075976085840433 * Math.pow(z, 9.0)
-.00146478085779541508 * Math.pow(z,11.0)
-.00001320794062487696 * Math.pow(z,13.0)
+.00005922748701847141 * Math.pow(z,15.0)
+.00000598024258537345 * Math.pow(z,17.0)
-.00000096413224561698 * Math.pow(z,19.0)
-.00000018334733722714 * Math.pow(z,21.0)
+.00000000446708756272 * Math.pow(z,23.0)
+.00000000270963508218 * Math.pow(z,25.0)
+.00000000007785288654 * Math.pow(z,27.0)
-.00000000002343762601 * Math.pow(z,29.0)
-.00000000000158301728 * Math.pow(z,31.0)
+.00000000000012119942 * Math.pow(z,33.0)
+.00000000000001458378 * Math.pow(z,35.0)
-.00000000000000028786 * Math.pow(z,37.0)
-.00000000000000008663 * Math.pow(z,39.0)
-.00000000000000000084 * Math.pow(z,41.0)
+.00000000000000000036 * Math.pow(z,43.0)
+.00000000000000000001 * Math.pow(z,45.0));
else if (n==2)
return(+.00518854283029316849 * Math.pow(z, 0.0)
+.00030946583880634746 * Math.pow(z, 2.0)
-.01133594107822937338 * Math.pow(z, 4.0)
+.00223304574195814477 * Math.pow(z, 6.0)
+.00519663740886233021 * Math.pow(z, 8.0)
+.00034399144076208337 * Math.pow(z,10.0)
-.00059106484274705828 * Math.pow(z,12.0)
-.00010229972547935857 * Math.pow(z,14.0)
+.00002088839221699276 * Math.pow(z,16.0)
+.00000592766549309654 * Math.pow(z,18.0)
-.00000016423838362436 * Math.pow(z,20.0)
-.00000015161199700941 * Math.pow(z,22.0)
-.00000000590780369821 * Math.pow(z,24.0)
+.00000000209115148595 * Math.pow(z,26.0)
+.00000000017815649583 * Math.pow(z,28.0)
-.00000000001616407246 * Math.pow(z,30.0)
-.00000000000238069625 * Math.pow(z,32.0)
+.00000000000005398265 * Math.pow(z,34.0)
+.00000000000001975014 * Math.pow(z,36.0)
+.00000000000000023333 * Math.pow(z,38.0)
-.00000000000000011188 * Math.pow(z,40.0)
-.00000000000000000416 * Math.pow(z,42.0)
+.00000000000000000044 * Math.pow(z,44.0)
+.00000000000000000003 * Math.pow(z,46.0));
else if (n==3)
return(-.00133971609071945690 * Math.pow(z, 1.0)
+.00374421513637939370 * Math.pow(z, 3.0)
-.00133031789193214681 * Math.pow(z, 5.0)
-.00226546607654717871 * Math.pow(z, 7.0)
+.00095484999985067304 * Math.pow(z, 9.0)
+.00060100384589636039 * Math.pow(z,11.0)
-.00010128858286776622 * Math.pow(z,13.0)
-.00006865733449299826 * Math.pow(z,15.0)
+.00000059853667915386 * Math.pow(z,17.0)
+.00000333165985123995 * Math.pow(z,19.0)
+.00000021919289102435 * Math.pow(z,21.0)
-.00000007890884245681 * Math.pow(z,23.0)
-.00000000941468508130 * Math.pow(z,25.0)
+.00000000095701162109 * Math.pow(z,27.0)
+.00000000018763137453 * Math.pow(z,29.0)
-.00000000000443783768 * Math.pow(z,31.0)
-.00000000000224267385 * Math.pow(z,33.0)
-.00000000000003627687 * Math.pow(z,35.0)
+.00000000000001763981 * Math.pow(z,37.0)
+.00000000000000079608 * Math.pow(z,39.0)
-.00000000000000009420 * Math.pow(z,41.0)
-.00000000000000000713 * Math.pow(z,43.0)
+.00000000000000000033 * Math.pow(z,45.0)
+.00000000000000000004 * Math.pow(z,47.0));
else
return(+.00046483389361763382 * Math.pow(z, 0.0)
-.00100566073653404708 * Math.pow(z, 2.0)
+.00024044856573725793 * Math.pow(z, 4.0)
+.00102830861497023219 * Math.pow(z, 6.0)
-.00076578610717556442 * Math.pow(z, 8.0)
-.00020365286803084818 * Math.pow(z,10.0)
+.00023212290491068728 * Math.pow(z,12.0)
+.00003260214424386520 * Math.pow(z,14.0)
-.00002557906251794953 * Math.pow(z,16.0)
-.00000410746443891574 * Math.pow(z,18.0)
+.00000117811136403713 * Math.pow(z,20.0)
+.00000024456561422485 * Math.pow(z,22.0)
-.00000002391582476734 * Math.pow(z,24.0)
-.00000000750521420704 * Math.pow(z,26.0)
+.00000000013312279416 * Math.pow(z,28.0)
+.00000000013440626754 * Math.pow(z,30.0)
+.00000000000351377004 * Math.pow(z,32.0)
-.00000000000151915445 * Math.pow(z,34.0)
-.00000000000008915418 * Math.pow(z,36.0)
+.00000000000001119589 * Math.pow(z,38.0)
+.00000000000000105160 * Math.pow(z,40.0)
-.00000000000000005179 * Math.pow(z,42.0)
-.00000000000000000807 * Math.pow(z,44.0)
+.00000000000000000011 * Math.pow(z,46.0)
+.00000000000000000004 * Math.pow(z,48.0));
}
}
I would like to develop a desktop application which is able to draw a given function's graph but in a coordinate-system with custom axises.
E.g.: user can change between linear, logarithmic, exponential etc.. axis types in case of both X and Y axis.
Do you think that Java AWT is suitable to this purpose? (I don't know yet),
Do you have any idea what other technologies can/should be used?
In this case time is the most important, so I need the simplest way..
Thank you in advance,
Marton
Swing or JavaFX would be better than AWT.
Here's some code I developed to lay a Cartesian and / or Polar coordinate system on a Swing drawing area. You can use this as a starting point for what you want to do.
CoordinateSystem class
package com.ggl.game.utilities;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.geom.Point2D;
/**
* <p>
* This class creates a Cartesian and Polar coordinate system to overlay a Swing
* drawing area (usually a <code>JPanel</code>). The user of the class sets a
* limit as to how far the X axis or the Y axis extends in the negative and
* positive direction from (0, 0). Point (0, 0) will be placed in the center of
* the drawing area.
* </p>
* <p>
* Since the drawing area is usually not square, the limit applies to the
* shorter dimension. The actual limits can be retrieved from this class, and
* will change if the user of the application changes the drawing area size by
* maximizing or normalizing the application <code>JFrame</code> window.
* </p>
* <p>
* Using a Cartesian or Polar coordinate system frees the user of this class
* from having to worry about Swing pixel coordinates.
* </p>
*
* #author Gilbert G. Le Blanc
* #version 1.0 - 23 February 2015
*
* #see com.ggl.game.utilities.Polar2D
* #see java.awt.geom.Point2D
* #see javax.swing.JFrame
* #see javax.swing.JPanel
*/
public class CoordinateSystem {
private double conversionFactor;
private double xLimit;
private double yLimit;
private int height;
private int width;
/**
* <p>
* This creates a Cartesian and Polar coordinate system over a Swing drawing
* area (usually a <code>JPanel</code>). If the drawing area is square, the
* X axis extends from -limit to limit and the Y axis extends from -limit to
* limit.
* </p>
* <p>
* If the drawing area is not square, then the smaller dimension, either X
* or Y, extends from -limit to limit. The larger dimension extends beyond
* the limit in both directions.
* </p>
* <p>
* Since most displays are not square, the X and Y axis will usually have
* different limits.
* </p>
*
* #param limit
* - The limit of the X and Y axis in a Cartesian coordinate
* system.
* #param width
* - The width of the drawing area in pixels.
* #param height
* - The height of the drawing area in pixels.
*/
public CoordinateSystem(double limit, int width, int height) {
this.width = width;
this.height = height;
if (width > height) {
this.xLimit = limit * width / height;
this.yLimit = limit;
this.conversionFactor = (limit + limit) / (double) height;
} else if (width < height) {
this.xLimit = limit;
this.yLimit = limit * height / width;
this.conversionFactor = (limit + limit) / (double) width;
} else {
this.xLimit = limit;
this.yLimit = limit;
this.conversionFactor = (limit + limit) / (double) width;
}
}
/**
* This method changes the drawing area dimension, along with the X and Y
* axis limits.
*
* #param dimension
* - A <code>Dimension</code> with the new drawing area
* dimension.
*/
public void setDrawingSize(Dimension dimension) {
setDrawingSize(dimension.width, dimension.height);
}
/**
* This method changes the drawing area width and height, along with the X
* and Y axis limits.
*
* #param width
* - The width of the drawing area in pixels.
* #param height
* - The height of the drawing area in pixels.
*/
public void setDrawingSize(int width, int height) {
xLimit = xLimit / this.width * width;
yLimit = yLimit / this.height * height;
this.width = width;
this.height = height;
}
/**
* This method returns the Cartesian coordinate limit for the X axis.
*
* #return The Cartesian coordinate limit for the X axis.
*/
public double getxLimit() {
return xLimit;
}
/**
* This method returns the Cartesian coordinate limit for the Y axis.
*
* #return The Cartesian coordinate limit for the Y axis.
*/
public double getyLimit() {
return yLimit;
}
/**
* This method converts a Polar coordinate distance and theta angle in
* radians to a pixel location on a drawing area.
*
* #param distance
* - A Polar coordinate distance
* #param theta
* - A Polar coordinate theta angle in radians
* #return A pixel location on a drawing area.
*/
public Point convertPolarToPixels(double distance, double theta) {
return convertToPixels(new Polar2D.Double(distance, theta));
}
/**
* This method converts a Cartesian coordinate x and y to a pixel location
* on a drawing area.
*
* #param x
* - A Cartesian coordinate x.
* #param y
* - A Cartesian coordinate y.
* #return A pixel location on a drawing area.
*/
public Point convertPointToPixels(double x, double y) {
return convertToPixels(new Point2D.Double(x, y));
}
/**
* This method converts a Polar coordinate to a pixel location on a drawing
* area.
*
* #param polar
* - A Polar coordinate.
* #return A pixel location on a drawing area.
*/
public Point convertToPixels(Polar2D polar) {
double x = polar.getDistance() * Math.cos(polar.getTheta());
double y = polar.getDistance() * Math.sin(polar.getTheta());
return convertToPixels(new Point2D.Double(x, y));
}
/**
* This method converts a Cartesian coordinate to a pixel location on a
* drawing area.
*
* #param cartesian
* - A Cartesian coordinate.
* #return A pixel location on a drawing area.
*/
public Point convertToPixels(Point2D cartesian) {
int x = (int) Math
.round((cartesian.getX() + xLimit) / conversionFactor);
int y = (int) Math.round((-cartesian.getY() + yLimit)
/ conversionFactor);
return new Point(x, y);
}
/**
* This method converts a pixel location on a drawing area to a Cartesian
* coordinate.
*
* #param x
* - The x pixel location.
* #param y
* - The y pixel location.
* #return A Cartesian coordinate.
*/
public Point2D convertToCartesian(int x, int y) {
return convertToCartesian(new Point(x, y));
}
/**
* This method converts a pixel location on a drawing area to a Cartesian
* coordinate.
*
* #param point
* - The pixel location.
* #return A Cartesian coordinate.
*/
public Point2D convertToCartesian(Point point) {
double x = (double) point.x * conversionFactor - xLimit;
double y = (double) -point.y * conversionFactor + yLimit;
return new Point2D.Double(x, y);
}
/**
* This method converts a pixel location on a drawing area to a Polar
* coordinate.
*
* #param x
* - The x pixel location.
* #param y
* - The y pixel location.
* #return A Polar coordinate.
*/
public Polar2D convertToPolar(int x, int y) {
return convertToPolar(new Point(x, y));
}
/**
* This method converts a pixel location on a drawing area to a Polar
* coordinate.
*
* #param point
* - The pixel location.
* #return A Polar coordinate.
*/
public Polar2D convertToPolar(Point point) {
double x = (double) point.x * conversionFactor - xLimit;
double y = (double) -point.y * conversionFactor + yLimit;
double distance = Math.sqrt(x * x + y * y);
double theta = Math.atan2(y, x);
return new Polar2D.Double(distance, theta);
}
}
Polar2D class
package com.ggl.game.utilities;
/**
* The <code>Polar2D</code> class defines a point representing a location in
* distance, theta angle coordinate space.
* <p>
* This class is only the abstract superclass for all objects that store a 2D
* coordinate. The actual storage representation of the coordinates is left to
* the subclass.
*
* #version 1.0 - 23 February 2015
* #author Jim Graham (author of Point2D), Gilbert Le Blanc
*/
public abstract class Polar2D implements Cloneable {
/**
* The <code>Float</code> class defines a point specified in float
* precision.
*/
public static class Float extends Polar2D {
/**
* The distance of this <code>Polar2D</code>.
*
* #since 1.7
*/
public float distance;
/**
* The theta angle of this <code>Polar2D</code>.
*
* #since 1.7
*/
public float theta;
/**
* Constructs and initializes a <code>Polar2D</code> with coordinates
* (0, 0).
*
* #since 1.7
*/
public Float() {
}
/**
* Constructs and initializes a <code>Polar2D</code> with the specified
* coordinates.
*
* #param distance
* The distance to which to set the newly constructed
* <code>Polar2D</code>
* #param theta
* The theta angle in radians to which to set the newly
* constructed <code>Polar2D</code>
* #since 1.7
*/
public Float(float distance, float theta) {
this.distance = distance;
this.theta = theta;
}
/**
* Returns the distance of this <code>Polar2D</code> in
* <code>double</code> precision.
*
* #return the distance of this <code>Polar2D</code>.
* #since 1.7
*/
#Override
public double getDistance() {
return (double) distance;
}
/**
* Returns the theta angle in radians of this <code>Polar2D</code> in
* <code>double</code> precision.
*
* #return the theta angle in radians of this <code>Polar2D</code>.
* #since 1.7
*/
#Override
public double getTheta() {
return (double) theta;
}
/**
* Returns the theta angle in degrees of this <code>Polar2D</code> in
* <code>double</code> precision.
*
* #return the theta angle in degrees of this <code>Polar2D</code>.
* #since 1.7
*/
#Override
public double getThetaInDegrees() {
double degrees = 180D / Math.PI * theta;
return (degrees < 0D) ? degrees + 360D : degrees;
}
/**
* Sets the location of this <code>Polar2D</code> to the specified
* <code>double</code> distance and theta angle in radians.
*
* #param distance
* The distance to which to set this <code>Polar2D</code>
* #param theta
* The theta angle in radians to which to set this
* <code>Polar2D</code>
* #since 1.7
*/
#Override
public void setLocation(double distance, double theta) {
this.distance = (float) distance;
this.theta = (float) theta;
}
/**
* Sets the location of this <code>Polar2D</code> to the specified
* <code>float</code> coordinates.
*
* #param distance
* The distance to which to set this <code>Polar2D</code>
* #param theta
* The theta angle in radians to which to set this
* <code>Polar2D</code>
* #since 1.7
*/
public void setLocation(float distance, float theta) {
this.distance = distance;
this.theta = theta;
}
/**
* Returns a <code>String</code> that represents the value of this
* <code>Polar2D</code>.
*
* #return A <code>String</code> representation of this
* <code>Polar2D</code>.
* #since 1.7
*/
#Override
public String toString() {
return "Polar2D.Float[" + distance + ", " + theta + "]";
}
}
/**
* The <code>Double</code> class defines a point specified in
* <code>double</code> precision.
*/
public static class Double extends Polar2D {
/**
* The distance of this <code>Polar2D</code>.
*
* #since 1.7
*/
public double distance;
/**
* The theta angle in radians of this <code>Polar2D</code>.
*
* #since 1.7
*/
public double theta;
/**
* Constructs and initializes a <code>Polar2D</code> with (0, 0)
* distance and theta angle in radians.
*
* #since 1.7
*/
public Double() {
}
/**
* Constructs and initializes a <code>Polar2D</code> with the specified
* coordinates.
*
* #param distance
* The distance to which to set the newly constructed
* <code>Polar2D</code>
* #param theta
* The theta angle in radians to which to set the newly
* constructed <code>Polar2D</code>
* #since 1.7
*/
public Double(double distance, double theta) {
this.distance = distance;
this.theta = theta;
}
/**
* Returns the distance of this <code>Polar2D</code> in
* <code>double</code> precision.
*
* #return The distance of this <code>Polar2D</code>.
* #since 1.7
*/
#Override
public double getDistance() {
return distance;
}
/**
* Returns the theta angle in radians of this <code>Polar2D</code> in
* <code>double</code> precision.
*
* #return The theta angle in radians of this <code>Polar2D</code>.
* #since 1.7
*/
#Override
public double getTheta() {
return theta;
}
/**
* Returns the theta angle in degrees of this <code>Polar2D</code> in
* <code>double</code> precision.
*
* #return The theta angle in degrees of this <code>Polar2D</code>.
* #since 1.7
*/
#Override
public double getThetaInDegrees() {
double degrees = 180D / Math.PI * theta;
return (degrees < 0D) ? degrees + 360D : degrees;
}
/**
* Sets the location of this <code>Polar2D</code> to the specified
* <code>double</code> coordinates.
*
* #param distance
* The distance to which to set this <code>Polar2D</code>
* #param theta
* The theta angle in radians to which to set this
* <code>Polar2D</code>
* #since 1.7
*/
#Override
public void setLocation(double distance, double theta) {
this.distance = distance;
this.theta = theta;
}
/**
* Returns a <code>String</code> that represents the value of this
* <code>Polar2D</code>.
*
* #return A <code>String</code> representation of this
* <code>Polar2D</code>.
* #since 1.7
*/
#Override
public String toString() {
return "Polar2D.Double[" + distance + ", " + theta + "]";
}
}
/**
* This is an abstract class that cannot be instantiated directly.
* Type-specific implementation subclasses are available for instantiation
* and provide a number of formats for storing the information necessary to
* satisfy the various accessor methods below.
*
* #see java.awt.geom.Polar2D.Float
* #see java.awt.geom.Polar2D.Double
* #see java.awt.Point
*/
protected Polar2D() {
}
/**
* Returns the distance of this <code>Polar2D</code> in <code>double</code>
* precision.
*
* #return The distance of this <code>Polar2D</code>.
* #since 1.7
*/
public abstract double getDistance();
/**
* Returns the theta angle in radians of this <code>Polar2D</code> in
* <code>double</code> precision.
*
* #return The theta angle in radians of this <code>Polar2D</code>.
* #since 1.7
*/
public abstract double getTheta();
/**
* Returns the theta angle in degrees of this <code>Polar2D</code> in
* <code>double</code> precision.
*
* #return The theta angle in degrees of this <code>Polar2D</code>.
* #since 1.7
*/
public abstract double getThetaInDegrees();
/**
* Sets the location of this <code>Polar2D</code> to the specified
* <code>double</code> coordinates.
*
* #param distance
* The distance of this <code>Polar2D</code>
* #param theta
* The theta angle in radians of this <code>Polar2D</code>
* #since 1.7
*/
public abstract void setLocation(double distance, double theta);
/**
* Sets the location of this <code>Polar2D</code> to the same coordinates as
* the specified <code>Polar2D</code> object.
*
* #param p
* the specified <code>Polar2D</code> the which to set this
* <code>Polar2D</code>
* #since 1.7
*/
public void setLocation(Polar2D p) {
setLocation(p.getDistance(), p.getTheta());
}
/**
* Returns the square of the distance between two points.
*
* #param distance1
* The distance of the first point
* #Parm theta1 The theta angle in radians of the first point
* #param distance2
* The distance of the second point
* #param theta2
* The theta angle in radians of the second point
* #return The square of the distance between the two specified points.
*/
public static double distanceSq(double distance1, double theta1,
double distance2, double theta2) {
double x1 = distance1 * Math.cos(theta1);
double y1 = distance1 * Math.sin(theta1);
double x2 = distance2 * Math.cos(theta2);
double y2 = distance2 * Math.sin(theta2);
return (x1 * x2 + y1 * y2);
}
/**
* Returns the distance between two points.
*
* #param distance1
* The distance of the first point
* #param theta1
* The theta angle in radians of the first point
* #param distance2
* The distance of the second point
* #param theta2
* The theta angle in radians of the second point
* #return The distance between the two specified points.
*/
public static double distance(double distance1, double theta1,
double distance2, double theta2) {
double x1 = distance1 * Math.cos(theta1);
double y1 = distance1 * Math.sin(theta1);
double x2 = distance2 * Math.cos(theta2);
double y2 = distance2 * Math.sin(theta2);
return Math.sqrt(x1 * x2 + y1 * y2);
}
/**
* Returns the square of the distance from this <code>Polar2D</code> to a
* specified point.
*
* #param distance
* The distance of the specified point
* #param theta
* The theta angle in radians of the specified point
* #return The square of the distance between this <code>Polar2D</code> and
* the specified point.
*/
public double distanceSq(double distance, double theta) {
double x1 = distance * Math.cos(theta);
double y1 = distance * Math.sin(theta);
double x2 = getDistance() * Math.cos(getTheta());
double y2 = getDistance() * Math.sin(getTheta());
return (x1 * x2 + y1 * y2);
}
/**
* Returns the square of the distance from this <code>Polar2D</code> to a
* specified <code>Polar2D</code>.
*
* #param pt
* The specified <code>Polar2D</code>
* #return The square of the distance between this <code>Polar2D</code> to a
* specified <code>Polar2D</code>.
*/
public double distanceSq(Polar2D pt) {
double x1 = pt.getDistance() * Math.cos(pt.getTheta());
double y1 = pt.getDistance() * Math.sin(pt.getTheta());
double x2 = getDistance() * Math.cos(getTheta());
double y2 = getDistance() * Math.sin(getTheta());
return (x1 * x2 + y1 * y2);
}
/**
* Returns the distance from this <code>Polar2D</code> to a specified point.
*
* #param distance
* The distance of the specified point
* #param theta
* The theta angle in radians of the specified point
* #return The distance between this <code>Polar2D</code> and a specified
* point.
*/
public double distance(double distance, double theta) {
double x1 = distance * Math.cos(theta);
double y1 = distance * Math.sin(theta);
double x2 = getDistance() * Math.cos(getTheta());
double y2 = getDistance() * Math.sin(getTheta());
return Math.sqrt(x1 * x2 + y1 * y2);
}
/**
* Returns the distance from this <code>Polar2D</code> to a specified
* <code>Polar2D</code>.
*
* #param pt
* the specified <code>Polar2D</code>
* #return The distance between this <code>Polar2D</code> and the specified
* <code>Polar2D</code>.
*/
public double distance(Polar2D pt) {
double x1 = pt.getDistance() * Math.cos(pt.getTheta());
double y1 = pt.getDistance() * Math.sin(pt.getTheta());
double x2 = getDistance() * Math.cos(getTheta());
double y2 = getDistance() * Math.sin(getTheta());
return Math.sqrt(x1 * x2 + y1 * y2);
}
/**
* Creates a new object of the same class and with the same contents as this
* object.
*
* #return a clone of this instance.
* #exception OutOfMemoryError
* if there is not enough memory.
* #see java.lang.Cloneable
* #since 1.7
*/
#Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
}
/**
* Returns the hash code for this <code>Polar2D</code>.
*
* #return a hash code for this <code>Polar2D</code>.
*/
#Override
public int hashCode() {
long bits = java.lang.Double.doubleToLongBits(getDistance());
bits ^= java.lang.Double.doubleToLongBits(getTheta()) * 31;
return (((int) bits) ^ ((int) (bits >> 32)));
}
/**
* Determines whether or not two points are equal. Two instances of
* <code>Polar2D</code> are equal if the values of their <code>x</code> and
* <code>y</code> member fields, representing their position in the
* coordinate space, are the same.
*
* #param obj
* an object to be compared with this <code>Polar2D</code>
* #return <code>true</code> if the object to be compared is an instance of
* <code>Polar2D</code> and has the same values; <code>false</code>
* otherwise.
* #since 1.7
*/
#Override
public boolean equals(Object obj) {
if (obj instanceof Polar2D) {
Polar2D p2d = (Polar2D) obj;
return (getDistance() == p2d.getDistance())
&& (getTheta() == p2d.getTheta());
}
return super.equals(obj);
}
}
Continued in another answer.
Continued from the first part of the answer because of an annoying 30,000 character limit on answers.
Here's some code to test the two classes in the first part of the answer.
CoordinateSystemTester class
package com.ggl.game.utilities.swing;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.font.FontRenderContext;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import com.ggl.game.utilities.CoordinateSystem;
import com.ggl.game.utilities.Polar2D;
public class CoordinateSystemTester implements Runnable {
private DrawingPanel drawingPanel;
private JFrame frame;
#Override
public void run() {
frame = new JFrame("Coordinate System Tester");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
drawingPanel = new DrawingPanel(640, 480);
mainPanel.add(drawingPanel);
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new CoordinateSystemTester());
}
private class DrawingPanel extends JPanel {
private static final long serialVersionUID = 1519119839534910933L;
private CoordinateSystem coordinateSystem;
private Point pixelPoint;
private Point2D coordinatePoint;
private String coordinateString;
public DrawingPanel(int width, int height) {
this.coordinateSystem = new CoordinateSystem(25.0D, width, height);
this.coordinatePoint = new Point2D.Double();
this.pixelPoint = new Point();
this.coordinateString = "";
addComponentListener(new SizeListener());
addMouseListener(new CoordinateListener());
setPreferredSize(new Dimension(width, height));
}
public CoordinateSystem getCoordinateSystem() {
return coordinateSystem;
}
public Point2D getCoordinatePoint() {
return coordinatePoint;
}
public void setCoordinatePoint(Point2D coordinatePoint) {
this.coordinatePoint = coordinatePoint;
}
public Point getPixelPoint() {
return pixelPoint;
}
public void setPixelPoint(Point pixelPoint) {
this.pixelPoint = pixelPoint;
}
public void setCoordinateString(String coordinateString) {
this.coordinateString = coordinateString;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.setColor(Color.BLACK);
g2d.drawString(createLimitsString(), 10, 20);
drawXAxis(g2d, g);
drawYAxis(g2d, g);
drawCoordinate(g2d, g);
}
private String createLimitsString() {
String xs = String.format("%.2f", coordinateSystem.getxLimit());
String ys = String.format("%.2f", coordinateSystem.getyLimit());
StringBuilder builder = new StringBuilder();
builder.append("The actual limits are (");
builder.append(xs);
builder.append(", ");
builder.append(ys);
builder.append(")");
return builder.toString();
}
private void drawXAxis(Graphics2D g2d, Graphics g) {
g2d.setColor(Color.BLACK);
g2d.setStroke(new BasicStroke(5.0F));
Point p1 = coordinateSystem.convertPointToPixels(-20.0D, 0.0D);
Point p2 = coordinateSystem.convertPointToPixels(20.0D, 0.0D);
g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
g2d.setStroke(new BasicStroke(3.0F));
p1 = coordinateSystem.convertPointToPixels(-20.0D, -1.0D);
p2 = coordinateSystem.convertPointToPixels(-20.0D, 1.0D);
g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
Font font = getFont();
Point p3 = coordinateSystem.convertPointToPixels(-20.0D, -1.0D);
Rectangle r = new Rectangle(p3.x - 20, p3.y, 40, 20);
centerString(g, r, "-20.0", font);
p1 = coordinateSystem.convertPointToPixels(-10.0D, -1.0D);
p2 = coordinateSystem.convertPointToPixels(-10.0D, 1.0D);
g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
p3 = coordinateSystem.convertPointToPixels(-10.0D, -1.0D);
r = new Rectangle(p3.x - 20, p3.y, 40, 20);
centerString(g, r, "-10.0", font);
p1 = coordinateSystem.convertPointToPixels(10.0D, -1.0D);
p2 = coordinateSystem.convertPointToPixels(10.0D, 1.0D);
g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
p3 = coordinateSystem.convertPointToPixels(10.0D, -1.0D);
r = new Rectangle(p3.x - 20, p3.y, 40, 20);
centerString(g, r, "10.0", font);
p1 = coordinateSystem.convertPointToPixels(20.0D, -1.0D);
p2 = coordinateSystem.convertPointToPixels(20.0D, 1.0D);
g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
p3 = coordinateSystem.convertPointToPixels(20.0D, -1.0D);
r = new Rectangle(p3.x - 20, p3.y, 40, 20);
centerString(g, r, "20.0", font);
}
private void drawYAxis(Graphics2D g2d, Graphics g) {
g2d.setColor(Color.BLACK);
g2d.setStroke(new BasicStroke(5.0F));
Point p1 = coordinateSystem.convertPointToPixels(0.0D, -20.0D);
Point p2 = coordinateSystem.convertPointToPixels(0.0D, 20.0D);
g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
g2d.setStroke(new BasicStroke(3.0F));
p1 = coordinateSystem.convertPointToPixels(-1.0D, -20.0D);
p2 = coordinateSystem.convertPointToPixels(1.0D, -20.0D);
g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
Font font = getFont();
Point p3 = coordinateSystem.convertPointToPixels(3.0D, -20.0D);
Rectangle r = new Rectangle(p3.x - 20, p3.y, 40, 20);
centerString(g, r, "-20.0", font);
p1 = coordinateSystem.convertPointToPixels(-1.0D, -10.0D);
p2 = coordinateSystem.convertPointToPixels(1.0D, -10.0D);
g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
p3 = coordinateSystem.convertPointToPixels(3.0D, -10.0D);
r = new Rectangle(p3.x - 20, p3.y, 40, 20);
centerString(g, r, "-10.0", font);
p1 = coordinateSystem.convertPointToPixels(-1.0D, 10.0D);
p2 = coordinateSystem.convertPointToPixels(1.0D, 10.0D);
g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
p3 = coordinateSystem.convertPointToPixels(3.0D, 10.0D);
r = new Rectangle(p3.x - 20, p3.y, 40, 20);
centerString(g, r, "10.0", font);
p1 = coordinateSystem.convertPointToPixels(-1.0D, 20.0D);
p2 = coordinateSystem.convertPointToPixels(1.0D, 20.0D);
g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
p3 = coordinateSystem.convertPointToPixels(3.0D, 20.0D);
r = new Rectangle(p3.x - 20, p3.y, 40, 20);
centerString(g, r, "20.0", font);
}
private void drawCoordinate(Graphics2D g2d, Graphics g) {
if (!coordinateString.equals("")) {
g2d.setColor(Color.BLUE);
g2d.fillOval(pixelPoint.x - 5, pixelPoint.y - 5, 10, 10);
Font font = getFont();
Rectangle r = new Rectangle(pixelPoint.x - 30, pixelPoint.y,
60, 20);
centerString(g, r, coordinateString, font);
}
}
/**
* This method centers a <code>String</code> in a bounding
* <code>Rectangle</code>.
*
* #param g
* - The <code>Graphics</code> instance.
* #param r
* - The bounding <code>Rectangle</code>.
* #param s
* - The <code>String</code> to center in the bounding
* rectangle.
* #param font
* - The display font of the <code>String</code>
*
* #see java.awt.Graphics
* #see java.awt.Rectangle
* #see java.lang.String
*/
private void centerString(Graphics g, Rectangle r, String s, Font font) {
FontRenderContext frc = new FontRenderContext(null, true, true);
Rectangle2D r2D = font.getStringBounds(s, frc);
int rWidth = (int) Math.round(r2D.getWidth());
int rHeight = (int) Math.round(r2D.getHeight());
int rX = (int) Math.round(r2D.getX());
int rY = (int) Math.round(r2D.getY());
int a = (r.width / 2) - (rWidth / 2) - rX;
int b = (r.height / 2) - (rHeight / 2) - rY;
g.setFont(font);
g.drawString(s, r.x + a, r.y + b);
}
}
private class CoordinateListener extends MouseAdapter {
#Override
public void mousePressed(MouseEvent event) {
drawingPanel.setPixelPoint(event.getPoint());
Point2D coordinatePoint = drawingPanel.getCoordinateSystem()
.convertToCartesian(event.getPoint());
drawingPanel.setCoordinatePoint(coordinatePoint);
StringBuilder builder = new StringBuilder();
if (event.getButton() == MouseEvent.BUTTON1) {
builder.append("(");
builder.append(String.format("%.2f", coordinatePoint.getX()));
builder.append(", ");
builder.append(String.format("%.2f", coordinatePoint.getY()));
builder.append(")");
} else if (event.getButton() == MouseEvent.BUTTON3) {
Polar2D polarPoint = drawingPanel.getCoordinateSystem()
.convertToPolar(event.getPoint());
builder.append("(");
builder.append(String.format("%.2f", polarPoint.getDistance()));
builder.append(", ");
builder.append(String.format("%.2f",
polarPoint.getThetaInDegrees()));
builder.append(")");
}
drawingPanel.setCoordinateString(builder.toString());
drawingPanel.repaint();
}
}
private class SizeListener extends ComponentAdapter {
#Override
public void componentResized(ComponentEvent event) {
Dimension d = drawingPanel.getSize();
drawingPanel.getCoordinateSystem().setDrawingSize(d);
if (!drawingPanel.getPixelPoint().equals(new Point())) {
Point2D p2d = drawingPanel.getCoordinatePoint();
Point p = drawingPanel.getCoordinateSystem().convertToPixels(
p2d);
drawingPanel.setPixelPoint(p);
}
drawingPanel.repaint();
}
}
}