Skip to content
Snippets Groups Projects
Forked from ogs / ogs
26132 commits behind the upstream repository.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
Raster.cpp 5.54 KiB
/**
 * Copyright (c) 2012, OpenGeoSys Community (http://www.opengeosys.org)
 *            Distributed under a Modified BSD License.
 *              See accompanying file LICENSE.txt or
 *              http://www.opengeosys.org/project/license
 *
 *
 * \file Raster.cpp
 *
 * Created on 2011-09-07 by Thomas Fischer
 */

#include <fstream>

#include "Raster.h"

// BaseLib
#include "StringTools.h"

namespace GeoLib {

Raster::Raster(std::size_t n_cols, std::size_t n_rows, double xllcorner, double yllcorner,
				double cell_size, double no_data_val, double* raster_data) :
	_n_cols(n_cols), _n_rows(n_rows), _ll_pnt(xllcorner, yllcorner, 0.0),
	_cell_size(cell_size), _no_data_val(no_data_val), _raster_data(raster_data)
{}

void Raster::refineRaster(std::size_t n_cols, std::size_t n_rows)
{
	if (n_rows <= _n_rows || n_cols <= _n_cols) return;

	std::size_t row_blk_size(n_rows / _n_rows);
	std::size_t col_blk_size(n_cols / _n_cols);
	double *new_raster_data(new double[n_rows*n_cols]);

	for (std::size_t row(0); row<_n_rows; row++) {
		for (std::size_t col(0); col<_n_cols; col++) {
			for (std::size_t new_row(row*row_blk_size); new_row<(row+1)*row_blk_size; new_row++) {
				for (std::size_t new_col(col*row_blk_size); new_col<(col+1)*col_blk_size; new_col++) {
					new_raster_data[new_row*n_cols+new_col] = _raster_data[row*_n_cols+col];
				}
			}
		}
	}

	std::swap(_raster_data, new_raster_data);
	delete [] new_raster_data;
}

Raster::~Raster()
{
	if (_raster_data != NULL)
		delete [] _raster_data;
}

void Raster::setCellSize(double cell_size)
{
	_cell_size = cell_size;
}

void Raster::setNoDataVal (double no_data_val)
{
	_no_data_val = no_data_val;
}

void Raster::writeRasterAsASC(std::ostream &os) const
{
	// write header
	os << "ncols " << _n_rows << std::endl;
	os << "nrows " << _n_cols << std::endl;
	os << "xllcorner " << _ll_pnt[0] << std::endl;
	os << "yllcorner " << _ll_pnt[1] << std::endl;
	os << "cellsize " <<  _cell_size << std::endl;
	os << "NODATA_value " << _no_data_val << std::endl;

	// write data
	for (unsigned row(0); row<_n_rows; row++) {
		for (unsigned col(0); col<_n_cols; col++) {
			os << _raster_data[(_n_rows-row-1)*_n_cols+col] << " ";
		}
		os << std::endl;
	}
}

Raster* Raster::getRasterFromSurface(Surface const& sfc, double cell_size, double no_data_val)
{
	Point const& ll (sfc.getAABB().getMinPoint());
	Point const& ur (sfc.getAABB().getMaxPoint());

	std::size_t n_cols = static_cast<size_t>(fabs(ur[0]-ll[0]) / cell_size)+1;
	std::size_t n_rows = static_cast<size_t>(fabs(ur[1]-ll[1]) / cell_size)+1;
	const size_t n_triangles (sfc.getNTriangles());
	double *z_vals (new double[n_cols*n_rows]);
	if (!z_vals) {
		std::cout << "DEBUG: CreateRaster::getRaster " << n_cols << " x " << n_rows << " to big" << std::endl;
		return NULL;
	}
	size_t k(0);

	for (size_t r(0); r < n_cols; r++) {
		for (size_t c(0); c < n_rows; c++) {
			const double test_pnt[3] = { ll[0] + r*cell_size, ll[1] + c*cell_size, 0};
			for (k=0; k<n_triangles; k++) {
				if (sfc[k]->containsPoint2D(test_pnt)) {
					Triangle const * const tri (sfc[k]);
					// compute coefficients c0, c1, c2 for the plane f(x,y) = c0 x + c1 y + c2
					double coeff[3] = {0.0, 0.0, 0.0};
					GeoLib::getPlaneCoefficients(*tri, coeff);
					z_vals[r*n_rows+c] = coeff[0] * test_pnt[0] + coeff[1] * test_pnt[1] + coeff[2];
					break;
				}
			}
			if (k==n_triangles) {
				z_vals[r*n_rows+c] = no_data_val;
			}
		}
	}

	return new Raster(n_cols, n_rows, ll[0], ll[1], cell_size, -9999, z_vals);
}

Raster* Raster::getRasterFromASCFile(std::string const& fname)
{
	std::ifstream in(fname.c_str());

	if (!in.is_open()) {
		std::cout << "Raster::getRasterFromASCFile() - Could not open file..." << fname << std::endl;
		return NULL;
	}

	// header information
	std::size_t n_cols(0), n_rows(0);
	double xllcorner(0.0), yllcorner(0.0), cell_size(0.0), no_data_val(-9999);

	if (readASCHeader(in, n_cols, n_rows, xllcorner, yllcorner, cell_size, no_data_val)) {
		double* values = new double[n_cols*n_rows];
		std::string s;
		// read the data into the double-array
		for (size_t j(0); j < n_rows; ++j) {
			size_t idx ((n_rows - j - 1) * n_cols);
			for (size_t i(0); i < n_cols; ++i) {
				in >> s;
				values[idx+i] = strtod(BaseLib::replaceString(",", ".", s).c_str(),0);

			}
		}
		in.close();
		return new Raster(n_cols, n_rows, xllcorner, yllcorner,
						cell_size, no_data_val, values);
	} else {
		std::cout << "Raster::getRasterFromASCFile() - could not read header of file " << fname << std::endl;
		return NULL;
	}
}

bool Raster::readASCHeader(std::ifstream &in, size_t &n_cols, std::size_t &n_rows,
				double &xllcorner, double &yllcorner, double &cell_size, double &no_data_val)
{
	std::string tag, value;

	in >> tag;
	if (tag.compare("ncols") == 0) {
		in >> value;
		n_cols = atoi(value.c_str());
	} else return false;

	in >> tag;
	if (tag.compare("nrows") == 0) {
		in >> value;
		n_rows = atoi(value.c_str());
	} else return false;

	in >> tag;
	if (tag.compare("xllcorner") == 0) {
		in >> value;
		xllcorner = strtod(BaseLib::replaceString(",", ".", value).c_str(), 0);
	} else return false;

	in >> tag;
	if (tag.compare("yllcorner") == 0) {
		in >> value;
		yllcorner = strtod(BaseLib::replaceString(",", ".", value).c_str(), 0);
	} else return false;

	in >> tag;
	if (tag.compare("cellsize") == 0) {
		in >> value;
		cell_size = strtod(BaseLib::replaceString(",", ".", value).c_str(), 0);
	} else return false;

	in >> tag;
	if (tag.compare("NODATA_value") == 0) {
		in >> value;
		no_data_val = strtod(BaseLib::replaceString(",", ".", value).c_str(), 0);
	} else return false;

	return true;
}

} // end namespace GeoLib