[mapserver-users] Coordinate transformation in Java (latlong to LCC)

Michael Soracco Michael.Soracco at noaa.gov
Wed Nov 20 13:07:04 EST 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