[mapserver-users] Coordinate transformation in Java (latlong to LCC)
Michael Soracco
Michael.Soracco at noaa.gov
Wed Nov 20 10:07:04 PST 2002
Jan-
Here's a class that will do it using the equations per Snyder's Handbook (as seen
in GCTP). Although I did not write the snipet (I can put you in contact with the
original author offline if needed), I have used it routinely in a Java applet. You
will see comments in the code describing the inputs (XY) and a parameter array
which identifies the SP1,2 , ellipsoid, etc.
-m
Jan Kunzmann wrote:
> Hi there folks,
>
> I know this is a kind of of-topic question, but I really need help...
>
> I need to convert lat-long coordinates to Lambert Conic Conformal (2SP)
> coordinates and vice versa, as figured at
> http://www.remotesensing.org/geotiff/proj_list/lambert_conic_conformal_2sp.html
>
> I already found the PROJ.4 library being capable of doing this simple
> conversion, but I need to do it in Java. I searched the web and found
> some complex packages, but they are too complicated to understand for
> me, and none of them is as easy as
>
> (x,y) := convert(x,y, originlat, originlong, sp1lat, sp2lat)
>
> Does anyone know where I can find such a class, or can send me the
> algorithm (it's already on the remotesensing page but it's unreadable
> for me...)?
>
> Thanks in advance,
> Jan
--
////
Michael Soracco
SES, Inc. for NOAA/NESDIS
at NOAA Science Center (WWB)
5200 Auth Road, Room 607
Camp Springs, MD 20746
Voice: 301.763.8142 x117
FAX: 301.763.8131
Michael.Soracco at noaa.gov
-------------- next part --------------
/**
LCC - Lambert Conformal Conic Projection class
*/
package /*ENTER YOUR PATH*/;
public class LCC extends Projection {
private double stdpar1=0, stdpar2=0, centmer=0, origlat=0;
private double sin_po = 0; // sin of 1st std par
private double cos_po = 0; // cos of 1nd std par
private double false_east, false_north;
private double ns = 0; //ratio of angle between meridian
private double f0 = 0; //flattening of ellipsoid
private double rh = 0; //height above ellipsoid
private double ms1, ms2;
private double ts0, ts1, ts2;
public LCC (){
// new state plane projection, nothing set
}
public LCC (double[] param){
setParam(param);
}
/**
Convert from Planar coords to Geographic
@param x easting value
@param y northing value
@return lat lon coordinates
*/
public synchronized GeoCoord XYToGeo(double x, double y){
this.x = x;
this.y = y;
return (XYToGeo());
}
/**
Convert from Planar coords to Geographic
@param location easting and northing values
@return lat lon coordinates
*/
public synchronized GeoCoord XYToGeo(XYCoord location){
this.x = location.x;
this.y = location.y;
return (XYToGeo());
}
/**
Convert from Planar coords to Geographic
@return GeoCoord class with lat lon coordinates
*/
private GeoCoord XYToGeo(){
double rh1; /* height above ellipsoid */
double con; /* sign variable */
double ts; /* small t */
double theta; /* angle */
double xx = x;
double yy = y;
long errflag = 0;
double lat = 0, lon = 0;
xx -= false_east;
yy = rh - y + false_north;
if(ns > 0){
rh1 = Math.sqrt(xx * xx + yy * yy);
con = 1.0;
}else{
rh1 = -Math.sqrt(xx * xx + yy * yy);
con = -1.0;
}
theta = 0.0;
if(rh1 != 0){
theta = Math.atan2((con * xx), (con * yy));
}
if((rh1 != 0) || (ns > 0.0)){
con = 1.0 /ns;
ts = Math.pow((rh1/(majorAxis * f0)), con);
try{
lat =phi2z(eccen,ts,errflag);
}catch(ConvergenceException e){
System.out.println(e);
return null;
}
}else{
lat =(-HALF_PI);
}
lon = adjust_lon(theta/ns + centmer);
return (new GeoCoord(rtd(lat),rtd(lon)));
}
/**
Convert from Geographic coords to Lambert Conformal Conic.
@param g The latitude and longitude.
@return The easting and northing values, null on error.
*/
public synchronized XYCoord GeoToXY(GeoCoord g){
double con; // temporary angle variable
double rh1; // height above ellipsoid
double sinphi; // sin value
double theta; // angle
double ts; // small value t
double lat = g.getLatRad();
double lon = g.getLonRad();
con = Math.abs(Math.abs(lat - HALF_PI));
if(con > EPSLN){
sinphi = Math.sin(lat);
ts = tsfnz(eccen,lat,sinphi);
rh1 = majorAxis * f0 * Math.pow(ts,ns);
}else{
con = lat * ns;
if(con <= 0)
{
System.out.println("Point cannot be projected to Lambert");
return null;
}
rh1 = 0;
}
theta = ns * adjust_lon(lon - centmer);
double x = rh1 * Math.sin(theta) + false_east;
double y = rh - rh1 * Math.cos(theta) + false_north;
return (new XYCoord(x,y));
}
public double[] getParam(){ return param; }
/**
@param param A double array with the following elements:
<ul>
<li>param[0] - Semi-major axis in meters
<li>param[1] - Semi-minor axis in meters. If 0, then param[0] is a sphere
number.
<li>param[2] - First standard parallel in decimal degrees.
<li>param[3] - Second standard parallel in decimal degrees.
<li>param[4] - Central meridian in decimal degrees.
<li>param[5] - Latitide of origin in decimal degrees.
<li>param[6] - False Easting.
<li>param[7] - False Northing.
</UL
@return -1 if failure.
@see Sphere
*/
public int setParam(double[] param){
this.param = param;
if(param == null) return -1;
if(param.length < 8) return -1;
if(param[1] == 0){ // sphere given
SetSphere((int)param[0]);
}else{
SetSphere(param[0],param[1]);
}
stdpar1 = param[2];
stdpar2 = param[3];
centmer = param[4];
origlat = param[5];
false_east = param[6];
false_north = param[7];
// switch to radians
stdpar1 *= Math.PI / 180.;
stdpar2 *= Math.PI / 180.;
origlat *= Math.PI /180.;
centmer *= Math.PI / 180.;
sin_po = Math.sin(stdpar1);
cos_po = Math.cos(stdpar1);
ns = sin_po;
ms1 = msfnz(eccen,sin_po,cos_po);
ts1 = tsfnz(eccen,stdpar1,sin_po);
sin_po = Math.sin(stdpar2);
cos_po = Math.cos(stdpar2);
ms2 = msfnz(eccen,sin_po,cos_po);
ts2 = tsfnz(eccen,stdpar1,sin_po);
sin_po = Math.sin(origlat);
ts0 = tsfnz(eccen, origlat, sin_po);
if(Math.abs(stdpar1 - stdpar2) > EPSLN){
ns = Math.log(ms1/ms2) / Math.log(ts1/ts2);
}
f0 = ms1/(ns * Math.pow(ts1,ns));
rh = majorAxis * f0 * Math.pow(ts0,ns);
return 0;
}
/**
@return Text descriptions of the elements needed for initialization using an array of doubles.
*/
public String[] getParamDefs(){
String[] paramdef = new String[8];
paramdef[0] = "Major Axis [m] or sphere number";
paramdef[1] = "Minor Axis [m] or zero";
paramdef[2] = "First Standard parallel [degrees]";
paramdef[3] = "Second Standard parallel [degrees]";
paramdef[4] = "Central Meridian [degrees]";
paramdef[5] = "Latitude of Origin [degrees]";
paramdef[6] = "False Easting [m]";
paramdef[7] = "False Northing [m]";
return paramdef;
}
}
More information about the MapServer-users
mailing list