diff --git a/Applications/Utils/CMakeLists.txt b/Applications/Utils/CMakeLists.txt index 333890eabce7f2c1a046f73a3e935fb61d9c0323..56386eb5b5ce4ee0bec70545e65e40f6868e471d 100644 --- a/Applications/Utils/CMakeLists.txt +++ b/Applications/Utils/CMakeLists.txt @@ -1,4 +1,5 @@ ADD_SUBDIRECTORY( FileConverter ) +ADD_SUBDIRECTORY( GeoTools ) ADD_SUBDIRECTORY( MeshEdit ) ADD_SUBDIRECTORY( SimpleMeshCreation ) diff --git a/Applications/Utils/GeoTools/CMakeLists.txt b/Applications/Utils/GeoTools/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..3420b9ddb390d6bdd78b7e709e289fd8f4109503 --- /dev/null +++ b/Applications/Utils/GeoTools/CMakeLists.txt @@ -0,0 +1,21 @@ + +INCLUDE_DIRECTORIES( + ${CMAKE_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/BaseLib + ${CMAKE_SOURCE_DIR}/GeoLib + ${CMAKE_SOURCE_DIR}/FileIO + ${CMAKE_SOURCE_DIR}/MathLib +) + +IF(QT4_FOUND) +ADD_EXECUTABLE( TriangulatePolyline TriangulatePolyline.cpp ) +TARGET_LINK_LIBRARIES( TriangulatePolyline + BaseLib + FileIO + MathLib + ${QT_LIBRARIES} +) +ENDIF() # QT4_FOUND + +SET_TARGET_PROPERTIES(TriangulatePolyline PROPERTIES FOLDER Utilities) + diff --git a/Applications/Utils/GeoTools/TriangulatePolyline.cpp b/Applications/Utils/GeoTools/TriangulatePolyline.cpp new file mode 100644 index 0000000000000000000000000000000000000000..824b4cfec6c439f807150c5da37706b4d524f87d --- /dev/null +++ b/Applications/Utils/GeoTools/TriangulatePolyline.cpp @@ -0,0 +1,132 @@ +/** + * \file TriangulatePolyline.h + * \author Karsten Rink + * \date 2015-02-02 + * \brief Utility for triangulating polylines. + * + * Copyright (c) 2012-2015, OpenGeoSys Community (http://www.opengeosys.org) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.org/LICENSE.txt + * + */ + +#include <string> + +#include "logog/include/logog.hpp" +#include "tclap/CmdLine.h" + +#include "BaseLib/BuildInfo.h" +#include "BaseLib/LogogSimpleFormatter.h" +#include "FileIO/XmlIO/Qt/XmlGmlInterface.h" +#include "GeoLib/AnalyticalGeometry.h" +#include "GeoLib/GEOObjects.h" +#include "GeoLib/Polyline.h" + +#include <QApplication> + + +std::string output_question() +{ + WARN ("Given polyline is not closed. Close polyline now?"); + WARN ("Enter (Y)es for closing the line or (N)o for abort and press ENTER."); + std::string input; + std::cin >> input; + return input; +} + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv, false); + + LOGOG_INITIALIZE(); + BaseLib::LogogSimpleFormatter *custom_format (new BaseLib::LogogSimpleFormatter); + logog::Cout *logogCout(new logog::Cout); + logogCout->SetFormatter(*custom_format); + + TCLAP::CmdLine cmd("Triangulates the specified polyline in the given geometry file.", ' ', BaseLib::BuildInfo::git_describe); + TCLAP::ValueArg<std::string> input_arg("i", "input", "GML input file (*.gml)", true, "", "string"); + TCLAP::ValueArg<std::string> output_arg("o", "output", "GML output file (*.gml)", true, "", "string"); + TCLAP::ValueArg<std::string> name_arg("n", "name", "Name of polyline in given file", true, "", "string"); + cmd.add( input_arg ); + cmd.add( name_arg ); + cmd.add( output_arg ); + cmd.parse( argc, argv ); + + std::string const& file_name(input_arg.getValue()); + std::string const& polyline_name(name_arg.getValue()); + + GeoLib::GEOObjects geo_objects; + FileIO::XmlGmlInterface xml(geo_objects); + if (!xml.readFile(file_name)) + { + ERR ("Failed to load geometry file."); + return 1; + } + + std::vector<std::string> geo_names; + geo_objects.getGeometryNames(geo_names); + GeoLib::PolylineVec const*const line_vec (geo_objects.getPolylineVecObj(geo_names[0])); + GeoLib::Polyline* line = const_cast<GeoLib::Polyline*>(line_vec->getElementByName(polyline_name)); + + // check if line exists + if (line == nullptr) + { + ERR ("No polyline found with name \"%s\". Aborting...", polyline_name.c_str()); + return 1; + } + + // check if polyline can be triangulated (i.e. closed + coplanar) + if (!line->isCoplanar()) + { + ERR ("Polyline is not coplanar, no unambiguous triangulation possible. Aborting..."); + return 1; + } + + if (!line->isClosed()) + { + std::string input (""); + while (input != "y" && input != "Y" && input != "n" && input != "N") + input = output_question(); + + if (input == "y" || input == "Y") + { + line->closePolyline(); + INFO ("Polyline closed."); + } + else + return 1; + } + + // create surface + INFO ("Triangulating surface..."); + std::vector<GeoLib::Surface*> *new_sfc = new std::vector<GeoLib::Surface*>; + new_sfc->push_back(GeoLib::Surface::createSurface(*line)); + + GeoLib::SurfaceVec* sfc_vec (geo_objects.getSurfaceVecObj(geo_names[0])); + if (sfc_vec == nullptr) + geo_objects.addSurfaceVec(new_sfc, geo_names[0]); + else + geo_objects.appendSurfaceVec(*new_sfc, geo_names[0]); + std::size_t const sfc_id = geo_objects.getSurfaceVec(geo_names[0])->size() - 1; + std::string const surface_name (polyline_name + "_surface"); + for (std::size_t i=1;;++i) + { + std::string const new_surface_name = (i>1) ? (surface_name + std::to_string(i)) : surface_name; + if (sfc_vec->getElementByName(new_surface_name) == nullptr) + { + sfc_vec->setNameForElement(sfc_id, new_surface_name); + break; + } + } + + // write new file + xml.setNameForExport(geo_names[0]); + xml.writeToFile(output_arg.getValue()); + INFO ("...done."); + + delete logogCout; + delete custom_format; + LOGOG_SHUTDOWN(); + return 0; +} diff --git a/GeoLib/Polyline.cpp b/GeoLib/Polyline.cpp index b3a8af26b9ab02e2284df84ba1c2c99891f5e156..56688a179abd82f2fe11c1dab7b14994ff6e4456 100644 --- a/GeoLib/Polyline.cpp +++ b/GeoLib/Polyline.cpp @@ -193,6 +193,26 @@ bool Polyline::isClosed() const return false; } +bool Polyline::isCoplanar() const +{ + std::size_t const n_points (_ply_pnt_ids.size()); + if (n_points < 4) + return true; + + GeoLib::Point const& p0 (*this->getPoint(0)); + GeoLib::Point const& p1 (*this->getPoint(1)); + GeoLib::Point const& p2 (*this->getPoint(2)); + for (std::size_t i=3; i<n_points; ++i) + { + if (!GeoLib::isCoplanar(p0, p1, p2, *this->getPoint(i))) + { + DBUG ("Point %d is not coplanar to the first three points of the line.", i); + return false; + } + } + return true; +} + bool Polyline::isPointIDInPolyline(std::size_t pnt_id) const { return std::find(_ply_pnt_ids.begin(), _ply_pnt_ids.end(), pnt_id) != _ply_pnt_ids.end(); diff --git a/GeoLib/Polyline.h b/GeoLib/Polyline.h index 1f5e5bf8d52ec36eaa22d70fa5fece01429b693e..6a90c156bddea9dd8fa9945f15a999f977aa74ec 100644 --- a/GeoLib/Polyline.h +++ b/GeoLib/Polyline.h @@ -112,6 +112,9 @@ public: /** returns true if the polyline is closed */ bool isClosed() const; + /** returns true if the polyline is coplanar */ + bool isCoplanar() const; + /** * Method tests if the given id of a point (within the vector of points the polyline is * based on) is inside the polyline.