Browse Source

Gmt module: Conversion function for GMTProjection now using new parameter reading scheme and error reporting.

gmtdatadir
Michael Uleysky 8 years ago
parent
commit
59dfac220a
  1. 572
      modules/gmt/modgmt_func.h

572
modules/gmt/modgmt_func.h

@ -323,18 +323,15 @@ template<>
class Convert2Struct<struct gmt_projection, ObjectList>
{
public:
struct gmt_projection operator()(const ObjectList* input, bool* issuc) const
struct gmt_projection operator()(const ObjectList* input, bool* issuc, std::string& err) const
{
typedef SearchParameter<double,false,PMin<0> > BaseM2Nonneg;
struct gmt_projection p;
auto size=input->Size();
bool suc=true;
if(1==size) // Cases 1, and 2
if(1==input->Size()) // Cases 1, and 2
{
Base2Projection proj(input,0);
Base2Proj proj;
bool suc=true;
p=proj(&suc);
p=proj.Convert(input->At(0),&suc,err);
if(!suc) goto fail; // Conversion failed
return p;
}
@ -343,502 +340,321 @@ class Convert2Struct<struct gmt_projection, ObjectList>
{
bool upd;
bool changetype=false;
{
BaseMT2Projection updarg(input,"p","proj","projection");
p=updarg(&upd,&suc);
if(upd && !suc) goto fail; // Conversion failed or too many arguments
suc=true;
}
// Try to set type of projection
{
BaseM2String type(input,"t","type","projtype");
if(!(type.Exist() || upd)) goto case4; // No named parameter, not update mode, go to case 4
// Check on redundant parameters
if(type.Exist())
{
std::string typestr=type(&suc);
if(!suc) goto fail; // Wrong parameter type
if(!p.SetType(typestr)) goto fail; // Incorrect projection type
changetype=true;
}
}
ONFPar<Base2Proj,ObjectGMTProjection> proj("projection");
ONFPar<Base2Region,ObjectGMTRegion> region("region");
ONPar<Base2StringD> type("[projection][( |_)]t[ype]","mercator");
ONPar<Base2NonNegD> width("width",gmt_projection::default_width),height("height",gmt_projection::default_width);
{ParseNamedParameters params(input,type,region,proj,width,height); if(!params) {err=params.Error(); goto fail;}} // Fail to parse by variant 3
// We need the region
upd=proj.Exist();
if(upd) p=proj;
if(!(type.Exist() || upd)) goto case4; // No named parameter, not update mode, go to case 4
// Check projection type
if(type.Exist())
{
BaseMT2Region region(input,"r","region");
if(!(region.Exist() || upd)) goto fail; // Region must be defined in "new" mode
if(region.Exist()) p.region=region(&suc);
if(!suc) goto fail; // Conversion failed
if(!p.SetType(type,err)) goto fail; // Incorrect projection type
changetype=true;
}
// Region required in new mode
if(!(region.Exist() || upd)) {err="Region must be specified"; goto fail;}
if(region.Exist()) p.region=region;
ONPar<Base2CoordD> cmer("c[entral][( |_)]meridian",(p.region.xb+p.region.xe)*0.5), stpar("s[tandar(t|d)][( |_)]parallel",(p.region.yb+p.region.ye)*0.5);
ONPar<Base2CoordD> clon("(l[ongitude][( |_)][of( |_)]center|c[enter][( |_)]longitude)",(p.region.xb+p.region.xe)*0.5);
ONPar<Base2CoordD> clat("(l[atitude][( |_)][of( |_)]center|c[enter][( |_)]latitude)",(p.region.yb+p.region.ye)*0.5);
// Get parameters of projection
switch(p.proj)
{
case(gmt_projection::XY): // x Parameter height (by default equal width)
{
BaseM2Nonneg height(input,"height","h");
if(height.Exist())
{
bool suc=true;
p.x.height=height(&suc);
if(!suc) goto fail; // Parsing error
}
else
{
BaseM2Nonneg width(input,"width","w");
if(!width.Exist() && changetype) p.x.height=gmt_projection::default_width; // We ignore case when parameter width exists but have wrong type. It will be handled later.
else
{
bool suc=true;
p.x.height=width(&suc);
if(!suc) goto fail; // Parsing error
}
}
// Width is processing later
if(height.Exist()) p.x.height=height;
else if(changetype) p.x.height=width; // By default, height equal width
break;
}
case(gmt_projection::CYL_EQU): // q Parameters: central meridian (cmer, default is center of region), standart parallel (stpar, default is center of region)
case(gmt_projection::CYL_EQU): // q Parameters: central meridian (cmer, default is center of region), standart parallel (stpar, default is center of region)
{
Base2Coord cmer(input,"cmer"), stpar(input,"stpar");
if(cmer.Exist())
{
bool suc=true;
p.q.cmer=cmer(&suc);
if(!suc) goto fail; // Parsing error
}
else if(changetype) p.q.cmer.Convert((p.region.xb+p.region.xe)*0.5);
if(stpar.Exist())
{
bool suc=true;
p.q.stpar=stpar(&suc);
if(!suc) goto fail; // Parsing error
}
else if(changetype) p.q.stpar.Convert((p.region.yb+p.region.ye)*0.5);
{ParseNamedParameters apar(input,cmer,stpar); if(!apar) {err=apar.Error(); goto fail;}} // Fail to parse additional parameters
if( cmer.Exist() || changetype) p.q.cmer =cmer;
if(stpar.Exist() || changetype) p.q.stpar=stpar;
break;
}
case(gmt_projection::MERCATOR): // m Parameters: central meridian (cmer, default is center of region), standart parallel (stpar, default is center of region)
{
Base2Coord cmer(input,"cmer"), stpar(input,"stpar");
if(cmer.Exist())
{
bool suc=true;
p.m.cmer=cmer(&suc);
if(!suc) goto fail; // Parsing error
}
else if(changetype) p.m.cmer.Convert((p.region.xb+p.region.xe)*0.5);
if(stpar.Exist())
{
bool suc=true;
p.m.stpar=stpar(&suc);
if(!suc) goto fail; // Parsing error
}
else if(changetype) p.m.stpar.Convert((p.region.yb+p.region.ye)*0.5);
{ParseNamedParameters apar(input,cmer,stpar); if(!apar) {err=apar.Error(); goto fail;}} // Fail to parse additional parameters
if( cmer.Exist() || changetype) p.m.cmer =cmer;
if(stpar.Exist() || changetype) p.m.stpar=stpar;
break;
}
case(gmt_projection::TRANSMERCATOR): // t Parameters: central meridian (cmer, default is center of region), latitude of origin (orlat, default is 0.0), scale factor (scale, default is 1.0)
{
Base2Coord cmer(input,"cmer"), orlat(input,"orlat");
Base2Double scale(input,"scale");
if(cmer.Exist())
{
bool suc=true;
p.t.cmer=cmer(&suc);
if(!suc) goto fail; // Parsing error
}
else if(changetype) p.t.cmer.Convert((p.region.xb+p.region.xe)*0.5);
if(orlat.Exist())
{
bool suc=true;
p.t.orlat=orlat(&suc);
if(!suc) goto fail; // Parsing error
}
else if(changetype) p.t.orlat.Convert(0.0);
if(scale.Exist())
{
bool suc=true;
p.t.scale=scale(&suc);
if(!suc) goto fail; // Parsing error
}
else if(changetype) p.t.scale=1.0;
ONPar<Base2NonNegD> scale("scale",1.0);
ONPar<Base2CoordD> orlat("(l[atitude][( |_)][of( |_)]origin|o[rigin][( |_)]latitude)",0.0);
{ParseNamedParameters apar(input,cmer,scale,orlat); if(!apar) {err=apar.Error(); goto fail;}} // Fail to parse additional parameters
if( cmer.Exist() || changetype) p.t.cmer =cmer;
if(orlat.Exist() || changetype) p.t.orlat=orlat;
if(scale.Exist() || changetype) p.t.scale=scale;
break;
}
case(gmt_projection::OBLIQMERCATOR): // o Parameters: longitude of projection center (clon, default is center of region), latitude of projection center (clat, default is center of region). Other parameters may form one of three combinations and doesn't have default values. 1) Azimuth of the oblique equator (azimuth). 2) Longitude and latitude of second point on oblique equator (eqlon, eqlat). 3) Longitude and latitude of projection pole (polelon, polelat).
{
Base2Coord clon(input,"clon"), clat(input,"clat");
Base2Coord azimuth(input,"azimuth"), eqlon(input,"eqlon"), eqlat(input,"eqlat"), polelon(input,"polelon"), polelat(input,"polelat");
ONPar<Base2Coord> eqlon("(l[ongitude][( |_)][of( |_)]equator|e[quator][( |_)]longitude)"), eqlat("(l[atitude][( |_)][of( |_)]equator|e[quator][( |_)]latitude)");
ONPar<Base2Coord> polelon("(l[ongitude][( |_)][of( |_)]pole|p[ole][( |_)]longitude)"), polelat("(l[atitude][( |_)][of( |_)]pole|p[ole][( |_)]latitude)");
ONPar<Base2Coord> azimuth("azimuth");
{ParseNamedParameters apar(input,clon,clat,eqlon,eqlat,polelon,polelat,azimuth); if(!apar) {err=apar.Error(); goto fail;}} // Fail to parse additional parameters
if(changetype) p.o.type=gmt_projection::OType::NOTDEF;
if(clon.Exist())
{
bool suc=true;
p.o.clon=clon(&suc);
if(!suc) goto fail; // Parsing error
}
else if(changetype) p.o.clon.Convert((p.region.xb+p.region.xe)*0.5);
if(clat.Exist())
if(clon.Exist() || changetype) p.o.clon=clon;
if(clat.Exist() || changetype) p.o.clat=clat;
// Check conflict in parameters
if(
(azimuth.Exist() && (eqlon.Exist() || eqlat.Exist() || polelon.Exist() || polelat.Exist() ) ) ||
( (eqlon.Exist() || eqlat.Exist()) && (azimuth.Exist() || polelon.Exist() || polelat.Exist() ) ) ||
( (polelon.Exist() || polelat.Exist()) && (azimuth.Exist() || eqlon.Exist() || eqlat.Exist() ) )
)
{
bool suc=true;
p.o.clat=clat(&suc);
if(!suc) goto fail; // Parsing error
err="Conflict in parameters for oblique Mercator projection, must specify only one variant: 1) azimuth of oblique equator, or 2) longitude and latitude of point on oblique equator, or 3) longitude and latitude of projection pole";
goto fail; // Insufficient data for this projection
}
else if(changetype) p.o.clat.Convert((p.region.yb+p.region.ye)*0.5);
// Variant 1
if(azimuth)
if(azimuth.Exist())
{
bool suc=(gmt_projection::OType::NOTDEF==p.o.type); // If projection subtype already defined, this is an error
p.o.type=gmt_projection::OType::A;
p.o.azimuth=azimuth(&suc);
if(!suc) goto fail; // Parsing error
p.o.azimuth=azimuth;
}
if(eqlon && eqlat)
// Variant 2
if(eqlon.Exist() && eqlat.Exist())
{
bool suc=(gmt_projection::OType::NOTDEF==p.o.type); // If projection subtype already defined, this is an error
p.o.type=gmt_projection::OType::B;
p.o.eqlon=eqlon(&suc);
p.o.eqlat=eqlat(&suc);
if(!suc) goto fail; // Parsing error
p.o.eqlon=eqlon;
p.o.eqlat=eqlat;
}
if(polelon && polelat)
// Variant 3
if(polelon.Exist() && polelat.Exist())
{
bool suc=(gmt_projection::OType::NOTDEF==p.o.type); // If projection subtype already defined, this is an error
p.o.type=gmt_projection::OType::C;
p.o.polelon=polelon(&suc);
p.o.polelat=polelat(&suc);
if(!suc) goto fail; // Parsing error
p.o.polelon=polelon;
p.o.polelat=polelat;
}
if(gmt_projection::OType::NOTDEF==p.o.type) goto fail; // Insufficient data for this projection
break;
}
case(gmt_projection::CASSINI): // c Parameters: longitude (clon, default is center of region) and latitude (clat, default is center of region) of central point.
{
Base2Coord clon(input,"clon"), clat(input,"clat");
if(clon.Exist())
// Special processing of update case
if(!changetype)
{
bool suc=true;
p.c.clon=clon(&suc);
if(!suc) goto fail; // Parsing error
if(eqlon.Exist() && !eqlat.Exist())
{
if(gmt_projection::OType::B!=p.o.type) {err="Insufficient parameters for oblique Mercator projection, must specify latitude of point on oblique equator"; goto fail;}
else p.o.eqlon=eqlon;
}
if(!eqlon.Exist() && eqlat.Exist())
{
if(gmt_projection::OType::B!=p.o.type) {err="Insufficient parameters for oblique Mercator projection, must specify longitude of point on oblique equator"; goto fail;}
else p.o.eqlat=eqlat;
}
if(polelon.Exist() && !polelat.Exist())
{
if(gmt_projection::OType::C!=p.o.type) {err="Insufficient parameters for oblique Mercator projection, must specify latitude of projection pole"; goto fail;}
else p.o.polelon=polelon;
}
if(!polelon.Exist() && polelat.Exist())
{
if(gmt_projection::OType::C!=p.o.type) {err="Insufficient parameters for oblique Mercator projection, must specify longitude of projection pole"; goto fail;}
else p.o.polelat=polelat;
}
}
else if(changetype) p.c.clon.Convert((p.region.xb+p.region.xe)*0.5);
if(clat.Exist())
if(gmt_projection::OType::NOTDEF==p.o.type)
{
bool suc=true;
p.c.clat=clat(&suc);
if(!suc) goto fail; // Parsing error
err="Insufficient parameters for oblique Mercator projection, must specify azimuth of oblique equator, or longitude and latitude of point on oblique equator, or longitude and latitude of projection pole";
goto fail; // Insufficient data for this projection
}
else if(changetype) p.c.clat.Convert((p.region.yb+p.region.ye)*0.5);
break;
}
case(gmt_projection::CASSINI): // c Parameters: longitude (clon, default is center of region) and latitude (clat, default is center of region) of central point.
{
{ParseNamedParameters apar(input,clon,clat); if(!apar) {err=apar.Error(); goto fail;}} // Fail to parse additional parameters
if(clon.Exist() || changetype) p.c.clon =clon;
if(clat.Exist() || changetype) p.c.clat =clat;
break;
}
case(gmt_projection::CYL_EQA): // y Parameters: central meridian (cmer, default is center of region), standart parallel (stpar, default is center of region)
{
Base2Coord cmer(input,"cmer"), stpar(input,"stpar");
if(cmer.Exist())
{
bool suc=true;
p.y.cmer=cmer(&suc);
if(!suc) goto fail; // Parsing error
}
else if(changetype) p.y.cmer.Convert((p.region.xb+p.region.xe)*0.5);
if(stpar.Exist())
{
bool suc=true;
p.y.stpar=stpar(&suc);
if(!suc) goto fail; // Parsing error
}
else if(changetype) p.y.stpar.Convert((p.region.yb+p.region.ye)*0.5);
{ParseNamedParameters apar(input,cmer,stpar); if(!apar) {err=apar.Error(); goto fail;}} // Fail to parse additional parameters
if( cmer.Exist() || changetype) p.y.cmer =cmer;
if(stpar.Exist() || changetype) p.y.stpar=stpar;
break;
}
case(gmt_projection::MILLER): // j Parameters: central meridian (cmer, default is center of region)
{
Base2Coord cmer(input,"cmer");
if(cmer.Exist())
{
bool suc=true;
p.j.cmer=cmer(&suc);
if(!suc) goto fail; // Parsing error
}
else if(changetype) p.j.cmer.Convert((p.region.xb+p.region.xe)*0.5);
{ParseNamedParameters apar(input,cmer); if(!apar) {err=apar.Error(); goto fail;}} // Fail to parse additional parameters
if(cmer.Exist() || changetype) p.j.cmer=cmer;
break;
}
case(gmt_projection::CYL_STERE): // cyl_stere Parameters: central meridian (cmer, default is center of region), standart parallel (stpar, default is center of region)
{
Base2Coord cmer(input,"cmer"), stpar(input,"stpar");
if(cmer.Exist())
{
bool suc=true;
p.cyl_stere.cmer=cmer(&suc);
if(!suc) goto fail; // Parsing error
}
else if(changetype) p.cyl_stere.cmer.Convert((p.region.xb+p.region.xe)*0.5);
if(stpar.Exist())
{
bool suc=true;
p.cyl_stere.stpar=stpar(&suc);
if(!suc) goto fail; // Parsing error
}
else if(changetype) p.cyl_stere.stpar.Convert((p.region.yb+p.region.ye)*0.5);
{ParseNamedParameters apar(input,cmer,stpar); if(!apar) {err=apar.Error(); goto fail;}} // Fail to parse additional parameters
if( cmer.Exist() || changetype) p.cyl_stere.cmer =cmer;
if(stpar.Exist() || changetype) p.cyl_stere.stpar=stpar;
break;
}
default: goto fail; // Unknown projection
default: {err="Code error, unknown projection"; goto fail;} // Unknown projection
}
// Try to find width parameter
if(!upd) p.width=p.default_width;
// Width and height manipulations
if(width.Exist() && height.Exist() && gmt_projection::XY!=p.proj) {err="For geographic projections only one of width or height can be specified"; goto fail;}
if(!upd) p.width=width;
{
BaseM2Nonneg w(input,"width","w"),h(input,"height","h");
bool suc=true;
if(w.Exist()) // width is present
if(width.Exist()) // width is present
{
p.width=w(&suc);
if(!suc) goto fail; // Parameter width exists, but can't be converted to double
if(!ProjectionRealSize(p)) goto fail; // Something go wrong with determining real dimensions
p.width=width;
if(!ProjectionRealSize(p)) goto failrealsize; // Something go wrong with determining real dimensions
}
else if(h.Exist()) // width is not present, but height is present
else if(height.Exist()) // width is not present, but height is present
{
double hval=h(&suc);
if(!suc) goto fail; // Parameter height exists, but can't be converted to double
if(gmt_projection::XY==p.proj) p.width=hval; // For decart projection we use height as width if width is not specified
if(!ProjectionRealSize(p,hval)) goto fail; // Something go wrong with determining real dimensions
if(gmt_projection::XY==p.proj) p.width=height; // For decart projection we use height as width if width is not specified
if(!ProjectionRealSize(p,height)) goto failrealsize;
}
else // No width, no height, using default or old width
if(!ProjectionRealSize(p)) goto fail; // Something go wrong with determining real dimensions
if(!ProjectionRealSize(p)) goto failrealsize; // Something go wrong with determining real dimensions
}
return p; // All parameters setted
failrealsize:
err="Can't determine real size of projection "+p.Value();
goto fail;
}
case4:
// Case 4
if(size>=3)
{
// First argument, try to set type of projection
{
Base2String type(input,0);
bool suc=true;
std::string typestr;
typestr=type(&suc);
if(!suc) goto fail; // No type - no projection
if(!p.SetType(typestr)) goto fail; // Unknown type - no projection
}
// Second argument, set up width
{
Base2Double w(input,1);
bool suc=true;
p.width=w(&suc);
if(!suc) goto fail; // Conversion failed, no width
}
// Third argument, set up region
{
Base2Region reg(input,2);
bool suc=true;
p.region=reg(&suc);
if(!suc) goto fail; // Conversion failed, no region
}
RPosPar<Base2String> type("projection type");
RPosPar<Base2NonNeg> width("width");
RPosPar<Base2Region> region("region");
{ParsePositionalParameters params(input,0,3,type,width,region); if(!params) {err=params.Error(); goto fail;}} // Fail to parse by variant 4
if(!p.SetType(type,err)) goto fail; // Incorrect projection type
p.width=width;
p.region=region;
// Projection specific parameters
switch(p.proj)
{
case(gmt_projection::XY): // x Parameter 4 is height (by default equal width)
{
Base2Double height(input,3);
if(height.Exist())
{
bool suc=true;
p.x.height=height(&suc);
if(!suc) goto fail; // Parsing error
}
else p.x.height=p.width;
if(size>4) goto fail; // Unknown parameter(s)
OPosPar<Base2NonNegD> height("height",p.width);
{ParsePositionalParameters params(input,3,input->Size(),height); if(!params) {err=params.Error(); goto fail;}} // Fail to parse additional parameters
p.x.height=height;
break;
}
case(gmt_projection::CYL_EQU): // q Parameters: 4 is central meridian (default is center of region), 5 is standart parallel (default is center of region)
{
Base2Coord cmer(input,3), stpar(input,4);
if(cmer.Exist())
{
bool suc=true;
p.q.cmer=cmer(&suc);
if(!suc) goto fail; // Parsing error
}
else p.q.cmer.Convert((p.region.xb+p.region.xe)*0.5);
if(stpar.Exist())
{
bool suc=true;
p.q.stpar=stpar(&suc);
if(!suc) goto fail; // Parsing error
}
else p.q.stpar.Convert((p.region.yb+p.region.ye)*0.5);
if(size>5) goto fail; // Unknown parameter(s)
OPosPar<Base2CoordD> cmer("central meridian",(p.region.xb+p.region.xe)*0.5);
OPosPar<Base2CoordD> stpar("standart parallel",(p.region.yb+p.region.ye)*0.5);
{ParsePositionalParameters params(input,3,input->Size(),cmer,stpar); if(!params) {err=params.Error(); goto fail;}} // Fail to parse additional parameters
p.q.cmer=cmer; p.q.stpar=stpar;
break;
}
case(gmt_projection::MERCATOR): // m Parameters: 4 is central meridian (default is center of region), 5 is standart parallel (default is center of region)
{
Base2Coord cmer(input,3), stpar(input,4);
if(cmer.Exist())
{
bool suc=true;
p.m.cmer=cmer(&suc);
if(!suc) goto fail; // Parsing error
}
else p.m.cmer.Convert((p.region.xb+p.region.xe)*0.5);
if(stpar.Exist())
{
bool suc=true;
p.m.stpar=stpar(&suc);
if(!suc) goto fail; // Parsing error
}
else p.m.stpar.Convert((p.region.yb+p.region.ye)*0.5);
if(size>5) goto fail; // Unknown parameter(s)
OPosPar<Base2CoordD> cmer("central meridian",(p.region.xb+p.region.xe)*0.5);
OPosPar<Base2CoordD> stpar("standart parallel",(p.region.yb+p.region.ye)*0.5);
{ParsePositionalParameters params(input,3,input->Size(),cmer,stpar); if(!params) {err=params.Error(); goto fail;}} // Fail to parse additional parameters
p.m.cmer=cmer; p.m.stpar=stpar;
break;
}
case(gmt_projection::TRANSMERCATOR): // t Parameters: 4 is central meridian (default is center of region), 5 is latitude of origin (default is 0.0), 6 is scale factor (default is 1.0)
{
Base2Coord cmer(input,3), orlat(input,4);
Base2Double scale(input,5);
if(cmer.Exist())
{
bool suc=true;
p.t.cmer=cmer(&suc);
if(!suc) goto fail; // Parsing error
}
else p.t.cmer.Convert((p.region.xb+p.region.xe)*0.5);
if(orlat.Exist())
{
bool suc=true;
p.t.orlat=orlat(&suc);
if(!suc) goto fail; // Parsing error
}
else p.t.orlat.Convert(0.0);
if(scale.Exist())
{
bool suc=true;
p.t.scale=scale(&suc);
if(!suc) goto fail; // Parsing error
}
else p.t.scale=1.0;
if(size>6) goto fail; // Unknown parameter(s)
OPosPar<Base2CoordD> cmer("central meridian",(p.region.xb+p.region.xe)*0.5);
OPosPar<Base2CoordD> orlat("latitude of origin",0.0);
OPosPar<Base2NonNegD> scale("scale",1.0);
{ParsePositionalParameters params(input,3,input->Size(),cmer,orlat,scale); if(!params) {err=params.Error(); goto fail;}} // Fail to parse additional parameters
p.t.cmer=cmer; p.t.orlat=orlat; p.t.scale=scale;
break;
}
case(gmt_projection::OBLIQMERCATOR): // o There is no default values for this projection. Parameters: 4 is subtype ("a" or "azimuth", "b" or "equator", "c" or "pole"), 5 is longitude of projection center, 6 is latitude of projection center. Other parameters may form one of three combinations. 1) 7 is azimuth of the oblique equator. 2) Longitude and latitude of second point on oblique equator (7, 8). 3) Longitude and latitude of projection pole (7, 8).
{
if(size<4) goto fail; // Insufficient data for this projection
OBType<ObjectString> stype(input->At(3));
if(!stype) goto fail; // Incorrect parameter type
std::string subtype=stype->Value();
tolower(subtype);
Base2Coord clon(input,4), clat(input,5);
Base2Coord azimuth(input,6), eqlon(input,6), eqlat(input,7), polelon(input,6), polelat(input,7);
RPosPar<Base2String> pstype("subtype");
RPosPar<Base2Coord> clon("longitude of center");
RPosPar<Base2Coord> clat("latitude of center");
{ParsePositionalParameters params(input,3,6,pstype,clon,clat); if(!params) {err=params.Error(); goto fail;}} // Fail to parse additional parameters
TemplateComparator a("azimuth"),b("(b|equator)"),c("(c|pole)");
std::string stype=pstype;
tolower(stype);
p.o.clon=clon; p.o.clat=clat;
p.o.type=gmt_projection::OType::NOTDEF;
{
bool suc=true;
p.o.clon=clon(&suc);
p.o.clat=clat(&suc);
if(!suc) goto fail; // Parsing error
}
// Variant 1
if("a"==subtype || "azimuth"==subtype)
if(a.Compare(stype))
{
RPosPar<Base2Coord> azimuth("azimuth");
{ParsePositionalParameters params(input,6,input->Size(),azimuth); if(!params) {err=params.Error(); goto fail;}} // Fail to parse additional parameters
p.o.type=gmt_projection::OType::A;
bool suc=true;
p.o.azimuth=azimuth(&suc);
if(!suc) goto fail; // Parsing error
if(size>7) goto fail; // Unknown parameter(s)
p.o.azimuth=azimuth;
}
if("b"==subtype || "equator"==subtype)
if(b.Compare(stype))
{
RPosPar<Base2Coord> eqlon("longitude of equator");
RPosPar<Base2Coord> eqlat("latitude of equator");
{ParsePositionalParameters params(input,6,input->Size(),eqlon,eqlat); if(!params) {err=params.Error(); goto fail;}} // Fail to parse additional parameters
p.o.type=gmt_projection::OType::B;
bool suc=true;
p.o.eqlon=eqlon(&suc);
p.o.eqlat=eqlat(&suc);
if(!suc) goto fail; // Parsing error
if(size>8) goto fail; // Unknown parameter(s)
p.o.eqlon=eqlon;
p.o.eqlat=eqlat;
}
if("c"==subtype || "pole"==subtype)
if(c.Compare(stype))
{
RPosPar<Base2Coord> polelon("longitude of pole");
RPosPar<Base2Coord> polelat("latitude of pole");
{ParsePositionalParameters params(input,6,input->Size(),polelon,polelat); if(!params) {err=params.Error(); goto fail;}} // Fail to parse additional parameters
p.o.type=gmt_projection::OType::C;
bool suc=true;
p.o.polelon=polelon(&suc);
p.o.polelat=polelat(&suc);
if(!suc) goto fail; // Parsing error
if(size>8) goto fail; // Unknown parameter(s)
p.o.polelon=polelon;
p.o.polelat=polelat;
}
if(gmt_projection::OType::NOTDEF==p.o.type) goto fail; // Insufficient data for this projection
if(gmt_projection::OType::NOTDEF==p.o.type) {err="String "+pstype.Value()+" is invalid subtype for oblique Mercator projection. The valid subtypes are azimuth, equator or pole"; goto fail;}
break;
}
case(gmt_projection::CASSINI): // c Parameters: longitude (4, default is center of region) and latitude (5, default is center of region) of central point.
{
Base2Coord clon(input,3), clat(input,4);
if(clon.Exist())
{
bool suc=true;
p.c.clon=clon(&suc);
if(!suc) goto fail; // Parsing error
}
else p.c.clon.Convert((p.region.xb+p.region.xe)*0.5);
if(clat.Exist())
{
bool suc=true;
p.c.clat=clat(&suc);
if(!suc) goto fail; // Parsing error
}
else p.c.clat.Convert((p.region.yb+p.region.ye)*0.5);
if(size>5) goto fail; // Unknown parameter(s)
OPosPar<Base2CoordD> clon("longitude of center",(p.region.xb+p.region.xe)*0.5);
OPosPar<Base2CoordD> clat("latitude of center",(p.region.yb+p.region.ye)*0.5);
{ParsePositionalParameters params(input,3,input->Size(),clon,clat); if(!params) {err=params.Error(); goto fail;}} // Fail to parse additional parameters
p.c.clon=clon; p.c.clat=clat;
break;
}
case(gmt_projection::CYL_EQA): // y Parameters: central meridian (4, default is center of region), standart parallel (5, default is center of region)
{
Base2Coord cmer(input,3), stpar(input,4);
if(cmer.Exist())
{
bool suc=true;
p.y.cmer=cmer(&suc);
if(!suc) goto fail; // Parsing error
}
else p.y.cmer.Convert((p.region.xb+p.region.xe)*0.5);
if(stpar.Exist())
{
bool suc=true;
p.y.stpar=stpar(&suc);
if(!suc) goto fail; // Parsing error
}
else p.y.stpar.Convert((p.region.yb+p.region.ye)*0.5);
if(size>5) goto fail; // Unknown parameter(s)
OPosPar<Base2CoordD> cmer("central meridian",(p.region.xb+p.region.xe)*0.5);
OPosPar<Base2CoordD> stpar("standart parallel",(p.region.yb+p.region.ye)*0.5);
{ParsePositionalParameters params(input,3,input->Size(),cmer,stpar); if(!params) {err=params.Error(); goto fail;}} // Fail to parse additional parameters
p.y.cmer=cmer; p.y.stpar=stpar;
break;
}
case(gmt_projection::MILLER): // j Parameters: central meridian (4, default is center of region)
{
Base2Coord cmer(input,3);
if(cmer.Exist())
{
bool suc=true;
p.j.cmer=cmer(&suc);
if(!suc) goto fail; // Parsing error
}
else p.j.cmer.Convert((p.region.xb+p.region.xe)*0.5);
if(size>4) goto fail; // Unknown parameter(s)
OPosPar<Base2CoordD> cmer("central meridian",(p.region.xb+p.region.xe)*0.5);
{ParsePositionalParameters params(input,3,input->Size(),cmer); if(!params) {err=params.Error(); goto fail;}} // Fail to parse additional parameters
p.j.cmer=cmer;
break;
}
case(gmt_projection::CYL_STERE): // cyl_stere Parameters: central meridian (3, default is center of region), standart parallel (4, default is center of region)
{
Base2Coord cmer(input,3), stpar(input,4);
if(cmer.Exist())
{
bool suc=true;
p.cyl_stere.cmer=cmer(&suc);
if(!suc) goto fail; // Parsing error
}
else p.cyl_stere.cmer.Convert((p.region.xb+p.region.xe)*0.5);
if(stpar.Exist())
{
bool suc=true;
p.cyl_stere.stpar=stpar(&suc);
if(!suc) goto fail; // Parsing error
}
else p.cyl_stere.stpar.Convert((p.region.yb+p.region.ye)*0.5);
if(size>5) goto fail; // Unknown parameter(s)
OPosPar<Base2CoordD> cmer("central meridian",(p.region.xb+p.region.xe)*0.5);
OPosPar<Base2CoordD> stpar("standart parallel",(p.region.yb+p.region.ye)*0.5);
{ParsePositionalParameters params(input,3,input->Size(),cmer,stpar); if(!params) {err=params.Error(); goto fail;}} // Fail to parse additional parameters
p.cyl_stere.cmer=cmer; p.cyl_stere.stpar=stpar;
break;
}
default: goto fail; // Unknown projection
}
if(ProjectionRealSize(p)) return p;
err="Can't determine real size of projection "+p.Value();
}
fail:

Loading…
Cancel
Save