diff --git a/Applications/DataExplorer/DataView/GeoTreeView.cpp b/Applications/DataExplorer/DataView/GeoTreeView.cpp index 7fe5c9967ac7eb6ba56acd0e2564d65f0c94c121..d2f6b4e6daed4ad0f9f2ecdf3207ab0c49e7c474 100644 --- a/Applications/DataExplorer/DataView/GeoTreeView.cpp +++ b/Applications/DataExplorer/DataView/GeoTreeView.cpp @@ -125,6 +125,13 @@ void GeoTreeView::contextMenuEvent( QContextMenuEvent* event ) // The current index is a list of points/polylines/surfaces if (list != nullptr) { + QAction* convertToStationAction(nullptr); + if (list->getType() == GeoLib::GEOTYPE::POINT) + { + convertToStationAction = menu.addAction("Convert to Stations"); + connect(convertToStationAction, SIGNAL(triggered()), + this, SLOT(convertPointsToStations())); + } QAction* connectPlyAction(nullptr); if (list->getType() == GeoLib::GEOTYPE::POLYLINE) { @@ -183,6 +190,14 @@ void GeoTreeView::contextMenuEvent( QContextMenuEvent* event ) menu.exec(event->globalPos()); } +void GeoTreeView::convertPointsToStations() +{ + TreeItem const*const item = static_cast<GeoTreeModel*>(model()) + ->getItem(this->selectionModel()->currentIndex()) + ->parentItem(); + emit requestPointToStationConversion(item->data(0).toString().toStdString()); +} + void GeoTreeView::connectPolylines() { TreeItem* item = static_cast<GeoTreeModel*>(model())->getItem( diff --git a/Applications/DataExplorer/DataView/GeoTreeView.h b/Applications/DataExplorer/DataView/GeoTreeView.h index 03e601f484a0c03f263b42a1b0618dcfcdaa10d5..5b2d2df63f82e9664db26d1a2d3b9722e43f0dce 100644 --- a/Applications/DataExplorer/DataView/GeoTreeView.h +++ b/Applications/DataExplorer/DataView/GeoTreeView.h @@ -58,6 +58,7 @@ private slots: void on_Clicked(QModelIndex idx); /// Calls a LineEditDialog. void connectPolylines(); + void convertPointsToStations(); void mapGeometry(); /// Calls a SetNameDialog. void setNameForElement(); @@ -84,5 +85,6 @@ signals: void requestCondSetupDialog(const std::string&, const GeoLib::GEOTYPE, const std::size_t, bool on_points); void requestLineEditDialog(const std::string&); void requestNameChangeDialog(const std::string&, const GeoLib::GEOTYPE, const std::size_t); + void requestPointToStationConversion(std::string const&); //void saveFEMConditionsRequested(QString, QString); }; diff --git a/Applications/DataExplorer/mainwindow.cpp b/Applications/DataExplorer/mainwindow.cpp index 000116abbd4896a27fa936d60b6fae7d671d6742..ea4f79a776ad4a1a8ce9f5b54d5f721be164c940 100644 --- a/Applications/DataExplorer/mainwindow.cpp +++ b/Applications/DataExplorer/mainwindow.cpp @@ -139,6 +139,8 @@ MainWindow::MainWindow(QWidget* parent /* = 0*/) this, SLOT(mapGeometry(const std::string&))); connect(geoTabWidget->treeView, SIGNAL(saveToFileRequested(QString, QString)), this, SLOT(writeGeometryToFile(QString, QString))); // save geometry to file + connect(geoTabWidget->treeView, SIGNAL(requestPointToStationConversion(std::string const&)), this, + SLOT(convertPointsToStations( std::string const&))); connect(geoTabWidget->treeView, SIGNAL(requestLineEditDialog(const std::string &)), this, SLOT(showLineEditDialog(const std::string &))); // open line edit dialog connect(geoTabWidget->treeView, SIGNAL(requestNameChangeDialog(const std::string&, const GeoLib::GEOTYPE, std::size_t)), @@ -1097,6 +1099,14 @@ void MainWindow::showMeshAnalysisDialog() dlg->exec(); } +void MainWindow::convertPointsToStations(std::string const& geo_name) +{ + std::string stn_name = geo_name + " Stations"; + int ret = _project.getGEOObjects().geoPointsToStations(geo_name, stn_name); + if (ret == 1) + OGSError::box("No points found to convert."); +} + void MainWindow::showLineEditDialog(const std::string &geoName) { LineEditDialog lineEdit( diff --git a/Applications/DataExplorer/mainwindow.h b/Applications/DataExplorer/mainwindow.h index 5765f0c6416df39c907ec79bdace24d7b06e9916..8baee849e3b12f01621b4df88c8f8cdd911e2459 100644 --- a/Applications/DataExplorer/mainwindow.h +++ b/Applications/DataExplorer/mainwindow.h @@ -76,6 +76,7 @@ protected slots: void loadPetrelFiles(); void mapGeometry(const std::string &geo_name); void convertMeshToGeometry(const MeshLib::Mesh* mesh); + void convertPointsToStations(std::string const& geo_name); void openRecentFile(); void about(); void showAddPipelineFilterItemDialog(QModelIndex parentIndex); diff --git a/GeoLib/GEOObjects.cpp b/GeoLib/GEOObjects.cpp index ee1d9baa8ef4d55dbdb5c981e59137017c204c50..1ca37464f2eed20335ee9bef6a0cb132b13e87a6 100644 --- a/GeoLib/GEOObjects.cpp +++ b/GeoLib/GEOObjects.cpp @@ -554,9 +554,84 @@ void GEOObjects::renameGeometry(std::string const& old_name, } } -const GeoLib::GeoObject* GEOObjects::getGeoObject(const std::string &geo_name, - GeoLib::GEOTYPE type, - const std::string &geo_obj_name) const +void GEOObjects::markUnusedPoints(std::string const& geo_name, + std::vector<bool>& transfer_pnts) const +{ + GeoLib::PolylineVec const* const ply_obj(getPolylineVecObj(geo_name)); + if (ply_obj) + { + std::vector<GeoLib::Polyline*> const& lines(*ply_obj->getVector()); + for (auto* line : lines) + { + std::size_t const n_pnts(line->getNumberOfPoints()); + for (std::size_t i = 0; i < n_pnts; ++i) + transfer_pnts[line->getPointID(i)] = false; + } + } + + GeoLib::SurfaceVec const* const sfc_obj(getSurfaceVecObj(geo_name)); + if (sfc_obj) + { + std::vector<GeoLib::Surface*> const& surfaces = *sfc_obj->getVector(); + for (auto* sfc : surfaces) + { + std::size_t const n_tri(sfc->getNumberOfTriangles()); + for (std::size_t i = 0; i < n_tri; ++i) + { + GeoLib::Triangle const& t = *(*sfc)[i]; + transfer_pnts[t[0]] = false; + transfer_pnts[t[1]] = false; + transfer_pnts[t[2]] = false; + } + } + } +} + +int GEOObjects::geoPointsToStations(std::string const& geo_name, + std::string& stn_name, + bool const only_unused_pnts) +{ + GeoLib::PointVec const* const pnt_obj(getPointVecObj(geo_name)); + if (pnt_obj == nullptr) + { + ERR("Point vector %s not found.", geo_name.c_str()); + return -1; + } + std::vector<GeoLib::Point*> const& pnts = *pnt_obj->getVector(); + if (pnts.empty()) + { + ERR("Point vector %s is empty.", geo_name.c_str()); + return -1; + } + std::size_t const n_pnts(pnts.size()); + std::vector<bool> transfer_pnts(n_pnts, true); + if (only_unused_pnts) + markUnusedPoints(geo_name, transfer_pnts); + + auto stations = std::make_unique<std::vector<GeoLib::Point*>>(); + for (std::size_t i = 0; i < n_pnts; ++i) + { + if (!transfer_pnts[i]) + continue; + std::string name = pnt_obj->getItemNameByID(i); + if (name.empty()) + name = "Station " + std::to_string(i); + stations->push_back(new GeoLib::Station(pnts[i], name)); + } + if (!stations->empty()) + addStationVec(std::move(stations), stn_name); + else + { + WARN("No points found to convert."); + return 1; + } + return 0; +} + +const GeoLib::GeoObject* GEOObjects::getGeoObject( + const std::string& geo_name, + GeoLib::GEOTYPE type, + const std::string& geo_obj_name) const { GeoLib::GeoObject *geo_obj(nullptr); switch (type) { diff --git a/GeoLib/GEOObjects.h b/GeoLib/GEOObjects.h index 15f0ef42bafb7330707e5e29565c74bce786c659..a3a9779bc83df7aca5878208d99a7e50c05399db 100644 --- a/GeoLib/GEOObjects.h +++ b/GeoLib/GEOObjects.h @@ -249,6 +249,15 @@ public: void renameGeometry(std::string const& old_name, std::string const& new_name); + /// Constucts a station-vector based on the points of a given geometry. + // @param geo_name name of the geometry + // @param stn_name name of the new station vector + // @param only_usused_pnts if true only points not in a line or surface are + // transferred, otherwise all points + int geoPointsToStations(std::string const& geo_name, + std::string& stn_name, + bool const only_unused_pnts = true); + /// Returns the geo object for a geometric item of the given name and type for the associated geometry. const GeoLib::GeoObject* getGeoObject(const std::string &geo_name, GeoLib::GEOTYPE type, @@ -367,5 +376,8 @@ private: */ void mergeSurfaces(std::vector<std::string> const & geo_names, std::string & merged_geo_name, std::vector<std::size_t> const& pnt_offsets); + + void markUnusedPoints(std::string const& geo_name, + std::vector<bool>& transfer_pnts) const; }; } // end namespace diff --git a/Tests/Data/MeshGeoToolsLib/Hamburg/BrunnenGOK_Outline_ModellHH.gml b/Tests/Data/MeshGeoToolsLib/Hamburg/BrunnenGOK_Outline_ModellHH.gml new file mode 100644 index 0000000000000000000000000000000000000000..27e3df356c9d6697e364cad1e5c55e01dc74b7ae --- /dev/null +++ b/Tests/Data/MeshGeoToolsLib/Hamburg/BrunnenGOK_Outline_ModellHH.gml @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f32ed9922fea2c51082aa05a4214b1727ae220ae786d6d9d5b0b5005d60831c3 +size 37074 diff --git a/Tests/GeoLib/TestPointToStationConversion.cpp b/Tests/GeoLib/TestPointToStationConversion.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a258d1d5b9c466da9a820b358a40650a8b621e3c --- /dev/null +++ b/Tests/GeoLib/TestPointToStationConversion.cpp @@ -0,0 +1,55 @@ +/** + * @brief Tests for GeoLib::GEOOnjects::geoPointsToStations() + * + * \copyright + * Copyright (c) 2012-2019, 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 "gtest/gtest.h" + +#include "BaseLib/BuildInfo.h" +#include "GeoLib/GEOObjects.h" +#include "GeoLib/IO/XmlIO/Boost/BoostXmlGmlInterface.h" + +TEST(GeoLib, PointToStationConversion) +{ + std::string const file_name( + BaseLib::BuildInfo::data_path + + "/MeshGeoToolsLib/Hamburg/BrunnenGOK_Outline_ModellHH.gml"); + GeoLib::GEOObjects geo_obj; + GeoLib::IO::BoostXmlGmlInterface io(geo_obj); + bool const ret = io.readFile(file_name); + EXPECT_TRUE(ret); + std::vector<std::string> geo_names; + geo_obj.getGeometryNames(geo_names); + auto const* const pnts = geo_obj.getPointVec(geo_names[0]); + assert(pnts != nullptr); + std::size_t const exp_all_pnts(310); + EXPECT_EQ(exp_all_pnts, pnts->size()); + + // converting only unused points + std::string stn_orphaned_pnts("Orphaned Points"); + int const res_orphaned_pnts = + geo_obj.geoPointsToStations(geo_names[0], stn_orphaned_pnts, true); + EXPECT_EQ(0, res_orphaned_pnts); + auto const* const stns = geo_obj.getStationVec(stn_orphaned_pnts); + assert(stns != nullptr); + std::size_t const n_stns = stns->size(); + EXPECT_EQ(18, n_stns); + for (std::size_t i = 0; i < n_stns; ++i) + { + EXPECT_EQ((*(*stns)[i])[0], (*(*pnts)[i])[0]); + EXPECT_EQ((*(*stns)[i])[1], (*(*pnts)[i])[1]); + EXPECT_EQ((*(*stns)[i])[2], (*(*pnts)[i])[2]); + } + + // converting all points + std::string stn_all_pnts("All Points"); + int const res_all_pnts = + geo_obj.geoPointsToStations(geo_names[0], stn_all_pnts, false); + EXPECT_EQ(0, res_all_pnts); + EXPECT_EQ(exp_all_pnts, geo_obj.getStationVec(stn_all_pnts)->size()); +}