mirror of
https://github.com/csharpee/Map-Projections.git
synced 2025-12-15 00:00:14 -05:00
The Complete Set
I made inverse solutions for all my invented projections, and even threw in a new one, "Tetrachamfer", which kind of sucks, but I felt like I should include it for completeness's sake. I found a bug in MapConfigurationDialog and squashed it, as well. And I added a couple new maps to the output folder. Oh, I never explained what the problem with Tobler was! There was an issue with the way Z was being generated, so last commit, I cleaned that up and may have made it slightly slower, but I don't really care given how well it works now and how much faster it still is than Lee (seriously, what is the deal with that?). Did I do anything else? Not really. Next step: conic projections!
This commit is contained in:
parent
18d2d8266f
commit
ab155f2c9e
BIN
MapAnalyzer.jar
BIN
MapAnalyzer.jar
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 43 KiB |
BIN
output/Compass Rose.jpg
Normal file
BIN
output/Compass Rose.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 375 KiB |
BIN
output/Fancy Tetrafillet.jpg
Normal file
BIN
output/Fancy Tetrafillet.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 383 KiB |
@ -1,13 +0,0 @@
|
||||
We got the best Tobler projections using:
|
||||
t0=0.25022057521781305; t1=4.49997342476493; (4.0724237830145623E-4, 0.5079777001726435)
|
||||
t0=0.2505753087520266; t1=4.499956546953281; (4.064604422025349E-4, 0.5079765807787102)
|
||||
t0=0.2508838353035556; t1=4.4999316499660384; (4.0573108482153483E-4, 0.5079755362982413)
|
||||
t0=0.2508314520322239; t1=4.499728417979239; (4.0450171936633287E-4, 0.5079758925954643)
|
||||
t0=0.2500693069768243; t1=4.499328429617362; (4.0750703627578564E-4, 0.5079785011865504)
|
||||
t0=0.2600667982838587; t1=4.5008562930364775; (3.8249122842821693E-4, 0.5079640977617719)
|
||||
t0=0.2558237748512546; t1=4.4998740643492035; (3.9365452439070936E-4, 0.5079694226751023)
|
||||
t0=0.24889877394521065; t1=4.498227902031633; (4.100009439557956E-4, 0.507979411007307)
|
||||
t0=0.259316034943474; t1=4.4995552660836395; (3.8333968917550053E-4, 0.5079662063081046)
|
||||
t0=0.2759279673286983; t1=4.5009128718891915; (3.3514923608814645E-4, 0.5079628635806102)
|
||||
t0=0.2554293245455028; t1=4.492372958335096; (3.945025957463458E-4, 0.5079708674912415)
|
||||
|
||||
@ -90,7 +90,7 @@ public class MapAnalyzer extends MapApplication {
|
||||
Projection.ALBERS, Projection.LEE, Projection.TETRAGRAPH, Projection.SINUSOIDAL, Projection.MOLLWEIDE,
|
||||
Projection.HAMMER, Projection.TOBLER, Projection.AITOFF, Projection.VAN_DER_GRINTEN, Projection.ROBINSON,
|
||||
Projection.WINKEL_TRIPEL, Projection.PEIRCE_QUINCUNCIAL, Projection.GUYOU, Projection.MAGNIFIER,
|
||||
Projection.EXPERIMENT, Projection.HYPERELLIPOWER, Projection.TETRAPOWER, Projection.TETRAFILLET };
|
||||
Projection.EXPERIMENT, Projection.HYPERELLIPOWER, Projection.TETRAPOWER, Projection.TETRAFILLET, Projection.TETRACHAMFER };
|
||||
|
||||
|
||||
private Button updateBtn;
|
||||
|
||||
@ -113,7 +113,7 @@ public abstract class MapApplication extends Application {
|
||||
final Label label = new Label("Current input:");
|
||||
final Text inputLabel = new Text("None");
|
||||
|
||||
final FileChooser inputChooser = new FileChooser();
|
||||
final FileChooser inputChooser = new FileChooser(); //TODO: remember last directory
|
||||
inputChooser.setInitialDirectory(new File("input"));
|
||||
inputChooser.setTitle("Choose an input map");
|
||||
inputChooser.getExtensionFilters().addAll(allowedExtensions);
|
||||
@ -376,7 +376,7 @@ public abstract class MapApplication extends Application {
|
||||
Slider[] sliders, Spinner<Double>[] spinners) {
|
||||
if (presetName.equals("Antipode")) {
|
||||
sliders[0].setValue(-sliders[0].getValue());
|
||||
sliders[1].setValue((sliders[1].getValue()+180)%360);
|
||||
sliders[1].setValue((sliders[1].getValue()+360)%360-180);
|
||||
sliders[2].setValue(-sliders[2].getValue());
|
||||
}
|
||||
else if (presetName.equals("Random")) {
|
||||
|
||||
@ -72,7 +72,7 @@ public class MapDesignerRaster extends MapApplication {
|
||||
Projection.ALBERS, Projection.LEE, Projection.TETRAGRAPH, Projection.AUTHAGRAPH, Projection.SINUSOIDAL,
|
||||
Projection.MOLLWEIDE, Projection.TOBLER, Projection.AITOFF, Projection.VAN_DER_GRINTEN, Projection.ROBINSON,
|
||||
Projection.WINKEL_TRIPEL, Projection.PEIRCE_QUINCUNCIAL, Projection.GUYOU, Projection.LEMONS,
|
||||
Projection.MAGNIFIER, Projection.EXPERIMENT };
|
||||
Projection.MAGNIFIER, Projection.EXPERIMENT, Projection.HYPERELLIPOWER, Projection.TETRAPOWER, Projection.TETRAFILLET, Projection.TETRACHAMFER };
|
||||
|
||||
|
||||
private Button updateBtn, saveMapBtn;
|
||||
|
||||
@ -69,7 +69,7 @@ public class MapDesignerVector extends MapApplication {
|
||||
Projection.ALBERS, Projection.LEE, Projection.TETRAGRAPH, Projection.SINUSOIDAL, Projection.MOLLWEIDE,
|
||||
Projection.TOBLER, Projection.AITOFF, Projection.VAN_DER_GRINTEN, Projection.ROBINSON,
|
||||
Projection.WINKEL_TRIPEL, Projection.PEIRCE_QUINCUNCIAL, Projection.GUYOU, Projection.MAGNIFIER,
|
||||
Projection.EXPERIMENT, Projection.HYPERELLIPOWER, Projection.TETRAPOWER, Projection.TETRAFILLET };
|
||||
Projection.EXPERIMENT, Projection.HYPERELLIPOWER, Projection.TETRAPOWER, Projection.TETRAFILLET, Projection.TETRACHAMFER };
|
||||
|
||||
private static final int DEF_MAX_VTX = 5000;
|
||||
|
||||
|
||||
@ -73,10 +73,10 @@ public class MapOptimizer extends Application {
|
||||
|
||||
chart.getData().add(analyzeAll(globe, EXISTING_PROJECTIONS));
|
||||
// chart.getData().add(optimizeFamily(Projection.WINKEL_TRIPEL, globe, log));
|
||||
chart.getData().add(optimizeFamily(Projection.TOBLER, globe, log));
|
||||
// chart.getData().add(optimizeFamily(Projection.TOBLER, globe, log));
|
||||
// chart.getData().add(optimizeFamily(Projection.HYPERELLIPOWER, globe, log));
|
||||
// chart.getData().add(optimizeFamily(Projection.TETRAPOWER, globe, log));
|
||||
// chart.getData().add(optimizeFamily(Projection.TETRAFILLET, globe, log));
|
||||
chart.getData().add(optimizeFamily(Projection.TETRAFILLET, globe, log));
|
||||
|
||||
System.out.println("Total time elapsed: "+
|
||||
(System.currentTimeMillis()-startTime)/1000.+"s");
|
||||
|
||||
@ -69,7 +69,7 @@ public class MapConfigurationDialog extends Dialog<Boolean> {
|
||||
this.widthBox.valueProperty().addListener((observable, prev, now) -> { // link the Spinners
|
||||
if (realEdit && maintainRatio.isSelected()) {
|
||||
realEdit = false;
|
||||
int prefHeight = (int)Math.floor(widthBox.getValue()/defaultRatio);
|
||||
int prefHeight = (int)Math.round(widthBox.getValue()/defaultRatio);
|
||||
heightBox.getValueFactory().setValue(prefHeight);
|
||||
realEdit = true;
|
||||
}
|
||||
@ -77,7 +77,7 @@ public class MapConfigurationDialog extends Dialog<Boolean> {
|
||||
this.heightBox.valueProperty().addListener((observable, prev, now) -> {
|
||||
if (realEdit && maintainRatio.isSelected()) {
|
||||
realEdit = false;
|
||||
int prefWidth = (int)Math.ceil(heightBox.getValue()*defaultRatio);
|
||||
int prefWidth = (int)Math.round(heightBox.getValue()*defaultRatio);
|
||||
widthBox.getValueFactory().setValue(prefWidth);
|
||||
realEdit = true;
|
||||
}
|
||||
@ -87,7 +87,7 @@ public class MapConfigurationDialog extends Dialog<Boolean> {
|
||||
if (!now) widthBox.increment(0);
|
||||
});
|
||||
this.heightBox.focusedProperty().addListener((observable, prev,now) -> { //values when focus is lost
|
||||
if (!now) heightBox.increment();
|
||||
if (!now) heightBox.increment(0);
|
||||
});
|
||||
|
||||
ObservableList<String> items = FXCollections.observableArrayList(
|
||||
|
||||
@ -667,12 +667,21 @@ public enum Projection {
|
||||
new double[][] {{1,5,3.7308},{.5,2.,1.2027},{.5,2.,1.1443}}) {
|
||||
public double[] project(double lat, double lon, double[] params) {
|
||||
final double k = params[0], n = params[1], a = params[2];
|
||||
final double ynorm = (1-Math.pow(1-Math.abs(lat/(Math.PI/2)), n));
|
||||
return new double[] {
|
||||
Math.pow(1 - Math.pow(Math.abs(lat/(Math.PI/2)), k),1/k)*lon,
|
||||
(1-Math.pow(1-Math.abs(lat/(Math.PI/2)), n))/Math.sqrt(n)*Math.signum(lat)*Math.PI/2*a};
|
||||
Math.pow(1 - Math.pow(ynorm, k),1/k)*lon,
|
||||
ynorm*Math.PI/2/Math.sqrt(n)*a*Math.signum(lat)
|
||||
};
|
||||
}
|
||||
public double[] inverse(double x, double y, double[] params) {
|
||||
return null;
|
||||
final double k = params[0], n = params[1];
|
||||
return new double[] {
|
||||
(1 - Math.pow(1-Math.abs(y), 1/n))*Math.PI/2*Math.signum(y),
|
||||
x/Math.pow(1 - Math.pow(Math.abs(y),k),1/k)*Math.PI };
|
||||
}
|
||||
public double getAspectRatio(double[] params) {
|
||||
final double n = params[1], a = params[2];
|
||||
return 2*Math.sqrt(n)/a;
|
||||
}
|
||||
},
|
||||
|
||||
@ -687,19 +696,34 @@ public enum Projection {
|
||||
final double thtP = Math.PI/3*(1 - Math.pow(1-Math.abs(tht)/(Math.PI/2),k1))/(1 - 1/Math.pow(3,k1))*Math.signum(tht);
|
||||
final double kRad = k3*Math.abs(thtP)/(Math.PI/3) + k2*(1-Math.abs(thtP)/(Math.PI/3));
|
||||
final double rmax = .5/Math.cos(thtP); //the max normalized radius of this triangle (in the plane)
|
||||
final double rtgf = Math.atan(1/Math.tan(coordR[0])*Math.cos(tht))/Math.atan(Math.sqrt(2))*rmax; //normalized tetragraph radius
|
||||
final double rtgf = Math.atan(1/Math.tan(coordR[0])*Math.cos(tht))/Math.atan(Math.sqrt(2))*rmax;
|
||||
return new double[] {
|
||||
(1 - Math.pow(1-rtgf,kRad))/(1 - Math.pow(1-rmax,kRad))*rmax*2*Math.PI/3,
|
||||
thtP + t0 };
|
||||
});
|
||||
}
|
||||
public double[] inverse(double x, double y, double[] params) {
|
||||
return null;
|
||||
final double k1 = params[0], k2 = params[1], k3 = params[2];
|
||||
final double[] doubles = tetrahedralProjectionInverse(x,y);
|
||||
final double[] faceCenter = { doubles[0], doubles[1], doubles[2] };
|
||||
final double tht = doubles[3], xp = doubles[4], yp = doubles[5];
|
||||
final double R = Math.hypot(xp, yp)*Math.sqrt(3)/2;
|
||||
final double t = Math.atan2(yp, xp) + tht;
|
||||
final double t0 = Math.floor((t+Math.PI/2)/(2*Math.PI/3)+0.5)*(2*Math.PI/3) - Math.PI/2;
|
||||
final double thtP = t-t0;
|
||||
final double lamS = (1-Math.pow(1-Math.abs(thtP)*(1-1/Math.pow(3,k1))/(Math.PI/3), 1/k1))*Math.PI/2*Math.signum(thtP);
|
||||
final double kRad = k3*Math.abs(thtP)/(Math.PI/3) + k2*(1-Math.abs(thtP)/(Math.PI/3));
|
||||
final double rmax = .5/Math.cos(thtP); //the max normalized radius of this triangle (in the plane)
|
||||
final double rtgf = 1-Math.pow(1-R/rmax*(1-Math.pow(Math.abs(1-rmax), kRad)), 1/kRad); //normalized tetragraph radius
|
||||
double[] triCoords = {
|
||||
Math.atan(Math.cos(lamS)/Math.tan(rtgf/rmax*Math.atan(Math.sqrt(2)))),
|
||||
Math.PI/2 + t0 + lamS };
|
||||
return obliquifyPlnr(triCoords, faceCenter);
|
||||
}
|
||||
},
|
||||
|
||||
TETRAFILLET("Tetrafillet", "A parametric projection that I'm still testing",
|
||||
2., 0b1111, "other", "compromise", new String[] {"k1","k2","k3"},
|
||||
Math.sqrt(3), 0b1111, "other", "compromise", new String[] {"k1","k2","k3"},
|
||||
new double[][] {{.25,4.,1.1598},{.25,4.,.36295},{.25,4.,1.9553}}) {
|
||||
public double[] project(double lat, double lon, double[] params) {
|
||||
final double k1 = params[0], k2 = params[1], k3 = params[2];
|
||||
@ -708,7 +732,9 @@ public enum Projection {
|
||||
final double tht = coordR[1] - t0;
|
||||
final double thtP = Math.PI/3*(1 - Math.pow(1-Math.abs(tht)/(Math.PI/2),k1))/(1 - 1/Math.pow(3,k1))*Math.signum(tht);
|
||||
final double kRad = k3*Math.abs(thtP)/(Math.PI/3) + k2*(1-Math.abs(thtP)/(Math.PI/3));
|
||||
final double rmax = 1/2. + 1/4.*Math.pow(thtP,2) + 5/48.*Math.pow(thtP,4) - .132621*Math.pow(thtP,6); //the max normalized radius of this triangle (in the plane)
|
||||
final double rmax; //the max normalized radius of this triangle (in the plane)
|
||||
if (Math.abs(thtP) < .70123892) rmax = .5/Math.cos(thtP);
|
||||
else rmax = .75 - 1.5972774*Math.pow(Math.PI/3-Math.abs(thtP),2)/2;
|
||||
final double rtgf = Math.atan(1/Math.tan(coordR[0])*Math.cos(tht))/Math.atan(Math.sqrt(2))*rmax; //normalized tetragraph radius
|
||||
return new double[] {
|
||||
(1 - Math.pow(1-rtgf,kRad))/(1 - Math.pow(1-rmax,kRad))*rmax*2*Math.PI/3,
|
||||
@ -717,7 +743,64 @@ public enum Projection {
|
||||
});
|
||||
}
|
||||
public double[] inverse(double x, double y, double[] params) {
|
||||
return null;
|
||||
final double k1 = params[0], k2 = params[1], k3 = params[2];
|
||||
final double[] doubles = tetrahedralProjectionInverse(x,y);
|
||||
final double[] faceCenter = { doubles[0], doubles[1], doubles[2] };
|
||||
final double tht = doubles[3], xp = doubles[4], yp = doubles[5];
|
||||
final double R = Math.hypot(xp, yp)*Math.sqrt(3)/2;
|
||||
final double t = Math.atan2(yp, xp) + tht;
|
||||
final double t0 = Math.floor((t+Math.PI/2)/(2*Math.PI/3)+0.5)*(2*Math.PI/3) - Math.PI/2;
|
||||
final double thtP = t-t0;
|
||||
final double lamS = (1-Math.pow(1-Math.abs(thtP)*(1-1/Math.pow(3,k1))/(Math.PI/3), 1/k1))*Math.PI/2*Math.signum(thtP);
|
||||
final double kRad = k3*Math.abs(thtP)/(Math.PI/3) + k2*(1-Math.abs(thtP)/(Math.PI/3));
|
||||
final double rmax; //the max normalized radius of this triangle (in the plane)
|
||||
if (Math.abs(thtP) < .70123892) rmax = .5/Math.cos(thtP);
|
||||
else rmax = .75 - 1.5972774*Math.pow(Math.PI/3-Math.abs(thtP),2)/2;
|
||||
final double rtgf = 1-Math.pow(1-R/rmax*(1-Math.pow(Math.abs(1-rmax), kRad)), 1/kRad); //normalized tetragraph radius
|
||||
if (R > rmax) return null;
|
||||
double[] triCoords = {
|
||||
Math.atan(Math.cos(lamS)/Math.tan(rtgf/rmax*Math.atan(Math.sqrt(2)))),
|
||||
Math.PI/2 + t0 + lamS };
|
||||
return obliquifyPlnr(triCoords, faceCenter);
|
||||
}
|
||||
},
|
||||
|
||||
TETRACHAMFER("Tetrachamfer", "A parametric projection that I'm still testing",
|
||||
Math.sqrt(3), 0b1111, "other", "compromise", new String[] {"k1","k2","k3"},
|
||||
new double[][] {{.25,4.,1.1598},{.25,4.,.36295},{.25,4.,1.9553}}) {
|
||||
public double[] project(double lat, double lon, double[] params) {
|
||||
final double k1 = params[0], k2 = params[1], k3 = params[2];
|
||||
return tetrahedralProjectionForward(lat, lon, (coordR) -> {
|
||||
final double t0 = Math.floor(coordR[1]/(2*Math.PI/3))*(2*Math.PI/3) + Math.PI/3;
|
||||
final double tht = coordR[1] - t0;
|
||||
final double thtP = Math.PI/3*(1 - Math.pow(1-Math.abs(tht)/(Math.PI/2),k1))/(1 - 1/Math.pow(3,k1))*Math.signum(tht);
|
||||
final double kRad = k3*Math.abs(thtP)/(Math.PI/3) + k2*(1-Math.abs(thtP)/(Math.PI/3));
|
||||
final double rmax = Math.min(.5/Math.cos(thtP), .75/Math.cos(Math.PI/3-Math.abs(thtP))); //the max normalized radius of this triangle (in the plane)
|
||||
final double rtgf = Math.atan(1/Math.tan(coordR[0])*Math.cos(tht))/Math.atan(Math.sqrt(2))*rmax; //normalized tetragraph radius
|
||||
return new double[] {
|
||||
(1 - Math.pow(1-rtgf,kRad))/(1 - Math.pow(1-rmax,kRad))*rmax*2*Math.PI/3,
|
||||
thtP + t0
|
||||
};
|
||||
});
|
||||
}
|
||||
public double[] inverse(double x, double y, double[] params) {
|
||||
final double k1 = params[0], k2 = params[1], k3 = params[2];
|
||||
final double[] doubles = tetrahedralProjectionInverse(x,y);
|
||||
final double[] faceCenter = { doubles[0], doubles[1], doubles[2] };
|
||||
final double tht = doubles[3], xp = doubles[4], yp = doubles[5];
|
||||
final double R = Math.hypot(xp, yp)*Math.sqrt(3)/2;
|
||||
final double t = Math.atan2(yp, xp) + tht;
|
||||
final double t0 = Math.floor((t+Math.PI/2)/(2*Math.PI/3)+0.5)*(2*Math.PI/3) - Math.PI/2;
|
||||
final double thtP = t-t0;
|
||||
final double lamS = (1-Math.pow(1-Math.abs(thtP)*(1-1/Math.pow(3,k1))/(Math.PI/3), 1/k1))*Math.PI/2*Math.signum(thtP);
|
||||
final double kRad = k3*Math.abs(thtP)/(Math.PI/3) + k2*(1-Math.abs(thtP)/(Math.PI/3));
|
||||
final double rmax = Math.min(.5/Math.cos(thtP), .75/Math.cos(Math.PI/3-Math.abs(thtP))); //the max normalized radius of this triangle (in the plane)
|
||||
final double rtgf = 1-Math.pow(1-R/rmax*(1-Math.pow(Math.abs(1-rmax), kRad)), 1/kRad); //normalized tetragraph radius
|
||||
if (R > rmax) return null;
|
||||
double[] triCoords = {
|
||||
Math.atan(Math.cos(lamS)/Math.tan(rtgf/rmax*Math.atan(Math.sqrt(2)))),
|
||||
Math.PI/2 + t0 + lamS };
|
||||
return obliquifyPlnr(triCoords, faceCenter);
|
||||
}
|
||||
};
|
||||
|
||||
@ -988,26 +1071,22 @@ public enum Projection {
|
||||
|
||||
|
||||
private static double[] tetrahedralProjectionInverse(double x, double y) { // a function to help with tetrahedral projections
|
||||
if (y < x-1) {
|
||||
if (y < x-1)
|
||||
return new double[] {
|
||||
-Math.PI/2, 0, 0,
|
||||
-Math.PI/2, Math.sqrt(3)*(x-2/3.), y+1 };
|
||||
}
|
||||
else if (y < -x-1) {
|
||||
else if (y < -x-1)
|
||||
return new double[] {
|
||||
-Math.PI/2, 0, 0,
|
||||
Math.PI/2, Math.sqrt(3)*(x+2/3.), y+1 };
|
||||
}
|
||||
else if (y > -x+1) {
|
||||
else if (y > -x+1)
|
||||
return new double[] {
|
||||
Math.PI/2-Math.asin(Math.sqrt(8)/3), Math.PI, 0,
|
||||
-Math.PI/2, Math.sqrt(3)*(x-2/3.), y-1 };
|
||||
}
|
||||
else if (y > x+1) {
|
||||
else if (y > x+1)
|
||||
return new double[] {
|
||||
Math.PI/2-Math.asin(Math.sqrt(8)/3), Math.PI, 0,
|
||||
Math.PI/2, Math.sqrt(3)*(x+2/3.), y-1 };
|
||||
}
|
||||
else if (x < 0)
|
||||
return new double[] {
|
||||
Math.PI/2-Math.asin(Math.sqrt(8)/3), -Math.PI/3, 0,
|
||||
@ -1078,8 +1157,7 @@ public enum Projection {
|
||||
lonf = lon0 -
|
||||
Math.acos(innerFunc);
|
||||
|
||||
double thtf = 0;
|
||||
thtf += pole[2];
|
||||
double thtf = pole[2];
|
||||
|
||||
double[] output = {latf, lonf, thtf};
|
||||
return output;
|
||||
@ -1150,5 +1228,26 @@ public enum Projection {
|
||||
public String getProperty() {
|
||||
return this.property;
|
||||
}
|
||||
|
||||
|
||||
public static final void main(String[] args) {
|
||||
double[] pole = {47, -173, 138};
|
||||
System.out.println("The pole is at "+Arrays.toString(pole));
|
||||
for (int i = 0; i < 3; i ++)
|
||||
pole[i] = Math.toRadians(pole[i]);
|
||||
for (double[] ref: new double[][] {{-Math.PI/2, 0, Math.PI/3},
|
||||
{Math.asin(1/3.0), Math.PI, Math.PI/3},
|
||||
{Math.asin(1/3.0), Math.PI/3, Math.PI/3},
|
||||
{Math.asin(1/3.0), -Math.PI/3, -Math.PI/3}}) {
|
||||
ref[0] *= -1;
|
||||
ref[1] = (ref[1]+2*Math.PI)%(2*Math.PI)-Math.PI;
|
||||
ref[2] *= -1;
|
||||
System.out.println("The relative singularity is at "+Arrays.toString(ref));
|
||||
final double[] coords = obliquifyPlnr(ref, pole);
|
||||
for (int i = 0; i < 3; i ++)
|
||||
coords[i] = Math.toDegrees(coords[i]);
|
||||
System.out.println("That comes out to "+Arrays.toString(coords));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user