// Returns the scale of a WMS request as compared to the base resolution double GDALWMSMiniDriver_TiledWMS::Scale(const char *request) { int bbox=FindBbox(request); if (bbox<0) return 0; double x,y,X,Y; CPLsscanf(request+bbox,"%lf,%lf,%lf,%lf",&x,&y,&X,&Y); return (m_data_window.m_x1-m_data_window.m_x0)/(X-x)*m_bsx/m_data_window.m_sx; }
OGRLayer * OGRTABDataSource::ICreateLayer( const char *pszLayerName, OGRSpatialReference *poSRSIn, OGRwkbGeometryType /* eGeomTypeIn */, char **papszOptions ) { if( !m_bUpdate ) { CPLError( CE_Failure, CPLE_AppDefined, "Cannot create layer on read-only dataset."); return nullptr; } // If it is a single file mode file, then we may have already // instantiated the low level layer. We would just need to // reset the coordinate system and (potentially) bounds. IMapInfoFile *poFile = nullptr; char *pszFullFilename = nullptr; const char *pszEncoding = CSLFetchNameValue( papszOptions, "ENCODING" ); const char *pszCharset( IMapInfoFile::EncodingToCharset( pszEncoding ) ); if( m_bSingleFile ) { if( m_bSingleLayerAlreadyCreated ) { CPLError( CE_Failure, CPLE_AppDefined, "Unable to create new layers in this single file dataset."); return nullptr; } m_bSingleLayerAlreadyCreated = TRUE; poFile = (IMapInfoFile *) m_papoLayers[0]; if( pszEncoding ) poFile->SetCharset( pszCharset ); } else { if( m_bCreateMIF ) { pszFullFilename = CPLStrdup(CPLFormFilename(m_pszDirectory, pszLayerName, "mif")); poFile = new MIFFile; if( poFile->Open(pszFullFilename, TABWrite, FALSE, pszCharset) != 0 ) { CPLFree(pszFullFilename); delete poFile; return nullptr; } } else { pszFullFilename = CPLStrdup(CPLFormFilename(m_pszDirectory, pszLayerName, "tab")); TABFile *poTABFile = new TABFile; if( poTABFile->Open(pszFullFilename, TABWrite, FALSE, m_nBlockSize, pszCharset) != 0 ) { CPLFree(pszFullFilename); delete poTABFile; return nullptr; } poFile = poTABFile; } m_nLayerCount++; m_papoLayers = static_cast<IMapInfoFile **>( CPLRealloc(m_papoLayers,sizeof(void*)*m_nLayerCount)); m_papoLayers[m_nLayerCount-1] = poFile; CPLFree(pszFullFilename); } poFile->SetDescription(poFile->GetName()); // Assign the coordinate system (if provided) and set // reasonable bounds. if( poSRSIn != nullptr ) { poFile->SetSpatialRef(poSRSIn); // SetSpatialRef() has cloned the passed geometry poFile->GetLayerDefn()->GetGeomFieldDefn(0)->SetSpatialRef( poFile->GetSpatialRef()); } // Pull out the bounds if supplied const char *pszOpt = nullptr; if( (pszOpt = CSLFetchNameValue(papszOptions, "BOUNDS")) != nullptr ) { double dfBounds[4]; if( CPLsscanf(pszOpt, "%lf,%lf,%lf,%lf", &dfBounds[0], &dfBounds[1], &dfBounds[2], &dfBounds[3]) != 4 ) { CPLError( CE_Failure, CPLE_IllegalArg, "Invalid BOUNDS parameter, expected min_x,min_y,max_x,max_y"); } else { poFile->SetBounds(dfBounds[0], dfBounds[1], dfBounds[2], dfBounds[3]); } } if( !poFile->IsBoundsSet() && !m_bCreateMIF ) { if( poSRSIn != nullptr && poSRSIn->GetRoot() != nullptr && EQUAL(poSRSIn->GetRoot()->GetValue(),"GEOGCS") ) poFile->SetBounds(-1000, -1000, 1000, 1000); else poFile->SetBounds(-30000000, -15000000, 30000000, 15000000); } if(m_bQuickSpatialIndexMode == TRUE && poFile->SetQuickSpatialIndexMode(TRUE) != 0) { CPLError(CE_Warning, CPLE_AppDefined, "Setting Quick Spatial Index Mode failed."); } else if(m_bQuickSpatialIndexMode == FALSE && poFile->SetQuickSpatialIndexMode(FALSE) != 0) { CPLError(CE_Warning, CPLE_AppDefined, "Setting Normal Spatial Index Mode failed."); } return poFile; }
CPLErr GDALWMSMiniDriver_TiledWMS::Initialize(CPLXMLNode *config, CPL_UNUSED char **OpenOptions) { CPLErr ret = CE_None; CPLXMLNode *tileServiceConfig=NULL; CPLHTTPResult *psResult=NULL; CPLXMLNode *TG=NULL; char **requests=NULL; char **substs=NULL; char **keys=NULL; for (int once=1;once;once--) { // Something to break out of // Parse info from the service m_end_url = CPLGetXMLValue(config,"AdditionalArgs",""); m_base_url = CPLGetXMLValue(config, "ServerURL", ""); if (m_base_url.empty()) { CPLError(ret=CE_Failure, CPLE_AppDefined, "%s ServerURL missing.",SIG); break; } CPLString tiledGroupName (CPLGetXMLValue(config, "TiledGroupName", "")); if (tiledGroupName.empty()) { CPLError(ret=CE_Failure, CPLE_AppDefined, "%s TiledGroupName missing.",SIG); break; } // Change strings, key is an attribute, value is the value of the Change node // Multiple substitutions are possible TG=CPLSearchXMLNode(config, "Change"); while(TG!=NULL) { CPLString name=CPLGetXMLValue(TG,"key",""); if (name.empty()) { CPLError(ret=CE_Failure, CPLE_AppDefined, "%s Change element needs a non-empty \"key\" attribute",SIG); break; } substs=CSLSetNameValue(substs,name,CPLGetXMLValue(TG,"","")); TG=SearchXMLSiblings(TG,"Change"); } if (ret!=CE_None) break; CPLString getTileServiceUrl = m_base_url + "request=GetTileService"; psResult = CPLHTTPFetch(getTileServiceUrl, NULL); if (NULL==psResult) { CPLError(ret=CE_Failure, CPLE_AppDefined, "%s Can't use HTTP", SIG); break; } if ((psResult->nStatus!=0)||(NULL==psResult->pabyData)||('\0'==psResult->pabyData[0])) { CPLError(ret=CE_Failure, CPLE_AppDefined, "%s Server response error on GetTileService.",SIG); break; } if (NULL==(tileServiceConfig=CPLParseXMLString((const char*)psResult->pabyData))) { CPLError(ret=CE_Failure,CPLE_AppDefined, "%s Error parsing the GetTileService response.",SIG); break; } if (NULL==(TG=CPLSearchXMLNode(tileServiceConfig, "TiledPatterns"))) { CPLError(ret=CE_Failure,CPLE_AppDefined, "%s Can't locate TiledPatterns in server response.",SIG); break; } // Get the global base_url and bounding box, these can be overwritten at the tileGroup level // They are just pointers into existing structures, cleanup is not required const char *global_base_url=CPLGetXMLValue(tileServiceConfig,"TiledPatterns.OnlineResource.xlink:href",""); CPLXMLNode *global_latlonbbox=CPLGetXMLNode(tileServiceConfig, "TiledPatterns.LatLonBoundingBox"); CPLXMLNode *global_bbox=CPLGetXMLNode(tileServiceConfig, "TiledPatterns.BoundingBox"); if (NULL==(TG=SearchLeafGroupName(TG->psChild,tiledGroupName))) { CPLError(ret=CE_Failure,CPLE_AppDefined, "%s Can't locate TiledGroup ""%s"" in server response.",SIG, tiledGroupName.c_str()); break; } int band_count=atoi(CPLGetXMLValue(TG, "Bands", "3")); if (!GDALCheckBandCount(band_count, FALSE)) { CPLError(ret=CE_Failure,CPLE_AppDefined,"%s%s",SIG, "Invalid number of bands in server response"); break; } // Collect all keys defined by this tileset if (NULL!=CPLGetXMLNode(TG,"Key")) { CPLXMLNode *node=CPLGetXMLNode(TG,"Key"); while (NULL!=node) { const char *val=CPLGetXMLValue(node,NULL,NULL); if (val) keys=CSLAddString(keys,val); node=SearchXMLSiblings(node,"Key"); } } // Data values are attributes, they include NoData Min and Max if (NULL!=CPLGetXMLNode(TG,"DataValues")) { const char *nodata=CPLGetXMLValue(TG,"DataValues.NoData",NULL); if (nodata!=NULL) m_parent_dataset->WMSSetNoDataValue(nodata); const char *min=CPLGetXMLValue(TG,"DataValues.min",NULL); if (min!=NULL) m_parent_dataset->WMSSetMinValue(min); const char *max=CPLGetXMLValue(TG,"DataValues.max",NULL); if (max!=NULL) m_parent_dataset->WMSSetMaxValue(max); } m_parent_dataset->WMSSetBandsCount(band_count); m_parent_dataset->WMSSetDataType(GDALGetDataTypeByName(CPLGetXMLValue(TG, "DataType", "Byte"))); m_projection_wkt=CPLGetXMLValue(TG, "Projection",""); m_base_url=CPLGetXMLValue(TG,"OnlineResource.xlink:href",global_base_url); if (m_base_url[0]=='\0') { CPLError(ret=CE_Failure,CPLE_AppDefined, "%s%s",SIG, "Can't locate OnlineResource in the server response."); break; } // Bounding box, local, global, local lat-lon, global lat-lon, in this order CPLXMLNode *bbox = CPLGetXMLNode(TG, "BoundingBox"); if (NULL==bbox) bbox=global_bbox; if (NULL==bbox) bbox=CPLGetXMLNode(TG, "LatLonBoundingBox"); if (NULL==bbox) bbox=global_latlonbbox; if (NULL==bbox) { CPLError(ret=CE_Failure,CPLE_AppDefined,"%s%s",SIG, "Can't locate the LatLonBoundingBox in server response."); break; } m_data_window.m_x0=CPLAtof(CPLGetXMLValue(bbox,"minx","0")); m_data_window.m_x1=CPLAtof(CPLGetXMLValue(bbox,"maxx","-1")); m_data_window.m_y0=CPLAtof(CPLGetXMLValue(bbox,"maxy","0")); m_data_window.m_y1=CPLAtof(CPLGetXMLValue(bbox,"miny","-1")); if ((m_data_window.m_x1-m_data_window.m_x0)<0) { CPLError(ret=CE_Failure,CPLE_AppDefined,"%s%s", SIG, "Coordinate order in BBox, problem in server response"); break; } // Is there a palette? // // Format is // <Palette> // <Size>N</Size> : Optional // <Model>RGBA|RGB|CMYK|HSV|HLS|L</Model> :mandatory // <Entry idx=i c1=v1 c2=v2 c3=v3 c4=v4/> :Optional // <Entry .../> // </Palette> // the idx attribute is optional, it autoincrements // The entries are actually vertices, interpolation takes place inside // The palette starts initialized with zeros // HSV and HLS are the similar, with c2 and c3 swapped // RGB or RGBA are same // GDALColorTable *poColorTable=NULL; if ((band_count==1) && CPLGetXMLNode(TG,"Palette")) { CPLXMLNode *node=CPLGetXMLNode(TG,"Palette"); int entries=static_cast<int>(getXMLNum(node,"Size","255")); GDALPaletteInterp eInterp=GPI_RGB; CPLString pModel=CPLGetXMLValue(node,"Model","RGB"); if (!pModel.empty() && pModel.find("RGB")!=std::string::npos) eInterp=GPI_RGB; else { CPLError(CE_Failure, CPLE_AppDefined, "%s Palette Model %s is unknown, use RGB or RGBA", SIG, pModel.c_str()); return CE_Failure; } if ((entries>0)&&(entries<257)) { int start_idx, end_idx; GDALColorEntry ce_start={0,0,0,255},ce_end={0,0,0,255}; // Create it and initialize it to nothing poColorTable = new GDALColorTable(eInterp); poColorTable->CreateColorRamp(0,&ce_start,entries-1,&ce_end); // Read the values CPLXMLNode *p=CPLGetXMLNode(node,"Entry"); if (p) { // Initialize the first entry start_idx=static_cast<int>(getXMLNum(p,"idx","0")); ce_start=GetXMLColorEntry(p); if (start_idx<0) { CPLError(CE_Failure, CPLE_AppDefined, "%s Palette index %d not allowed",SIG,start_idx); delete poColorTable; return CE_Failure; } poColorTable->SetColorEntry(start_idx,&ce_start); while (NULL!=(p=SearchXMLSiblings(p,"Entry"))) { // For every entry, create a ramp ce_end=GetXMLColorEntry(p); end_idx=static_cast<int>(getXMLNum(p,"idx",CPLString().FormatC(start_idx+1).c_str())); if ((end_idx<=start_idx)||(start_idx>=entries)) { CPLError(CE_Failure, CPLE_AppDefined, "%s Index Error at index %d",SIG,end_idx); delete poColorTable; return CE_Failure; } poColorTable->CreateColorRamp(start_idx,&ce_start, end_idx,&ce_end); ce_start=ce_end; start_idx=end_idx; } } m_parent_dataset->SetColorTable(poColorTable); } else { CPLError(CE_Failure, CPLE_AppDefined,"%s Palette definition error",SIG); return CE_Failure; } } int overview_count=0; CPLXMLNode *Pattern=TG->psChild; m_bsx=m_bsy=-1; m_data_window.m_sx=m_data_window.m_sy=0; for (int once2=1;once2;once2--) { // Something to break out of while ((NULL!=Pattern)&&(NULL!=(Pattern=SearchXMLSiblings(Pattern,"=TilePattern")))) { int mbsx,mbsy; CPLString request; FindChangePattern(Pattern->psChild->pszValue,substs,keys,request); char **papszTokens=CSLTokenizeString2(request,"&",0); const char* pszWIDTH = CSLFetchNameValue(papszTokens,"WIDTH"); const char* pszHEIGHT = CSLFetchNameValue(papszTokens,"HEIGHT"); if (pszWIDTH == NULL || pszHEIGHT == NULL) { CPLError(ret=CE_Failure,CPLE_AppDefined,"%s%s",SIG, "Cannot find width and/or height parameters."); overview_count=0; CSLDestroy(papszTokens); break; } mbsx=atoi(pszWIDTH); mbsy=atoi(pszHEIGHT); if (m_projection_wkt.empty()) { m_projection_wkt = CSLFetchNameValueDef(papszTokens,"SRS", ""); if (!m_projection_wkt.empty()) m_projection_wkt=ProjToWKT(m_projection_wkt); } if (-1==m_bsx) m_bsx=mbsx; if (-1==m_bsy) m_bsy=mbsy; if ((m_bsx!=mbsx)||(m_bsy!=mbsy)) { CPLError(ret=CE_Failure,CPLE_AppDefined,"%s%s",SIG, "Tileset uses different block sizes."); overview_count=0; CSLDestroy(papszTokens); break; } double x,y,X,Y; if (CPLsscanf(CSLFetchNameValueDef(papszTokens,"BBOX", ""),"%lf,%lf,%lf,%lf",&x,&y,&X,&Y)!=4) { CPLError(ret=CE_Failure,CPLE_AppDefined, "%s Error parsing BBOX, pattern %d\n",SIG,overview_count+1); CSLDestroy(papszTokens); break; } // Pick the largest size int sx=static_cast<int>((m_data_window.m_x1-m_data_window.m_x0)/(X-x)*m_bsx); int sy=static_cast<int>(fabs((m_data_window.m_y1-m_data_window.m_y0)/(Y-y)*m_bsy)); if (sx>m_data_window.m_sx) m_data_window.m_sx=sx; if (sy>m_data_window.m_sy) m_data_window.m_sy=sy; CSLDestroy(papszTokens); // Only use overlays where the top coordinate is within a pixel from the top of coverage double pix_off,temp; pix_off=m_bsy*modf(fabs((Y-m_data_window.m_y0)/(Y-y)),&temp); if ((pix_off<1)||((m_bsy-pix_off)<1)) { requests=CSLAddString(requests,request); overview_count++; } else CPLError(CE_Warning,CPLE_AppDefined, "%s Overlay size %dX%d can't be used due to alignment",SIG,sx,sy); Pattern=Pattern->psNext; } // The tlevel is needed, the tx and ty are not used by this minidriver m_data_window.m_tlevel = 0; m_data_window.m_tx = 0; m_data_window.m_ty = 0; // Make sure the parent_dataset values are set before creating the bands m_parent_dataset->WMSSetBlockSize(m_bsx,m_bsy); m_parent_dataset->WMSSetRasterSize(m_data_window.m_sx,m_data_window.m_sy); m_parent_dataset->WMSSetDataWindow(m_data_window); //m_parent_dataset->WMSSetOverviewCount(overview_count); m_parent_dataset->WMSSetClamp(false); // Ready for the Rasterband creation for (int i=0;i<overview_count;i++) { CPLString request=GetLowestScale(requests,i); double scale=Scale(request); // Base scale should be very close to 1 if ((0==i)&&(fabs(scale-1) > 1e-6)) { CPLError(ret=CE_Failure,CPLE_AppDefined,"%s%s",SIG, "Base resolution pattern missing."); break; } // Prepare the request and insert it back into the list // Find returns an answer relative to the original string start! size_t startBbox=FindBbox(request); size_t endBbox=request.find('&',startBbox); if (endBbox==std::string::npos) endBbox=request.size(); request.replace(startBbox,endBbox-startBbox,"${GDAL_BBOX}"); requests = CSLInsertString(requests,i,request); // Create the Rasterband or overview for (int j = 1; j <= band_count; j++) { if (i!=0) m_parent_dataset->mGetBand(j)->AddOverview(scale); else { // Base resolution GDALWMSRasterBand *band=new GDALWMSRasterBand(m_parent_dataset,j,1); if (poColorTable!=NULL) band->SetColorInterpretation(GCI_PaletteIndex); else band->SetColorInterpretation(BandInterp(band_count,j)); m_parent_dataset->mSetBand(j, band); }; } } if ((overview_count==0)||(m_bsx<1)||(m_bsy<1)) { CPLError(ret=CE_Failure,CPLE_AppDefined, "%s No usable TilePattern elements found",SIG); break; } } } CSLDestroy(keys); CSLDestroy(substs); if (tileServiceConfig) CPLDestroyXMLNode(tileServiceConfig); if (psResult) CPLHTTPDestroyResult(psResult); m_requests=requests; return ret; }
OGRFeature *OGRGmtLayer::GetNextRawFeature() { #if 0 int bMultiVertex = poFeatureDefn->GetGeomType() != wkbPoint && poFeatureDefn->GetGeomType() != wkbUnknown; #endif CPLString osFieldData; OGRGeometry *poGeom = NULL; /* -------------------------------------------------------------------- */ /* Read lines associated with this feature. */ /* -------------------------------------------------------------------- */ for( ; true; ReadLine() ) { if( osLine.length() == 0 ) break; if( osLine[0] == '>' ) { if( poGeom != NULL && wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon ) { OGRMultiPolygon *poMP = (OGRMultiPolygon *) poGeom; if( ScanAheadForHole() ) { // Add a hole to the current polygon. ((OGRPolygon *) poMP->getGeometryRef( poMP->getNumGeometries()-1 ))-> addRingDirectly( new OGRLinearRing() ); } else if( !NextIsFeature() ) { OGRPolygon *poPoly = new OGRPolygon(); poPoly->addRingDirectly( new OGRLinearRing() ); poMP->addGeometryDirectly( poPoly ); } else break; /* done geometry */ } else if( poGeom != NULL && wkbFlatten(poGeom->getGeometryType()) == wkbPolygon) { if( ScanAheadForHole() ) ((OGRPolygon *)poGeom)-> addRingDirectly( new OGRLinearRing() ); else break; /* done geometry */ } else if( poGeom != NULL && (wkbFlatten(poGeom->getGeometryType()) == wkbMultiLineString) && !NextIsFeature() ) { ((OGRMultiLineString *) poGeom)-> addGeometryDirectly( new OGRLineString() ); } else if( poGeom != NULL ) { break; } else if( poFeatureDefn->GetGeomType() == wkbUnknown ) { poFeatureDefn->SetGeomType( wkbLineString ); /* bMultiVertex = TRUE; */ } } else if( osLine[0] == '#' ) { for( int i = 0; papszKeyedValues != NULL && papszKeyedValues[i] != NULL; i++ ) { if( papszKeyedValues[i][0] == 'D' ) osFieldData = papszKeyedValues[i] + 1; } } else { // Parse point line. double dfX; double dfY; double dfZ = 0.0; const int nDim = CPLsscanf( osLine, "%lf %lf %lf", &dfX, &dfY, &dfZ ); if( nDim >= 2 ) { if( poGeom == NULL ) { switch( poFeatureDefn->GetGeomType() ) { case wkbLineString: poGeom = new OGRLineString(); break; case wkbPolygon: poGeom = new OGRPolygon(); reinterpret_cast<OGRPolygon *>(poGeom)->addRingDirectly( new OGRLinearRing() ); break; case wkbMultiPolygon: { OGRPolygon *poPoly = new OGRPolygon(); poPoly->addRingDirectly( new OGRLinearRing() ); poGeom = new OGRMultiPolygon(); reinterpret_cast<OGRMultiPolygon *>(poGeom)-> addGeometryDirectly( poPoly ); } break; case wkbMultiPoint: poGeom = new OGRMultiPoint(); break; case wkbMultiLineString: poGeom = new OGRMultiLineString(); reinterpret_cast<OGRMultiLineString *>(poGeom)-> addGeometryDirectly(new OGRLineString() ); break; case wkbPoint: case wkbUnknown: default: poGeom = new OGRPoint(); break; } } switch( wkbFlatten(poGeom->getGeometryType()) ) { case wkbPoint: reinterpret_cast<OGRPoint *>(poGeom)->setX( dfX ); reinterpret_cast<OGRPoint *>(poGeom)->setY( dfY ); if( nDim == 3 ) reinterpret_cast<OGRPoint *>(poGeom)->setZ( dfZ ); break; case wkbLineString: if( nDim == 3 ) reinterpret_cast<OGRLineString *>(poGeom)-> addPoint( dfX, dfY, dfZ); else reinterpret_cast<OGRLineString *>(poGeom)-> addPoint( dfX, dfY ); break; case wkbPolygon: case wkbMultiPolygon: { OGRPolygon *poPoly = NULL; if( wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon ) { OGRMultiPolygon *poMP = (OGRMultiPolygon *) poGeom; poPoly = (OGRPolygon*) poMP->getGeometryRef( poMP->getNumGeometries() - 1 ); } else poPoly = reinterpret_cast<OGRPolygon *>(poGeom); OGRLinearRing *poRing = NULL; if( poPoly->getNumInteriorRings() == 0 ) poRing = poPoly->getExteriorRing(); else poRing = poPoly->getInteriorRing( poPoly->getNumInteriorRings()-1 ); if( nDim == 3 ) poRing->addPoint( dfX, dfY, dfZ ); else poRing->addPoint( dfX, dfY ); } break; case wkbMultiLineString: { OGRMultiLineString *poML = (OGRMultiLineString *) poGeom; OGRLineString *poLine = reinterpret_cast<OGRLineString *>( poML->getGeometryRef( poML->getNumGeometries() -1 ) ); if( nDim == 3 ) poLine->addPoint( dfX, dfY, dfZ ); else poLine->addPoint( dfX, dfY ); } break; default: CPLAssert( FALSE ); } } } if( poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint ) { ReadLine(); break; } } if( poGeom == NULL ) return NULL; /* -------------------------------------------------------------------- */ /* Create feature. */ /* -------------------------------------------------------------------- */ OGRFeature *poFeature = new OGRFeature( poFeatureDefn ); poGeom->assignSpatialReference(poSRS); poFeature->SetGeometryDirectly( poGeom ); poFeature->SetFID( iNextFID++ ); /* -------------------------------------------------------------------- */ /* Process field values. */ /* -------------------------------------------------------------------- */ char **papszFD = CSLTokenizeStringComplex( osFieldData, "|", TRUE, TRUE ); for( int iField = 0; papszFD != NULL && papszFD[iField] != NULL; iField++ ) { if( iField >= poFeatureDefn->GetFieldCount() ) break; poFeature->SetField( iField, papszFD[iField] ); } CSLDestroy( papszFD ); m_nFeaturesRead++; return poFeature; }