Ejemplo n.º 1
0
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;
}