Browse Source

Gmt module: Change logic of Projection and Region function.

Now, if arguments list contains object of corresponding type, function no just makes copy of this argument, but modify it parameters by other arguments.
ObjPtr
Michael Uleysky 9 years ago
parent
commit
86ecc17747
  1. 219
      modules/gmt/modgmt_func.cpp

219
modules/gmt/modgmt_func.cpp

@ -74,71 +74,98 @@ class RegionConv<ObjectList>
struct gmt_region operator()(const ObjectList* input, bool* issuc) const
{
struct gmt_region r;
auto size=input->Size();
// Case 1
for(ObjectList::ListValues::size_type i=0;i<input->Size();i++)
if(1==size) // Cases 1, 2 and 3
{
OBType<ObjectGMTRegion> region(input->At(i));
const ObjectBase *arg=input->At(0);
OBType<ObjectGMTRegion> region(arg);
if(region) return r=region->Data(); // Case 1
OBType<ObjectString> string(arg);
if(string && r.Convert(string->Value())) return r; // Case 2
OBType<ObjectList> list(arg);
if(list) return r=operator()(list,issuc); // Case 3
*issuc=false;
return r; // Conversion failed
}
// Case 4
{
// Special case, arguments list contains parameter region.
bool upd=false;
// Update case, arguments list contains parameter with type GMTRegion.
for(ObjectList::ListValues::size_type i=0;i<size;i++)
{
OBType<ObjectGMTRegion> region(input->At(i));
if(region)
{
if(upd){*issuc=false; return r;} // We already have region to update
r=region->Data();
upd=true;
}
}
// Update case, arguments list contains parameter region.
if(0!=input->Get("region"))
{
if(upd) {*issuc=false; return r;} // We already have region to update
ObjectList* list=new ObjectList;
list->PushBack(input->Get("region"));
r=operator()(list,issuc);
delete list;
return r;
if(!*issuc) return r; // Fail to convert
upd=true;
}
OBType<ObjectString> type(input->Get("type"));
if(type && r.Convert(type->Value())) return r; // type is one of "global*" string
if(type && r.Convert(type->Value())) return r; // type is one of "global*" string, we can return, becuse upd is irrelevant
Base2Coord ixb(input,"xb"), ixe(input,"xe"), iyb(input,"yb"), iye(input,"ye");
bool suc=true;
struct gmt_coord xb=ixb(&suc),yb=iyb(&suc),xe=ixe(&suc),ye=iye(&suc);
bool isbbox=false;
bool isbbox=upd?(gmt_region::BBOX==r.type):false;
if(type)
{
std::string s=type->Value();
tolower(s);
if("bbox"==s) isbbox=true;
if("nobbox"==s) isbbox=false;
if("bbox"!=s && "nobbox"!=s) suc=false; // Unknown type
}
if(ixb && ixe && iyb && iye && suc)
if(upd)
{
if(!r.Convert(xb,xe,yb,ye,isbbox)) *issuc=false;
return r; // Case 3 with all parameters
}
if(!ixb.Exist()) xb=r.xb;
if(!ixe.Exist()) xe=r.xe;
if(!iyb.Exist()) yb=r.yb;
if(!iye.Exist()) ye=r.ye;
}
else suc=suc && ixb && ixe && iyb && iye; // In "new" mode all parameters must exists and have correct type
if(ixb.Exist()) xb=ixb(&suc);
if(ixe.Exist()) xe=ixe(&suc);
if(iyb.Exist()) yb=iyb(&suc);
if(iye.Exist()) ye=iye(&suc);
if(input->Size()==1) // Cases 2 and 3
if(suc)
{
const ObjectBase *arg=input->At(0);
OBType<ObjectString> string(arg);
if(string && r.Convert(string->Value())) return r; // Case 2
OBType<ObjectList> list(arg);
if(list) r=operator()(list,issuc); // Case 3
else *issuc=false; // Unknown argument
return r;
if(!r.Convert(xb,xe,yb,ye,isbbox)) *issuc=false;
return r; // Case 3 with all parameters
}
}
// Case 5
if(4==input->Size() || 5==input->Size())
if(4==size || 5==size)
{
bool isbbox=false;
if(5==input->Size())
if(5==size)
{
OBType<ObjectString> type(input->At(4));
if(!type) {*issuc=false; return r;} // Unknown fifth parameter
std::string str=type->Value();
tolower(str);
if("bbox"!=str) {*issuc=false; return r;} // Unknown fifth parameter
isbbox=true;
if("bbox"!=str || "nobbox"!=str) {*issuc=false; return r;} // Unknown fifth parameter
if("bbox"==str) isbbox=true;
}
Base2Coord ixb(input,0), ixe(input,(isbbox?2:1)), iyb(input,(isbbox?1:2)), iye(input,3);
bool suc=true;
@ -192,37 +219,72 @@ class ProjConv<ObjectList>
struct gmt_projection p;
auto size=input->Size();
// Case 1
for(ObjectList::ListValues::size_type i=0;i<size;i++)
if(1==size) // Cases 1, and 2
{
OBType<ObjectGMTProjection> proj(input->At(i));
const ObjectBase *arg=input->At(0);
OBType<ObjectGMTProjection> proj(arg);
if(proj) return p=proj->Data(); // Case 1
OBType<ObjectList> list(arg);
if(list) return p=operator()(list,issuc); // Case 2
*issuc=false;
return p; // Conversion failed
}
// Case 3
{
// Special case, arguments list contains parameter proj or projection and this parameter is projection.
bool upd=false;
bool longisproj=false; // "projection" is good defined projection
bool shortisproj=false; // "proj" is good defined projection
bool changetype=false; // Projection type was specified in update mode. If new type is same as old type parameters of projection reset to default for this type.
// Update case, arguments list contains parameter with type GMTProjection.
for(ObjectList::ListValues::size_type i=0;i<size;i++)
{
OBType<ObjectGMTProjection> proj(input->At(i));
if(proj)
{
if(upd) goto fail; // Only one projection in list allowed
p=proj->Data();
upd=true;
}
}
// Update case, arguments list contains parameter proj or projection and this parameter is projection.
{
const ObjectBase* prg;
prg=input->Get("projection");
if(0!=prg)
{
struct gmt_projection ps;
bool suc=true;
ObjectList* list=new ObjectList;
list->PushBack(prg->Copy());
p=operator()(list,&suc);
ps=operator()(list,&suc);
delete list;
if(suc) return p; // Projection found, return
if(suc)
{
if(upd) goto fail; // Already have projection to update
upd=true;
longisproj=true;
p=ps;
}
}
prg=input->Get("proj");
if(0!=prg)
{
struct gmt_projection ps;
bool suc=true;
ObjectList* list=new ObjectList;
list->PushBack(prg->Copy());
p=operator()(list,&suc);
ps=operator()(list,&suc);
delete list;
if(suc) return p; // Projection found, return
if(suc)
{
if(upd) goto fail; // Already have projection to update
upd=true;
shortisproj=true;
p=ps;
}
}
}
@ -231,13 +293,30 @@ class ProjConv<ObjectList>
OBType<ObjectString> type1(input->Get("projtype"));
OBType<ObjectString> type2(input->Get("projection"));
OBType<ObjectString> type3(input->Get("proj"));
if(!(type1.Exist() || type2.Exist() || type3.Exist())) goto case24; // No named parameter, go to another case
if(!(type1.Exist() || type2.Exist() || type3.Exist() || upd)) goto case4; // No named parameter, not update mode, go to case 4
// Check on redundant parameters
if(type1.Exist() && type2.Exist() && type3.Exist()) goto fail; // Too many variants
if(type1.Exist() && type2.Exist() && !type3.Exist() && !longisproj) goto fail; // "projtype" and "projection" exists, but "projection" is not parse to Projection
if(type1.Exist() && !type2.Exist() && type3.Exist() && !shortisproj) goto fail; // "projtype" and "proj" exists, but "proj" is not parse to Projection
if(!type1.Exist() && type2.Exist() && type3.Exist() && !(shortisproj || longisproj)) goto fail; // "projection" and "proj" exists, but no one is parse to Projection
// Check on type correctness
if(type1.Exist() && !type1) goto fail; // "projtype" is not String
if(type2.Exist() && !type2 && !longisproj) goto fail; // "projection" is not String or Projection
if(type3.Exist() && !type3 && !shortisproj) goto fail; // "proj" is not String or Projection
bool suc=false;
if(!(type1 || type2 || type3) ) goto fail; // No type - no projection
if(!(type1 || type2 || type3)) // No String parameter
{
if(!upd) goto fail; // No type - no projection
changetype=false;
}
else
{
changetype=true;
if(!suc && type1) suc=p.SetType(type1->Value());
if(!suc && type2) suc=p.SetType(type2->Value());
if(!suc && type3) suc=p.SetType(type3->Value());
if(!suc) goto fail; // Unknown type - no projection
if(!suc) goto fail; // Incorrect projection type
}
}
// We need the region
@ -256,9 +335,14 @@ class ProjConv<ObjectList>
for(ObjectList::ListValues::size_type i=0;i<input->Size();i++)
{
OBType<ObjectGMTRegion> reg(input->At(i));
if(reg) {p.region=reg->Data(); suc=true;}
if(reg)
{
if(suc) goto fail; // Too many regions
p.region=reg->Data();
suc=true;
}
}
if(!suc) goto fail; // No such objects found
if(!suc && !upd) goto fail; // No such objects found in "new" mode
}
}
@ -277,7 +361,7 @@ class ProjConv<ObjectList>
else
{
Base2Double width(input,"width");
if(!width) p.x.height=gmt_projection::default_width; // We ignore case when parameter width exists but have wrong type. It will be handled later.
if(!width && 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;
@ -296,14 +380,14 @@ class ProjConv<ObjectList>
p.q.cmer=cmer(&suc);
if(!suc) goto fail; // Parsing error
}
else p.q.cmer.Convert((p.region.xb+p.region.xe)*0.5);
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 p.q.stpar.Convert((p.region.yb+p.region.ye)*0.5);
else if(changetype) p.q.stpar.Convert((p.region.yb+p.region.ye)*0.5);
break;
}
case(gmt_projection::MERCATOR): // m Parameters: central meridian (cmer, default is center of region), standart parallel (stpar, default is center of region)
@ -315,14 +399,14 @@ class ProjConv<ObjectList>
p.m.cmer=cmer(&suc);
if(!suc) goto fail; // Parsing error
}
else p.m.cmer.Convert((p.region.xb+p.region.xe)*0.5);
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 p.m.stpar.Convert((p.region.yb+p.region.ye)*0.5);
else if(changetype) p.m.stpar.Convert((p.region.yb+p.region.ye)*0.5);
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)
@ -335,42 +419,42 @@ class ProjConv<ObjectList>
p.t.cmer=cmer(&suc);
if(!suc) goto fail; // Parsing error
}
else p.t.cmer.Convert((p.region.xb+p.region.xe)*0.5);
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 p.t.orlat.Convert(0.0);
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 p.t.scale=1.0;
else if(changetype) p.t.scale=1.0;
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");
p.o.type=gmt_projection::OType::NOTDEF;
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 p.o.clon.Convert((p.region.xb+p.region.xe)*0.5);
else if(changetype) p.o.clon.Convert((p.region.xb+p.region.xe)*0.5);
if(clat.Exist())
{
bool suc=true;
p.o.clat=clat(&suc);
if(!suc) goto fail; // Parsing error
}
else p.o.clat.Convert((p.region.yb+p.region.ye)*0.5);
else if(changetype) p.o.clat.Convert((p.region.yb+p.region.ye)*0.5);
// Variant 1
if(azimuth)
{
@ -407,14 +491,14 @@ class ProjConv<ObjectList>
p.c.clon=clon(&suc);
if(!suc) goto fail; // Parsing error
}
else p.c.clon.Convert((p.region.xb+p.region.xe)*0.5);
else if(changetype) 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);
else if(changetype) p.c.clat.Convert((p.region.yb+p.region.ye)*0.5);
break;
}
case(gmt_projection::CYL_EQA): // y Parameters: central meridian (cmer, default is center of region), standart parallel (stpar, default is center of region)
@ -426,14 +510,14 @@ class ProjConv<ObjectList>
p.y.cmer=cmer(&suc);
if(!suc) goto fail; // Parsing error
}
else p.y.cmer.Convert((p.region.xb+p.region.xe)*0.5);
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 p.y.stpar.Convert((p.region.yb+p.region.ye)*0.5);
else if(changetype) p.y.stpar.Convert((p.region.yb+p.region.ye)*0.5);
break;
}
case(gmt_projection::MILLER): // j Parameters: central meridian (cmer, default is center of region)
@ -445,7 +529,7 @@ class ProjConv<ObjectList>
p.j.cmer=cmer(&suc);
if(!suc) goto fail; // Parsing error
}
else p.j.cmer.Convert((p.region.xb+p.region.xe)*0.5);
else if(changetype) p.j.cmer.Convert((p.region.xb+p.region.xe)*0.5);
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)
@ -457,21 +541,21 @@ class ProjConv<ObjectList>
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);
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 p.cyl_stere.stpar.Convert((p.region.yb+p.region.ye)*0.5);
else if(changetype) p.cyl_stere.stpar.Convert((p.region.yb+p.region.ye)*0.5);
break;
}
default: goto fail; // Unknown projection
}
// Try to find width parameter
p.width=p.default_width;
if(!upd) p.width=p.default_width;
{
Base2Double w(input,"width"),h(input,"height");
bool suc=true;
@ -488,20 +572,13 @@ class ProjConv<ObjectList>
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
}
else // No width, no height, using default width
else // No width, no height, using default or old width
if(!ProjectionRealSize(p)) goto fail; // Something go wrong with determining real dimensions
}
return p; // All parameters setted
}
case24:
if(input->Size()==1) // Case 2
{
OBType<ObjectList> list(input->At(0));
if(list) p=operator()(list,issuc);
else *issuc=false; // Unknown argument
return p;
}
case4:
// Case 4
if(size>=3)
@ -770,12 +847,13 @@ ObjectBase* GMT_Coord(const ObjectList* input)
/*
Input:
1) Any number of arguments, search argument with ObjectGMTRegion type and copy it.
1) One argument, Region. Return copy of this argument.
2) One argument, case insensitive string "global180" (global domain -R-180/180/-90/90), "global360" (global domain -R0/360/-90/90) or "global" (synonym of "global360").
3) One argument, list. Recursively calling GMT_Region.
4) Pairs list. Names are xb, xe, yb, ye, and, optionally, type="bbox|global180|global360|global". Names are case sensitive, values can be Int, Real, String or GMTCoord.
If pair with name region exists in list, when recursively calling GMT_Region on the value of this parameter, instead.
5) 4 or 5 parameters. If fifth parameter is string "bbox", when first four parameters interprets as xb,yb,xe,ye, else as xb,xe,yb,ye.
4) Pairs list. Names are xb, xe, yb, ye, and, optionally, type="bbox|nobbox|global180|global360|global". Names are case sensitive, values can be Int, Real, String or GMTCoord.
If pair with name region exists in list, when recursively calling GMT_Region on the value of this parameter, when modify it with specified parameters.
If argument with type Region exists in list, when copy it and modify with specified parameters.
5) 4 or 5 parameters. Fifth parameter can be "bbox" or "nobbox" (default). If fifth parameter is string "bbox", when first four parameters interprets as xb,yb,xe,ye, else as xb,xe,yb,ye.
*/
ObjectBase* GMT_Region(const ObjectList* input)
{
@ -788,12 +866,13 @@ ObjectBase* GMT_Region(const ObjectList* input)
/*
Input:
1) Any number of arguments, search argument with ObjectGMTProjection type and copy it.
1) One argument, Projection. Return copy of this argument.
2) One argument, list. Recursively calling GMT_Projection.
3) Pairs list. Names are projtype (string), region (GMTRegion, string or list, which can be converted to GMTRegion),
width (or height) in centimeters (may be absent, default width is 10 cm) and projection-dependent parameters.
Pair with name region may absent, in this case search in list and using as region object with ObjectGMTRegion type.
If pair with name proj (or projection) exists in list, when recursively calling GMT_Region on the value of this parameter, instead.
If pair with name proj (or projection) exists in list, when recursively calling GMT_Projection on the value of this parameter, when modify it with specified parameters.
If argument with type Projection exists in list, when copy it and modify with specified parameters.
4) 3 or more parameters. First parameter is projection type (string), second - width in centimeters,
third - region (any type which can be converted to GMTRegion), other parameters are projection-dependent.
Height can be set only in form 3.

Loading…
Cancel
Save