Contour lines generation
The generation of contour lines is a crucial step in accurately representing the
terrain features within a mesh. In this project, the ContourConstraint
class
is responsible for implementing the contour lines computation. This class is
defined in contour_constraint.hpp
and implemented in contour_constraint.cpp
.
1. Class definition
The ContourConstraint
class is designed to work with an existing mesh, analyzing
its vertices and edges to generate contour lines at specified intervals of
elevation (z values). Below is the class definition:
class ContourConstraint
{
public:
using mesh_type = Mesh;
using edge_type = mesh_type::edge_type;
using poly_type = Polygon;
using value_type = mesh_type::point_type::value_type;
using cache_type = std::unordered_map<std::string, value_type>;
ContourConstraint(mesh_type const &mesh);
std::unique_ptr<mesh_type> apply(value_type precision);
std::pair<value_type, value_type> getMinMaxZ() const;
poly_type getBorder() const;
private:
cache_type M_cache;
mesh_type const &M_meshref;
poly_type M_border;
std::vector<std::unique_ptr<mesh_type>> computeAllContoursMeshes(value_type interval);
std::unique_ptr<mesh_type> assembleContourMeshes(std::vector<std::unique_ptr<mesh_type>> const &meshes);
std::unique_ptr<mesh_type> triangulateAssembledMesh(mesh_type const &nonTriangulated);
std::unique_ptr<mesh_type> computeContourMesh(value_type z);
void registerZs(mesh_type const &mesh);
void postprocess(mesh_type &mesh);
void restoreHeight(mesh_type &target);
void reset_cache();
value_type findClosestZ(mesh_type::point_type const &vertex);
void registerVertex(mesh_type::point_type const &vertex);
std::string hash_xy(value_type const &x, value_type const &y) const;
decltype(M_cache)::const_iterator getZFromCache(value_type const &x, value_type const &y) const;
};
2. Implementation details
The ContourConstraint
class works by iterating through the mesh’s triangles and
computing where each triangle intersects with the horizontal planes at the specified
contour levels. These intersections form the contour lines.
This process primarily involves the
following steps:
2.1. computeAllContoursMeshes
This function first determines the minimum
and maximum elevation (z
values) present in the mesh using the
getMinMaxZ()
method. It then computes contour lines for each level
within this range based on the specified precision. The main work of
generating contour lines is done by computeContourMesh()
, which finds
intersections of mesh triangles with horizontal planes at the specified
z
levels.
std::vector<std::unique_ptr<ContourConstraint::mesh_type>> ContourConstraint::computeAllContoursMeshes(value_type interval)
{
auto [min, max] = getMinMaxZ();
std::vector<std::unique_ptr<mesh_type>> meshes;
for (auto z = min; z <= max; z += interval)
{
auto msh = computeContourMesh(z);
meshes.push_back(std::move(msh));
}
return meshes;
}
2.2. getMinMaxZ
This function scans through all the nodes of the provided
mesh to find the lowest and highest z
values. These values are then used
to determine the range of elevations at which contour lines will be generated.
std::pair<ContourConstraint::value_type, ContourConstraint::value_type> ContourConstraint::getMinMaxZ() const
{
auto const &points = M_meshref.points();
std::vector<value_type> zs;
zs.reserve(points.size());
std::transform(points.begin(), points.end(), std::back_insert_iterator(zs), [](auto const &it)
{ return it.second->z(); });
auto mimas = std::minmax_element(zs.cbegin(), zs.cend());
value_type min = *(mimas.first);
value_type max = *(mimas.second);
return {min, max};
}
2.3. computeContourMesh
This method is responsable for finding the intersection points between the meshs triangles and a horizontal plane at a specific z level iterating over all the triangles of the mesh. While going through one triangle the method checks for the following cases:
-
The line coincides with the edge of the triangle
-
The line intersects with the triangle
-
One of the vertices of the triangle is at the contour level
The case where all 3 vertices of the triangle are at the contour level is not considered as it represents a flat area.
If the intersection points are found, they are stored as segments.
std::unique_ptr<ContourConstraint::mesh_type> ContourConstraint::computeContourMesh(value_type contourLevel)
{
auto medges = std::make_unique<mesh_type>();
for (const auto &triangle : M_meshref.triangles())
{
std::vector<mesh_type::point_type> localIntersections;
for (int i = 0; i < 3; i++)
{
int j = (i + 1) % 3;
const auto &pt1 = triangle->point(i);
const auto &pt2 = triangle->point(j);
value_type z1 = pt1.z();
value_type z2 = pt2.z();
// CASE 1: Line coincides with edge
if (std::fabs(z1 - contourLevel) < TOLERANCE && std::fabs(z2 - contourLevel) < TOLERANCE)
{
localIntersections.emplace_back(pt1.x(), pt1.y(), pt1.z());
localIntersections.emplace_back(pt2.x(), pt2.y(), pt2.z());
continue;
}
// CASE 2: Intersection with triangle
if ((z1 < contourLevel && z2 > contourLevel) || (z1 > contourLevel && z2 < contourLevel))
{
value_type t = (contourLevel - z1) / (z2 - z1);
value_type x = pt1.x() + t * (pt2.x() - pt1.x());
value_type y = pt1.y() + t * (pt2.y() - pt1.y());
localIntersections.emplace_back(x, y, contourLevel);
}
// CASE 3: One vertex at contour level
if (std::fabs(z1 - contourLevel) < TOLERANCE && std::fabs(z2 - contourLevel) >= TOLERANCE)
{
localIntersections.emplace_back(pt1.x(), pt1.y(), pt1.z());
}
if (std::fabs(z2 - contourLevel) < TOLERANCE && std::fabs(z1 - contourLevel) >= TOLERANCE)
{
localIntersections.emplace_back(pt2.x(), pt2.y(), pt2.z());
}
}
// Store the intersection as a segment if there are exactly two points
if (localIntersections.size() == 2)
{
auto pt1 = std::make_unique<mesh_type::point_type>(localIntersections[0].x(), localIntersections[0].y(), localIntersections[0].z());
auto pt2 = std::make_unique<mesh_type::point_type>(localIntersections[1].x(), localIntersections[1].y(), localIntersections[1].z());
auto pt1b = medges->addPoint(std::move(pt1));
auto pt2b = medges->addPoint(std::move(pt2));
medges->addEdge(std::make_unique<mesh_type::edge_type>(pt1b, pt2b));
}
}
algorithms::mergeDuplicatePoints(*medges);
return medges;
}
The methods assembleContourMeshes
and triangulateAssembledMesh
are used for
combining the computed contour meshes and preparing them for further processing,
but these details will be discussed in the next subsection.
In summary, the ContourConstraint
class effectively generates contour lines
from a given mesh by finding the intersections between the mesh’s triangles and
horizontal planes at specified intervals, creating a series of contour meshes
that represent these intersections.
3. Results
Here are visualizations of the contour lines for the mesh generated with the
LambdaGenerator
using the \(z(x, y) = \sqrt{r^2 - (x - x_0)^2 - (y - y_0)^2}\) function:


Here are visualizations of the contour lines for the mesh generated with the
LambdaGenerator
using the \(z(x, y) = sin(x) + sin(y)\) function:


Here are visualizations of contour lines for the mesh generated with the
GpsGenerator
class for the tiles containing the tile with coordinates
(x, y) = (33809, 23527) at zoom level 16, which includes the
location at longitude 5.7232 and latitude 45.1835, located in Grenoble, France:


All the meshes visualized here were exported in the MSH format, using the ExporterMeshGmsh
class, and were visualized using the Gmsh software.
References
-
[cemosis] Cemosis. Center for Modeling and Simulation in Strasbourg. 2024. (www.cemosis.fr)
-
[irma] IRMA. Institut de recherche mathématique avancée. 2024 (irma.math.unistra.fr)
-
[unistra] University of Strasbourg. 2024. (en.unistra.fr)
-
[numpex] PEPR Numpex. Priority Research Program and Equipment for Numerical Exascale computing. 2024. (numpex.org/numpex-program)
-
[exama] Exa-MA. Methods and Algorithms for Exascale. 2024. (numpex.org/exama-methods-and-algorithms-for-exascale)
-
[ktirio] Ktirio Urban Building application. Prud’homme Christophe. Expanding horizons: Ktirio and the urban building vision in Hidalgo2. October 2023. 2024. (github.com/orgs/feelpp/discussions/2167)
-
[hidalgo2] CoE Hidalgo2. HPC and big data technologies for global challenges. 2024. (www.hidalgo2.eu/about)
-
[ubm] CoE Hidalgo2. The Urban Building Model 2024. (www.hidalgo2.eu/urban-building-model)
-
[inria] Inria. National Institute for Research in Digital Science and Technology. 2024. (www.inria.fr/en)
-
[eea1] European Environment Agency. Greenhouse gas emissions from energy use in buildings in Europe. Octber 2023. 2024. (www.eea.europa.eu/en/analysis/indicators/greenhouse-gas-emissions-from-energy?activeAccordion=546a7c35-9188-4d23-94ee-005d97c26f2b)
-
[eea2] European Environment Agency. Accelerating the energy efficiency renovation of residential buildings — a behavioural approach. June 2023. 2024. (www.eea.europa.eu/publications/accelerating-the-energy-efficiency)
-
[ec1] European Commission. 2050 long-term strategy. 2024. (climate.ec.europa.eu/eu-action/climate-strategies-targets/2050-long-term-strategy_en#:~:text=Striving%20to%20become%20the%20world’s%20first%20climate%2Dneutral%20continent%20by%202050.&text=The%20EU%20aims%20to%20be,to%20the%20European%20Climate%20Law%20.)
-
[ec2] European Commission. The European Green Deal. 2024. (commission.europa.eu/strategy-and-policy/priorities-2019-2024/european-green-deal_en)
-
[ec3] European Commission. European Climate Law. 2024. (climate.ec.europa.eu/eu-action/european-climate-law_en)
-
[ubp] Urban Building Pilot. Prud’homme Christophe. CoE Hidalgo2 Urban Building Pilot at NumPEx workshop on Discretization@Exascale. November 2023. 2024. (github.com/orgs/feelpp/discussions/2188)
-
[eurohpc] EuroHPC JU. The European High Performance Computing Joint Undertaking. 2024. (eurohpc-ju.europa.eu/index_en)
-
[mapbox] Wikipedia contributors. Mapbox. Wikipedia, The Free Encyclopedia. August 2024. 2024. (en.wikipedia.org/wiki/Mapbox)
-
[mapbox-terrain-rgb] Mapbox. Mapbox Terrain-RGB v1. Mapbox Documentation. 2024. (docs.mapbox.com/data/tilesets/reference/mapbox-terrain-rgb-v1)
-
[mapbox-raster-tiles] Mapbox. Mapbox Raster Tiles API. Mapbox Documentation. 2024. (docs.mapbox.com/api/maps/raster-tiles)
-
[json-nlohmann] Lohmann, Niels. JSON for Modern C++. 2024. (json.nlohmann.me)
-
[curl] Stenberg, Daniel. cURL: A Command Line Tool and Library for Transferring Data with URLs. 2024. (curl.se)
-
[libpng] libpng: The Official PNG Reference Library. 2024. (www.libpng.org/pub/png/libpng.html)
-
[cgal] CGAL: The Computational Geometry Algorithms Library. 2024. (www.cgal.org)
-
[stl] STL (STereoLithography) File Format Specification. 2024. (www.fabbers.com/tech/STL_Format)
-
[gmsh] Geuzaine Christophe, and Jean-François Remacle. Gmsh: A 3D Finite Element Mesh Generator with Built-in Pre- and Post-Processing Facilities. Version 4.10, 2024. (gmsh.info)
-
[msh] MSH: The Gmsh Mesh File Format. 2024. (gmsh.info/doc/texinfo/gmsh.html#MSH-file-format)
-
[img:lat-lon] Latitude and Longitude. BBC Bitesize. 2024. (www.bbc.co.uk/bitesize/guides/ztqtyrd/revision/1)
-
[world-geodetic-system] Wikipedia contributors. World Geodetic System. Wikipedia, The Free Encyclopedia. 2024. (en.wikipedia.org/wiki/World_Geodetic_System)
-
[marcator-projection] Wikipedia contributors. Mercator projection. Wikipedia, The Free Encyclopedia. 2024. (en.wikipedia.org/wiki/Mercator_projection)
-
[web-marcator-projection] Wikipedia contributors. Web Mercator projection. Wikipedia, The Free Encyclopedia. 2024. (en.wikipedia.org/wiki/Web_Mercator_projection)
-
[cdt1] Wikipedia contributors. Constrained Delaunay triangulation. Wikipedia, The Free Encyclopedia. 2024. (en.wikipedia.org/wiki/Constrained_Delaunay_triangulation)
-
[cdt2] L. Paul Chew. Constrained Delaunay Triangulations. Dartmouth College. 1987. 2024. (www.cs.jhu.edu/~misha/Spring16/Chew87.pdf)
-
[dt] Wikipedia contributors. Delaunay triangulation. Wikipedia, The Free Encyclopedia. 2024. (en.wikipedia.org/wiki/Voronoi_diagram)
-
[voronoi] Wikipedia contributors. Voronoi diagram. Wikipedia, The Free Encyclopedia. 2024. ()
-
[tiled-web-map] Wikipedia contributors. Tiled web map. Wikipedia, The Free Encyclopedia. 2024. (en.wikipedia.org/wiki/Tiled_web_map)
-
[img:tiles-coordinates] XYZ Tiles coordinate numbers. Wikipedia, The Free Encyclopedia. 2024. (en.wikipedia.org/wiki/File:XYZ_Tiles.png)
-
[img:tiled-web-map] Tiled Web Map. Wikipedia, The Free Encyclopedia. 2024. (en.wikipedia.org/wiki/Tiled_web_map#/media/File:Tiled_web_map_Stevage.png)
-
[img:dt] Delaunay triangulation. Wikipedia, The Free Encyclopedia. 2024. (en.wikipedia.org/wiki/Delaunay_triangulation#/media/File:Delaunay_circumcircles_vectorial.svg)
-
[img:dt-centers] Delaunay triangulation with all the circumcircles and their centers. Wikipedia, The Free Encyclopedia. 2024. (en.wikipedia.org/wiki/Delaunay_triangulation#/media/File:Delaunay_circumcircles_centers.svg)
-
[img:dt-voronoi] Delaunay triangulation and its Voronoi diagram. Wikipedia, The Free Encyclopedia. 2024. (en.wikipedia.org/wiki/Delaunay_triangulation#/media/File:Delaunay_Voronoi.svg)
-
[img:constrained-mesh] Pierre Alliez, Senior Researcher and Team Leader at Inria, Image provided during personal communication. 2024.
-
[img:constrained-refined-mesh] Pierre Alliez, Senior Researcher and Team Leader at Inria, Image provided during personal communication. 2024.