/*\file Ll2xy.c
 *\brief: lat/long to x/y coordinate mex module.
 */
#include "./Ll2xy.h"

void Ll2xyUsage(void){/*{{{*/
	_pprintLine_("Ll2xy - lat/long to x/y coordinate transformation module:");
	_pprintLine_("");
	_pprintLine_("   This module transforms lat/long to x/y coordinates.");
	_pprintLine_("");
	_pprintLine_("   Usage:");
	_pprintLine_("      [x,y]=Ll2xy(lat,lon,sgn,'param name',param,...);");
	_pprintLine_("");
	_pprintLine_("      lat         latitude coordinates (double vector)");
	_pprintLine_("      lon         longitude coordinates (double vector)");
	_pprintLine_("      sgn         sign for hemisphere (double, +1 (north) or -1 (south))");
	_pprintLine_("");
	_pprintLine_("      central_meridian     central meridian (double, optional, but must specify with sp)");
	_pprintLine_("      standard_parallel    standard parallel (double, optional, but must specify with cm)");
	_pprintLine_("");
	_pprintLine_("      x           x coordinates (double vector)");
	_pprintLine_("      y           y coordinates (double vector)");
	_pprintLine_("");
	_pprintLine_("   Examples:");
	_pprintLine_("      [x,y]=Ll2xy(lat,lon, 1);");
	_pprintLine_("      [x,y]=Ll2xy(lat,lon, 1,'central_meridian',45,'standard_parallel',70);");
	_pprintLine_("      [x,y]=Ll2xy(lat,lon,-1,'central_meridian', 0,'standard_parallel',71);");
	_pprintLine_("");
}/*}}}*/
WRAPPER(Ll2xy){

	int i,verbose=1;

	/*input: */
	double  *lat=NULL,*lon=NULL;
	int     nlat,nlon,ncoord;
	int     sgn;

	Options* options=NULL;
	double   cm=0.,sp=0.;

	/* output: */
	double  *x=NULL,*y=NULL;
	int     iret=0;

	/*Boot module: */
	MODULEBOOT();

	/*checks on arguments on the matlab side: */
	if (nlhs > NLHS) {
		Ll2xyUsage(); _error_("Ll2xy usage error");
	}
	if (nrhs < NRHS) {
		Ll2xyUsage(); _error_("Ll2xy usage error");
	}

	/*Input datasets: */
	FetchData(&lat,&nlat,LAT_IN);
	FetchData(&lon,&nlon,LON_IN);
	FetchData(&sgn,SGN_IN);
	FetchData(&options,NRHS,nrhs,prhs);

	/*  defaults are in Ll2xydef, so don't duplicate them here, and only use user values if both have been specified  */
	if(options->GetOption("central_meridian") || options->GetOption("standard_parallel")){
		options->Get(&cm,"central_meridian");
		if (verbose) _printLine_("  cm=" << cm);
		options->Get(&sp,"standard_parallel");
		if (verbose) _printLine_("  sp=" << sp);
	}

	/*some checks*/
	if (verbose) _printLine_("Checking inputs:");
	if (nlat != nlon){_error_("Must have same number of lat[" << nlat << "] and lon[" << nlon << "] coordinates.");}
	else                ncoord=nlat;
	if (sgn != +1 && sgn != -1) _error_("Hemisphere sgn=" << sgn << " must be +1 (north) or -1 (south).");
	if (fabs(cm)      > 180.) _error_("Central meridian cm=" << cm << " must be between -180 (west) and +180 (east) degrees.");
	if (sp < 0. || sp >  90.) _error_("Standard parallel sp=" << sp << " must be between 0 and 90 degrees (in specified hemisphere).");

	x=(double*)mxMalloc(ncoord*sizeof(double));
	y=(double*)mxMalloc(ncoord*sizeof(double));

	/* Run core computations: */
	if (options->GetOption("central_meridian") && options->GetOption("standard_parallel"))
		iret=Ll2xyx(x,y,lat,lon,ncoord,sgn,cm,sp);
	else
		iret=Ll2xyx(x,y,lat,lon,ncoord,sgn);

	/*Write data: */
	WriteData(X_OUT,x,ncoord);
	WriteData(Y_OUT,y,ncoord);

	/*Clean-up*/
	delete options;

	/*end module: */
	MODULEEND();
}
