getHorizonString.cc [tools/Rusle2SoilsXMLCreator/pg/rusle2_from_ssurgo_build_newbackup] Revision: default Date:
#include <string>
#include <iostream>
#include <boost/lexical_cast.hpp>
#include "rusle2_from_ssurgo.h"
using namespace std;
using boost::lexical_cast;
/**
* Query the [CHORIZON] information for XML output
* chkey gets passed back to parent program to query this information directly
*
* Yeah...it's a second query but I didn't really want to be passing data all over
* This just makes more sense to me...sorry if it doesn't to someone else later
*/
PGresult*
queryHorizonForXML( PGconn* conn, string chKEY )
{
string Query = "SELECT "
"om_l, om_r, om_h, "
"ph1to1h2o_l, ph1to1h2o_r, ph1to1h2o_h, "
"kffact, "
"sandtotal_l, sandtotal_r, sandtotal_h, "
"silttotal_l, silttotal_r, silttotal_h, "
"claytotal_l, claytotal_r, claytotal_h, "
"cec7_l, cec7_r, cec7_h, "
"wthirdbar_l, wthirdbar_r, wthirdbar_h, "
"wfifteenbar_l, wfifteenbar_r, wfifteenbar_h, "
"dbthirdbar_l, dbthirdbar_r, dbthirdbar_h "
"FROM ssurgo.chorizon WHERE chkey=$1::varchar";
const char * paramValues[1];
paramValues[0] = chKEY.c_str();
int numParams = 1;
PGresult *chHorizRes;
chHorizRes = PQexecParams( conn,
Query.c_str(),
numParams,
NULL,
paramValues,
NULL,
NULL,
0);
if( PQresultStatus(chHorizRes) != PGRES_TUPLES_OK ){
PQclear(chHorizRes);
exit_nicely(conn);
}
return chHorizRes;
}
/**
* Query out the [CHTEXTUREGRP] information
*/
PGresult*
queryHorizonTextureGroup( PGconn* conn, string chKEY )
{
string chTexGrpQuery = "SELECT texture, texdesc, chtgkey FROM ssurgo.chtexturegrp WHERE chkey=$1::varchar";
const char * paramValues[1];
paramValues[0] = chKEY.c_str();
int numParams = 1;
PGresult *chtexgrpRes;
chtexgrpRes = PQexecParams( conn,
chTexGrpQuery.c_str(),
numParams,
NULL,
paramValues,
NULL,
NULL,
0);
if( PQresultStatus(chtexgrpRes) != PGRES_TUPLES_OK ){
PQclear(chtexgrpRes);
exit_nicely(conn);
}
return chtexgrpRes;
}
/**
* Query out the [CHTEXTURE] information
*/
PGresult*
queryHorizonTextureLieutex( PGconn* conn, string chtgKEY)
{
string chTexQuery = "SELECT lieutex FROM ssurgo.chtexture WHERE chtgkey=$1::varchar";
const char * paramValues[1];
paramValues[0] = chtgKEY.c_str();
int numParams = 1;
PGresult *chtexRes;
chtexRes = PQexecParams( conn,
chTexQuery.c_str(),
numParams,
NULL,
paramValues,
NULL,
NULL,
0);
if( PQresultStatus(chtexRes) != PGRES_TUPLES_OK ){
PQclear(chtexRes);
exit_nicely(conn);
}
return chtexRes;
}
/**
* Query out the [HORIZON] information
*/
PGresult*
queryHorizons(PGconn* conn, string coKEY)
{
string horizQuery = "SELECT cokey, chkey, hzdept_l, hzdept_r, hzdept_h "
"FROM ssurgo.chorizon "
"WHERE cokey=$1::varchar "
"ORDER BY hzdept_r, hzdept_l";
const char * paramValues[1];
paramValues[0] = coKEY.c_str();
int numParams = 1;
PGresult *horizRes;
horizRes = PQexecParams( conn,
horizQuery.c_str(),
numParams,
NULL,
paramValues,
NULL,
NULL,
0);
if( PQresultStatus(horizRes) != PGRES_TUPLES_OK ){
PQclear(horizRes);
exit_nicely(conn);
}
return horizRes;
}
/**
* Get the Texture Group
*/
bool
getHorizonTextureGroup(string& hzGrp, PGresult* hzRes, int hzROW, PGconn* conn)
{
if( hzROW >= PQntuples(hzRes) )
return false;
hzGrp = GetNasisString("chtgkey", hzRes, hzROW);
return hzGrp.length() > 0 ? true : false;
}
/**
* Get the Lieutex
*/
bool
getHorizonTextureLieutex(string& hzTex, PGresult* hzRes, int hzROW)
{
if( hzROW >= PQntuples(hzRes) )
return false;
hzTex = GetNasisString("lieutex", hzRes, hzROW);
/** Frustrating...
* lieutex is often NULL...so can't test for length() > 0
*/
return true;
}
/**
* Query parent [COMPONENT] Taxonomic information...
*/
PGresult*
getParentComponentTaxInfo(string& coKEY, PGconn* conn )
{
string Query = "SELECT taxorder, taxsubgrp "
"FROM ssurgo.component "
"WHERE cokey=$1::varchar";
const char * paramValues[1];
paramValues[0] = coKEY.c_str();
int numParams = 1;
PGresult *res;
res = PQexecParams( conn,
Query.c_str(),
numParams,
NULL,
paramValues,
NULL,
NULL,
0);
if( PQresultStatus(res) != PGRES_TUPLES_OK ){
PQclear(res);
exit_nicely(conn);
}
return res;
}
/**
* Get the horizon string
* Or to be more specific, jump through all the hoops to get a texture
* Each horizon has mulitple textures...so we have to find a valid one
* But texture is not a property of a horizon, texture group is...
* So this is kind of a pain in the rear-end.
*
* @note There are checks for lieutex which skip over Organic Soils
* Specifically, remember if the component IS a histosol (organic?), we just take
* the first result.
* If it is NOT a histosol, then we want to find a valid texture which then does not
* describe a histosol...
*/
bool
getHorizonString(string& horizString, PGresult* chRes, int hROW, PGconn* conn)
{
#ifndef NDEBUG
cout << "getHorizonString()" << endl;
#endif
if( hROW >= PQntuples(chRes) || horizString.length() > 0 )
return false;
int i_horiz = 0;
string hzTexGrp;
string chKEY = GetNasisString("chkey", chRes, hROW);
PGresult *chHorizonTexGrpRes = queryHorizonTextureGroup(conn, chKEY);
int hzRow = 0;
string coKEY = GetNasisString("cokey", chRes, hROW);
PGresult *compTaxInfo = getParentComponentTaxInfo( coKEY, conn);
while( getHorizonTextureGroup( hzTexGrp , chHorizonTexGrpRes, hzRow, conn ) == true ){
string hzTexGrp = GetNasisString("chtgkey", chHorizonTexGrpRes, hzRow);
PGresult *chHoizonTextureRes = queryHorizonTextureLieutex(conn, hzTexGrp);
/*
* Protect against not finding a lieutex
* Rare but have found it happen with MI003
*/
if( PQntuples(chHoizonTextureRes) <= 0 ){
hzRow++;
continue;
}
int hzTexRow = 0;
string lieutex = GetNasisString("lieutex", chHoizonTextureRes, 0);
bool foundGoodHorizon = false;
while( getHorizonTextureLieutex(lieutex, chHoizonTextureRes, hzTexRow) == true ){
if( GetNasisString("taxorder", compTaxInfo, 0) == "Histosols" || GetNasisString("taxsubgrp", compTaxInfo, 0).find("Histic") != string::npos ){
/* This is the basic check for a good Horizon */
if( GetNasisString("hzdept_r", chRes, hROW) == "0" || GetNasisString("hzdept_l", chRes, hROW) == "0" ){
/* We have a the top Horizon */
foundGoodHorizon = true;
}else{
/* We only want the top Horizon */
hzTexRow++;
lieutex.erase(0);
continue;
}
}else if( lieutex == "Highly decomposed plant material" || lieutex == "Moderately decomposed plant material" ||
lieutex == "Mucky peat" || lieutex == "Muck" ||
lieutex == "Partially decomposed organic matter" || lieutex == "Peat" ||
lieutex == "Slightly decomposed plant material" || lieutex == "Undecomposed organic matter"){
/* the above lieutex checks are not acceptable for soils which are not histosols (organic?)
* so if we are here...we are a regular soil annd want a better horizon texture
* set as false and continue searching
*/
foundGoodHorizon = false;
}
/* A blank lieutex is acceptable... */
if( lieutex.length() == 0 || lieutex == "" )
foundGoodHorizon = true;
/* Similar to components, erase the lieutex */
hzTexRow++;
lieutex.erase(0);
}
/* Did we find a horizon with a valid texture ?
* If so...get the horizon description and return
* Otherwise...continue the iter
*/
if( foundGoodHorizon == true ){
horizString = GetNasisString("texdesc", chHorizonTexGrpRes, hzRow);
return true;
}
hzRow++;
}
#ifndef NDEBUG
cout << "\tleaving getHorizonString()" << endl;
#endif
return true;
}