OGS
Mesh2Raster.cpp File Reference

Detailed Description

Definition in file Mesh2Raster.cpp.

#include <tclap/CmdLine.h>
#include <fstream>
#include <memory>
#include <string>
#include "GeoLib/AABB.h"
#include "InfoLib/GitInfo.h"
#include "MeshLib/IO/readMeshFromFile.h"
#include "MeshLib/Mesh.h"
#include "MeshLib/MeshEditing/ProjectPointOnMesh.h"
#include "MeshLib/MeshSearch/MeshElementGrid.h"
#include "MeshLib/Node.h"
Include dependency graph for Mesh2Raster.cpp:

Go to the source code of this file.

Functions

int main (int argc, char *argv[])
 

Function Documentation

◆ main()

int main ( int  argc,
char *  argv[] 
)

Definition at line 24 of file Mesh2Raster.cpp.

25 {
26  TCLAP::CmdLine cmd(
27  "Mesh to raster converter.\n"
28  "Rasterises a 2D mesh, pixel values are set to the elevation of a "
29  "regular grid superimposed on the mesh. If no mesh element is located "
30  "beneath a pixel it is set to NODATA.\n\n"
31  "OpenGeoSys-6 software, version " +
33  ".\n"
34  "Copyright (c) 2012-2021, OpenGeoSys Community "
35  "(http://www.opengeosys.org)",
37  TCLAP::ValueArg<double> cell_arg("c", "cellsize",
38  "edge length of raster cells in result",
39  false, 1, "real");
40  cmd.add(cell_arg);
41  TCLAP::ValueArg<std::string> output_arg(
42  "o", "output-file", "Raster output file (*.asc)", true, "", "string");
43  cmd.add(output_arg);
44  TCLAP::ValueArg<std::string> input_arg("i", "input-file",
45  "Mesh input file (*.vtu, *.msh)",
46  true, "", "string");
47  cmd.add(input_arg);
48  cmd.parse(argc, argv);
49 
50  INFO("Rasterising mesh...");
51  std::unique_ptr<MeshLib::Mesh> const mesh(
52  MeshLib::IO::readMeshFromFile(input_arg.getValue()));
53  if (mesh == nullptr)
54  {
55  ERR("Error reading mesh file.");
56  return 1;
57  }
58  if (mesh->getDimension() != 2)
59  {
60  ERR("The programme requires a mesh containing two-dimensional elements "
61  "(i.e. triangles or quadrilaterals.");
62  return 2;
63  }
64 
65  double const cellsize =
66  (cell_arg.isSet()) ? cell_arg.getValue() : mesh->getMinEdgeLength();
67  INFO("Cellsize set to {:f}", cellsize);
68 
69  std::vector<MeshLib::Node*> const& nodes_vec(mesh->getNodes());
70  GeoLib::AABB const bounding_box(nodes_vec.begin(), nodes_vec.end());
71  auto const& min(bounding_box.getMinPoint());
72  auto const& max(bounding_box.getMaxPoint());
73  auto const n_cols =
74  static_cast<std::size_t>(std::ceil((max[0] - min[0]) / cellsize));
75  auto const n_rows =
76  static_cast<std::size_t>(std::ceil((max[1] - min[1]) / cellsize));
77  double const half_cell = cellsize / 2.0;
78 
79  // raster header
80  std::ofstream out(output_arg.getValue());
81  out << "ncols " << n_cols + 1 << "\n";
82  out << "nrows " << n_rows + 1 << "\n";
83  out << std::fixed << "xllcorner " << (min[0] - half_cell) << "\n";
84  out << std::fixed << "yllcorner " << (min[1] - half_cell) << "\n";
85  out << std::fixed << "cellsize " << cellsize << "\n";
86  out << "NODATA_value "
87  << "-9999\n";
88  INFO("Writing raster with {:d} x {:d} pixels.", n_cols, n_rows);
89 
90  MeshLib::MeshElementGrid const grid(*mesh);
91  double const max_edge(mesh->getMaxEdgeLength() + cellsize);
92 
93  for (std::size_t row = 0; row <= n_rows; ++row)
94  {
95  double const y = max[1] - row * cellsize;
96  for (std::size_t column = 0; column <= n_cols; ++column)
97  {
98  // pixel values
99  double const x = min[0] + column * cellsize;
100  MeshLib::Node const node(x, y, 0);
101  MathLib::Point3d min_vol{{x - max_edge, y - max_edge,
102  -std::numeric_limits<double>::max()}};
103  MathLib::Point3d max_vol{{x + max_edge, y + max_edge,
104  std::numeric_limits<double>::max()}};
105  std::vector<const MeshLib::Element*> const& elems =
106  grid.getElementsInVolume(min_vol, max_vol);
107  auto const* element =
109  // centre of the pixel is located within a mesh element
110  if (element != nullptr)
111  {
112  out << MeshLib::ProjectPointOnMesh::getElevation(*element, node)
113  << " ";
114  }
115  else
116  {
117  std::array<double, 4> const x_off{
118  {-half_cell, half_cell, -half_cell, half_cell}};
119  std::array<double, 4> const y_off{
120  {-half_cell, -half_cell, half_cell, half_cell}};
121  double sum(0);
122  std::size_t nonzero_count(0);
123  // test all of the pixel's corners if there are any within an
124  // element
125  for (std::size_t i = 0; i < 4; ++i)
126  {
127  MeshLib::Node const corner_node(x + x_off[i], y + y_off[i],
128  0);
129  auto const* corner_element =
131  elems, corner_node);
132  if (corner_element != nullptr)
133  {
135  *corner_element, corner_node);
136  nonzero_count++;
137  }
138  }
139  if (nonzero_count > 0)
140  {
141  // calculate pixel value as average of corner values
142  out << sum / nonzero_count << " ";
143  }
144  else
145  {
146  // if none of the corners give a value, set pixel to NODATA
147  out << "-9999 ";
148  }
149  }
150  }
151  out << "\n";
152  }
153  out.close();
154  INFO("Result written to {:s}", output_arg.getValue());
155  return 0;
156 }
void INFO(char const *fmt, Args const &... args)
Definition: Logging.h:32
void ERR(char const *fmt, Args const &... args)
Definition: Logging.h:42
Class AABB is an axis aligned bounding box around a given set of geometric points of (template) type ...
Definition: AABB.h:49
GITINFOLIB_EXPORT const std::string ogs_version
MeshLib::Mesh * readMeshFromFile(const std::string &file_name)
double getElevation(Element const &element, Node const &node)
Element const * getProjectedElement(std::vector< const Element * > const &elements, Node const &node)

References ERR(), MeshLib::MeshElementGrid::getElementsInVolume(), MeshLib::ProjectPointOnMesh::getElevation(), GeoLib::AABB::getMaxPoint(), GeoLib::AABB::getMinPoint(), MeshLib::ProjectPointOnMesh::getProjectedElement(), INFO(), GitInfoLib::GitInfo::ogs_version, and MeshLib::IO::readMeshFromFile().