std::string SpatialReference::getVerticalUnits() const { std::string tmp(""); std::string wkt = getWKT(eCompoundOK); const char* poWKT = wkt.c_str(); OGRSpatialReference* poSRS = (OGRSpatialReference*)OSRNewSpatialReference(m_wkt.c_str()); if (poSRS) { OGR_SRSNode* node = poSRS->GetAttrNode("VERT_CS"); if (node) { char* units(0); double u = poSRS->GetLinearUnits(&units); tmp = units; CPLFree(units); Utils::trim(tmp); } } return tmp; }
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; }
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; }
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; }
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; }