| 1 |
|
|---|
| 2 |
void doGeoTest() { |
|---|
| 3 |
|
|---|
| 4 |
println(); |
|---|
| 5 |
println("geo test"); |
|---|
| 6 |
println(); |
|---|
| 7 |
|
|---|
| 8 |
Transformation t = new Transformation(1, 0, 0, 0, 1, 0); |
|---|
| 9 |
Point p = new Point(1, 1); |
|---|
| 10 |
println( p.toString().equals("(1.000, 1.000)") ); |
|---|
| 11 |
|
|---|
| 12 |
Point p_ = t.transform(p); |
|---|
| 13 |
println( p_.toString().equals("(1.000, 1.000)") ); |
|---|
| 14 |
|
|---|
| 15 |
Point p__ = t.untransform(p_); |
|---|
| 16 |
println( p__.toString().equals("(1.000, 1.000)") ); |
|---|
| 17 |
|
|---|
| 18 |
t = new Transformation(0, 1, 0, 1, 0, 0); |
|---|
| 19 |
p = new Point(0, 1); |
|---|
| 20 |
println( p.toString().equals("(0.000, 1.000)") ); |
|---|
| 21 |
p_ = t.transform(p); |
|---|
| 22 |
println( p_.toString().equals("(1.000, 0.000)") ); |
|---|
| 23 |
p__ = t.untransform(p_); |
|---|
| 24 |
// !!! I will accept -0 here, but clearly something is a bit hairy |
|---|
| 25 |
println( p__.toString().equals("(0.000, 1.000)") || p__.toString().equals("(-0.000, 1.000)") ); |
|---|
| 26 |
|
|---|
| 27 |
t = new Transformation(1, 0, 1, 0, 1, 1); |
|---|
| 28 |
p = new Point(0, 0); |
|---|
| 29 |
println( p.toString().equals("(0.000, 0.000)") ); |
|---|
| 30 |
p_ = t.transform(p); |
|---|
| 31 |
println( p_.toString().equals("(1.000, 1.000)") ); |
|---|
| 32 |
p__ = t.untransform(p_); |
|---|
| 33 |
// !!! I will accept -0 here, but clearly something is a bit hairy |
|---|
| 34 |
println( p__.toString().equals("(0.000, 0.000)") || p__.toString().equals("(0.000, -0.000)") ); |
|---|
| 35 |
|
|---|
| 36 |
AbstractProjection m = new MercatorProjection(10); |
|---|
| 37 |
Coordinate c = m.locationCoordinate(new Location(0, 0)); |
|---|
| 38 |
// !!! python version has a negative here, but I think this is OK |
|---|
| 39 |
println( c.toString().equals("(-0.000, 0.000 @10.000)") || c.toString().equals("(0.000, 0.000 @10.000)") ); |
|---|
| 40 |
|
|---|
| 41 |
Location l = m.coordinateLocation(new Coordinate(0, 0, 10)); |
|---|
| 42 |
println( l.toString().equals("(0.000, 0.000)") ); |
|---|
| 43 |
|
|---|
| 44 |
c = m.locationCoordinate(new Location(37, -122)); |
|---|
| 45 |
println( c.toString().equals("(0.696, -2.129 @10.000)") ); |
|---|
| 46 |
|
|---|
| 47 |
l = m.coordinateLocation(new Coordinate(0.696, -2.129, 10.000)); |
|---|
| 48 |
println( l.toString().equals("(37.001, -121.983)") ); |
|---|
| 49 |
|
|---|
| 50 |
} |
|---|
| 51 |
|
|---|
| 52 |
|
|---|
| 53 |
|
|---|
| 54 |
class Location { |
|---|
| 55 |
|
|---|
| 56 |
float lat; |
|---|
| 57 |
float lon; |
|---|
| 58 |
|
|---|
| 59 |
Location(float lat, float lon) { |
|---|
| 60 |
this.lat = lat; |
|---|
| 61 |
this.lon = lon; |
|---|
| 62 |
} |
|---|
| 63 |
|
|---|
| 64 |
String toString() { |
|---|
| 65 |
return "(" + nf(lat,1,3) + ", " + nf(lon,1,3) + ")"; |
|---|
| 66 |
} |
|---|
| 67 |
|
|---|
| 68 |
} |
|---|
| 69 |
|
|---|
| 70 |
class Transformation { |
|---|
| 71 |
|
|---|
| 72 |
float ax, bx, cx, ay, by, cy; |
|---|
| 73 |
|
|---|
| 74 |
Transformation(float ax, float bx, float cx, float ay, float by, float cy) { |
|---|
| 75 |
this.ax = ax; |
|---|
| 76 |
this.bx = bx; |
|---|
| 77 |
this.cx = cx; |
|---|
| 78 |
this.ay = ay; |
|---|
| 79 |
this.by = by; |
|---|
| 80 |
this.cy = cy; |
|---|
| 81 |
} |
|---|
| 82 |
|
|---|
| 83 |
Point transform(Point point) { |
|---|
| 84 |
return new Point(ax*point.x + bx*point.y + cx, ay*point.x + by*point.y + cy); |
|---|
| 85 |
} |
|---|
| 86 |
|
|---|
| 87 |
Point untransform(Point point) { |
|---|
| 88 |
return new Point((point.x*by - point.y*bx - cx*by + cy*bx) / (ax*by - ay*bx), (point.x*ay - point.y*ax - cx*ay + cy*ax) / (bx*ay - by*ax)); |
|---|
| 89 |
} |
|---|
| 90 |
|
|---|
| 91 |
} |
|---|
| 92 |
|
|---|
| 93 |
abstract class AbstractProjection { |
|---|
| 94 |
|
|---|
| 95 |
float zoom; |
|---|
| 96 |
Transformation transformation; |
|---|
| 97 |
|
|---|
| 98 |
AbstractProjection() { |
|---|
| 99 |
this(0); |
|---|
| 100 |
} |
|---|
| 101 |
|
|---|
| 102 |
AbstractProjection(float zoom) { |
|---|
| 103 |
this(zoom, new Transformation(1, 0, 0, 0, 1, 0)); |
|---|
| 104 |
} |
|---|
| 105 |
|
|---|
| 106 |
AbstractProjection(float zoom, Transformation transformation) { |
|---|
| 107 |
this.zoom = zoom; |
|---|
| 108 |
this.transformation = transformation; |
|---|
| 109 |
} |
|---|
| 110 |
|
|---|
| 111 |
abstract Point rawProject(Point point); |
|---|
| 112 |
|
|---|
| 113 |
abstract Point rawUnproject(Point point); |
|---|
| 114 |
|
|---|
| 115 |
Point project(Point point) { |
|---|
| 116 |
point = this.rawProject(point); |
|---|
| 117 |
if(this.transformation != null) { |
|---|
| 118 |
point = this.transformation.transform(point); |
|---|
| 119 |
} |
|---|
| 120 |
return point; |
|---|
| 121 |
} |
|---|
| 122 |
|
|---|
| 123 |
Point unproject(Point point) { |
|---|
| 124 |
if(this.transformation != null) { |
|---|
| 125 |
point = this.transformation.untransform(point); |
|---|
| 126 |
} |
|---|
| 127 |
point = this.rawUnproject(point); |
|---|
| 128 |
return point; |
|---|
| 129 |
} |
|---|
| 130 |
|
|---|
| 131 |
Coordinate locationCoordinate(Location location) { |
|---|
| 132 |
Point point = new Point(PI * location.lon / 180.0, PI * location.lat / 180.0); |
|---|
| 133 |
point = this.project(point); |
|---|
| 134 |
return new Coordinate(point.y, point.x, this.zoom); |
|---|
| 135 |
} |
|---|
| 136 |
|
|---|
| 137 |
Location coordinateLocation(Coordinate coordinate) { |
|---|
| 138 |
coordinate = coordinate.zoomTo(this.zoom); |
|---|
| 139 |
Point point = new Point(coordinate.column, coordinate.row); |
|---|
| 140 |
point = this.unproject(point); |
|---|
| 141 |
return new Location(180.0 * point.y / PI, 180.0 * point.x / PI); |
|---|
| 142 |
} |
|---|
| 143 |
|
|---|
| 144 |
} |
|---|
| 145 |
|
|---|
| 146 |
class LinearProjection extends AbstractProjection { |
|---|
| 147 |
|
|---|
| 148 |
LinearProjection() { |
|---|
| 149 |
super(0); |
|---|
| 150 |
} |
|---|
| 151 |
|
|---|
| 152 |
LinearProjection(float zoom) { |
|---|
| 153 |
super(zoom, new Transformation(1, 0, 0, 0, 1, 0)); |
|---|
| 154 |
} |
|---|
| 155 |
|
|---|
| 156 |
LinearProjection(float zoom, Transformation transformation) { |
|---|
| 157 |
super(zoom, transformation); |
|---|
| 158 |
} |
|---|
| 159 |
|
|---|
| 160 |
Point rawProject(Point point) { |
|---|
| 161 |
return new Point(point.x, point.y); |
|---|
| 162 |
} |
|---|
| 163 |
|
|---|
| 164 |
Point rawUnproject(Point point) { |
|---|
| 165 |
return new Point(point.x, point.y); |
|---|
| 166 |
} |
|---|
| 167 |
|
|---|
| 168 |
} |
|---|
| 169 |
|
|---|
| 170 |
class MercatorProjection extends AbstractProjection { |
|---|
| 171 |
|
|---|
| 172 |
MercatorProjection() { |
|---|
| 173 |
super(0); |
|---|
| 174 |
} |
|---|
| 175 |
|
|---|
| 176 |
MercatorProjection(float zoom) { |
|---|
| 177 |
super(zoom, new Transformation(1, 0, 0, 0, 1, 0)); |
|---|
| 178 |
} |
|---|
| 179 |
|
|---|
| 180 |
MercatorProjection(float zoom, Transformation transformation) { |
|---|
| 181 |
super(zoom, transformation); |
|---|
| 182 |
} |
|---|
| 183 |
|
|---|
| 184 |
Point rawProject(Point point) { |
|---|
| 185 |
return new Point(point.x, log(tan(0.25 * PI + 0.5 * point.y))); |
|---|
| 186 |
} |
|---|
| 187 |
|
|---|
| 188 |
Point rawUnproject(Point point) { |
|---|
| 189 |
return new Point(point.x, 2.0 * atan(pow((float)Math.E, point.y)) - 0.5 * PI); |
|---|
| 190 |
} |
|---|
| 191 |
|
|---|
| 192 |
} |
|---|