Beispiel #1
0
OGR_SRSNode *OGR_SRSNode::Clone() const

{
    OGR_SRSNode *poNew = new OGR_SRSNode( pszValue );

    for( int i = 0; i < nChildren; i++ )
    {
        poNew->AddChild( papoChildNodes[i]->Clone() );
    }

    return poNew;
}
/**
 * \brief Validate the current VERT_DATUM's arguments.
 *
 * @return OGRERR_NONE if the VERT_DATUM's arguments validate, an error code
 *         otherwise
 */
OGRErr OGRSpatialReference::ValidateVertDatum(OGR_SRSNode *poRoot)
{
    if ( !EQUAL(poRoot->GetValue(), "VERT_DATUM") )
        return OGRERR_NONE;

    if (poRoot->GetChildCount() < 2 )
    {
        CPLDebug( "OGRSpatialReference::Validate",
                  "Invalid number of children : %d", poRoot->GetChildCount() );
        return OGRERR_CORRUPT_DATA;
    }

    if (atoi(poRoot->GetChild(1)->GetValue()) == 0)
    {
        CPLDebug( "OGRSpatialReference::Validate",
                  "Invalid value for datum type (%s) : must be a number\n",
                  poRoot->GetChild(1)->GetValue());
        return OGRERR_CORRUPT_DATA;
    }

    OGR_SRSNode     *poNode;
    int             i;

    for( i = 2; i < poRoot->GetChildCount(); i++ )
    {
        poNode = poRoot->GetChild(i);

        if( EQUAL(poNode->GetValue(),"AUTHORITY") )
        {
            OGRErr eErr = ValidateAuthority(poNode);
            if (eErr != OGRERR_NONE)
                return eErr;
        }
        else if( EQUAL(poNode->GetValue(),"EXTENSION") )
        {
            // We do not try to control the sub-organization of
            // EXTENSION nodes.
        }
        else
        {
            CPLDebug( "OGRSpatialReference::Validate",
                      "Unexpected child for VERT_DATUM `%s'.\n",
                      poNode->GetValue() );

            return OGRERR_CORRUPT_DATA;
        }
    }

    return OGRERR_NONE;
}
std::string CSpatialReference::GetProjName() const
{
	if(!m_Handle)
	{
		return "";
	}

	OGRSpatialReference* psr = (OGRSpatialReference*)m_Handle;

	//查找GEOGCS节点
	OGR_SRSNode *pNode =psr->GetAttrNode("PROJCS");

	if(!pNode)
	{
		return "";
	}

	return pNode->GetChild(0)->GetValue();
}
std::string SpatialReference::getVertical() const
{
    std::string tmp("");

    OGRSpatialReference* poSRS =
        (OGRSpatialReference*)OSRNewSpatialReference(m_wkt.c_str());
    char *pszWKT = NULL;

    OGR_SRSNode* node = poSRS->GetAttrNode("VERT_CS");
    if (node && poSRS)
    {
        node->exportToWkt(&pszWKT);
        tmp = pszWKT;
        CPLFree(pszWKT);
        OSRDestroySpatialReference(poSRS);
    }

    return tmp;
}
Beispiel #5
0
void ProjectionDlg::OnItemRightClick( wxListEvent &event )
{
	int item_clicked = event.GetIndex();

	OGR_SRSNode *root = m_proj.GetRoot();
	OGR_SRSNode *node, *par1, *par2;
	const char *value;
	int children = root->GetChildCount();
	int i, item = 0;
	wxString str;

	for (i = 0; i < children; i++)
	{
		node = root->GetChild(i);
		value = node->GetValue();
		if (strcmp(value, "PARAMETER"))
			continue;
		par1 = node->GetChild(0);
		par2 = node->GetChild(1);
		value = par2->GetValue();
		if (item == item_clicked)
		{
			wxString caption = _("Value for ");
			str = wxString(par1->GetValue(), wxConvUTF8);
			caption += str;
			str = wxString(value, wxConvUTF8);
			wxString result = wxGetTextFromUser(caption, _("Enter new value"),
				str, this);
			if (result != _T(""))
			{
//			  double newval = atof((const char *)result);
				par2->SetValue(result.mb_str(wxConvUTF8));
				DisplayProjectionSpecificParams();
				return;
			}
		}
		item++;
	}
}
Beispiel #6
0
void ProjectionDlg::DisplayProjectionSpecificParams()
{
	m_pParamCtrl->DeleteAllItems();

	OGR_SRSNode *root = m_proj.GetRoot();
	if (!root)
	{
		m_pParamCtrl->InsertItem(0, _("(Invalid projection)"));
		return;	 // bogus projection
	}

	OGR_SRSNode *node, *par1, *par2;
	const char *value;
	int children = root->GetChildCount();
	int i, item = 0;

	wxString str;
	for (i = 0; i < children; i++)
	{
		node = root->GetChild(i);
		value = node->GetValue();
		if (!strcmp(value, "PARAMETER"))
		{
			par1 = node->GetChild(0);
			value = par1->GetValue();
			str = wxString(value, wxConvUTF8);
			item = m_pParamCtrl->InsertItem(item, str);

			par2 = node->GetChild(1);
			value = par2->GetValue();
			str = wxString(value, wxConvUTF8);
			m_pParamCtrl->SetItem(item, 1, str);
			item++;
		}
	}
}
/**
 * \brief Validate the current PROJECTION's arguments.
 *
 * @return OGRERR_NONE if the PROJECTION's arguments validate, an error code
 *         otherwise
 */
OGRErr OGRSpatialReference::ValidateProjection(OGR_SRSNode *poRoot)
{
    OGR_SRSNode *poPROJCS = poRoot->GetNode( "PROJCS" );

    if( poPROJCS == NULL  )
        return OGRERR_NONE;

    if( poPROJCS->GetNode( "PROJECTION" ) == NULL )
    {
        CPLDebug( "OGRSpatialReference::Validate", 
                  "PROJCS does not have PROJECTION subnode." );
        return OGRERR_CORRUPT_DATA;
    }

/* -------------------------------------------------------------------- */
/*      Find the matching group in the proj and parms table.            */
/* -------------------------------------------------------------------- */
    const char *pszProjection;
    int        iOffset;
    
    pszProjection = poPROJCS->GetNode("PROJECTION")->GetChild(0)->GetValue();

    for( iOffset = 0; 
         papszProjWithParms[iOffset] != NULL
             && !EQUAL(papszProjWithParms[iOffset],pszProjection); )
    {
        while( papszProjWithParms[iOffset] != NULL )
            iOffset++;
        iOffset++;
    }

    if( papszProjWithParms[iOffset] == NULL )
        return OGRERR_UNSUPPORTED_SRS;

    iOffset++;

/* -------------------------------------------------------------------- */
/*      Check all parameters, and verify they are in the permitted      */
/*      list.                                                           */
/* -------------------------------------------------------------------- */
    int iNode;

    for( iNode = 0; iNode < poPROJCS->GetChildCount(); iNode++ )
    {
        OGR_SRSNode *poParm = poPROJCS->GetChild(iNode);
        int          i;
        const char  *pszParmName;

        if( !EQUAL(poParm->GetValue(),"PARAMETER") )
            continue;

        pszParmName = poParm->GetChild(0)->GetValue();

        for( i = iOffset; papszProjWithParms[i] != NULL; i++ )
        {
            if( EQUAL(papszProjWithParms[i],pszParmName) )
                break;
        }

        /* This parameter is not an exact match, is it an alias? */
        if( papszProjWithParms[i] == NULL )
        {
            for( i = iOffset; papszProjWithParms[i] != NULL; i++ )
            {
                if( IsAliasFor(papszProjWithParms[i],pszParmName) )
                    break;
            }

            if( papszProjWithParms[i] == NULL )
            {
                CPLDebug( "OGRSpatialReference::Validate", 
                          "PARAMETER %s for PROJECTION %s is not permitted.",
                          pszParmName, pszProjection );
                return OGRERR_CORRUPT_DATA;
            }
            else
            {
                CPLDebug( "OGRSpatialReference::Validate", 
                          "PARAMETER %s for PROJECTION %s is an alias for %s.",
                          pszParmName, pszProjection,
                          papszProjWithParms[i] );
                return OGRERR_CORRUPT_DATA;
            }
        }
    }

    return OGRERR_NONE;
}
Beispiel #8
0
OGRBoolean CheckCitationKeyForStatePlaneUTM(GTIF* hGTIF, GTIFDefn* psDefn, OGRSpatialReference* poSRS, OGRBoolean* pLinearUnitIsSet)
{
    if( !hGTIF || !psDefn || !poSRS )
        return FALSE;

/* -------------------------------------------------------------------- */
/*      For ESRI builds we are interested in maximizing PE              */
/*      compatability, but generally we prefer to use EPSG              */
/*      definitions of the coordinate system if PCS is defined.         */
/* -------------------------------------------------------------------- */
#if !defined(ESRI_BUILD)
    if( psDefn->PCS != KvUserDefined )
        return FALSE;
#endif

    char  szCTString[512];
    szCTString[0] = '\0';

    /* Check units */
    char units[32];
    units[0] = '\0';

    OGRBoolean hasUnits = FALSE;
    if( GTIFKeyGet( hGTIF, GTCitationGeoKey, szCTString, 0, sizeof(szCTString) ) )
    {
        CPLString osLCCT = szCTString;

        osLCCT.tolower();

        if( strstr(osLCCT,"us") && strstr(osLCCT,"survey")
            && (strstr(osLCCT,"feet") || strstr(osLCCT,"foot")) )
            strcpy(units, "us_survey_feet");
        else if(strstr(osLCCT, "linear_feet")  
                || strstr(osLCCT, "linear_foot") 
                || strstr(osLCCT, "international"))
            strcpy(units, "international_feet");
        else if( strstr(osLCCT,"meter") )
            strcpy(units, "meters");

        if (strlen(units) > 0)
            hasUnits = TRUE;

        if( strstr( szCTString, "Projection Name = ") && strstr( szCTString, "_StatePlane_"))
        {
            const char *pStr = strstr( szCTString, "Projection Name = ") + strlen("Projection Name = ");
            const char* pReturn = strchr( pStr, '\n');
            char CSName[128];
            strncpy(CSName, pStr, pReturn-pStr);
            CSName[pReturn-pStr] = '\0';
            if( poSRS->ImportFromESRIStatePlaneWKT(0, NULL, NULL, 32767, CSName) == OGRERR_NONE )
            {
                // for some erdas citation keys, the state plane CS name is incomplete, the unit check is necessary.
                OGRBoolean done = FALSE;
                if (hasUnits)
                {
                    OGR_SRSNode *poUnit = poSRS->GetAttrNode( "PROJCS|UNIT" );
      
                    if( poUnit != NULL && poUnit->GetChildCount() >= 2 )
                    {
                        CPLString unitName = poUnit->GetChild(0)->GetValue();
                        unitName.tolower();

                        if (strstr(units, "us_survey_feet"))
                        {              
                            if (strstr(unitName, "us_survey_feet") || strstr(unitName, "foot_us") )
                                done = TRUE;
                        }
                        else if (strstr(units, "international_feet"))
                        {
                            if (strstr(unitName, "feet") || strstr(unitName, "foot"))
                                done = TRUE;
                        }
                        else if (strstr(units, "meters"))
                        {
                            if (strstr(unitName, "meter") )
                                done = TRUE;
                        }
                    }
                }
                if (done)
                    return TRUE;
            }
        }
    }
    if( !hasUnits )
    {
        char	*pszUnitsName = NULL;
        GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
        if( pszUnitsName && strlen(pszUnitsName) > 0 )
        {
            CPLString osLCCT = pszUnitsName;
            GTIFFreeMemory( pszUnitsName );
            osLCCT.tolower();

            if( strstr(osLCCT, "us") && strstr(osLCCT, "survey")
                && (strstr(osLCCT, "feet") || strstr(osLCCT, "foot")))
                strcpy(units, "us_survey_feet");
            else if(strstr(osLCCT, "feet") || strstr(osLCCT, "foot"))
                strcpy(units, "international_feet");
            else if(strstr(osLCCT, "meter"))
                strcpy(units, "meters");
            hasUnits = TRUE;
        }
    }

    if (strlen(units) == 0)
        strcpy(units, "meters");

    /* check PCSCitationGeoKey if it exists */
    szCTString[0] = '\0';
    if( hGTIF && GTIFKeyGet( hGTIF, PCSCitationGeoKey, szCTString, 0, sizeof(szCTString)) )  
    {
        /* For tif created by LEICA(ERDAS), ESRI state plane pe string was used and */
        /* the state plane zone is given in PCSCitation. Therefore try Esri pe string first. */
        SetCitationToSRS(hGTIF, szCTString, strlen(szCTString), PCSCitationGeoKey, poSRS, pLinearUnitIsSet);
        const char *pcsName = poSRS->GetAttrValue("PROJCS");
        const char *pStr = NULL;
        if( (pcsName && (pStr = strstr(pcsName, "State Plane Zone ")) != NULL)
            || (pStr = strstr(szCTString, "State Plane Zone ")) != NULL )
        {
            pStr += strlen("State Plane Zone ");
            int statePlaneZone = abs(atoi(pStr));
            char nad[32];
            strcpy(nad, "HARN");
            if( strstr(szCTString, "NAD83") || strstr(szCTString, "NAD = 83") )
                strcpy(nad, "NAD83");
            else if( strstr(szCTString, "NAD27") || strstr(szCTString, "NAD = 27") )
                strcpy(nad, "NAD27");
            if( poSRS->ImportFromESRIStatePlaneWKT(statePlaneZone, (const char*)nad, (const char*)units, psDefn->PCS) == OGRERR_NONE )
                return TRUE;
        }
        else if( pcsName && (pStr = strstr(pcsName, "UTM Zone ")) != NULL )
            CheckUTM( psDefn, szCTString );
    }

    /* check state plane again to see if a pe string is available */
    if( psDefn->PCS != KvUserDefined )
    {
        if( poSRS->ImportFromESRIStatePlaneWKT(0, NULL, (const char*)units, psDefn->PCS) == OGRERR_NONE )
            return TRUE;
    }

    return FALSE;
}
Beispiel #9
0
int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn, 
                                  OGRSpatialReference * poTargetIn )

{
    if( poSourceIn == NULL || poTargetIn == NULL )
        return FALSE;

    poSRSSource = poSourceIn->Clone();
    poSRSTarget = poTargetIn->Clone();

    bSourceLatLong = poSRSSource->IsGeographic();
    bTargetLatLong = poSRSTarget->IsGeographic();

/* -------------------------------------------------------------------- */
/*      Setup source and target translations to radians for lat/long    */
/*      systems.                                                        */
/* -------------------------------------------------------------------- */
    dfSourceToRadians = DEG_TO_RAD;
    bSourceWrap = FALSE;
    dfSourceWrapLong = 0.0;

    if( bSourceLatLong )
    {
        OGR_SRSNode *poUNITS = poSRSSource->GetAttrNode( "GEOGCS|UNIT" );
        if( poUNITS && poUNITS->GetChildCount() >= 2 )
        {
            dfSourceToRadians = atof(poUNITS->GetChild(1)->GetValue());
            if( dfSourceToRadians == 0.0 )
                dfSourceToRadians = DEG_TO_RAD;
        }
    }

    dfTargetFromRadians = RAD_TO_DEG;
    bTargetWrap = FALSE;
    dfTargetWrapLong = 0.0;

    if( bTargetLatLong )
    {
        OGR_SRSNode *poUNITS = poSRSTarget->GetAttrNode( "GEOGCS|UNIT" );
        if( poUNITS && poUNITS->GetChildCount() >= 2 )
        {
            double dfTargetToRadians = atof(poUNITS->GetChild(1)->GetValue());
            if( dfTargetToRadians != 0.0 )
                dfTargetFromRadians = 1 / dfTargetToRadians;
        }
    }

/* -------------------------------------------------------------------- */
/*      Preliminary logic to setup wrapping.                            */
/* -------------------------------------------------------------------- */
    const char *pszCENTER_LONG;

    if( CPLGetConfigOption( "CENTER_LONG", NULL ) != NULL )
    {
        bSourceWrap = bTargetWrap = TRUE;
        dfSourceWrapLong = dfTargetWrapLong = 
            atof(CPLGetConfigOption( "CENTER_LONG", "" ));
        CPLDebug( "OGRCT", "Wrap at %g.", dfSourceWrapLong );
    }

    pszCENTER_LONG = poSRSSource->GetExtension( "GEOGCS", "CENTER_LONG" );
    if( pszCENTER_LONG != NULL )
    {
        dfSourceWrapLong = atof(pszCENTER_LONG);
        bSourceWrap = TRUE;
        CPLDebug( "OGRCT", "Wrap source at %g.", dfSourceWrapLong );
    }

    pszCENTER_LONG = poSRSTarget->GetExtension( "GEOGCS", "CENTER_LONG" );
    if( pszCENTER_LONG != NULL )
    {
        dfTargetWrapLong = atof(pszCENTER_LONG);
        bTargetWrap = TRUE;
        CPLDebug( "OGRCT", "Wrap target at %g.", dfTargetWrapLong );
    }
    
    bCheckWithInvertProj = CSLTestBoolean(CPLGetConfigOption( "CHECK_WITH_INVERT_PROJ", "NO" ));
    
    /* The threshold is rather experimental... Works well with the cases of ticket #2305 */
    if (bSourceLatLong)
        dfThreshold = atof(CPLGetConfigOption( "THRESHOLD", ".1" ));
    else
        /* 1 works well for most projections, except for +proj=aeqd that requires */
        /* a tolerance of 10000 */
        dfThreshold = atof(CPLGetConfigOption( "THRESHOLD", "10000" ));

/* -------------------------------------------------------------------- */
/*      Establish PROJ.4 handle for source if projection.               */
/* -------------------------------------------------------------------- */
    // OGRThreadSafety: The following variable is not a thread safety issue 
    // since the only issue is incrementing while accessing which at worse 
    // means debug output could be one "increment" late. 
    static int   nDebugReportCount = 0;

    char        *pszSrcProj4Defn = NULL;

    if( poSRSSource->exportToProj4( &pszSrcProj4Defn ) != OGRERR_NONE )
    {
        CPLFree( pszSrcProj4Defn );
        return FALSE;
    }

    if( strlen(pszSrcProj4Defn) == 0 )
    {
        CPLFree( pszSrcProj4Defn );
        CPLError( CE_Failure, CPLE_AppDefined, 
                  "No PROJ.4 translation for source SRS, coordinate\n"
                  "transformation initialization has failed." );
        return FALSE;
    }

    if (pjctx)
        psPJSource = pfn_pj_init_plus_ctx( pjctx, pszSrcProj4Defn );
    else
        psPJSource = pfn_pj_init_plus( pszSrcProj4Defn );
    
    if( psPJSource == NULL )
    {
        if( pjctx != NULL)
        {
            int pj_errno = pfn_pj_ctx_get_errno(pjctx);

            /* pfn_pj_strerrno not yet thread-safe in PROJ 4.8.0 */
            CPLMutexHolderD(&hPROJMutex);
            CPLError( CE_Failure, CPLE_NotSupported, 
                      "Failed to initialize PROJ.4 with `%s'.\n%s", 
                      pszSrcProj4Defn, pfn_pj_strerrno(pj_errno) );
        }
        else if( pfn_pj_get_errno_ref != NULL
            && pfn_pj_strerrno != NULL )
        {
            int *p_pj_errno = pfn_pj_get_errno_ref();

            CPLError( CE_Failure, CPLE_NotSupported, 
                      "Failed to initialize PROJ.4 with `%s'.\n%s", 
                      pszSrcProj4Defn, pfn_pj_strerrno(*p_pj_errno) );
        }
        else
        {
            CPLError( CE_Failure, CPLE_NotSupported, 
                      "Failed to initialize PROJ.4 with `%s'.\n", 
                      pszSrcProj4Defn );
        }
    }
    
    if( nDebugReportCount < 10 )
        CPLDebug( "OGRCT", "Source: %s", pszSrcProj4Defn );

    if( psPJSource == NULL )
    {
        CPLFree( pszSrcProj4Defn );
        return FALSE;
    }

/* -------------------------------------------------------------------- */
/*      Establish PROJ.4 handle for target if projection.               */
/* -------------------------------------------------------------------- */

    char        *pszDstProj4Defn = NULL;

    if( poSRSTarget->exportToProj4( &pszDstProj4Defn ) != OGRERR_NONE )
    {
        CPLFree( pszSrcProj4Defn );
        CPLFree( pszDstProj4Defn );
        return FALSE;
    }

    if( strlen(pszDstProj4Defn) == 0 )
    {
        CPLFree( pszSrcProj4Defn );
        CPLFree( pszDstProj4Defn );
        CPLError( CE_Failure, CPLE_AppDefined, 
                  "No PROJ.4 translation for destination SRS, coordinate\n"
                  "transformation initialization has failed." );
        return FALSE;
    }

    if (pjctx)
        psPJTarget = pfn_pj_init_plus_ctx( pjctx, pszDstProj4Defn );
    else
        psPJTarget = pfn_pj_init_plus( pszDstProj4Defn );
    
    if( psPJTarget == NULL )
        CPLError( CE_Failure, CPLE_NotSupported, 
                  "Failed to initialize PROJ.4 with `%s'.", 
                  pszDstProj4Defn );
    
    if( nDebugReportCount < 10 )
    {
        CPLDebug( "OGRCT", "Target: %s", pszDstProj4Defn );
        nDebugReportCount++;
    }

    if( psPJTarget == NULL )
    {
        CPLFree( pszSrcProj4Defn );
        CPLFree( pszDstProj4Defn );
        return FALSE;
    }

    /* Determine if we really have a transformation to do */
    bIdentityTransform = (strcmp(pszSrcProj4Defn, pszDstProj4Defn) == 0);

    /* In case of identity transform, under the following conditions, */
    /* we can also avoid transforming from deegrees <--> radians. */
    if( bIdentityTransform && bSourceLatLong && !bSourceWrap &&
        bTargetLatLong && !bTargetWrap &&
        abs(dfSourceToRadians * dfTargetFromRadians - 1.0) < 1e-10 )
    {
        /*bSourceLatLong = FALSE;
        bTargetLatLong = FALSE;*/
    }

    CPLFree( pszSrcProj4Defn );
    CPLFree( pszDstProj4Defn );

    return TRUE;
}
bool rspfOgcWktTranslator::toOssimKwl( const rspfString& wktString,
                                        rspfKeywordlist &kwl,
                                        const char *prefix)const
{
   static const char MODULE[] = "rspfOgcWktTranslator::toOssimKwl";
   if(traceDebug())
   {
      rspfNotify(rspfNotifyLevel_DEBUG) << MODULE << " entered...\n";
   }
   
   const char* wkt = wktString.c_str();
   
   OGRSpatialReferenceH  hSRS = NULL;
   rspfDpt falseEastingNorthing;
   
   hSRS = OSRNewSpatialReference(NULL);
   if( OSRImportFromWkt( hSRS, (char **) &wkt ) != OGRERR_NONE )
   {
      OSRDestroySpatialReference( hSRS );
      return false;
   }
   
   rspfString rspfProj = "";
   const char* epsg_code = OSRGetAttrValue( hSRS, "AUTHORITY", 1 );
   if(traceDebug())
   {
      rspfNotify(rspfNotifyLevel_DEBUG)
         << "epsg_code: " << (epsg_code?epsg_code:"null") << "\n";
   }
   
   const char* units = NULL;
   OGR_SRSNode* node = ((OGRSpatialReference *)hSRS)->GetRoot();
   int nbChild  = node->GetChildCount();
   for (int i = 0; i < nbChild; i++)
   {
      OGR_SRSNode* curChild = node->GetChild(i);
      if (strcmp(curChild->GetValue(), "UNIT") == 0)
      {
         units = curChild->GetChild(0)->GetValue();
      }
   }
   if(traceDebug())
   {
      rspfNotify(rspfNotifyLevel_DEBUG)
         << "units: " << (units?units:"null") << "\n";
   }
   
   rspfString rspf_units;
   bool bGeog = OSRIsGeographic(hSRS);
   if ( bGeog == false )
   {
      rspf_units = "meters";
      if ( units != NULL )
      {
         rspfString s = units;
         s.downcase();
         
         if( ( s == rspfString("us survey foot") ) ||
             ( s == rspfString("u.s. foot") ) ||
             ( s == rspfString("foot_us") ) )
         {
            rspf_units = "us_survey_feet";
         }
         else if( s == rspfString("degree") )
         {
            rspf_units = "degrees";
         }
         else if( ( s == rspfString("meter") ) ||
                  ( s == rspfString("metre") ) )
         {
            rspf_units = "meters";
         }
      }
   }
   else
   {
      rspf_units = "degrees";
   }
   if(traceDebug())
   {
      rspfNotify(rspfNotifyLevel_DEBUG)
         << "rspf_units: " << rspf_units << "\n";
   }
   if (epsg_code)
   {
      rspfString epsg_spec ("EPSG:"); 
      epsg_spec += rspfString::toString(epsg_code);
      rspfProjection* proj = rspfEpsgProjectionFactory::instance()->createProjection(epsg_spec);
      if (proj)
         rspfProj = proj->getClassName();
      delete proj;
   }
   if(rspfProj == "") 
   {
      const char* pszProjection = OSRGetAttrValue( hSRS, "PROJECTION", 0 );
      if(pszProjection)
      {
         rspfProj = wktToOssimProjection(pszProjection);
      }
      else
      {
         rspfString localCs = OSRGetAttrValue( hSRS, "LOCAL_CS", 0 );
         localCs = localCs.upcase();
         if(localCs == "GREATBRITAIN_GRID")
         {
            rspfProj = "rspfBngProjection";
         }
         else if (rspf_units.contains("degree"))
         {
            rspfProj = "rspfEquDistCylProjection";
         }
      }
   }
   if(rspfProj == "rspfEquDistCylProjection" )
      rspf_units = "degrees";
   kwl.add(prefix, rspfKeywordNames::UNITS_KW, rspf_units, true);
   if (traceDebug())
   {
      rspfNotify(rspfNotifyLevel_DEBUG)
         << MODULE << "DEBUG:"
         << "\nrspfProj = " << rspfProj << endl;
   }
   
   kwl.add(prefix, rspfKeywordNames::TYPE_KW, rspfProj.c_str(), true);
   falseEastingNorthing.x = OSRGetProjParm(hSRS, SRS_PP_FALSE_EASTING, 0.0, NULL);
   falseEastingNorthing.y = OSRGetProjParm(hSRS, SRS_PP_FALSE_NORTHING, 0.0, NULL);
   if (epsg_code)
   {
      kwl.add(prefix, rspfKeywordNames::PCS_CODE_KW, epsg_code, true);
   }
   if(rspfProj == "rspfBngProjection")
   {
      kwl.add(prefix,
              rspfKeywordNames::TYPE_KW,
              "rspfBngProjection",
              true);
   }
   else if(rspfProj == "rspfCylEquAreaProjection")
   {
      kwl.add(prefix,
              rspfKeywordNames::STD_PARALLEL_1_KW,
              OSRGetProjParm(hSRS, SRS_PP_STANDARD_PARALLEL_1, 0.0, NULL),
              true);
      
      kwl.add(prefix,
              rspfKeywordNames::ORIGIN_LATITUDE_KW,
              OSRGetProjParm(hSRS, SRS_PP_STANDARD_PARALLEL_1, 0.0, NULL),
              true);
      rspfUnitType units =
         static_cast<rspfUnitType>(rspfUnitTypeLut::instance()->
                                    getEntryNumber(rspf_units.c_str()));
      if ( units == RSPF_METERS || 
           units == RSPF_FEET   || 
           units == RSPF_US_SURVEY_FEET )
      {
         kwl.add(prefix,
                 rspfKeywordNames::FALSE_EASTING_NORTHING_KW,
                 falseEastingNorthing.toString(),
                 true);
         kwl.add(prefix,
                 rspfKeywordNames::FALSE_EASTING_NORTHING_UNITS_KW,
                 rspf_units,
                 true);
      }
   }
   else if(rspfProj == "rspfEquDistCylProjection")
   {
      kwl.add(prefix,
              rspfKeywordNames::TYPE_KW,
              "rspfEquDistCylProjection",
              true);
      
      rspfUnitType units =
         static_cast<rspfUnitType>(rspfUnitTypeLut::instance()->
                                    getEntryNumber(rspf_units.c_str()));
      if ( units == RSPF_METERS || 
           units == RSPF_FEET   || 
           units == RSPF_US_SURVEY_FEET )
      {
         kwl.add(prefix,
                 rspfKeywordNames::FALSE_EASTING_NORTHING_KW,
                 falseEastingNorthing.toString(),
                 true);
         kwl.add(prefix,
                 rspfKeywordNames::FALSE_EASTING_NORTHING_UNITS_KW,
                 rspf_units,
                 true);
      }
      kwl.add(prefix,
              rspfKeywordNames::ORIGIN_LATITUDE_KW,
              OSRGetProjParm(hSRS, SRS_PP_LATITUDE_OF_ORIGIN, 0.0, NULL),
              true);
      kwl.add(prefix,
              rspfKeywordNames::CENTRAL_MERIDIAN_KW,
              OSRGetProjParm(hSRS, SRS_PP_CENTRAL_MERIDIAN, 0.0, NULL),
              true);
   }
   else if( (rspfProj == "rspfLambertConformalConicProjection") ||
            (rspfProj == "rspfAlbersProjection") )
   {
      kwl.add(prefix,
              rspfKeywordNames::TYPE_KW,
              rspfProj.c_str(),
              true);
      kwl.add(prefix,
              rspfKeywordNames::FALSE_EASTING_NORTHING_KW,
              falseEastingNorthing.toString(),
              true);
      kwl.add(prefix,
              rspfKeywordNames::FALSE_EASTING_NORTHING_UNITS_KW,
              rspf_units,
              true);
      kwl.add(prefix,
              rspfKeywordNames::ORIGIN_LATITUDE_KW,
              OSRGetProjParm(hSRS, SRS_PP_LATITUDE_OF_ORIGIN, 0.0, NULL),
              true);
      kwl.add(prefix,
              rspfKeywordNames::CENTRAL_MERIDIAN_KW,
              OSRGetProjParm(hSRS, SRS_PP_CENTRAL_MERIDIAN, 0.0, NULL),
              true);
      kwl.add(prefix,
              rspfKeywordNames::STD_PARALLEL_1_KW,
              OSRGetProjParm(hSRS, SRS_PP_STANDARD_PARALLEL_1, 0.0, NULL),
              true);
      kwl.add(prefix,
              rspfKeywordNames::STD_PARALLEL_2_KW,
              OSRGetProjParm(hSRS, SRS_PP_STANDARD_PARALLEL_2, 0.0, NULL),
              true);
   }
   else if(rspfProj == "rspfMercatorProjection")
   {
      kwl.add(prefix,
              rspfKeywordNames::TYPE_KW,
              "rspfMercatorProjection",
              true);
      kwl.add(prefix,
              rspfKeywordNames::ORIGIN_LATITUDE_KW,
              OSRGetProjParm(hSRS, SRS_PP_LATITUDE_OF_ORIGIN, 0.0, NULL),
              true);
      kwl.add(prefix,
              rspfKeywordNames::CENTRAL_MERIDIAN_KW,
              OSRGetProjParm(hSRS, SRS_PP_CENTRAL_MERIDIAN, 0.0, NULL),
              true);
      kwl.add(prefix,
              rspfKeywordNames::FALSE_EASTING_NORTHING_KW,
              falseEastingNorthing.toString(),
              true);
      kwl.add(prefix,
              rspfKeywordNames::FALSE_EASTING_NORTHING_UNITS_KW,
              rspf_units,
              true);
   }
   else if(rspfProj == "rspfSinusoidalProjection")
   {
      kwl.add(prefix,
              rspfKeywordNames::TYPE_KW,
              "rspfSinusoidalProjection",
              true);
      kwl.add(prefix,
              rspfKeywordNames::CENTRAL_MERIDIAN_KW,
              OSRGetProjParm(hSRS, SRS_PP_CENTRAL_MERIDIAN, 0.0, NULL),
              true);
      kwl.add(prefix,
              rspfKeywordNames::FALSE_EASTING_NORTHING_KW,
              falseEastingNorthing.toString(),
              true);
      kwl.add(prefix,
              rspfKeywordNames::FALSE_EASTING_NORTHING_UNITS_KW,
              rspf_units,
              true);
   }
   else if(rspfProj == "rspfTransMercatorProjection")
   {
      int bNorth;
      int nZone = OSRGetUTMZone( hSRS, &bNorth );
      if( nZone != 0 )
      {
         kwl.add(prefix,
                 rspfKeywordNames::TYPE_KW,
                 "rspfUtmProjection",
                 true);
         
         kwl.add(prefix,
                 rspfKeywordNames::ZONE_KW,
                 nZone,
                 true);
         if( bNorth )
         {
            kwl.add(prefix, rspfKeywordNames::HEMISPHERE_KW, "N", true);
         }
         else
         {
            kwl.add(prefix, rspfKeywordNames::HEMISPHERE_KW, "S", true);
         }
      }            
      else
      {
         kwl.add(prefix,
                 rspfKeywordNames::TYPE_KW,
                 "rspfTransMercatorProjection",
                 true);
         kwl.add(prefix,
                 rspfKeywordNames::SCALE_FACTOR_KW,
                 OSRGetProjParm(hSRS, SRS_PP_SCALE_FACTOR, 1.0, NULL),
                 true);
         
         kwl.add(prefix,
                 rspfKeywordNames::ORIGIN_LATITUDE_KW,
                 OSRGetProjParm(hSRS, SRS_PP_LATITUDE_OF_ORIGIN, 0.0, NULL),
                 true);
         kwl.add(prefix,
                 rspfKeywordNames::CENTRAL_MERIDIAN_KW,
                 OSRGetProjParm(hSRS, SRS_PP_CENTRAL_MERIDIAN, 0.0, NULL),
                 true);
         kwl.add(prefix,
                 rspfKeywordNames::FALSE_EASTING_NORTHING_KW,
                 falseEastingNorthing.toString(),
                 true);
         kwl.add(prefix,
                 rspfKeywordNames::FALSE_EASTING_NORTHING_UNITS_KW,
                 rspf_units,
                 true);
      }
   }
   else
   {
      if (traceDebug())
      {
         rspfNotify(rspfNotifyLevel_DEBUG)
            << "rspfOgcWktTranslator::toOssimKwl DEBUG:\n"
            << "Projection conversion to RSPF not supported !!!!!!!!!\n"
            << "Please send the following string to the development staff\n" 
            << "to be added to the transaltion to RSPF\n"
            << wkt << endl;
      }
      return false;
   }
   const char *datum = OSRGetAttrValue( hSRS, "DATUM", 0 );
   rspfString oDatum = "WGE";
    
   if( datum )
   {
      oDatum = wktToOssimDatum(datum);
      if(oDatum == "")
      {
         oDatum = "WGE";
      }
   }
       
   kwl.add(prefix, rspfKeywordNames::DATUM_KW, oDatum, true);
     
   OSRDestroySpatialReference( hSRS );
   if (traceDebug())
   {
      rspfNotify(rspfNotifyLevel_DEBUG)
         << MODULE << " exit status = true"
         << std::endl;
   }    
      
   return true;
}
Beispiel #11
0
static int WFS_ExprDumpAsOGCFilter(CPLString& osFilter,
                                   const swq_expr_node* poExpr,
                                   int bExpectBinary,
                                   ExprDumpFilterOptions* psOptions)
{
    if( poExpr->eNodeType == SNT_COLUMN )
    {
        if (bExpectBinary)
            return FALSE;

        /* Special fields not understood by server */
        if (EQUAL(poExpr->string_value, "gml_id") ||
            EQUAL(poExpr->string_value, "FID") ||
            EQUAL(poExpr->string_value, "OGR_GEOMETRY") ||
            EQUAL(poExpr->string_value, "OGR_GEOM_WKT") ||
            EQUAL(poExpr->string_value, "OGR_GEOM_AREA") ||
            EQUAL(poExpr->string_value, "OGR_STYLE"))
        {
            CPLDebug("WFS", "Attribute refers to a OGR special field. Cannot use server-side filtering");
            return FALSE;
        }

        const char* pszFieldname = NULL;
        int nIndex;
        int bSameTable = psOptions->poFDefn != NULL &&
                         ( poExpr->table_name == NULL ||
                           EQUAL(poExpr->table_name, psOptions->poFDefn->GetName()) );
        if( bSameTable )
        {
            if( (nIndex = psOptions->poFDefn->GetFieldIndex(poExpr->string_value)) >= 0 )
            {
                pszFieldname = psOptions->poFDefn->GetFieldDefn(nIndex)->GetNameRef();
            }
            else if( (nIndex = psOptions->poFDefn->GetGeomFieldIndex(poExpr->string_value)) >= 0 )
            {
                pszFieldname = psOptions->poFDefn->GetGeomFieldDefn(nIndex)->GetNameRef();
            }
        }
        else if( psOptions->poDS != NULL )
        {
            OGRLayer* poLayer = psOptions->poDS->GetLayerByName(poExpr->table_name);
            if( poLayer )
            {
                OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
                if( (nIndex = poFDefn->GetFieldIndex(poExpr->string_value)) >= 0 )
                {
                    pszFieldname = CPLSPrintf("%s/%s",
                                              poLayer->GetName(),
                                              poFDefn->GetFieldDefn(nIndex)->GetNameRef());
                }
                else if( (nIndex = poFDefn->GetGeomFieldIndex(poExpr->string_value)) >= 0 )
                {
                    pszFieldname = CPLSPrintf("%s/%s",
                                              poLayer->GetName(),
                                              poFDefn->GetGeomFieldDefn(nIndex)->GetNameRef());
                }
            }
        }
        
        if( psOptions->poFDefn == NULL && psOptions->poDS == NULL )
            pszFieldname = poExpr->string_value;

        if( pszFieldname == NULL )
        {
            if( poExpr->table_name != NULL )
                CPLDebug("WFS", "Field \"%s\".\"%s\" unknown. Cannot use server-side filtering",
                         poExpr->table_name, poExpr->string_value);
            else
                CPLDebug("WFS", "Field \"%s\" unknown. Cannot use server-side filtering",
                         poExpr->string_value);
            return FALSE;
        }

        if (psOptions->nVersion >= 200)
            osFilter += CPLSPrintf("<%sValueReference>", psOptions->pszNSPrefix);
        else
            osFilter += CPLSPrintf("<%sPropertyName>", psOptions->pszNSPrefix);
        char* pszFieldnameXML = CPLEscapeString(pszFieldname, -1, CPLES_XML);
        osFilter += pszFieldnameXML;
        CPLFree(pszFieldnameXML);
        if (psOptions->nVersion >= 200)
            osFilter += CPLSPrintf("</%sValueReference>", psOptions->pszNSPrefix);
        else
            osFilter += CPLSPrintf("</%sPropertyName>", psOptions->pszNSPrefix);

        return TRUE;
    }

    if( poExpr->eNodeType == SNT_CONSTANT )
    {
        if (bExpectBinary)
            return FALSE;

        osFilter += CPLSPrintf("<%sLiteral>", psOptions->pszNSPrefix);
        if( !WFS_ExprDumpRawLitteral(osFilter, poExpr) )
            return FALSE;
        osFilter += CPLSPrintf("</%sLiteral>", psOptions->pszNSPrefix);

        return TRUE;
    }
    
    if( poExpr->eNodeType != SNT_OPERATION )
        return FALSE; /* shouldn't happen */

    if( poExpr->nOperation == SWQ_NOT )
    {
        osFilter +=  CPLSPrintf("<%sNot>", psOptions->pszNSPrefix);
        if (!WFS_ExprDumpAsOGCFilter(osFilter, poExpr->papoSubExpr[0], TRUE, psOptions))
            return FALSE;
        osFilter +=  CPLSPrintf("</%sNot>", psOptions->pszNSPrefix);
        return TRUE;
    }

    if( poExpr->nOperation == SWQ_LIKE )
    {
        CPLString osVal;
        char ch;
        char firstCh = 0;
        int i;
        if (psOptions->nVersion == 100)
            osFilter += CPLSPrintf("<%sPropertyIsLike wildCard='*' singleChar='_' escape='!'>", psOptions->pszNSPrefix);
        else
            osFilter += CPLSPrintf("<%sPropertyIsLike wildCard='*' singleChar='_' escapeChar='!'>", psOptions->pszNSPrefix);
        if (!WFS_ExprDumpAsOGCFilter(osFilter, poExpr->papoSubExpr[0], FALSE, psOptions))
            return FALSE;
        if (poExpr->papoSubExpr[1]->eNodeType != SNT_CONSTANT &&
            poExpr->papoSubExpr[1]->field_type != SWQ_STRING)
            return FALSE;
        osFilter += CPLSPrintf("<%sLiteral>", psOptions->pszNSPrefix);

        /* Escape value according to above special characters */
        /* For URL compatibility reason, we remap the OGR SQL '%' wildchard into '*' */
        i = 0;
        ch = poExpr->papoSubExpr[1]->string_value[i];
        if (ch == '\'' || ch == '"')
        {
            firstCh = ch;
            i ++;
        }
        for(;(ch = poExpr->papoSubExpr[1]->string_value[i]) != '\0';i++)
        {
            if (ch == '%')
                osVal += "*";
            else if (ch == '!')
                osVal += "!!";
            else if (ch == '*')
                osVal += "!*";
            else if (ch == firstCh && poExpr->papoSubExpr[1]->string_value[i + 1] == 0)
                break;
            else
            {
                char ach[2];
                ach[0] = ch;
                ach[1] = 0;
                osVal += ach;
            }
        }
        char* pszXML = CPLEscapeString(osVal, -1, CPLES_XML);
        osFilter += pszXML;
        CPLFree(pszXML);
        osFilter += CPLSPrintf("</%sLiteral>", psOptions->pszNSPrefix);
        osFilter += CPLSPrintf("</%sPropertyIsLike>", psOptions->pszNSPrefix);
        return TRUE;
    }

    if( poExpr->nOperation == SWQ_ISNULL )
    {
        osFilter += CPLSPrintf("<%sPropertyIsNull>", psOptions->pszNSPrefix);
        if (!WFS_ExprDumpAsOGCFilter(osFilter, poExpr->papoSubExpr[0], FALSE, psOptions))
            return FALSE;
        osFilter += CPLSPrintf("</%sPropertyIsNull>", psOptions->pszNSPrefix);
        psOptions->bOutNeedsNullCheck = TRUE;
        return TRUE;
    }

    if( poExpr->nOperation == SWQ_EQ ||
        poExpr->nOperation == SWQ_NE ||
        poExpr->nOperation == SWQ_LE ||
        poExpr->nOperation == SWQ_LT ||
        poExpr->nOperation == SWQ_GE ||
        poExpr->nOperation == SWQ_GT )
    {
        int nOperation = poExpr->nOperation;
        int bAddClosingNot = FALSE;
        if (!psOptions->bPropertyIsNotEqualToSupported && nOperation == SWQ_NE)
        {
            osFilter += CPLSPrintf("<%sNot>", psOptions->pszNSPrefix);
            nOperation = SWQ_EQ;
            bAddClosingNot = TRUE;
        }

        const char* pszName = NULL;
        switch(nOperation)
        {
            case SWQ_EQ:  pszName = "PropertyIsEqualTo"; break;
            case SWQ_NE:  pszName = "PropertyIsNotEqualTo"; break;
            case SWQ_LE:  pszName = "PropertyIsLessThanOrEqualTo"; break;
            case SWQ_LT:  pszName = "PropertyIsLessThan"; break;
            case SWQ_GE:  pszName = "PropertyIsGreaterThanOrEqualTo"; break;
            case SWQ_GT:  pszName = "PropertyIsGreaterThan"; break;
            default: break;
        }
        osFilter += "<";
        osFilter += psOptions->pszNSPrefix;
        osFilter += pszName;
        osFilter += ">";
        if (!WFS_ExprDumpAsOGCFilter(osFilter, poExpr->papoSubExpr[0], FALSE, psOptions))
            return FALSE;
        if (!WFS_ExprDumpAsOGCFilter(osFilter, poExpr->papoSubExpr[1], FALSE, psOptions))
            return FALSE;
        osFilter += "</";
        osFilter += psOptions->pszNSPrefix;
        osFilter += pszName;
        osFilter += ">";
        if (bAddClosingNot)
            osFilter += CPLSPrintf("</%sNot>", psOptions->pszNSPrefix);
        return TRUE;
    }

    if( poExpr->nOperation == SWQ_AND ||
        poExpr->nOperation == SWQ_OR )
    {
        const char* pszName = (poExpr->nOperation == SWQ_AND) ? "And" : "Or";
        osFilter += "<";
        osFilter += psOptions->pszNSPrefix;
        osFilter += pszName;
        osFilter += ">";
        if (!WFS_ExprDumpAsOGCFilter(osFilter, poExpr->papoSubExpr[0], TRUE, psOptions))
            return FALSE;
        if (!WFS_ExprDumpAsOGCFilter(osFilter, poExpr->papoSubExpr[1], TRUE, psOptions))
            return FALSE;
        osFilter += "</";
        osFilter += psOptions->pszNSPrefix;
        osFilter += pszName;
        osFilter += ">";
        return TRUE;
    }
    
    if( poExpr->nOperation == SWQ_CUSTOM_FUNC &&
        EQUAL(poExpr->string_value, "ST_MakeEnvelope") )
    {
        OGRSpatialReference oSRS;
        const char* pszSRSName = WFS_ExprGetSRSName( poExpr, 4, psOptions, oSRS );
        int bAxisSwap = FALSE;

        osFilter += "<gml:Envelope";
        if( pszSRSName )
        {
            osFilter += " srsName=\"";
            osFilter += pszSRSName;
            osFilter += "\"";
            if( oSRS.EPSGTreatsAsLatLong() || oSRS.EPSGTreatsAsNorthingEasting() )
                bAxisSwap = TRUE;
        }
        osFilter += ">";
        osFilter += "<gml:lowerCorner>";
        if (!WFS_ExprDumpRawLitteral(osFilter, poExpr->papoSubExpr[(bAxisSwap) ? 1 : 0]))
            return FALSE;
        osFilter += " ";
        if (!WFS_ExprDumpRawLitteral(osFilter, poExpr->papoSubExpr[(bAxisSwap) ? 0 : 1]))
            return FALSE;
        osFilter += "</gml:lowerCorner>";
        osFilter += "<gml:upperCorner>";
        if (!WFS_ExprDumpRawLitteral(osFilter, poExpr->papoSubExpr[(bAxisSwap) ? 3 : 2]))
            return FALSE;
        osFilter += " ";
        if (!WFS_ExprDumpRawLitteral(osFilter, poExpr->papoSubExpr[(bAxisSwap) ? 2 : 3]))
            return FALSE;
        osFilter += "</gml:upperCorner>";
        osFilter += "</gml:Envelope>";
        return TRUE;
    }

    if( poExpr->nOperation == SWQ_CUSTOM_FUNC &&
        EQUAL(poExpr->string_value, "ST_GeomFromText") )
    {
        OGRSpatialReference oSRS;
        const char* pszSRSName = WFS_ExprGetSRSName( poExpr, 1, psOptions, oSRS );
        OGRGeometry* poGeom = NULL;
        char* pszWKT = (char*)poExpr->papoSubExpr[0]->string_value;
        OGRGeometryFactory::createFromWkt(&pszWKT, NULL, &poGeom);
        char** papszOptions = NULL;
        papszOptions = CSLSetNameValue(papszOptions, "FORMAT", "GML3");
        if( pszSRSName != NULL )
        {
            if( oSRS.EPSGTreatsAsLatLong() || oSRS.EPSGTreatsAsNorthingEasting() )
            {
                OGR_SRSNode *poGEOGCS = oSRS.GetAttrNode( "GEOGCS" );
                if( poGEOGCS != NULL )
                    poGEOGCS->StripNodes( "AXIS" );

                OGR_SRSNode *poPROJCS = oSRS.GetAttrNode( "PROJCS" );
                if (poPROJCS != NULL && oSRS.EPSGTreatsAsNorthingEasting())
                    poPROJCS->StripNodes( "AXIS" );
            }

            if( EQUALN(pszSRSName, "urn:ogc:def:crs:EPSG::", strlen("urn:ogc:def:crs:EPSG::")) )
                papszOptions = CSLSetNameValue(papszOptions, "GML3_LONGSRS", "YES");
            else
                papszOptions = CSLSetNameValue(papszOptions, "GML3_LONGSRS", "NO");

            poGeom->assignSpatialReference(&oSRS);
        }
        papszOptions = CSLSetNameValue(papszOptions, "GMLID",
                                       CPLSPrintf("id%d", psOptions->nUniqueGeomGMLId ++));
        char* pszGML = OGR_G_ExportToGMLEx( (OGRGeometryH)poGeom, papszOptions );
        osFilter += pszGML;
        CSLDestroy(papszOptions);
        delete poGeom;
        CPLFree(pszGML);
        return TRUE;
    }

    if( poExpr->nOperation == SWQ_CUSTOM_FUNC )
    {
        const char* pszName =
            EQUAL(poExpr->string_value, "ST_Equals") ? "Equals" :
            EQUAL(poExpr->string_value, "ST_Disjoint") ? "Disjoint" :
            EQUAL(poExpr->string_value, "ST_Touches") ? "Touches" :
            EQUAL(poExpr->string_value, "ST_Contains") ? "Contains" :
            EQUAL(poExpr->string_value, "ST_Intersects") ? "Intersects" :
            EQUAL(poExpr->string_value, "ST_Within") ? "Within" :
            EQUAL(poExpr->string_value, "ST_Crosses") ? "Crosses" :
            EQUAL(poExpr->string_value, "ST_Overlaps") ? "Overlaps" :
            EQUAL(poExpr->string_value, "ST_DWithin") ? "DWithin" :
            EQUAL(poExpr->string_value, "ST_Beyond") ? "Beyond" :
            NULL;
        if( pszName == NULL )
            return FALSE;
        osFilter += "<";
        osFilter += psOptions->pszNSPrefix;
        osFilter += pszName;
        osFilter += ">";
        for(int i=0;i<2;i++)
        {
            if( i == 1 && poExpr->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
                poExpr->papoSubExpr[1]->eNodeType == SNT_OPERATION &&
                poExpr->papoSubExpr[1]->nOperation == SWQ_CUSTOM_FUNC &&
                (EQUAL(poExpr->papoSubExpr[1]->string_value, "ST_GeomFromText") ||
                 EQUAL(poExpr->papoSubExpr[1]->string_value, "ST_MakeEnvelope")) )
            {
                int bSameTable = psOptions->poFDefn != NULL &&
                                ( poExpr->papoSubExpr[0]->table_name == NULL ||
                                EQUAL(poExpr->papoSubExpr[0]->table_name, psOptions->poFDefn->GetName()) );
                if( bSameTable )
                {
                    int nIndex;
                    if( (nIndex = psOptions->poFDefn->GetGeomFieldIndex(poExpr->papoSubExpr[0]->string_value)) >= 0 )
                    {
                        psOptions->poSRS = psOptions->poFDefn->GetGeomFieldDefn(nIndex)->GetSpatialRef();
                    }
                }
                else if( psOptions->poDS != NULL )
                {
                    OGRLayer* poLayer = psOptions->poDS->GetLayerByName(poExpr->papoSubExpr[0]->table_name);
                    if( poLayer )
                    {
                        OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
                        int nIndex;
                        if( (nIndex = poFDefn->GetGeomFieldIndex(poExpr->papoSubExpr[0]->string_value)) >= 0 )
                        {
                            psOptions->poSRS = poFDefn->GetGeomFieldDefn(nIndex)->GetSpatialRef();
                        }
                    }
                }
            }
            int bRet = WFS_ExprDumpAsOGCFilter(osFilter, poExpr->papoSubExpr[i], FALSE, psOptions);
            psOptions->poSRS = NULL;
            if( !bRet )
                return FALSE;
        }
        if( poExpr->nSubExprCount > 2 )
        {
            osFilter += CPLSPrintf("<%sDistance unit=\"m\">", psOptions->pszNSPrefix);
            if (!WFS_ExprDumpRawLitteral(osFilter, poExpr->papoSubExpr[2]) )
                return FALSE;
            osFilter += CPLSPrintf("</%sDistance>", psOptions->pszNSPrefix);
        }
        osFilter += "</";
        osFilter += psOptions->pszNSPrefix;
        osFilter += pszName;
        osFilter += ">";
        return TRUE;
    }

    return FALSE;
}
Beispiel #12
0
void ProjectionDlg::SetUIFromProjection()
{
	if (m_proj.IsDymaxion())
		SetProjectionUI(PT_DYMAX);
	else if (m_proj.IsGeographic())
		SetProjectionUI(PT_GEO);
	else
	{
		const char *proj_string = m_proj.GetProjectionName();

		if (!strcmp(proj_string, SRS_PT_TRANSVERSE_MERCATOR))
		{
			if (m_proj.GetUTMZone() != 0)
				SetProjectionUI(PT_UTM);
			else
				SetProjectionUI(PT_TM);
		}

		// Supposedly, Gauss-Kruger is just a form of Transverse Mercator
		else if (!strcmp(proj_string, "Gauss_Kruger"))
			SetProjectionUI(PT_TM);

		else if (!strcmp(proj_string, SRS_PT_ALBERS_CONIC_EQUAL_AREA))
			SetProjectionUI(PT_ALBERS);

		else if (!strcmp(proj_string, SRS_PT_MERCATOR_1SP))
			SetProjectionUI(PT_MERC);

		else if (!strcmp(proj_string, SRS_PT_HOTINE_OBLIQUE_MERCATOR))
			SetProjectionUI(PT_HOM);

		else if (!strcmp(proj_string, SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP))
			SetProjectionUI(PT_LCC1SP);

		else if (!strcmp(proj_string, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP))
			SetProjectionUI(PT_LCC);

		else if (!strcmp(proj_string, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA))
			SetProjectionUI(PT_LAEA);

		else if (!strcmp(proj_string, SRS_PT_NEW_ZEALAND_MAP_GRID))
			SetProjectionUI(PT_NZMG);

		else if (!strcmp(proj_string, SRS_PT_SINUSOIDAL))
			SetProjectionUI(PT_SINUS);

		else if (!strcmp(proj_string, SRS_PT_STEREOGRAPHIC))
			SetProjectionUI(PT_STEREO);

		else if (!strcmp(proj_string, SRS_PT_OBLIQUE_STEREOGRAPHIC))
			SetProjectionUI(PT_OS);

		else if (!strcmp(proj_string, SRS_PT_POLAR_STEREOGRAPHIC))
			SetProjectionUI(PT_PS);

		else if (!strcmp(proj_string, SRS_PT_KROVAK))
			SetProjectionUI(PT_KROVAK);

		// I've seen a .prj file for Stereo70 which refers to the projection
		//  as "Double_Stereographic", but this is unknown by OGR.  We do know
		//  about Oblique Stereographic, which is what i believe is meant.
		else if (!strcmp(proj_string, "Double_Stereographic"))
		{
			OGR_SRSNode *node = m_proj.GetAttrNode("PROJECTION");
			node = node->GetChild(0);
			node->SetValue(SRS_PT_OBLIQUE_STEREOGRAPHIC);
			SetProjectionUI(PT_OS);
		}
		else
		{
			wxString str = _("Unknown projection: ");
			str += wxString(proj_string, wxConvUTF8);
			wxMessageBox(str);
		}
	}
}
Beispiel #13
0
OGRErr OGR_SRSNode::importFromWkt( char ** ppszInput )

{
    const char  *pszInput = *ppszInput;
    int         bInQuotedString = FALSE;
    
/* -------------------------------------------------------------------- */
/*      Clear any existing children of this node.                       */
/* -------------------------------------------------------------------- */
    ClearChildren();
    
/* -------------------------------------------------------------------- */
/*      Read the ``value'' for this node.                               */
/* -------------------------------------------------------------------- */
    char        szToken[512];
    int         nTokenLen = 0;
    
    while( *pszInput != '\0' && nTokenLen < (int) sizeof(szToken)-1 )
    {
        if( *pszInput == '"' )
        {
            bInQuotedString = !bInQuotedString;
        }
        else if( !bInQuotedString
              && (*pszInput == '[' || *pszInput == ']' || *pszInput == ','
                  || *pszInput == '(' || *pszInput == ')' ) )
        {
            break;
        }
        else
        {
            szToken[nTokenLen++] = *pszInput;
        }

        pszInput++;
    }

    if( *pszInput == '\0' || nTokenLen == sizeof(szToken) - 1 )
        return OGRERR_CORRUPT_DATA;

    szToken[nTokenLen++] = '\0';
    SetValue( szToken );

/* -------------------------------------------------------------------- */
/*      Read children, if we have a sublist.                            */
/* -------------------------------------------------------------------- */
    if( *pszInput == '[' || *pszInput == '(' )
    {
        do
        {
            OGR_SRSNode *poNewChild;
            OGRErr      eErr;

            pszInput++; // Skip bracket or comma.

            poNewChild = new OGR_SRSNode();

            eErr = poNewChild->importFromWkt( (char **) &pszInput );
            if( eErr != OGRERR_NONE )
                return eErr;

            AddChild( poNewChild );
            
        } while( *pszInput == ',' );

        if( *pszInput != ')' && *pszInput != ']' )
            return OGRERR_CORRUPT_DATA;

        pszInput++;
    }

    *ppszInput = (char *) pszInput;

    return OGRERR_NONE;
}
Beispiel #14
0
int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
                                  OGRSpatialReference * poTargetIn )

{
    if( poSourceIn == NULL || poTargetIn == NULL )
        return FALSE;

    poSRSSource = poSourceIn->Clone();
    poSRSTarget = poTargetIn->Clone();

    bSourceLatLong = CPL_TO_BOOL(poSRSSource->IsGeographic());
    bTargetLatLong = CPL_TO_BOOL(poSRSTarget->IsGeographic());

/* -------------------------------------------------------------------- */
/*      Setup source and target translations to radians for lat/long    */
/*      systems.                                                        */
/* -------------------------------------------------------------------- */
    dfSourceToRadians = DEG_TO_RAD;
    bSourceWrap = false;
    dfSourceWrapLong = 0.0;

    if( bSourceLatLong )
    {
        OGR_SRSNode *poUNITS = poSRSSource->GetAttrNode( "GEOGCS|UNIT" );
        if( poUNITS && poUNITS->GetChildCount() >= 2 )
        {
            dfSourceToRadians = CPLAtof(poUNITS->GetChild(1)->GetValue());
            if( dfSourceToRadians == 0.0 )
                dfSourceToRadians = DEG_TO_RAD;
        }
    }

    dfTargetFromRadians = RAD_TO_DEG;
    bTargetWrap = false;
    dfTargetWrapLong = 0.0;

    if( bTargetLatLong )
    {
        OGR_SRSNode *poUNITS = poSRSTarget->GetAttrNode( "GEOGCS|UNIT" );
        if( poUNITS && poUNITS->GetChildCount() >= 2 )
        {
            double dfTargetToRadians = CPLAtof(poUNITS->GetChild(1)->GetValue());
            if( dfTargetToRadians != 0.0 )
                dfTargetFromRadians = 1 / dfTargetToRadians;
        }
    }

/* -------------------------------------------------------------------- */
/*      Preliminary logic to setup wrapping.                            */
/* -------------------------------------------------------------------- */
    if( CPLGetConfigOption( "CENTER_LONG", NULL ) != NULL )
    {
        bSourceWrap = true;
        bTargetWrap = true;
        dfSourceWrapLong = dfTargetWrapLong =
            CPLAtof(CPLGetConfigOption( "CENTER_LONG", "" ));
        CPLDebug( "OGRCT", "Wrap at %g.", dfSourceWrapLong );
    }

    const char *pszCENTER_LONG =
        poSRSSource->GetExtension( "GEOGCS", "CENTER_LONG" );
    if( pszCENTER_LONG != NULL )
    {
        dfSourceWrapLong = CPLAtof(pszCENTER_LONG);
        bSourceWrap = true;
        CPLDebug( "OGRCT", "Wrap source at %g.", dfSourceWrapLong );
    }

    pszCENTER_LONG = poSRSTarget->GetExtension( "GEOGCS", "CENTER_LONG" );
    if( pszCENTER_LONG != NULL )
    {
        dfTargetWrapLong = CPLAtof(pszCENTER_LONG);
        bTargetWrap = true;
        CPLDebug( "OGRCT", "Wrap target at %g.", dfTargetWrapLong );
    }

    bCheckWithInvertProj =
        CPLTestBool(CPLGetConfigOption( "CHECK_WITH_INVERT_PROJ", "NO" ));

    // The threshold is experimental. Works well with the cases of ticket #2305.
    if( bSourceLatLong )
        dfThreshold = CPLAtof(CPLGetConfigOption( "THRESHOLD", ".1" ));
    else
        // 1 works well for most projections, except for +proj=aeqd that
        // requires a tolerance of 10000.
        dfThreshold = CPLAtof(CPLGetConfigOption( "THRESHOLD", "10000" ));

    // OGRThreadSafety: The following variable is not a thread safety issue
    // since the only issue is incrementing while accessing which at worse
    // means debug output could be one "increment" late.
    static int   nDebugReportCount = 0;

    char        *pszSrcProj4Defn = NULL;

    if( poSRSSource->exportToProj4( &pszSrcProj4Defn ) != OGRERR_NONE )
    {
        CPLFree( pszSrcProj4Defn );
        return FALSE;
    }

    if( strlen(pszSrcProj4Defn) == 0 )
    {
        CPLFree( pszSrcProj4Defn );
        CPLError( CE_Failure, CPLE_AppDefined,
                  "No PROJ.4 translation for source SRS, coordinate\n"
                  "transformation initialization has failed." );
        return FALSE;
    }

    char        *pszDstProj4Defn = NULL;

    if( poSRSTarget->exportToProj4( &pszDstProj4Defn ) != OGRERR_NONE )
    {
        CPLFree( pszSrcProj4Defn );
        CPLFree( pszDstProj4Defn );
        return FALSE;
    }

    if( strlen(pszDstProj4Defn) == 0 )
    {
        CPLFree( pszSrcProj4Defn );
        CPLFree( pszDstProj4Defn );
        CPLError( CE_Failure, CPLE_AppDefined,
                  "No PROJ.4 translation for destination SRS, coordinate\n"
                  "transformation initialization has failed." );
        return FALSE;
    }

/* -------------------------------------------------------------------- */
/*      Optimization to avoid useless nadgrids evaluation.              */
/*      For example when converting between WGS84 and WebMercator       */
/* -------------------------------------------------------------------- */
    if( pszSrcProj4Defn[strlen(pszSrcProj4Defn)-1] == ' ' )
        pszSrcProj4Defn[strlen(pszSrcProj4Defn)-1] = 0;
    if( pszDstProj4Defn[strlen(pszDstProj4Defn)-1] == ' ' )
        pszDstProj4Defn[strlen(pszDstProj4Defn)-1] = 0;
    char* pszNeedle = strstr(pszSrcProj4Defn, "  ");
    if( pszNeedle )
        memmove(pszNeedle, pszNeedle + 1, strlen(pszNeedle + 1)+1);
    pszNeedle = strstr(pszDstProj4Defn, "  ");
    if( pszNeedle )
        memmove(pszNeedle, pszNeedle + 1, strlen(pszNeedle + 1)+1);

    if( (strstr(pszSrcProj4Defn, "+datum=WGS84") != NULL ||
         strstr(pszSrcProj4Defn, "+ellps=WGS84 +towgs84=0,0,0,0,0,0,0 ") != NULL) &&
        strstr(pszDstProj4Defn, "+nadgrids=@null ") != NULL &&
        strstr(pszDstProj4Defn, "+towgs84") == NULL )
    {
        char* pszDst = strstr(pszSrcProj4Defn, "+towgs84=0,0,0,0,0,0,0 ");
        if( pszDst != NULL )
        {
            char *pszSrc = pszDst + strlen("+towgs84=0,0,0,0,0,0,0 ");
            memmove(pszDst, pszSrc, strlen(pszSrc)+1);
        }
        else
        {
            memcpy(strstr(pszSrcProj4Defn, "+datum=WGS84"), "+ellps", 6);
        }

        pszDst = strstr(pszDstProj4Defn, "+nadgrids=@null ");
        char *pszSrc = pszDst + strlen("+nadgrids=@null ");
        memmove(pszDst, pszSrc, strlen(pszSrc)+1);

        pszDst = strstr(pszDstProj4Defn, "+wktext ");
        if( pszDst )
        {
            pszSrc = pszDst + strlen("+wktext ");
            memmove(pszDst, pszSrc, strlen(pszSrc)+1);
        }

        //bWGS84ToWebMercator =
        //    strcmp(pszSrcProj4Defn, "+proj=longlat +ellps=WGS84 +no_defs") == 0 &&
        //    strcmp(pszDstProj4Defn, "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +no_defs") == 0;
    }
    else
    if( (strstr(pszDstProj4Defn, "+datum=WGS84") != NULL ||
         strstr(pszDstProj4Defn, "+ellps=WGS84 +towgs84=0,0,0,0,0,0,0 ") != NULL) &&
        strstr(pszSrcProj4Defn, "+nadgrids=@null ") != NULL &&
        strstr(pszSrcProj4Defn, "+towgs84") == NULL )
    {
        char* pszDst = strstr(pszDstProj4Defn, "+towgs84=0,0,0,0,0,0,0 ");
        if( pszDst != NULL)
        {
            char* pszSrc = pszDst + strlen("+towgs84=0,0,0,0,0,0,0 ");
            memmove(pszDst, pszSrc, strlen(pszSrc)+1);
        }
        else
            memcpy(strstr(pszDstProj4Defn, "+datum=WGS84"), "+ellps", 6);

        pszDst = strstr(pszSrcProj4Defn, "+nadgrids=@null ");
        char* pszSrc = pszDst + strlen("+nadgrids=@null ");
        memmove(pszDst, pszSrc, strlen(pszSrc)+1);

        pszDst = strstr(pszSrcProj4Defn, "+wktext ");
        if( pszDst )
        {
            pszSrc = pszDst + strlen("+wktext ");
            memmove(pszDst, pszSrc, strlen(pszSrc)+1);
        }
        bWebMercatorToWGS84 =
            strcmp(pszDstProj4Defn,
                   "+proj=longlat +ellps=WGS84 +no_defs") == 0 &&
            strcmp(pszSrcProj4Defn,
                   "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 "
                   "+x_0=0.0 +y_0=0 +k=1.0 +units=m +no_defs") == 0;
    }

/* -------------------------------------------------------------------- */
/*      Establish PROJ.4 handle for source if projection.               */
/* -------------------------------------------------------------------- */
    if( !bWebMercatorToWGS84 )
    {
        if (pjctx)
            psPJSource = pfn_pj_init_plus_ctx( pjctx, pszSrcProj4Defn );
        else
            psPJSource = pfn_pj_init_plus( pszSrcProj4Defn );

        if( psPJSource == NULL )
        {
            if( pjctx != NULL)
            {
                int l_pj_errno = pfn_pj_ctx_get_errno(pjctx);

                /* pfn_pj_strerrno not yet thread-safe in PROJ 4.8.0 */
                CPLMutexHolderD(&hPROJMutex);
                CPLError( CE_Failure, CPLE_NotSupported,
                        "Failed to initialize PROJ.4 with `%s'.\n%s",
                        pszSrcProj4Defn, pfn_pj_strerrno(l_pj_errno) );
            }
            else if( pfn_pj_get_errno_ref != NULL
                && pfn_pj_strerrno != NULL )
            {
                int *p_pj_errno = pfn_pj_get_errno_ref();

                CPLError( CE_Failure, CPLE_NotSupported,
                        "Failed to initialize PROJ.4 with `%s'.\n%s",
                        pszSrcProj4Defn, pfn_pj_strerrno(*p_pj_errno) );
            }
            else
            {
                CPLError( CE_Failure, CPLE_NotSupported,
                        "Failed to initialize PROJ.4 with `%s'.\n",
                        pszSrcProj4Defn );
            }
        }
    }

    if( nDebugReportCount < 10 )
        CPLDebug( "OGRCT", "Source: %s", pszSrcProj4Defn );

    if( !bWebMercatorToWGS84 && psPJSource == NULL )
    {
        CPLFree( pszSrcProj4Defn );
        CPLFree( pszDstProj4Defn );
        return FALSE;
    }

/* -------------------------------------------------------------------- */
/*      Establish PROJ.4 handle for target if projection.               */
/* -------------------------------------------------------------------- */
    if( !bWebMercatorToWGS84 )
    {
        if (pjctx)
            psPJTarget = pfn_pj_init_plus_ctx( pjctx, pszDstProj4Defn );
        else
            psPJTarget = pfn_pj_init_plus( pszDstProj4Defn );

        if( psPJTarget == NULL )
            CPLError( CE_Failure, CPLE_NotSupported,
                    "Failed to initialize PROJ.4 with `%s'.",
                    pszDstProj4Defn );
    }
    if( nDebugReportCount < 10 )
    {
        CPLDebug( "OGRCT", "Target: %s", pszDstProj4Defn );
        nDebugReportCount++;
    }

    if( !bWebMercatorToWGS84 && psPJTarget == NULL )
    {
        CPLFree( pszSrcProj4Defn );
        CPLFree( pszDstProj4Defn );
        return FALSE;
    }

    /* Determine if we really have a transformation to do */
    bIdentityTransform = strcmp(pszSrcProj4Defn, pszDstProj4Defn) == 0;

#if 0
    /* In case of identity transform, under the following conditions, */
    /* we can also avoid transforming from degrees <--> radians. */
    if( bIdentityTransform && bSourceLatLong && !bSourceWrap &&
        bTargetLatLong && !bTargetWrap &&
        fabs(dfSourceToRadians * dfTargetFromRadians - 1.0) < 1e-10 )
    {
        // bSourceLatLong = false;
        // bTargetLatLong = false;
    }
#endif

    CPLFree( pszSrcProj4Defn );
    CPLFree( pszDstProj4Defn );

    return TRUE;
}
static void importXMLUnits(CPLXMLNode *psSrcXML, const char *pszClass,
                           OGRSpatialReference *poSRS, const char *pszTarget)

{
    const char  *pszUnitName, *pszUnitsPer;
    OGR_SRSNode *poNode = poSRS->GetAttrNode(pszTarget);
    OGR_SRSNode *poUnits;

    CPLAssert(EQUAL(pszClass, "AngularUnit")
              || EQUAL(pszClass, "LinearUnit"));

    psSrcXML = CPLGetXMLNode(psSrcXML, pszClass);
    if (psSrcXML == NULL)
        goto DefaultTarget;

    pszUnitName = CPLGetXMLValue(psSrcXML, "NameSet.name", "unnamed");
    if (EQUAL(pszClass, "AngularUnit"))
        pszUnitsPer = CPLGetXMLValue(psSrcXML, "radiansPerUnit", NULL);
    else
        pszUnitsPer = CPLGetXMLValue(psSrcXML, "metresPerUnit", NULL);

    if (pszUnitsPer == NULL)
    {
        CPLDebug("OGR_SRS_XML",
                 "Missing PerUnit value for %s.",
                 pszClass);
        goto DefaultTarget;
    }

    if (poNode == NULL)
    {
        CPLDebug("OGR_SRS_XML", "Can't find %s in importXMLUnits.",
                 pszTarget);
        goto DefaultTarget;
    }

    if (poNode->FindChild("UNIT") != -1)
    {
        poUnits = poNode->GetChild(poNode->FindChild("UNIT"));
        poUnits->GetChild(0)->SetValue(pszUnitName);
        poUnits->GetChild(1)->SetValue(pszUnitsPer);
    }
    else
    {
        poUnits = new OGR_SRSNode("UNIT");
        poUnits->AddChild(new OGR_SRSNode(pszUnitName));
        poUnits->AddChild(new OGR_SRSNode(pszUnitsPer));

        poNode->AddChild(poUnits);
    }

    return;

DefaultTarget:
    poUnits = new OGR_SRSNode("UNIT");
    if (EQUAL(pszClass, "AngularUnit"))
    {
        poUnits->AddChild(new OGR_SRSNode(SRS_UA_DEGREE));
        poUnits->AddChild(new OGR_SRSNode(SRS_UA_DEGREE_CONV));
    }
    else
    {
        poUnits->AddChild(new OGR_SRSNode(SRS_UL_METER));
        poUnits->AddChild(new OGR_SRSNode("1.0"));
    }

    poNode->AddChild(poUnits);
}
OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
{
    if( !EQUAL(poRoot->GetValue(),"GEOGCS")
        && !EQUAL(poRoot->GetValue(),"PROJCS")
        && !EQUAL(poRoot->GetValue(),"LOCAL_CS")
        && !EQUAL(poRoot->GetValue(),"GEOCCS")
        && !EQUAL(poRoot->GetValue(),"VERT_CS")
        && !EQUAL(poRoot->GetValue(),"COMPD_CS"))
    {
        CPLDebug( "OGRSpatialReference::Validate",
                  "Unrecognised root node `%s'\n",
                  poRoot->GetValue() );
        return OGRERR_CORRUPT_DATA;
    }

/* -------------------------------------------------------------------- */
/*      For a COMPD_CS, validate subparameters and head & tail cs       */
/* -------------------------------------------------------------------- */
    if( EQUAL(poRoot->GetValue(),"COMPD_CS") )
    {
        OGR_SRSNode     *poNode;
        int             i;

        for( i = 1; i < poRoot->GetChildCount(); i++ )
        {
            poNode = poRoot->GetChild(i);

            if( EQUAL(poNode->GetValue(),"GEOGCS") ||
                EQUAL(poNode->GetValue(),"PROJCS") ||
                EQUAL(poNode->GetValue(),"LOCAL_CS") ||
                EQUAL(poNode->GetValue(),"GEOCCS") ||
                EQUAL(poNode->GetValue(),"VERT_CS") ||
                EQUAL(poNode->GetValue(),"COMPD_CS") )
            {
                OGRErr eErr = Validate(poNode);
                if (eErr != OGRERR_NONE)
                    return eErr;
            }
            else if( EQUAL(poNode->GetValue(),"AUTHORITY") )
            {
                OGRErr eErr = ValidateAuthority(poNode);
                if (eErr != OGRERR_NONE)
                    return eErr;
            }
            else
            {
                CPLDebug( "OGRSpatialReference::Validate",
                          "Unexpected child for COMPD_CS `%s'.\n",
                          poNode->GetValue() );

                return OGRERR_CORRUPT_DATA;
            }
        }

        return OGRERR_NONE;
    }

/* -------------------------------------------------------------------- */
/*      Validate VERT_CS                                                */
/* -------------------------------------------------------------------- */
    if( EQUAL(poRoot->GetValue(),"VERT_CS") )
    {
        OGR_SRSNode     *poNode;
        int             i;
        int             bGotVertDatum = FALSE;
        int             bGotUnit = FALSE;
        int             nCountAxis = 0;

        for( i = 1; i < poRoot->GetChildCount(); i++ )
        {
            poNode = poRoot->GetChild(i);

            if( EQUAL(poNode->GetValue(),"VERT_DATUM") )
            {
                OGRErr eErr = ValidateVertDatum(poNode);
                if (eErr != OGRERR_NONE)
                    return eErr;
                bGotVertDatum = TRUE;
            }
            else if( EQUAL(poNode->GetValue(),"UNIT") )
            {
                OGRErr eErr = ValidateUnit(poNode);
                if (eErr != OGRERR_NONE)
                    return eErr;
                bGotUnit = TRUE;
            }
            else if( EQUAL(poNode->GetValue(),"AXIS") )
            {
                OGRErr eErr = ValidateAxis(poNode);
                if (eErr != OGRERR_NONE)
                    return eErr;
                nCountAxis ++;
            }
            else if( EQUAL(poNode->GetValue(),"AUTHORITY") )
            {
                OGRErr eErr = ValidateAuthority(poNode);
                if (eErr != OGRERR_NONE)
                    return eErr;
            }
            else
            {
                CPLDebug( "OGRSpatialReference::Validate",
                          "Unexpected child for VERT_CS `%s'.\n",
                          poNode->GetValue() );

                return OGRERR_CORRUPT_DATA;
            }
        }

        if (!bGotVertDatum)
        {
            CPLDebug( "OGRSpatialReference::Validate",
                      "No VERT_DATUM child in VERT_CS.\n" );

            return OGRERR_CORRUPT_DATA;
        }

        if (!bGotUnit)
        {
            CPLDebug( "OGRSpatialReference::Validate",
                      "No UNIT child in VERT_CS.\n" );

            return OGRERR_CORRUPT_DATA;
        }

        if (nCountAxis > 1)
        {
            CPLDebug( "OGRSpatialReference::Validate",
                      "Too many AXIS children in VERT_CS.\n" );

            return OGRERR_CORRUPT_DATA;
        }
        return OGRERR_NONE;
    }

/* -------------------------------------------------------------------- */
/*      For a PROJCS, validate subparameters (other than GEOGCS).       */
/* -------------------------------------------------------------------- */
    if( EQUAL(poRoot->GetValue(),"PROJCS") )
    {
        OGR_SRSNode     *poNode;
        int             i;

        for( i = 1; i < poRoot->GetChildCount(); i++ )
        {
            poNode = poRoot->GetChild(i);

            if( EQUAL(poNode->GetValue(),"GEOGCS") )
            {
                /* validated elsewhere */
            }
            else if( EQUAL(poNode->GetValue(),"UNIT") )
            {
                OGRErr eErr = ValidateUnit(poNode);
                if (eErr != OGRERR_NONE)
                    return eErr;
            }
            else if( EQUAL(poNode->GetValue(),"PARAMETER") )
            {
                if( poNode->GetChildCount() != 2 )
                {
                    CPLDebug( "OGRSpatialReference::Validate",
                              "PARAMETER has wrong number of children (%d),"
                              "not 2 as expected.\n",
                              poNode->GetChildCount() );
                    
                    return OGRERR_CORRUPT_DATA;
                }
                else if( CSLFindString( (char **)papszParameters,
                                        poNode->GetChild(0)->GetValue()) == -1)
                {
                    CPLDebug( "OGRSpatialReference::Validate",
                              "Unrecognised PARAMETER `%s'.\n",
                              poNode->GetChild(0)->GetValue() );
                    
                    return OGRERR_UNSUPPORTED_SRS;
                }
            }
            else if( EQUAL(poNode->GetValue(),"PROJECTION") )
            {
                if( poNode->GetChildCount() != 1 && poNode->GetChildCount() != 2 )
                {
                    CPLDebug( "OGRSpatialReference::Validate",
                              "PROJECTION has wrong number of children (%d),"
                              "not 1 or 2 as expected.\n",
                              poNode->GetChildCount() );
                    
                    return OGRERR_CORRUPT_DATA;
                }
                else if( CSLFindString( (char **)papszProjectionSupported,
                                        poNode->GetChild(0)->GetValue()) == -1
                      && CSLFindString( (char **)papszProjectionUnsupported,
                                        poNode->GetChild(0)->GetValue()) == -1)
                {
                    CPLDebug( "OGRSpatialReference::Validate",
                              "Unrecognised PROJECTION `%s'.\n",
                              poNode->GetChild(0)->GetValue() );
                    
                    return OGRERR_UNSUPPORTED_SRS;
                }
                else if( CSLFindString( (char **)papszProjectionSupported,
                                        poNode->GetChild(0)->GetValue()) == -1)
                {
                    CPLDebug( "OGRSpatialReference::Validate",
                              "Unsupported, but recognised PROJECTION `%s'.\n",
                              poNode->GetChild(0)->GetValue() );
                    
                    return OGRERR_UNSUPPORTED_SRS;
                }

                if (poNode->GetChildCount() == 2)
                {
                    poNode = poNode->GetChild(1);
                    if( EQUAL(poNode->GetValue(),"AUTHORITY") )
                    {
                        OGRErr eErr = ValidateAuthority(poNode);
                        if (eErr != OGRERR_NONE)
                            return eErr;
                    }
                    else
                    {
                        CPLDebug( "OGRSpatialReference::Validate",
                                "Unexpected child for PROJECTION `%s'.\n",
                                poNode->GetValue() );

                        return OGRERR_CORRUPT_DATA;
                    }
                }
            }
            else if( EQUAL(poNode->GetValue(),"AUTHORITY") )
            {
                OGRErr eErr = ValidateAuthority(poNode);
                if (eErr != OGRERR_NONE)
                    return eErr;
            }
            else if( EQUAL(poNode->GetValue(),"AXIS") )
            {
                OGRErr eErr = ValidateAxis(poNode);
                if (eErr != OGRERR_NONE)
                    return eErr;
            }
            else if( EQUAL(poNode->GetValue(),"EXTENSION") )
            {
                // We do not try to control the sub-organization of 
                // EXTENSION nodes.
            }
            else
            {
                CPLDebug( "OGRSpatialReference::Validate",
                          "Unexpected child for PROJCS `%s'.\n",
                          poNode->GetValue() );
                
                return OGRERR_CORRUPT_DATA;
            }
        }
    }
    
/* -------------------------------------------------------------------- */
/*      Validate GEOGCS if found.                                       */
/* -------------------------------------------------------------------- */
    OGR_SRSNode *poGEOGCS = poRoot->GetNode( "GEOGCS" );

    if( poGEOGCS != NULL )
    {
        OGR_SRSNode     *poNode;
        int             i;

        for( i = 1; i < poGEOGCS->GetChildCount(); i++ )
        {
            poNode = poGEOGCS->GetChild(i);

            if( EQUAL(poNode->GetValue(),"DATUM") )
            {
                /* validated elsewhere */
            }
            else if( EQUAL(poNode->GetValue(),"PRIMEM") )
            {
                if( poNode->GetChildCount() < 2 
                    || poNode->GetChildCount() > 3 )
                {
                    CPLDebug( "OGRSpatialReference::Validate",
                              "PRIMEM has wrong number of children (%d),"
                              "not 2 or 3 as expected.\n",
                              poNode->GetChildCount() );
                    
                    return OGRERR_CORRUPT_DATA;
                }
            }
            else if( EQUAL(poNode->GetValue(),"UNIT") )
            {
                OGRErr eErr = ValidateUnit(poNode);
                if (eErr != OGRERR_NONE)
                    return eErr;
            }
            else if( EQUAL(poNode->GetValue(),"AXIS") )
            {
                OGRErr eErr = ValidateAxis(poNode);
                if (eErr != OGRERR_NONE)
                    return eErr;
            }
            else if( EQUAL(poNode->GetValue(),"AUTHORITY") )
            {
                OGRErr eErr = ValidateAuthority(poNode);
                if (eErr != OGRERR_NONE)
                    return eErr;
            }
            else
            {
                CPLDebug( "OGRSpatialReference::Validate",
                          "Unexpected child for GEOGCS `%s'.\n",
                          poNode->GetValue() );
                
                return OGRERR_CORRUPT_DATA;
            }
        }

        if( poGEOGCS->GetNode("DATUM") == NULL )
        {
            CPLDebug( "OGRSpatialReference::Validate",
                      "No DATUM child in GEOGCS.\n" );
            
            return OGRERR_CORRUPT_DATA;
        }
    }

/* -------------------------------------------------------------------- */
/*      Validate DATUM/SPHEROID.                                        */
/* -------------------------------------------------------------------- */
    OGR_SRSNode *poDATUM = poRoot->GetNode( "DATUM" );

    if( poDATUM != NULL )
    {
        OGR_SRSNode     *poSPHEROID;
        int             bGotSpheroid = FALSE;
        int             i;

        if( poDATUM->GetChildCount() == 0 )
        {
            CPLDebug( "OGRSpatialReference::Validate",
                      "DATUM has no children." );
            
            return OGRERR_CORRUPT_DATA;
        }

        for( i = 1; i < poDATUM->GetChildCount(); i++ )
        {
            OGR_SRSNode *poNode;
            poNode = poDATUM->GetChild(i);

            if( EQUAL(poNode->GetValue(),"SPHEROID") )
            {
                poSPHEROID = poDATUM->GetChild(1);
                bGotSpheroid = TRUE;

                if( poSPHEROID->GetChildCount() != 3 
                    && poSPHEROID->GetChildCount() != 4 )
                {
                    CPLDebug( "OGRSpatialReference::Validate",
                              "SPHEROID has wrong number of children (%d),"
                              "not 3 or 4 as expected.\n",
                              poSPHEROID->GetChildCount() );
                    
                    return OGRERR_CORRUPT_DATA;
                }
                else if( CPLAtof(poSPHEROID->GetChild(1)->GetValue()) == 0.0 )
                {
                    CPLDebug( "OGRSpatialReference::Validate",
                              "SPHEROID semi-major axis is zero (%s)!\n",
                              poSPHEROID->GetChild(1)->GetValue() );
                    return OGRERR_CORRUPT_DATA;
                }
            }
            else if( EQUAL(poNode->GetValue(),"AUTHORITY") )
            {
                OGRErr eErr = ValidateAuthority(poNode);
                if (eErr != OGRERR_NONE)
                    return eErr;
            }
            else if( EQUAL(poNode->GetValue(),"TOWGS84") )
            {
                if( poNode->GetChildCount() != 3 
                    && poNode->GetChildCount() != 7)
                {
                    CPLDebug( "OGRSpatialReference::Validate",
                   "TOWGS84 has wrong number of children (%d), not 3 or 7.\n",
                              poNode->GetChildCount() );
                    return OGRERR_CORRUPT_DATA;
                }
            }
            else
            {
                CPLDebug( "OGRSpatialReference::Validate",
                          "Unexpected child for DATUM `%s'.\n",
                          poNode->GetValue() );
                
                return OGRERR_CORRUPT_DATA;
            }
        }

        if( !bGotSpheroid )
        {
            CPLDebug( "OGRSpatialReference::Validate",
                      "No SPHEROID child in DATUM.\n" );
            
            return OGRERR_CORRUPT_DATA;
        }
    }        

/* -------------------------------------------------------------------- */
/*      If this is projected, try to validate the detailed set of       */
/*      parameters used for the projection.                             */
/* -------------------------------------------------------------------- */
    OGRErr  eErr;

    eErr = ValidateProjection(poRoot);
    if( eErr != OGRERR_NONE )
        return eErr;

/* -------------------------------------------------------------------- */
/*      Final check.                                                    */
/* -------------------------------------------------------------------- */
    if( EQUAL(poRoot->GetValue(),"GEOCCS") )
        return OGRERR_UNSUPPORTED_SRS;

    return OGRERR_NONE;
}
Beispiel #17
0
OGRErr OGR_SRSNode::importFromWkt( char ** ppszInput, int nRecLevel, int* pnNodes )

{
    const char  *pszInput = *ppszInput;
    int         bInQuotedString = FALSE;

    /* Sanity checks */
    if( nRecLevel == 10 )
    {
        return OGRERR_CORRUPT_DATA;
    }
    if( *pnNodes == 1000 )
    {
        return OGRERR_CORRUPT_DATA;
    }
    
/* -------------------------------------------------------------------- */
/*      Clear any existing children of this node.                       */
/* -------------------------------------------------------------------- */
    ClearChildren();
    
/* -------------------------------------------------------------------- */
/*      Read the ``value'' for this node.                               */
/* -------------------------------------------------------------------- */
    char        szToken[512];
    int         nTokenLen = 0;
    
    while( *pszInput != '\0' && nTokenLen < (int) sizeof(szToken)-1 )
    {
        if( *pszInput == '"' )
        {
            bInQuotedString = !bInQuotedString;
        }
        else if( !bInQuotedString
              && (*pszInput == '[' || *pszInput == ']' || *pszInput == ','
                  || *pszInput == '(' || *pszInput == ')' ) )
        {
            break;
        }
        else if( !bInQuotedString 
                 && (*pszInput == ' ' || *pszInput == '\t' 
                     || *pszInput == 10 || *pszInput == 13) )
        {
            /* just skip over whitespace */
        } 
        else
        {
            szToken[nTokenLen++] = *pszInput;
        }

        pszInput++;
    }

    if( *pszInput == '\0' || nTokenLen == sizeof(szToken) - 1 )
        return OGRERR_CORRUPT_DATA;

    szToken[nTokenLen++] = '\0';
    SetValue( szToken );

/* -------------------------------------------------------------------- */
/*      Read children, if we have a sublist.                            */
/* -------------------------------------------------------------------- */
    if( *pszInput == '[' || *pszInput == '(' )
    {
        do
        {
            OGR_SRSNode *poNewChild;
            OGRErr      eErr;

            pszInput++; // Skip bracket or comma.

            poNewChild = new OGR_SRSNode();

            (*pnNodes) ++;
            eErr = poNewChild->importFromWkt( (char **) &pszInput, nRecLevel + 1, pnNodes );
            if( eErr != OGRERR_NONE )
            {
                delete poNewChild;
                return eErr;
            }

            AddChild( poNewChild );
            
            // swallow whitespace
            while( isspace(*pszInput) ) 
                pszInput++;

        } while( *pszInput == ',' );

        if( *pszInput != ')' && *pszInput != ']' )
            return OGRERR_CORRUPT_DATA;

        pszInput++;
    }

    *ppszInput = (char *) pszInput;

    return OGRERR_NONE;
}
/** Apply a vertical shift grid to a source (DEM typically) dataset.
 * 
 * hGridDataset will typically use WGS84 as horizontal datum (but this is
 * not a requirement) and its values are the values to add to go from geoid
 * elevations to WGS84 ellipsoidal heights.
 * 
 * hGridDataset will be on-the-fly reprojected and resampled to the projection
 * and resolution of hSrcDataset, using bilinear resampling by default.
 * 
 * Both hSrcDataset and hGridDataset must be single band datasets, and have
 * a valid geotransform and projection.
 *
 * On success, a reference will be taken on hSrcDataset and hGridDataset.
 * Reference counting semantics on the source and grid datasets should be
 * honoured. That is, don't just GDALClose() it, unless it was opened with
 * GDALOpenShared(), but rather use GDALReleaseDataset() if wanting to
 * immediately release the reference(s) and make the returned dataset the
 * owner of them.
 *
 * Valid use cases:
 * 
 * \code
 * hSrcDataset = GDALOpen(...)
 * hGridDataset = GDALOpen(...)
 * hDstDataset = GDALApplyVerticalShiftGrid(hSrcDataset, hGridDataset, ...)
 * GDALReleaseDataset(hSrcDataset);
 * GDALReleaseDataset(hGridDataset);
 * if( hDstDataset )
 * {
 *     // Do things with hDstDataset 
 *     GDALClose(hDstDataset) // will close hSrcDataset and hGridDataset
 * }
 * \endcode

 *
 * @param hSrcDataset source (DEM) dataset. Must not be NULL.
 * @param hGridDataset vertical grid shift dataset. Must not be NULL.
 * @param bInverse if set to FALSE, hGridDataset values will be added to
 *                 hSrcDataset. If set to TRUE, they will be subtracted.
 * @param dfSrcUnitToMeter the factor to convert values from hSrcDataset to
 *                         meters (1.0 if source values are in meter).
 * @param dfDstUnitToMeter the factor to convert shifted values from meter
 *                          (1.0 if output values must be in meter).
 * @param papszOptions list of options, or NULL. Supported options are:
 * <ul>
 * <li>RESAMPLING=NEAREST/BILINEAR/CUBIC. Defaults to BILINEAR.</li>
 * <li>MAX_ERROR=val. Maximum error measured in input pixels that is allowed in
 * approximating the transformation (0.0 for exact calculations). Defaults
 * to 0.125</li>
 * <li>DATATYPE=Byte/UInt16/Int16/Float32/Float64. Output data type. If not
 * specified will be the same as the one of hSrcDataset.
 * <li>ERROR_ON_MISSING_VERT_SHIFT=YES/NO. Whether a missing/nodata value in
 * hGridDataset should cause I/O requests to fail. Default is NO (in which case
 * 0 will be used)
 * <li>SRC_SRS=srs_def. Override projection on hSrcDataset;
 * </ul>
 *
 * @return a new dataset corresponding to hSrcDataset adjusted with
 * hGridDataset, or NULL. If not NULL, it must be closed with GDALClose().
 *
 * @since GDAL 2.2
 */
GDALDatasetH GDALApplyVerticalShiftGrid( GDALDatasetH hSrcDataset,
                                         GDALDatasetH hGridDataset,
                                         int bInverse,
                                         double dfSrcUnitToMeter,
                                         double dfDstUnitToMeter,
                                         const char* const* papszOptions )
{
    VALIDATE_POINTER1( hSrcDataset, "GDALApplyVerticalShiftGrid", nullptr );
    VALIDATE_POINTER1( hGridDataset, "GDALApplyVerticalShiftGrid", nullptr );

    double adfSrcGT[6];
    if( GDALGetGeoTransform(hSrcDataset, adfSrcGT) != CE_None )
    {
        CPLError(CE_Failure, CPLE_NotSupported,
                 "Source dataset has no geotransform.");
        return nullptr;
    }
    const char* pszSrcProjection = CSLFetchNameValueDef(papszOptions,
                                            "SRC_SRS",
                                            GDALGetProjectionRef(hSrcDataset));
    if( pszSrcProjection == nullptr || pszSrcProjection[0] == '\0' )
    {
        CPLError(CE_Failure, CPLE_NotSupported,
                 "Source dataset has no projection.");
        return nullptr;
    }
    if(  GDALGetRasterCount(hSrcDataset) != 1 )
    {
        CPLError(CE_Failure, CPLE_NotSupported,
                 "Only single band source dataset is supported.");
        return nullptr;
    }

    double adfGridGT[6];
    if( GDALGetGeoTransform(hGridDataset, adfGridGT) != CE_None )
    {
        CPLError(CE_Failure, CPLE_NotSupported,
                 "Grid dataset has no geotransform.");
        return nullptr;
    }
    const char* pszGridProjection = GDALGetProjectionRef(hGridDataset);
    if( pszGridProjection == nullptr || pszGridProjection[0] == '\0' )
    {
        CPLError(CE_Failure, CPLE_NotSupported,
                 "Grid dataset has no projection.");
        return nullptr;
    }
    if(  GDALGetRasterCount(hGridDataset) != 1 )
    {
        CPLError(CE_Failure, CPLE_NotSupported,
                 "Only single band grid dataset is supported.");
        return nullptr;
    }

    GDALDataType eDT = GDALGetRasterDataType(GDALGetRasterBand(hSrcDataset,1));
    const char* pszDataType = CSLFetchNameValue(papszOptions, "DATATYPE");
    if( pszDataType )
        eDT = GDALGetDataTypeByName(pszDataType);
    if( eDT == GDT_Unknown )
    {
        CPLError(CE_Failure, CPLE_NotSupported,
                 "Invalid DATATYPE=%s", pszDataType);
        return nullptr;
    }

    const int nSrcXSize = GDALGetRasterXSize(hSrcDataset);
    const int nSrcYSize = GDALGetRasterYSize(hSrcDataset);

    OGRSpatialReference oSRS;
    CPLString osSrcProjection(pszSrcProjection);
    oSRS.SetFromUserInput(osSrcProjection);
    if( oSRS.IsCompound() )
    {
        OGR_SRSNode* poNode = oSRS.GetRoot()->GetChild(1);
        if( poNode != nullptr )
        {
            char* pszWKT = nullptr;
            poNode->exportToWkt(&pszWKT);
            osSrcProjection = pszWKT;
            CPLFree(pszWKT);
        }
    }

    void* hTransform = GDALCreateGenImgProjTransformer3( pszGridProjection,
                                                         adfGridGT,
                                                         osSrcProjection,
                                                         adfSrcGT );
    if( hTransform == nullptr )
        return nullptr;
    GDALWarpOptions* psWO = GDALCreateWarpOptions();
    psWO->hSrcDS = hGridDataset;
    psWO->eResampleAlg = GRA_Bilinear;
    const char* pszResampling = CSLFetchNameValue(papszOptions, "RESAMPLING");
    if( pszResampling )
    {
        if( EQUAL(pszResampling, "NEAREST") )
            psWO->eResampleAlg = GRA_NearestNeighbour;
        else if( EQUAL(pszResampling, "BILINEAR") )
            psWO->eResampleAlg = GRA_Bilinear;
        else if( EQUAL(pszResampling, "CUBIC") )
            psWO->eResampleAlg = GRA_Cubic;
    }
    psWO->eWorkingDataType = GDT_Float32;
    int bHasNoData = FALSE;
    const double dfSrcNoData = GDALGetRasterNoDataValue(
        GDALGetRasterBand(hGridDataset, 1), &bHasNoData );
    if( bHasNoData )
    {
        psWO->padfSrcNoDataReal =
                static_cast<double*>(CPLMalloc(sizeof(double)));
        psWO->padfSrcNoDataReal[0] = dfSrcNoData;
    }

    psWO->padfDstNoDataReal = static_cast<double*>(CPLMalloc(sizeof(double)));
    const bool bErrorOnMissingShift = CPLFetchBool( papszOptions,
                                              "ERROR_ON_MISSING_VERT_SHIFT",
                                              false );
    psWO->padfDstNoDataReal[0] = 
        (bErrorOnMissingShift) ? -std::numeric_limits<float>::infinity() : 0.0;
    psWO->papszWarpOptions = CSLSetNameValue(psWO->papszWarpOptions,
                                                 "INIT_DEST",
                                                 "NO_DATA");

    psWO->pfnTransformer = GDALGenImgProjTransform;
    psWO->pTransformerArg = hTransform;
    const double dfMaxError = CPLAtof(CSLFetchNameValueDef(papszOptions,
                                                           "MAX_ERROR",
                                                           "0.125"));
    if( dfMaxError > 0.0 )
    {
        psWO->pTransformerArg =
            GDALCreateApproxTransformer( psWO->pfnTransformer,
                                         psWO->pTransformerArg,
                                         dfMaxError );
        psWO->pfnTransformer = GDALApproxTransform;
        GDALApproxTransformerOwnsSubtransformer(psWO->pTransformerArg, TRUE);
    }
    psWO->nBandCount = 1;
    psWO->panSrcBands = static_cast<int *>(CPLMalloc(sizeof(int)));
    psWO->panSrcBands[0] = 1;
    psWO->panDstBands = static_cast<int *>(CPLMalloc(sizeof(int)));
    psWO->panDstBands[0] = 1;

    VRTWarpedDataset* poReprojectedGrid =
                new VRTWarpedDataset(nSrcXSize, nSrcYSize);
    // This takes a reference on hGridDataset
    CPLErr eErr = poReprojectedGrid->Initialize(psWO);
    CPLAssert(eErr == CE_None);
    CPL_IGNORE_RET_VAL(eErr);
    GDALDestroyWarpOptions(psWO);
    poReprojectedGrid->SetGeoTransform(adfSrcGT);
    poReprojectedGrid->AddBand(GDT_Float32, nullptr);

    GDALApplyVSGDataset* poOutDS = new GDALApplyVSGDataset(
        reinterpret_cast<GDALDataset*>(hSrcDataset),
        poReprojectedGrid,
        eDT,
        CPL_TO_BOOL(bInverse),
        dfSrcUnitToMeter,
        dfDstUnitToMeter,
        // Undocumented option. For testing only
        atoi(CSLFetchNameValueDef(papszOptions, "BLOCKSIZE", "256")) );

    poReprojectedGrid->ReleaseRef();

    if( !poOutDS->IsInitOK() )
    {
        delete poOutDS;
        return nullptr;
    }
    poOutDS->SetDescription( GDALGetDescription( hSrcDataset ) );
    return reinterpret_cast<GDALDatasetH>(poOutDS);
}