bool LocationSetIO::ParseCSVFile( const std::vector<std::wstring>& csvTableRows, StudyControllerPtr studyController, std::vector<LocationModelPtr>& locationModels ) { const int ROWS_TO_SHOW_PROGRESS_DLG = 2000; // tokenize column names tokenizer< escaped_list_separator<wchar_t>, wstring::const_iterator, wstring > columnTokens(csvTableRows.at(0)); vector<wstring> columnValues(columnTokens.begin(), columnTokens.end()); if(columnValues.size() == 1) { // assume a tab-delimited file columnValues.clear(); split(columnValues, csvTableRows.at(0), boost::is_any_of(_T("\t"))); } ProgressDlgPtr progressDlg; if(csvTableRows.size() > ROWS_TO_SHOW_PROGRESS_DLG) progressDlg.reset(new ProgressDlg(_T("Loading location set"), _T("Reading locations..."), csvTableRows.size(), App::Inst().GetMainWindow())); uint rowNum = 1; vector<wstring>::const_iterator it; for(it = ++csvTableRows.begin(); it != csvTableRows.end(); ++it) { if(progressDlg && rowNum % 25 == 0) progressDlg->Update(rowNum); rowNum++; tokenizer< escaped_list_separator<wchar_t>, wstring::const_iterator, wstring > rowTokens(*it); vector<wstring> rowValues(rowTokens.begin(), rowTokens.end()); if(rowValues.size() == 1) { // assume a tab-delimited file rowValues.clear(); split(rowValues, *it, boost::is_any_of(_T("\t"))); } if(columnValues.size() != rowValues.size()) { wxString warning; warning.Printf(wxT("(Warning) Location file contains %d headings, but line %d contains only %d values. "), columnValues.size(), rowNum, rowValues.size()); warning += (wxT("This line begins with the value '") + rowValues.at(0) + wxT("'.")).c_str(); Log::Inst().Warning(warning); return false; } wstring siteId = _T(""); wstring sampleId = _T(""); double northing = -std::numeric_limits<float>::max(); double easting = -std::numeric_limits<float>::max(); bool bIsLatLong = false; bool bReject = false; double latitude = -std::numeric_limits<float>::max(); double longitude = -std::numeric_limits<float>::max(); map<std::wstring,std::wstring> data; for(uint c = 0; c < columnValues.size(); ++c) { wstring header = StringTools::RemoveSurroundingWhiteSpaces(columnValues.at(c)); wstring value = StringTools::RemoveSurroundingWhiteSpaces(rowValues.at(c)); // determine which column we are looking at (this allows user to put columns in any order) if(StringTools::ToLower(header) == _T("site id") || StringTools::ToLower(header) == _T("siteid")) siteId = value; else if(StringTools::ToLower(header) == _T("sample id") || StringTools::ToLower(header) == _T("sampleid")) sampleId = value; else if(StringTools::ToLower(header) == _T("northing")) northing = StringTools::ToLong(value); else if(StringTools::ToLower(header) == _T("easting")) easting = StringTools::ToLong(value); else if(StringTools::ToLower(header) == _T("latitude")) { header = StringTools::ToUpper(header.substr(0,1)) + StringTools::ToLower(header.substr(1)); // check if latitude is numeric if(!StringTools::IsDecimalNumber( StringTools::ToString(value) ) && !StringTools::IsInteger( StringTools::ToString(value) ) ) bReject = true; latitude = StringTools::ToDouble(value); bIsLatLong = true; } else if(StringTools::ToLower(header) == _T("longitude")) { header = StringTools::ToUpper(header.substr(0,1)) + StringTools::ToLower(header.substr(1)); // check if longitude is numeric if(!StringTools::IsDecimalNumber( StringTools::ToString(value) ) && !StringTools::IsInteger( StringTools::ToString(value) ) ) bReject = true; longitude = StringTools::ToDouble(value); bIsLatLong = true; } data.insert(pair<wstring, wstring>(header, value)); } // transform lat/lon coordinates to projected coordinates if(bIsLatLong) { double tempLat = latitude; double tempLat2 = latitude; if(studyController->IsProjectData()) { ProjectionToolPtr projTool = studyController->GetProjectionTool(); if(!projTool->Transform(1, &longitude, &latitude)) { Log::Inst().Warning("(Warning) Failed to project data. Possibly missing 'Latitude' and 'Longitude' fields."); return false; } // if a point falls off the map, assume the map actually spans the 180 degree line if(longitude < App::Inst().GetMapController()->GetHeader()->projExtents.x) { double longNeg180 = -180; projTool->Transform(1, &longNeg180, &tempLat); double long180 = 180; projTool->Transform(1, &long180, &tempLat2); longitude = long180 + (longitude - longNeg180); } } northing = latitude; easting = longitude; } // check for required data if(siteId == _T("")) { if(sampleId != _T("")) siteId = sampleId; else { Log::Inst().Warning("(Warning) Missing 'Site Id' field."); return false; } } if(northing == -std::numeric_limits<float>::max()) { Log::Inst().Warning("(Warning) Missing 'Latitude or Northing' field."); return false; } if(easting == -std::numeric_limits<float>::max()) { Log::Inst().Warning("(Warning) Missing 'Longitude or Easting' field."); return false; } // remove spaces from siteId to avoid conflicts with trees siteId = StringTools::ReplaceChar(siteId, ' ','_'); if (!bReject) { // create a new location model from this data LocationModelPtr locationModel(new LocationModel(siteId, northing, easting, data)); locationModels.push_back(locationModel); } } return true; }
bool DemReader::Open(std::wstring fullPath, StudyControllerPtr studyController, MapControllerPtr mapController, ProgressDlgPtr progressDlg) { GDALAllRegister(); bool bElevationMap; uint numBands; double adfGeoTransform[6]; GDALDataset* gdalDataset; int nBlockXSize, nBlockYSize; MapModelPtr mapModel = mapController->GetMapModel(); FileHeader* header = mapModel->GetHeader(); GDALRasterBand* gdalBand; if(App::Inst().GetLayerTreeController()->GetIsBlankRaster()) { LayerTreeControllerPtr ltc = App::Inst().GetLayerTreeController(); VectorMapLayerPtr vectorMapLayer =ltc->GetVectorMapLayer(0); VectorMapModelPtr vectorMapModel= vectorMapLayer->GetVectorMapController()->GetVectorMapModel(); double vectorMinX = vectorMapModel->GetVectorBoundary_MinX(); double vectorMinY = vectorMapModel->GetVectorBoundary_MinY(); double vectorMaxX = vectorMapModel->GetVectorBoundary_MaxX(); double vectorMaxY = vectorMapModel->GetVectorBoundary_MaxY(); double bRaster_width = 1000; double bRaster_height= 1000; double x_res = (vectorMaxX - vectorMinX) / bRaster_width; double y_res = (vectorMaxY - vectorMinY) / bRaster_height; numBands = 3; bElevationMap = false; header->nCols = 1000; header->nRows = 1000; header->noDataValue=0.0; //adfGeoTransform[6]= {vectorMinX, x_res, 0.0, vectorMaxY, 0.0, -y_res}; adfGeoTransform[0]= vectorMinX; adfGeoTransform[1]= x_res; adfGeoTransform[2]= 0.0; adfGeoTransform[3]= vectorMaxY; adfGeoTransform[4] = 0.0; adfGeoTransform[5]= -y_res; } else { std::string tempStr(fullPath.begin(), fullPath.end()); gdalDataset = (GDALDataset*) GDALOpen( tempStr.c_str(), GA_ReadOnly ); if(gdalDataset == NULL) { Log::Inst().Warning("(Warning) Failed to open file at " + tempStr + "."); return false; } // determine type of file based on number of raster bands numBands = gdalDataset->GetRasterCount(); if(numBands == 1) bElevationMap = true; else if(numBands == 3 || numBands == 4) bElevationMap = false; else { Log::Inst().Warning("(Warning) File type not supported. Please contact the GenGIS to request support for the file format."); } CPLErr err = gdalDataset->GetGeoTransform( adfGeoTransform ); // check if we have a map without any transformation information // in which case assume we have a custom image file where y should // be in the south (down) direction if(err == CE_Failure) adfGeoTransform[5] = -1; gdalBand = gdalDataset->GetRasterBand( 1 ); gdalBand->GetBlockSize( &nBlockXSize, &nBlockYSize ); // get original data dimensions header->nCols = gdalBand->GetXSize(); header->nRows = gdalBand->GetYSize(); header->noDataValue = gdalBand->GetNoDataValue(); // Setup desired projection if(!SetupProjection(gdalDataset, studyController, adfGeoTransform, header->nCols, header->nRows, bElevationMap)) { GDALClose(gdalDataset); return false; } } if(progressDlg) { if(!App::Inst().GetLayerTreeController()->GetIsBlankRaster()) { if(!progressDlg->Update(0, _T("Reading map file..."))) { GDALClose(gdalDataset); return false; } } else { if(!progressDlg->Update(0, _T("Initializing the Visualization..."))) { GDALClose(gdalDataset); return false; } } } // check whether it's too large to handle all the data float* elevations = NULL; if(bElevationMap && !App::Inst().GetLayerTreeController()->GetIsBlankRaster()) { try { elevations = new float[gdalBand->GetXSize()* gdalBand->GetYSize()]; } catch(std::bad_alloc&) { Log::Inst().Warning("(Warning) Insufficent memory for elevation map."); GDALClose(gdalDataset); return false; } gdalBand->RasterIO( GF_Read, 0, 0, gdalBand->GetXSize(), gdalBand->GetYSize(), elevations, gdalBand->GetXSize(), gdalBand->GetYSize(), GDT_Float32, 0, 0 ); } // project all map model cells Point3D* grid; try { grid = new Point3D[header->nCols*header->nRows]; } catch(std::bad_alloc&) { Log::Inst().Warning("(Warning) Insufficent memory to load map."); GDALClose(gdalDataset); delete[] elevations; return false; } // populate grid with projected points and find extents of projected map double xOffset = adfGeoTransform[0]; double zOffset = adfGeoTransform[3]; int index = 0; double x, z; header->projExtents.x = header->projExtents.y = std::numeric_limits<float>::max(); header->projExtents.dx = header->projExtents.dy = -std::numeric_limits<float>::max(); ProjectionToolPtr projTool = studyController->GetProjectionTool(); for(int m = 0; m < header->nRows ; ++m) { xOffset = adfGeoTransform[0]; for(int n = 0; n < header->nCols; ++n) { x = xOffset; z = zOffset; if(studyController->IsProjectData() && studyController->IsGeographic() && !App::Inst().GetLayerTreeController()->GetIsBlankRaster()) { double elevation = (double)elevations[index]; if(!projTool->Transform(1, &x, &z, &elevation)) { Log::Inst().Warning("(Warning) Failed to project map."); GDALClose(gdalDataset); delete[] elevations; return false; } } xOffset += adfGeoTransform[1]; if(App::Inst().GetLayerTreeController()->GetIsBlankRaster()) { double X = x; double Z = z; grid[index].x = X; grid[index].z = Z; index++; if(X < header->projExtents.x) header->projExtents.x = X; if(Z < header->projExtents.y) header->projExtents.y = Z; if(X > header->projExtents.dx) header->projExtents.dx = X; if(Z > header->projExtents.dy) header->projExtents.dy = Z; } else { float X = (float)x; float Z = (float)z; grid[index].x = X; grid[index].z = Z; index++; if(X < header->projExtents.x) header->projExtents.x = X; if(Z < header->projExtents.y) header->projExtents.y = Z; if(X > header->projExtents.dx) header->projExtents.dx = X; if(Z > header->projExtents.dy) header->projExtents.dy = Z; } } zOffset += adfGeoTransform[5]; if(progressDlg) { if(!progressDlg->Update(int((float(m)/header->nRows)*50))) { GDALClose(gdalDataset); if(elevations != NULL) delete[] elevations; return false; } } } if(App::Inst().GetLayerTreeController()->GetIsBlankRaster()) { LayerTreeControllerPtr ltc = App::Inst().GetLayerTreeController(); VectorMapLayerPtr vectorMapLayer =ltc->GetVectorMapLayer(0); VectorMapModelPtr vectorMapModel= vectorMapLayer->GetVectorMapController()->GetVectorMapModel(); header->projExtents.x = vectorMapModel->GetVectorBoundary_MinX(); header->projExtents.dx = vectorMapModel->GetVectorBoundary_MaxX(); header->projExtents.y = vectorMapModel->GetVectorBoundary_MinY(); header->projExtents.dy = vectorMapModel->GetVectorBoundary_MaxY(); } // transform all points into unit grid space float minElevation = std::numeric_limits<float>::max(); float maxElevation = -std::numeric_limits<float>::max(); if(!TransformToGridSpace(grid, header, elevations, bElevationMap, minElevation, maxElevation, progressDlg)) { GDALClose(gdalDataset); if(elevations != NULL) delete[] elevations; return false; } // setup map model mapModel->SetMinElevationGridSpace(minElevation); mapModel->SetMaxElevationGridSpace(maxElevation); mapModel->SetMinElevation(minElevation/header->scaleFactor); mapModel->SetMaxElevation(maxElevation/header->scaleFactor); mapModel->SetElevationMap(bElevationMap); mapModel->SetGrid(grid); // report information in file to user if (!App::Inst().GetLayerTreeController()->GetIsBlankRaster()) MetaDataInfo(gdalDataset, mapController); else MetaDataInfoForBlankRaster(mapController, adfGeoTransform); // build texture that will be mapped onto terrain if(!App::Inst().GetLayerTreeController()->GetIsBlankRaster()){ if(!BuildTerrainTexture(gdalDataset, mapController, progressDlg)) { GDALClose(gdalDataset); if(elevations != NULL) delete[] elevations; return false; } // will free memory allocated to any GDALRasterBand objects GDALClose(gdalDataset); } // will free memory allocated to any GDALRasterBand objects if(elevations != NULL) delete[] elevations; return true; }