OGS
RemoveUnusedPoints.cpp
Go to the documentation of this file.
1
11#include <tclap/CmdLine.h>
12
13#include <algorithm>
14#include <memory>
15#include <range/v3/algorithm/for_each.hpp>
16#include <range/v3/range/conversion.hpp>
17#include <range/v3/view/filter.hpp>
18#include <range/v3/view/map.hpp>
19#include <range/v3/view/transform.hpp>
20#include <range/v3/view/zip.hpp>
21#include <vector>
22
23#include "BaseLib/Logging.h"
24#include "BaseLib/MPI.h"
26#include "GeoLib/GEOObjects.h"
28#include "GeoLib/Point.h"
29#include "GeoLib/Polyline.h"
30#include "GeoLib/Surface.h"
31#include "GeoLib/Triangle.h"
32#include "InfoLib/GitInfo.h"
33
34auto createMapping(std::vector<bool> const& used_points)
35{
36 auto getCountOrMax = [cnt = 0u](bool used) mutable
37 { return used ? cnt++ : std::numeric_limits<std::size_t>::max(); };
38
39 return used_points | ranges::views::transform(getCountOrMax) |
40 ranges::to<std::vector>;
41}
42
43int main(int argc, char* argv[])
44{
45 TCLAP::CmdLine cmd(
46 "Remove points from geometry that are not used in any polyline nor "
47 "surface. Attention: Names of points are not handled correctly in "
48 "every case.\n\n"
49 "OpenGeoSys-6 software, version " +
51 ".\n"
52 "Copyright (c) 2012-2025, OpenGeoSys Community "
53 "(http://www.opengeosys.org)",
55
56 TCLAP::ValueArg<std::string> geo_output_arg(
57 "o", "output", "Output (.gml) geometry", true, "", "OUTPUT_FILE");
58 cmd.add(geo_output_arg);
59 TCLAP::ValueArg<std::string> geo_input_arg(
60 "i", "input", "Input (.gml) geometry", true, "conceptual model",
61 "INPUT_FILE");
62 cmd.add(geo_input_arg);
63 auto log_level_arg = BaseLib::makeLogLevelArg();
64 cmd.add(log_level_arg);
65 cmd.parse(argc, argv);
66
67 BaseLib::MPI::Setup mpi_setup(argc, argv);
68 BaseLib::initOGSLogger(log_level_arg.getValue());
69
70 GeoLib::GEOObjects geometry;
72 try
73 {
74 if (!xml.readFile(geo_input_arg.getValue()))
75 {
76 ERR("Failed to read file `{:s}'.", geo_input_arg.getValue());
77 return EXIT_FAILURE;
78 }
79 }
80 catch (std::runtime_error const& err)
81 {
82 ERR("Failed to read file `{:s}'.", geo_input_arg.getValue());
83 ERR("{:s}", err.what());
84 return EXIT_FAILURE;
85 }
86
87 auto const geo_name = geometry.getGeometryNames()[0];
88 auto* points = const_cast<std::vector<GeoLib::Point*>*>(
89 geometry.getPointVec(geo_name));
90 auto* polylines = geometry.getPolylineVec(geo_name);
91 auto* surfaces = geometry.getSurfaceVec(geo_name);
92
93 // mark used points
94 auto used_points = std::vector<bool>(points->size(), false);
95
96 auto mark = [&](auto const* const object)
97 { GeoLib::markUsedPoints(*object, used_points); };
98
99 if (polylines)
100 {
101 ranges::for_each(*polylines, mark);
102 }
103 if (surfaces)
104 {
105 ranges::for_each(*surfaces, mark);
106 }
107
108 auto const number_of_used_points = static_cast<std::size_t>(
109 std::count(used_points.begin(), used_points.end(), true));
110 if (number_of_used_points == 0)
111 {
112 INFO(
113 "Geometry consists of points only. A new geometry file won't "
114 "be written.");
115 return EXIT_SUCCESS;
116 }
117 INFO(
118 "{} points in this geometry file are not used in any polyline or "
119 "surface",
120 points->size() - number_of_used_points);
121
122 auto const mapping = createMapping(used_points);
123
124 auto reset = [&mapping](auto* object)
125 { GeoLib::resetPointIDs(*object, mapping); };
126
127 // reset point ids is polylines
128 if (polylines)
129 {
130 ranges::for_each(*polylines, reset);
131 }
132 // reset point ids is surfaces
133 if (surfaces)
134 {
135 ranges::for_each(*surfaces, reset);
136 }
137
138 std::stringstream unused_points_info;
139 unused_points_info << std::fixed;
140
141 // cleanup unused points
142 for (GeoLib::Point*& point :
143 ranges::views::zip(*points, used_points) |
144 ranges::views::filter([](auto&& pair) { return !pair.second; }) |
145 ranges::views::keys)
146 {
147 unused_points_info << point->getID() << " " << *point << '\n';
148 delete point;
149 point = nullptr;
150 }
151
152 std::erase(*points, nullptr);
153 if (!unused_points_info.str().empty())
154 {
155 INFO("Removed the following points:\n{}", unused_points_info.str());
156 }
157
158 WARN("Names of points are not handled correctly in every case.");
159
160 xml.export_name = geometry.getGeometryNames()[0];
161 BaseLib::IO::writeStringToFile(xml.writeToString(),
162 geo_output_arg.getValue());
163
164 return EXIT_SUCCESS;
165}
Definition of the BoostXmlGmlInterface class.
Definition of the GEOObjects class.
Definition of the Point class.
Git information.
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:36
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:48
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:42
Definition of the PolyLine class.
int main(int argc, char *argv[])
auto createMapping(std::vector< bool > const &used_points)
Container class for geometric objects.
Definition GEOObjects.h:57
std::vector< std::string > getGeometryNames() const
Returns the names of all geometry vectors.
const std::vector< Point * > * getPointVec(const std::string &name) const
const std::vector< Surface * > * getSurfaceVec(const std::string &name) const
Returns the surface vector with the given name as a const.
const std::vector< Polyline * > * getPolylineVec(const std::string &name) const
int writeStringToFile(std::string_view content, std::filesystem::path const &file_path)
Definition Writer.cpp:45
TCLAP::ValueArg< std::string > makeLogLevelArg()
void initOGSLogger(std::string const &log_level)
Definition Logging.cpp:64
void markUsedPoints(Polyline const &polyline, std::vector< bool > &used_points)
Resets the point IDs of the polyline corresponding to the mapping.
Definition Polyline.cpp:490
void resetPointIDs(Polyline &polyline, std::vector< std::size_t > const &mapping)
Resets the point IDs of the polyline corresponding to the mapping.
Definition Polyline.cpp:475
GITINFOLIB_EXPORT const std::string ogs_version