diff --git a/BaseLib/CMakeLists.txt b/BaseLib/CMakeLists.txt index 906ac86afb04c3ea84cb567885d422c3a2f9adf6..fa5d9501cf402b213ca188247346770c19f42820 100644 --- a/BaseLib/CMakeLists.txt +++ b/BaseLib/CMakeLists.txt @@ -17,7 +17,4 @@ INCLUDE_DIRECTORIES( ADD_SUBDIRECTORY(logog) SET_PROPERTY(TARGET Continuous PROPERTY FOLDER "logog") SET_PROPERTY(TARGET logog PROPERTY FOLDER "logog") -IF (DOXYGEN_FOUND) - SET_PROPERTY(TARGET logog-doc PROPERTY FOLDER "logog") -ENDIF () SET_PROPERTY(TARGET test-logog PROPERTY FOLDER "logog") diff --git a/BaseLib/RapidXML/rapidxml_print.hpp b/BaseLib/RapidXML/rapidxml_print.hpp index 0ae2b14faa11a1e0c0c63ba8715983b132f6f2c6..f75fbea087d7c56faa767e83ea377a7484978d6e 100644 --- a/BaseLib/RapidXML/rapidxml_print.hpp +++ b/BaseLib/RapidXML/rapidxml_print.hpp @@ -28,10 +28,13 @@ namespace rapidxml //! \cond internal namespace internal { - + // LB Forward declaration (for clang) + template<class OutIt, class Ch> + inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent); + /////////////////////////////////////////////////////////////////////////// // Internal character operations - + // Copy characters from given range to given output iterator template<class OutIt, class Ch> inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out) @@ -40,7 +43,7 @@ namespace rapidxml *out++ = *begin++; return out; } - + // Copy characters from given range to given output iterator and expand // characters into references (< > ' " &) template<class OutIt, class Ch> @@ -59,17 +62,17 @@ namespace rapidxml case Ch('<'): *out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';'); break; - case Ch('>'): + case Ch('>'): *out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';'); break; - case Ch('\''): + case Ch('\''): *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';'); break; - case Ch('"'): + case Ch('"'): *out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';'); break; - case Ch('&'): - *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';'); + case Ch('&'): + *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';'); break; default: *out++ = *begin; // No expansion, copy character @@ -101,70 +104,8 @@ namespace rapidxml /////////////////////////////////////////////////////////////////////////// // Internal printing operations - - // Print node - template<class OutIt, class Ch> - inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent) - { - // Print proper node type - switch (node->type()) - { - - // Document - case node_document: - out = print_children(out, node, flags, indent); - break; - // Element - case node_element: - out = print_element_node(out, node, flags, indent); - break; - - // Data - case node_data: - out = print_data_node(out, node, flags, indent); - break; - - // CDATA - case node_cdata: - out = print_cdata_node(out, node, flags, indent); - break; - - // Declaration - case node_declaration: - out = print_declaration_node(out, node, flags, indent); - break; - - // Comment - case node_comment: - out = print_comment_node(out, node, flags, indent); - break; - - // Doctype - case node_doctype: - out = print_doctype_node(out, node, flags, indent); - break; - - // Pi - case node_pi: - out = print_pi_node(out, node, flags, indent); - break; - - // Unknown - default: - assert(0); - break; - } - - // If indenting not disabled, add line break after node - if (!(flags & print_no_indenting)) - *out = Ch('\n'), ++out; - - // Return modified iterator - return out; - } - - // Print children of the node + // Print children of the node template<class OutIt, class Ch> inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent) { @@ -177,6 +118,7 @@ namespace rapidxml template<class OutIt, class Ch> inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int flags) { + (void)flags; // Unused for (xml_attribute<Ch> *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute()) { if (attribute->name() && attribute->value()) @@ -249,7 +191,7 @@ namespace rapidxml *out = Ch('<'), ++out; out = copy_chars(node->name(), node->name() + node->name_size(), out); out = print_attributes(out, node, flags); - + // If node is childless if (node->value_size() == 0 && !node->first_node()) { @@ -308,11 +250,11 @@ namespace rapidxml // Print attributes out = print_attributes(out, node, flags); - + // Print declaration end *out = Ch('?'), ++out; *out = Ch('>'), ++out; - + return out; } @@ -373,6 +315,68 @@ namespace rapidxml return out; } + // Print node + template<class OutIt, class Ch> + inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent) + { + // Print proper node type + switch (node->type()) + { + + // Document + case node_document: + out = print_children(out, node, flags, indent); + break; + + // Element + case node_element: + out = print_element_node(out, node, flags, indent); + break; + + // Data + case node_data: + out = print_data_node(out, node, flags, indent); + break; + + // CDATA + case node_cdata: + out = print_cdata_node(out, node, flags, indent); + break; + + // Declaration + case node_declaration: + out = print_declaration_node(out, node, flags, indent); + break; + + // Comment + case node_comment: + out = print_comment_node(out, node, flags, indent); + break; + + // Doctype + case node_doctype: + out = print_doctype_node(out, node, flags, indent); + break; + + // Pi + case node_pi: + out = print_pi_node(out, node, flags, indent); + break; + + // Unknown + default: + assert(0); + break; + } + + // If indenting not disabled, add line break after node + if (!(flags & print_no_indenting)) + *out = Ch('\n'), ++out; + + // Return modified iterator + return out; + } + } //! \endcond @@ -384,7 +388,7 @@ namespace rapidxml //! \param node Node to be printed. Pass xml_document to print entire document. //! \param flags Flags controlling how XML is printed. //! \return Output iterator pointing to position immediately after last character of printed text. - template<class OutIt, class Ch> + template<class OutIt, class Ch> inline OutIt print(OutIt out, const xml_node<Ch> &node, int flags = 0) { return internal::print_node(out, &node, flags, 0); @@ -397,7 +401,7 @@ namespace rapidxml //! \param node Node to be printed. Pass xml_document to print entire document. //! \param flags Flags controlling how XML is printed. //! \return Output stream. - template<class Ch> + template<class Ch> inline std::basic_ostream<Ch> &print(std::basic_ostream<Ch> &out, const xml_node<Ch> &node, int flags = 0) { print(std::ostream_iterator<Ch>(out), node, flags); @@ -408,7 +412,7 @@ namespace rapidxml //! \param out Output stream to print to. //! \param node Node to be printed. //! \return Output stream. - template<class Ch> + template<class Ch> inline std::basic_ostream<Ch> &operator <<(std::basic_ostream<Ch> &out, const xml_node<Ch> &node) { return print(out, node); diff --git a/BaseLib/logog/CMakeLists.txt b/BaseLib/logog/CMakeLists.txt index 35bfb6c5764d3ac47e30f9dd368d3d698637fddd..31861996d351e5963460d4e6ad7593cd30a678b0 100644 --- a/BaseLib/logog/CMakeLists.txt +++ b/BaseLib/logog/CMakeLists.txt @@ -42,14 +42,16 @@ set_target_properties(logog PROPERTIES DEBUG_POSTFIX "d") add_executable( test-logog test/test.cpp ) target_link_libraries( test-logog logog ${CMAKE_THREAD_LIBS_INIT}) add_test( NAME test-harness COMMAND test-logog ) -install(TARGETS logog ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) -install(DIRECTORY include/ DESTINATION "${CMAKE_INSTALL_PREFIX}/include/logog" +if (CMAKE_PROJECT_NAME STREQUAL logog) + install(TARGETS logog ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) + install(DIRECTORY include/ DESTINATION "${CMAKE_INSTALL_PREFIX}/include/logog" FILES_MATCHING PATTERN "*.hpp") -# Docs generation with Doxygen -find_package( Doxygen ) -if( DOXYGEN_FOUND ) - add_custom_target (logog-doc ${DOXYGEN_EXECUTABLE} ${CMAKE_SOURCE_DIR}/doxyfile - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - COMMENT "Generating source code documentation with Doxygen." VERBATIM) -endif() # DOXYGEN_FOUND \ No newline at end of file + # Docs generation with Doxygen + find_package( Doxygen ) + if( DOXYGEN_FOUND ) + add_custom_target (logog-doc ${DOXYGEN_EXECUTABLE} ${CMAKE_SOURCE_DIR}/doxyfile + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMENT "Generating source code documentation with Doxygen." VERBATIM) + endif() # DOXYGEN_FOUND +endif () # CMAKE_PROJECT_NAME = logog diff --git a/BaseLib/logog/src/target.cpp b/BaseLib/logog/src/target.cpp index 7bc26943a0c5f7d3079e76418024b48b567d0e4b..da9883e1feb8c6b526bc7569d9a541b8212d0ce0 100644 --- a/BaseLib/logog/src/target.cpp +++ b/BaseLib/logog/src/target.cpp @@ -1,4 +1,4 @@ - /* + /* * \file target.cpp */ @@ -74,6 +74,8 @@ namespace logog { #else OutputDebugStringA( (const LOGOG_CHAR *)data ); #endif // LOGOG_UNICODE +#else + (void)data; #endif // LOGOG_FLAVOR_WINDOWS return 0; } @@ -125,6 +127,7 @@ namespace logog { #ifdef LOGOG_FLAVOR_WINDOWS nError = fopen_s( &fpTest, m_pFileName, "r"); // ignore the error code #else // LOGOG_FLAVOR_WINDOWS + (void)nError; // Unused fpTest = fopen( m_pFileName, "r"); #endif // LOGOG_FLAVOR_WINDOWS diff --git a/CMakeLists.txt b/CMakeLists.txt index eff063dafa31b15acc9fb30d04dc16d652a13c4c..f12857f65688bfae6476d2528c0dee22fcc8401f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,9 +37,15 @@ IF((CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC) AND GPROF_PATH) OPTION(OGS_PROFILE "Enables compiling with flags set for profiling with gprof." OFF) ENDIF() # GCC AND GPROF_PATH -# Disable Qt +# Enable / Disable parts OPTION(OGS_DONT_USE_QT "Disables all Qt specific code." OFF) +OPTION(OGS_BUILD_CLI "Should the OGS simulator be built?" ON) +OPTION(OGS_BUILD_TESTS "Should the test executables be built?" ON) +OPTION(OGS_BUILD_GUI "Should the Data Explorer be built?" OFF) + +OPTION(OGS_NO_EXTERNAL_LIBS "Builds OGS without any external dependencies." OFF) + # Print CMake variable values IF (OGS_CMAKE_DEBUG) INCLUDE(ListAllCMakeVariableValues) @@ -51,9 +57,12 @@ IF (OGS_BUILD_INFO) ADD_DEFINITIONS (-DOGS_BUILD_INFO) ENDIF (OGS_BUILD_INFO) -OPTION(OGS_BUILD_GUI "Should the Data Explorer be built?" OFF) - -OPTION(OGS_NO_EXTERNAL_LIBS "Builds OGS without any external dependencies." OFF) +# Packaging +OPTION(OGS_PACKAGING "Creating installers / packages" OFF) +OPTION_REQUIRES(OGS_PACKAGING_ZIP "Do you want to package as zip?" OGS_PACKAGING) +IF(OGS_PACKAGING) + INCLUDE( scripts/cmake/Pack.cmake) +ENDIF() #OGS_PACKAGING ###################### ### Subdirectories ### @@ -66,16 +75,20 @@ ADD_SUBDIRECTORY( FileIO ) ADD_SUBDIRECTORY( GeoLib ) ADD_SUBDIRECTORY( MathLib ) ADD_SUBDIRECTORY( MeshLib ) -ADD_SUBDIRECTORY( OGS ) -ADD_SUBDIRECTORY( SimpleTests/MatrixTests ) -ADD_SUBDIRECTORY( SimpleTests/MeshTests ) -IF(NOT MSVC AND BLAS_FOUND AND LAPACK_FOUND) - ADD_SUBDIRECTORY( SimpleTests/SolverTests ) -ENDIF() +IF( OGS_BUILD_CLI ) + ADD_SUBDIRECTORY( OGS ) +ENDIF() # OGS_BUILD_CLI +IF( OGS_BUILD_TESTS ) + ADD_SUBDIRECTORY( SimpleTests/MatrixTests ) + ADD_SUBDIRECTORY( SimpleTests/MeshTests ) + IF(NOT MSVC AND BLAS_FOUND AND LAPACK_FOUND) + ADD_SUBDIRECTORY( SimpleTests/SolverTests ) + ENDIF() +ENDIF() # OGS_BUILD_TESTS IF(OGS_BUILD_GUI) ADD_DEFINITIONS(-DOGS_BUILD_GUI) ADD_SUBDIRECTORY(Gui) -ENDIF() +ENDIF() # OGS_BUILD_GUI CONFIGURE_FILE (BaseLib/BuildInfo.h.in ${PROJECT_BINARY_DIR}/BaseLib/BuildInfo.h) -CONFIGURE_FILE (BaseLib/Configure.h.in ${PROJECT_BINARY_DIR}/BaseLib/Configure.h) \ No newline at end of file +CONFIGURE_FILE (BaseLib/Configure.h.in ${PROJECT_BINARY_DIR}/BaseLib/Configure.h) diff --git a/FemLib/ProcessInfo.h b/FemLib/ProcessInfo.h index 229c9ed816149cbd2ec1ac7630bba9aed9063ac7..876a84983a938b72d546316f567862eb2c40d609 100644 --- a/FemLib/ProcessInfo.h +++ b/FemLib/ProcessInfo.h @@ -41,7 +41,7 @@ public: * @param pcs a pointer to the process * @return */ - ProcessInfo (FiniteElement::ProcessType pcs_type, FiniteElement::PrimaryVariable pcs_pv/*, CRFProcess* pcs*/); + ProcessInfo (FiniteElement::ProcessType pcs_type, FiniteElement::PrimaryVariable pcs_pv/* TODO6 , CRFProcess* pcs*/); /** * Sets the process type. diff --git a/FileIO/ImportFileTypes.h b/FileIO/ImportFileTypes.h index 449092e3a08cfdefbe5c07d28628b4333f2a6d7f..9b4551ee02413d3e141ce2043e1f2824bf2a551d 100644 --- a/FileIO/ImportFileTypes.h +++ b/FileIO/ImportFileTypes.h @@ -62,7 +62,7 @@ public: else if (t==ImportFileType::NETCDF) return "NetCDF files (*.nc)"; else if (t==ImportFileType::OGS) - return "Geosys files (*.gsp *.gli *.gml *.msh *.stn);;Project files (*.gsp);;GeoSys FEM Conditions (*.cnd *.bc *.ic *.st);;GLI files (*.gli);;MSH files (*.msh);;STN files (*.stn);;All files (* *.*)"; + return "OpenGeosys files (*.gsp *.gml *.vtu *.stn);;GeoSys legacy files (*.gli *.msh);;GeoSys FEM Conditions (*.cnd *.bc *.ic *.st);;All files (* *.*)"; else if (t==ImportFileType::PETREL) return "Petrel files (*)"; else if (t==ImportFileType::RASTER) diff --git a/FileIO/Legacy/MeshIO.cpp b/FileIO/Legacy/MeshIO.cpp index 5aa53bd677eb9761c9e3f3d3c4593fc96242ad84..93d9aed5ceee488687e5598d746671f8552b2660 100644 --- a/FileIO/Legacy/MeshIO.cpp +++ b/FileIO/Legacy/MeshIO.cpp @@ -41,7 +41,7 @@ MeshLib::Mesh* MeshIO::loadMeshFromFile(const std::string& file_name) std::ifstream in (file_name.c_str(),std::ios::in); if (!in.is_open()) { - std::cout << std::endl << "CFEMesh::FEMRead() - Could not open file...\n"; + std::cout << std::endl << "MeshIO::loadMeshFromFile() - Could not open file...\n"; return NULL; } @@ -64,28 +64,28 @@ MeshLib::Mesh* MeshIO::loadMeshFromFile(const std::string& file_name) else if (line_string.find("$NODES") != std::string::npos) { double x, y, z, double_dummy; - unsigned nNodes, idx; - in >> nNodes >> std::ws; + unsigned idx; + getline(in, line_string); + trim(line_string); + unsigned nNodes = atoi(line_string.c_str()); std::string s; - std::ios::pos_type position = in.tellg(); for (unsigned i = 0; i < nNodes; i++) { - in >> idx >> x >> y >> z; - MeshLib::Node* node(new MeshLib::Node(x, y, z, nodes.size())); + getline(in, line_string); + std::stringstream iss(line_string); + iss >> idx >> x >> y >> z; + MeshLib::Node* node(new MeshLib::Node(x, y, z, idx)); nodes.push_back(node); - position = in.tellg(); - in >> s; + iss >> s; if (s.find("$AREA") != std::string::npos) - in >> double_dummy; - else - in.seekg(position, std::ios::beg); - in >> std::ws; + iss >> double_dummy; } } else if (line_string.find("$ELEMENTS") != std::string::npos) { - unsigned nElements; - in >> nElements >> std::ws; + getline(in, line_string); + trim(line_string); + unsigned nElements = atoi(line_string.c_str()); for (unsigned i = 0; i < nElements; i++) { getline(in, line_string); diff --git a/FileIO/Legacy/OGSIOVer4.cpp b/FileIO/Legacy/OGSIOVer4.cpp index 6a9b2e0b20953366b53f4256d8c90e1ea64f75a1..85191ba7f200022f4e1ff4a0c4846bbfc3514fca 100644 --- a/FileIO/Legacy/OGSIOVer4.cpp +++ b/FileIO/Legacy/OGSIOVer4.cpp @@ -12,8 +12,6 @@ #include <iomanip> #include <sstream> -//TODO6 #include "Configure.h" - // FileIO #include "MeshIO/GMSHInterface.h" #include "OGSIOVer4.h" diff --git a/FileIO/MeshIO/GMSHInterface.cpp b/FileIO/MeshIO/GMSHInterface.cpp index 40685f18175a4df476d4d38d69e89783e7567ec1..3b323e1e8b7d31734dfc0e4dade6f60d5c3e9c6e 100644 --- a/FileIO/MeshIO/GMSHInterface.cpp +++ b/FileIO/MeshIO/GMSHInterface.cpp @@ -17,6 +17,7 @@ #include "StringTools.h" #include "Configure.h" #include "BuildInfo.h" +#include "StringTools.h" // FileIO #include "GMSHInterface.h" @@ -86,7 +87,7 @@ bool GMSHInterface::isGMSHMeshFile(const std::string& fname) return false; } -void GMSHInterface::readGMSHMesh(std::string const& fname, MeshLib::Mesh* mesh) +MeshLib::Mesh* GMSHInterface::readGMSHMesh(std::string const& fname) { std::string line; std::ifstream in(fname.c_str(), std::ios::in); @@ -108,15 +109,19 @@ void GMSHInterface::readGMSHMesh(std::string const& fname, MeshLib::Mesh* mesh) long id; double x, y, z; in >> n_nodes >> std::ws; + nodes.resize(n_nodes); + std::map<unsigned, unsigned> id_map; for (size_t i = 0; i < n_nodes; i++) { in >> id >> x >> y >> z >> std::ws; - nodes.push_back(new MeshLib::Node(x,y,z,id)); + id_map.insert(std::map<unsigned, unsigned>::value_type(id, i)); + nodes[i] = new MeshLib::Node(x,y,z,id); } getline(in, line); // End Node keyword $EndNodes // Element data getline(in, line); // Element keyword $Elements in >> n_elements >> std::ws; // number-of-elements + elements.reserve(n_elements); unsigned idx, type, n_tags, dummy, mat_id; for (size_t i = 0; i < n_elements; i++) { @@ -132,38 +137,41 @@ void GMSHInterface::readGMSHMesh(std::string const& fname, MeshLib::Mesh* mesh) switch (type) { case 1: - readNodeIDs(in, 2, node_ids); + readNodeIDs(in, 2, node_ids, id_map); elem = new MeshLib::Edge(nodes[node_ids[0]], nodes[node_ids[1]], 0); break; case 2: - readNodeIDs(in, 3, node_ids); + readNodeIDs(in, 3, node_ids, id_map); elem = new MeshLib::Tri(nodes[node_ids[0]], nodes[node_ids[1]], nodes[node_ids[2]], mat_id); break; case 3: - readNodeIDs(in, 4, node_ids); + readNodeIDs(in, 4, node_ids, id_map); elem = new MeshLib::Quad(nodes[node_ids[0]], nodes[node_ids[1]], nodes[node_ids[2]], nodes[node_ids[3]], mat_id); break; case 4: - readNodeIDs(in, 4, node_ids); + readNodeIDs(in, 4, node_ids, id_map); elem = new MeshLib::Tet(nodes[node_ids[0]], nodes[node_ids[1]], nodes[node_ids[2]], nodes[node_ids[3]], mat_id); break; case 5: - readNodeIDs(in, 8, node_ids); + readNodeIDs(in, 8, node_ids, id_map); elem = new MeshLib::Hex(nodes[node_ids[0]], nodes[node_ids[1]], nodes[node_ids[2]], nodes[node_ids[3]], nodes[node_ids[4]], nodes[node_ids[5]], nodes[node_ids[6]], nodes[node_ids[7]], mat_id); break; case 6: - readNodeIDs(in, 6, node_ids); + readNodeIDs(in, 6, node_ids, id_map); elem = new MeshLib::Prism(nodes[node_ids[0]], nodes[node_ids[1]], nodes[node_ids[2]], nodes[node_ids[3]], nodes[node_ids[4]], nodes[node_ids[5]], mat_id); break; case 7: - readNodeIDs(in, 5, node_ids); + readNodeIDs(in, 5, node_ids, id_map); elem = new MeshLib::Pyramid(nodes[node_ids[0]], nodes[node_ids[1]], nodes[node_ids[2]], nodes[node_ids[3]], nodes[node_ids[4]], mat_id); break; + case 15: + in >> dummy; // skip rest of line + continue; + break; default: - in >> dummy; // skip rest of line (e.g. for type "15" ... whatever that is ... std::cout << "Error in GMSHInterface::readGMSHMesh() - Unknown element type " << type << "." << std::endl; } in >> std::ws; @@ -173,48 +181,19 @@ void GMSHInterface::readGMSHMesh(std::string const& fname, MeshLib::Mesh* mesh) } getline(in, line); // END keyword -/* TODO6: testen ob es auch so funktioniert - // ordering nodes and closing gaps TK - std::vector<size_t> gmsh_id; - size_t counter(0); - for (size_t i = 0; i < mesh->nod_vector.size(); i++) { - const size_t diff = mesh->nod_vector[i]->GetIndex() - counter; - if (diff == 0) { - gmsh_id.push_back(i); - counter++; - } else { - for (size_t j = 0; j < diff; j++) { - gmsh_id.push_back(i); - counter++; - } - i--; - } - } - - for (size_t i = 0; i < mesh->ele_vector.size(); i++) - for (long j = 0; j < mesh->ele_vector[i]->GetVertexNumber(); j++) - mesh->ele_vector[i]->getNodeIndices()[j] - = gmsh_id[mesh->ele_vector[i]->GetNodeIndex(j) + 1]; - - for (size_t i = 0; i < mesh->nod_vector.size(); i++) - mesh->nod_vector[i]->SetIndex(i); - // END OF: ordering nodes and closing gaps TK -*/ - } /*End while*/ + } } in.close(); - if (mesh == NULL) { - mesh = new MeshLib::Mesh(BaseLib::getFileNameFromPath(fname) ,nodes, elements); - } + return new MeshLib::Mesh(BaseLib::getFileNameFromPath(fname), nodes, elements); } -void GMSHInterface::readNodeIDs(std::ifstream &in, unsigned n_nodes, std::vector<unsigned> &node_ids) +void GMSHInterface::readNodeIDs(std::ifstream &in, unsigned n_nodes, std::vector<unsigned> &node_ids, std::map<unsigned, unsigned> &id_map) { unsigned idx; for (unsigned i=0; i<n_nodes; i++) { in >> idx; - node_ids.push_back(--idx); + node_ids.push_back(id_map[idx]); } } diff --git a/FileIO/MeshIO/GMSHInterface.h b/FileIO/MeshIO/GMSHInterface.h index c70fd01c8dbf2d97e981e3850b9418324a76a62e..cffa6ebea507e8485cf2b728a66828f2286bc296 100644 --- a/FileIO/MeshIO/GMSHInterface.h +++ b/FileIO/MeshIO/GMSHInterface.h @@ -76,10 +76,9 @@ public: /** * reads a mesh created by GMSH - this implementation is based on the former function GMSH2MSH * @param fname the file name of the mesh (including the path) - * @param mesh on input: the parameter have to be NULL on output: the new mesh * @return */ - static void readGMSHMesh (std::string const& fname, MeshLib::Mesh* mesh); + static MeshLib::Mesh* readGMSHMesh (std::string const& fname); protected: int write(std::ostream& stream); @@ -92,7 +91,7 @@ private: */ void writeGMSHInputFile(std::ostream & out); - static void readNodeIDs(std::ifstream &in, unsigned n_nodes, std::vector<unsigned> &node_ids); + static void readNodeIDs(std::ifstream &in, unsigned n_nodes, std::vector<unsigned> &node_ids, std::map<unsigned, unsigned> &id_map); void writePoints(std::ostream& out) const; diff --git a/FileIO/XmlIO/RapidXMLInterface.cpp b/FileIO/XmlIO/RapidXMLInterface.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4e30244ff8ac3da55306828a9eff489706f964d3 --- /dev/null +++ b/FileIO/XmlIO/RapidXMLInterface.cpp @@ -0,0 +1,226 @@ +/** + * Copyright (c) 2012, OpenGeoSys Community (http://www.opengeosys.net) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.net/LICENSE.txt + * + * \file RapidXMLInterface.cpp + * + * Created on 2012-08-16 by Karsten Rink + */ +//RapidXML +#include "RapidXMLInterface.h" +#include <iostream> + +#include "StringTools.h" +#include "Station.h" + +namespace FileIO +{ + +std::vector<GeoLib::Point*> *RapidXMLInterface::readStationFile(const std::string &fileName) +{ + std::vector<GeoLib::Point*> *stations = new std::vector<GeoLib::Point*>; + std::ifstream in(fileName.c_str()); + if (in.fail()) + { + std::cout << "XmlStnInterface::rapidReadFile() - Can't open xml-file." << std::endl; + return NULL; + } + + // buffer file + in.seekg(0, std::ios::end); + size_t length = in.tellg(); + in.seekg(0, std::ios::beg); + char* buffer = new char[length+1]; + in.read(buffer, length); + buffer[in.gcount()] = '\0'; + in.close(); + + // build DOM tree + rapidxml::xml_document<> doc; + doc.parse<0>(buffer); + + // parse content + if (std::string(doc.first_node()->name()).compare("OpenGeoSysSTN")) + { + std::cout << "XmlStnInterface::readFile() - Unexpected XML root." << std::endl; + return NULL; + } + + // iterate over all station lists + for (rapidxml::xml_node<>* station_list = doc.first_node()->first_node(); station_list; station_list = station_list->next_sibling()) + { + std::string stnName("[NN]"); + + stnName = station_list->first_node("name")->value(); + for (rapidxml::xml_node<>* list_item = station_list->first_node(); list_item; list_item = list_item->next_sibling()) + { + std::string b(list_item->name()); + if (std::string(list_item->name()).compare("stations") == 0) + RapidXMLInterface::readStations(list_item, stations, fileName); + if (std::string(list_item->name()).compare("boreholes") == 0) + RapidXMLInterface::readStations(list_item, stations, fileName); + } + } + + doc.clear(); + delete [] buffer; + + return stations; +} +/* +int RapidXMLInterface::rapidReadFile(const std::string &fileName) +{ + GEOLIB::GEOObjects* geoObjects = _project->getGEOObjects(); + + std::ifstream in(fileName.c_str()); + if (in.fail()) + { + std::cout << "XmlStnInterface::rapidReadFile() - Can't open xml-file." << std::endl; + return 0; + } + + // buffer file + in.seekg(0, std::ios::end); + size_t length = in.tellg(); + in.seekg(0, std::ios::beg); + char* buffer = new char[length+1]; + in.read(buffer, length); + buffer[in.gcount()] = '\0'; + in.close(); + + // build DOM tree + rapidxml::xml_document<> doc; + doc.parse<0>(buffer); + + // parse content + if (std::string(doc.first_node()->name()).compare("OpenGeoSysSTN")) + { + std::cout << "XmlStnInterface::readFile() - Unexpected XML root." << std::endl; + return 0; + } + + // iterate over all station lists + for (rapidxml::xml_node<>* station_list = doc.first_node()->first_node(); station_list; station_list = station_list->next_sibling()) + { + std::vector<GEOLIB::Point*>* stations = new std::vector<GEOLIB::Point*>; + std::string stnName("[NN]"); + + stnName = station_list->first_node("name")->value(); + for (rapidxml::xml_node<>* list_item = station_list->first_node(); list_item; list_item = list_item->next_sibling()) + { + std::string b(list_item->name()); + if (std::string(list_item->name()).compare("stations") == 0) + XmlStnInterface::rapidReadStations(list_item, stations, fileName); + if (std::string(list_item->name()).compare("boreholes") == 0) + XmlStnInterface::rapidReadStations(list_item, stations, fileName); + } + + if (!stations->empty()) + geoObjects->addStationVec(stations, stnName); + else + delete stations; + } + + doc.clear(); + delete [] buffer; + + return 1; +} +*/ +void RapidXMLInterface::readStations(const rapidxml::xml_node<>* station_root, std::vector<GeoLib::Point*> *stations, const std::string &file_name) +{ + for (rapidxml::xml_node<>* station_node = station_root->first_node(); station_node; station_node = station_node->next_sibling()) + { + if (station_node->first_attribute("id") && station_node->first_attribute("x") && station_node->first_attribute("y")) + { + double zVal(0.0); + if (station_node->first_attribute("z")) + zVal = strtod(station_node->first_attribute("z")->value(), 0); + + std::string station_name(""), sensor_data_file_name(""), bdate_str("0000-00-00"); + double station_value(0.0), borehole_depth(0.0); + if (station_node->first_node("name")) + station_name = station_node->first_node("name")->value(); + if (station_node->first_node("sensordata")) + sensor_data_file_name = station_node->first_node("sensordata")->value(); + if (station_node->first_node("value")) + station_value = strtod(station_node->first_node("value")->value(), 0); + /* add other station features here */ + + if (std::string(station_node->name()).compare("station") == 0) + { + GeoLib::Station* s = new GeoLib::Station( + strtod(station_node->first_attribute("x")->value(), 0), + strtod(station_node->first_attribute("y")->value(), 0), + zVal, + station_name); + s->setStationValue(station_value); + if (!sensor_data_file_name.empty()) + s->addSensorDataFromCSV(BaseLib::copyPathToFileName(sensor_data_file_name, file_name)); + stations->push_back(s); + } + else if (std::string(station_node->name()).compare("borehole") == 0) + { + if (station_node->first_node("bdepth")) + borehole_depth = strtod(station_node->first_node("bdepth")->value(), 0); + if (station_node->first_node("bdate")) + bdate_str = station_node->first_node("bdate")->value(); + /* add other borehole features here */ + + GeoLib::StationBorehole* s = GeoLib::StationBorehole::createStation( + station_name, + strtod(station_node->first_attribute("x")->value(), 0), + strtod(station_node->first_attribute("y")->value(), 0), + zVal, + borehole_depth, + bdate_str); + s->setStationValue(station_value); + + if (station_node->first_node("strat")) + RapidXMLInterface::readStratigraphy(station_node->first_node("strat"), s); + + stations->push_back(s); + + } + } + else + std::cout << "XmlStnInterface::rapidReadStations() - Attribute missing in <station> tag ..." << std::endl; + } +} + +void RapidXMLInterface::readStratigraphy( const rapidxml::xml_node<>* strat_root, GeoLib::StationBorehole* borehole ) +{ + double depth_check((*borehole)[2]); + + for (rapidxml::xml_node<>* horizon_node = strat_root->first_node("horizon"); horizon_node; horizon_node = horizon_node->next_sibling()) + { + if (horizon_node->first_attribute("id") && horizon_node->first_attribute("x") && + horizon_node->first_attribute("y") && horizon_node->first_attribute("z")) + { + std::string horizon_name("[NN]"); + if (horizon_node->first_node("name")) + horizon_name = horizon_node->first_node("name")->value(); + /* add other horizon features here */ + + double depth (strtod(horizon_node->first_attribute("z")->value(), 0)); + if (fabs(depth - depth_check) > std::numeric_limits<double>::epsilon()) // skip soil-layer if its thickness is zero + { + borehole->addSoilLayer(strtod(horizon_node->first_attribute("x")->value(), 0), + strtod(horizon_node->first_attribute("y")->value(), 0), + depth, + horizon_name); + depth_check = depth; + } + else + std::cout << "Warning: Skipped layer \"" << horizon_name << "\" in borehole \"" + << borehole->getName() << "\" because of thickness 0.0." << std::endl; + } + else + std::cout << + "XmlStnInterface::rapidReadStratigraphy() - Attribute missing in <horizon> tag ..." << std::endl; + } +} + +} diff --git a/FileIO/XmlIO/RapidXMLInterface.h b/FileIO/XmlIO/RapidXMLInterface.h new file mode 100644 index 0000000000000000000000000000000000000000..0ba9cd598e6e12a7525cba4733d715dbf59052ab --- /dev/null +++ b/FileIO/XmlIO/RapidXMLInterface.h @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2012, OpenGeoSys Community (http://www.opengeosys.net) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.net/LICENSE.txt + * + * \file RapidXMLInterface.h + * + * Created on 2012-08-16 by Karsten Rink + */ + +#ifndef RAPIDXMLINTERFACE_H +#define RAPIDXMLINTERFACE_H + +#include "RapidXML/rapidxml.hpp" +#include <vector> + +#include "Point.h" + +namespace GeoLib { + class StationBorehole; +} + +namespace FileIO +{ + +/** + * \brief Base class for writing any information to and from XML files. + */ +class RapidXMLInterface +{ +public: + /// Reads an xml-file using the RapidXML parser integrated in the source code (i.e. this function is usable without Qt) + //int rapidReadFile(const std::string &fileName); + static std::vector<GeoLib::Point*> *readStationFile(const std::string &fileName); + +private: + /// Reads GEOLIB::Station- or StationBorehole-objects from an xml-file using the RapidXML parser + static void readStations(const rapidxml::xml_node<>* station_root, std::vector<GeoLib::Point*> *stations, const std::string &file_name); + + /// Reads the stratigraphy of a borehole from an xml-file using the RapidXML parser + static void readStratigraphy(const rapidxml::xml_node<>* strat_root, GeoLib::StationBorehole* borehole); +}; + +} + +#endif // RAPIDXMLINTERFACE_H diff --git a/FileIO/XmlIO/VTKInterface.cpp b/FileIO/XmlIO/VTKInterface.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d706be51d0fa0488a33ab32b4e4003d9fc5fc5ec --- /dev/null +++ b/FileIO/XmlIO/VTKInterface.cpp @@ -0,0 +1,388 @@ +/** + * Copyright (c) 2012, OpenGeoSys Community (http://www.opengeosys.net) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.net/LICENSE.txt + * + * \file VTKInterface.cpp + * + * Created on 2012-08-30 by Karsten Rink + */ + +#include "VTKInterface.h" +#include <iostream> +#include <fstream> + +#include "RapidXML/rapidxml_print.hpp" +#include "StringTools.h" +#include "ProjectData.h" + +// MSH +#include "Mesh.h" +#include "Node.h" +#include "Elements/Edge.h" +#include "Elements/Tri.h" +#include "Elements/Quad.h" +#include "Elements/Tet.h" +#include "Elements/Hex.h" +#include "Elements/Pyramid.h" +#include "Elements/Prism.h" + + +namespace FileIO { + +using namespace rapidxml; + +VTKInterface::VTKInterface() +: _export_name(""), _mesh(NULL), _doc(new xml_document<>), _use_compressor(false) +{ +} + +VTKInterface::~VTKInterface() +{ + delete _doc; +} + +MeshLib::Mesh* VTKInterface::readVTUFile(const std::string &file_name) +{ + std::ifstream in(file_name.c_str()); + if (in.fail()) + { + std::cout << "VTKInterface::readVTUFile() - Can't open xml-file." << std::endl; + return NULL; + } + + in.seekg(0, std::ios::end); + const size_t length = in.tellg(); + in.seekg(0, std::ios::beg); + char* buffer = new char[length+1]; + in.read(buffer, length); + buffer[in.gcount()] = '\0'; + in.close(); + + // build DOM tree + rapidxml::xml_document<> doc; + doc.parse<0>(buffer); + + rapidxml::xml_node<>* root_node (doc.first_node()); + if (isVTKUnstructuredGrid(root_node)) + { + //check if content is compressed + const rapidxml::xml_attribute<>* compressor (root_node->first_attribute("compressor")); + + //skip to <Piece>-tag and start parsing content + const rapidxml::xml_node<>* piece_node (doc.first_node()->first_node()->first_node("Piece")); + if (piece_node) + { + const unsigned nNodes = static_cast<unsigned>(atoi(piece_node->first_attribute("NumberOfPoints")->value())); + const unsigned nElems = static_cast<unsigned>(atoi(piece_node->first_attribute("NumberOfCells")->value())); + std::vector<MeshLib::Node*> nodes(nNodes); + std::vector<MeshLib::Element*> elements(nElems); + std::vector<unsigned> mat_ids(nElems, 0); + std::vector<unsigned> cell_types(nElems); + + const rapidxml::xml_node<>* mat_id_node (piece_node->first_node("CellData")->first_node("DataArray")); + if (mat_id_node && + ((std::string(mat_id_node->first_attribute("Name")->value()).compare("MaterialIDs") == 0) || + (std::string(mat_id_node->first_attribute("Name")->value()).compare("MatGroup") == 0))) + { + if (std::string(mat_id_node->first_attribute("format")->value()).compare("ascii") == 0) + { + std::stringstream iss (mat_id_node->value()); + for(unsigned i=0; i<nElems; i++) + iss >> mat_ids[i]; + } + } + else + std::cout << "Warning in VTKInterface::readVTUFile() - MaterialID array not found." << std::endl; + + + const rapidxml::xml_node<>* points_node (piece_node->first_node("Points")->first_node("DataArray")); + // This _may_ have an attribute "Name" with the value "Points" but you cannot count on it. + // However, there shouldn't be any other DataArray nodes so most likely not checking the name isn't a problem. + if (points_node) + { + if (std::string(points_node->first_attribute("format")->value()).compare("ascii") == 0) + { + std::stringstream iss (points_node->value()); + double x,y,z; + for(unsigned i=0; i<nNodes; i++) + { + iss >> x >> y >> z; + nodes[i] = new MeshLib::Node(x,y,z,i); + } + } + } + else + { + std::cout << "Error in VTKInterface::readVTUFile() - Points array not found." << std::endl; + return NULL; + } + + rapidxml::xml_node<>* cells_node (piece_node->first_node("Cells")); + rapidxml::xml_node<>* connectivity_node (NULL); + rapidxml::xml_node<>* celltype_node (NULL); + for (rapidxml::xml_node<>* cells_data = cells_node->first_node("DataArray"); cells_data; cells_data = cells_data->next_sibling("DataArray")) + { + if (std::string(cells_data->first_attribute("Name")->value()).compare("connectivity") == 0) + connectivity_node = cells_data; + if (std::string(cells_data->first_attribute("Name")->value()).compare("types") == 0) + celltype_node = cells_data; + } + + if (connectivity_node && celltype_node) + { + if (std::string(celltype_node->first_attribute("format")->value()).compare("ascii") == 0) + { + std::stringstream iss (celltype_node->value()); + for(unsigned i=0; i<nElems; i++) + iss >> cell_types[i]; + } + if (std::string(connectivity_node->first_attribute("format")->value()).compare("ascii") == 0) + { + std::stringstream iss (connectivity_node->value()); + for(unsigned i=0; i<nElems; i++) + elements[i] = readElement(iss, nodes, mat_ids[i], cell_types[i]); + } + } + else + { + std::cout << "Error in VTKInterface::readVTUFile() - Cell data not found." << std::endl; + return NULL; + } + + return new MeshLib::Mesh(BaseLib::getFileNameFromPath(file_name), nodes, elements); + } + else + std::cout << "Error in VTKInterface::readVTUFile() - Number of nodes and elements not specified." << std::endl; + } + return NULL; +} + +MeshLib::Element* VTKInterface::readElement(std::stringstream &iss, const std::vector<MeshLib::Node*> &nodes, unsigned material, unsigned type) +{ + unsigned node_ids[8]; + switch (type) + { + case 3: //line + for (unsigned i(0); i<2; i++) iss >> node_ids[i]; + return new MeshLib::Edge(nodes[node_ids[0]], nodes[node_ids[1]], material); + break; + case 5: //triangle + for (unsigned i(0); i<3; i++) iss >> node_ids[i]; + return new MeshLib::Tri(nodes[node_ids[0]], nodes[node_ids[1]], nodes[node_ids[2]], material); + break; + case 9: //quad + for (unsigned i(0); i<4; i++) iss >> node_ids[i]; + return new MeshLib::Quad(nodes[node_ids[0]], nodes[node_ids[1]], nodes[node_ids[2]], nodes[node_ids[3]], material); + break; + case 8: //pixel + for (unsigned i(0); i<4; i++) iss >> node_ids[i]; + return new MeshLib::Quad(nodes[node_ids[0]], nodes[node_ids[1]], nodes[node_ids[3]], nodes[node_ids[2]], material); + break; + case 10: + for (unsigned i(0); i<4; i++) iss >> node_ids[i]; + return new MeshLib::Tet(nodes[node_ids[0]], nodes[node_ids[1]], nodes[node_ids[2]], nodes[node_ids[3]], material); + break; + case 12: //hexahedron + for (unsigned i(0); i<8; i++) iss >> node_ids[i]; + return new MeshLib::Hex(nodes[node_ids[0]], nodes[node_ids[1]], nodes[node_ids[2]], nodes[node_ids[3]], + nodes[node_ids[4]], nodes[node_ids[5]], nodes[node_ids[6]], nodes[node_ids[7]], material); + break; + case 11: //voxel + for (unsigned i(0); i<8; i++) iss >> node_ids[i]; + return new MeshLib::Hex(nodes[node_ids[0]], nodes[node_ids[1]], nodes[node_ids[3]], nodes[node_ids[2]], + nodes[node_ids[4]], nodes[node_ids[5]], nodes[node_ids[7]], nodes[node_ids[6]], material); + break; + case 14: //pyramid + for (unsigned i(0); i<5; i++) iss >> node_ids[i]; + return new MeshLib::Pyramid(nodes[node_ids[0]], nodes[node_ids[1]], nodes[node_ids[2]], + nodes[node_ids[3]], nodes[node_ids[4]], material); + break; + case 13: //wedge + for (unsigned i(0); i<6; i++) iss >> node_ids[i]; + return new MeshLib::Prism(nodes[node_ids[0]], nodes[node_ids[1]], nodes[node_ids[2]], + nodes[node_ids[3]], nodes[node_ids[4]], nodes[node_ids[5]], material); + break; + default: + std::cout << "Error in VTKInterface::readElement() - Unknown mesh element type \"" << type << "\" ..." << std::endl; + return NULL; + } + +} + +bool VTKInterface::isVTKFile(const rapidxml::xml_node<>* vtk_root) +{ + if (vtk_root == NULL || std::string(vtk_root->name()).compare("VTKFile")) + { + std::cout << "Error in VTKInterface::readVTUFile() - Not a VTK File." << std::endl; + return false; + } + if (std::string(vtk_root->first_attribute("version")->value()).compare("0.1")) + { + std::cout << "Error in VTKInterface::readVTUFile() - Unsupported file format version." << std::endl; + return false; + } + if (std::string(vtk_root->first_attribute("byte_order")->value()).compare("LittleEndian")) + { + std::cout << "Error in VTKInterface::readVTUFile() - Only little endian files are supported." << std::endl; + return false; + } + return true; +} + +bool VTKInterface::isVTKUnstructuredGrid(const rapidxml::xml_node<>* vtk_root) +{ + if (isVTKFile(vtk_root)) + { + if (std::string(vtk_root->first_node()->name()).compare("UnstructuredGrid") == 0) + return true; + std::cout << "Error in VTKInterface::readVTUFile() - Not an unstructured grid." << std::endl; + } + return false; +} + +int VTKInterface::write(std::ostream& stream) +{ + //if (this->_export_name.empty()) + if (!_mesh) + { + std::cout << "Error in XmlStnInterface::write() - No station list specified..." << std::endl; + return 0; + } + + const size_t nNodes (_mesh->getNNodes()); + const size_t nElems (_mesh->getNElements()); + const std::vector<MeshLib::Node*> &nodes (_mesh->getNodes()); + const std::vector<MeshLib::Element*> &elements (_mesh->getElements()); + + const std::string data_array_close("\t\t\t\t"); + const std::string data_array_indent("\t\t\t\t "); + + stream << "<?xml version=\"1.0\"?>" << std::endl; + + xml_node<> *root_node (_doc->allocate_node(node_element, "VTKFile")); + _doc->append_node(root_node); + root_node->append_attribute(_doc->allocate_attribute("type", "UnstructuredGrid")); + root_node->append_attribute(_doc->allocate_attribute("version", "0.1")); + root_node->append_attribute(_doc->allocate_attribute("byte_order", "LittleEndian")); + if (_use_compressor) + root_node->append_attribute(_doc->allocate_attribute("compressor", "vtkZLibDataCompressor")); + + xml_node<> *grid_node (_doc->allocate_node(node_element, "UnstructuredGrid")); + root_node->append_node(grid_node); + xml_node<> *piece_node (_doc->allocate_node(node_element, "Piece")); + grid_node->append_node(piece_node); + const std::string str_nNodes (number2str(nNodes)); + piece_node->append_attribute (_doc->allocate_attribute("NumberOfPoints", str_nNodes.c_str())); + const std::string str_nElems (number2str(nElems)); + piece_node->append_attribute(_doc->allocate_attribute("NumberOfCells", str_nElems.c_str())); + + // scalar arrays for point- and cell-data + xml_node<> *pointdata_node (_doc->allocate_node(node_element, "PointData", "\n\t\t\t")); + piece_node->append_node(pointdata_node); + // add node_area array here if necessary! + xml_node<> *celldata_node (_doc->allocate_node(node_element, "CellData")); + piece_node->append_node(celldata_node); + celldata_node->append_attribute(_doc->allocate_attribute("Scalars", "MaterialIDs")); + + std::stringstream oss(std::stringstream::out); + oss << std::endl << data_array_indent; + for (unsigned i=0; i<nElems; i++) + oss << elements[i]->getValue() << " "; + oss << std::endl << data_array_close; + celldata_node->append_node(this->addDataArray("MaterialIDs", "Int32", oss.str())); + oss.str(std::string()); + oss.clear(); + + // point coordinates + xml_node<> *points_node (_doc->allocate_node(node_element, "Points")); + piece_node->append_node(points_node); + oss << std::endl; + for (unsigned i=0; i<nNodes; i++) + oss << data_array_indent << (*nodes[i])[0] << " " << (*nodes[i])[1] << " " << (*nodes[i])[2] << std::endl; + oss << data_array_close; + points_node->append_node(this->addDataArray("Points", "Float32", oss.str(), 3)); + oss.str(std::string()); + oss.clear(); + + // cells with node ids + xml_node<> *cells_node (_doc->allocate_node(node_element, "Cells")); + piece_node->append_node(cells_node); + std::stringstream offstream(std::stringstream::out); + std::stringstream typestream(std::stringstream::out); + oss << std::endl; + offstream << std::endl << data_array_indent; + typestream << std::endl << data_array_indent; + + unsigned offset_count(0); + for (unsigned i=0; i<nElems; i++) + { + MeshLib::Element* element (elements[i]); + const unsigned nElemNodes (element->getNNodes()); + oss << data_array_indent; + for (unsigned j=0; j<nElemNodes; j++) + oss << element->getNode(j)->getID() << " "; + oss << std::endl; + offset_count += nElemNodes; + offstream << offset_count << " "; + typestream << this->getVTKElementID(element->getType()) << " "; + } + oss << data_array_close; + offstream << std::endl << data_array_close; + typestream << std::endl << data_array_close; + + // connectivity attributes + cells_node->append_node(this->addDataArray("connectivity", "Int32", oss.str())); + cells_node->append_node(this->addDataArray("offsets", "Int32", offstream.str())); + cells_node->append_node(this->addDataArray("types", "UInt8", typestream.str())); + + stream << *_doc; + return 1; +} + +unsigned VTKInterface::getVTKElementID(MshElemType::type type) const +{ + switch (type) + { + case MshElemType::EDGE: + return 3; + case MshElemType::TRIANGLE: + return 5; + case MshElemType::QUAD: + return 9; + case MshElemType::TETRAHEDRON: + return 10; + case MshElemType::HEXAHEDRON: + return 12; + case MshElemType::PYRAMID: + return 14; + case MshElemType::PRISM: + return 13; + default: + return std::numeric_limits<unsigned>::max(); + } +} + +xml_node<>* VTKInterface::addDataArray(const std::string &name, const std::string &data_type, const std::string &data, unsigned nComponents) +{ + + xml_attribute<> *attr (NULL); + xml_node<> *dataarray_node (_doc->allocate_node(node_element, _doc->allocate_string("DataArray"), _doc->allocate_string(data.c_str()))); + attr = _doc->allocate_attribute(_doc->allocate_string("type"), _doc->allocate_string(data_type.c_str())); + dataarray_node->append_attribute(attr); + attr = _doc->allocate_attribute(_doc->allocate_string("Name"), _doc->allocate_string(name.c_str())); + dataarray_node->append_attribute(attr); + if (nComponents > 1) + { + attr = _doc->allocate_attribute(_doc->allocate_string("NumberOfComponents"), _doc->allocate_string(number2str(nComponents).c_str())); + dataarray_node->append_attribute(attr); + } + std::string comp_type = (_use_compressor) ? "appended" : "ascii"; + attr = _doc->allocate_attribute(_doc->allocate_string("format"), _doc->allocate_string(comp_type.c_str())); + dataarray_node->append_attribute(attr); + // ---- offset attribute for compressed data! ---- + return dataarray_node; +} + +} // end namespace FileIO diff --git a/FileIO/XmlIO/VTKInterface.h b/FileIO/XmlIO/VTKInterface.h new file mode 100644 index 0000000000000000000000000000000000000000..1228d5791f9b931b9f20f47b79cbb15b64fdcbce --- /dev/null +++ b/FileIO/XmlIO/VTKInterface.h @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2012, OpenGeoSys Community (http://www.opengeosys.net) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.net/LICENSE.txt + * + * \file VTKInterface.h + * + * Created on 2012-08-30 by Karsten Rink + */ + +#ifndef VTKINTERFACE_H_ +#define VTKINTERFACE_H_ + +#include "Writer.h" + +#include <string> +#include <vector> + +#include "MshEnums.h" +#include "RapidXML/rapidxml.hpp" + +class ProjectData; + +namespace MeshLib { + class Mesh; + class Node; + class Element; +} + +namespace FileIO +{ + +/** + * \brief Reads and writes VtkXMLUnstructuredGrid-files (vtu) to and from OGS data structures. + * + * XML parsing is performed using RapidXML. Note, that this library uses string references instead + * of copies of strings, i.e. strings used in the DOM tree need to be available as long the DOM tree + * is needed. + */ +class VTKInterface : public Writer +{ +public: + VTKInterface(); + ~VTKInterface(); + + /// Read an unstructured grid from a VTU file + static MeshLib::Mesh* readVTUFile(const std::string &file_name); + + /// Decide if the mesh data should be written compressed (default is false). + void setCompressData(bool flag=true) { _use_compressor = flag; }; + + /// Set mesh for writing. + void setMesh(const MeshLib::Mesh* mesh) { this->_mesh = const_cast<MeshLib::Mesh*>(mesh); }; + +protected: + /// Adds a VTK-DataArray of the given name and datatype to the DOM tree and inserts the data-string at that node + rapidxml::xml_node<>* addDataArray(const std::string &name, const std::string &data_type, const std::string &data, unsigned nComponents = 1); + + int write(std::ostream& stream); + + std::string _export_name; + MeshLib::Mesh* _mesh; + rapidxml::xml_document<> *_doc; + +private: + /// Returns the ID used by VTK for a given cell type (e.g. "5" for a triangle, etc.) + unsigned getVTKElementID(MshElemType::type type) const; + + /// Check if the root node really specifies an XML file + static bool isVTKFile(const rapidxml::xml_node<>* node); + + /// Check if the file really specifies a VTK Unstructured Grid + static bool isVTKUnstructuredGrid(const rapidxml::xml_node<>* node); + + /// Construct an Element-object from the data given to the method and the data at the current stream position. + static MeshLib::Element* readElement(std::stringstream &iss, const std::vector<MeshLib::Node*> &nodes, unsigned material, unsigned type); + + bool _use_compressor; +}; +} + +#endif /* VTKINTERFACE_H_ */ diff --git a/Gui/DataExplorer.cmake b/Gui/DataExplorer.cmake index 2a79c966ddc3425dade068d17b596101a7ef3ea9..0780ae920101221abac144f7349487f2897b9326 100644 --- a/Gui/DataExplorer.cmake +++ b/Gui/DataExplorer.cmake @@ -186,9 +186,9 @@ IF (OGS_PACKAGING) INSTALL (TARGETS ogs-gui RUNTIME DESTINATION bin COMPONENT ogs_gui) IF(MSVC) - SET(OGS_GUI_EXE ${OGS_EXECUTABLE}-gui.exe) + SET(OGS_GUI_EXE ${EXECUTABLE_OUTPUT_PATH}/Release/ogs-gui.exe) ELSE(MSVC) - SET(OGS_GUI_EXE ${OGS_EXECUTABLE}-gui) + SET(OGS_GUI_EXE ${EXECUTABLE_OUTPUT_PATH}/ogs-gui) ENDIF(MSVC) INCLUDE(GetPrerequisites) diff --git a/Gui/DataView/DataView.cpp b/Gui/DataView/DataView.cpp index 227027e88f6d03070d4a26452dc8d4256a371d72..f0a9b1a6a2564336be88e39e778bb781a090a592 100644 --- a/Gui/DataView/DataView.cpp +++ b/Gui/DataView/DataView.cpp @@ -26,6 +26,7 @@ #include <QSettings> #include "Legacy/MeshIO.h" +#include "XmlIO/VTKInterface.h" #include "Writer.h" // necessary to avoid Linker Error in Windows DataView::DataView( QWidget* parent /*= 0*/ ) @@ -35,6 +36,10 @@ DataView::DataView( QWidget* parent /*= 0*/ ) //resizeRowsToContents(); } +DataView::~DataView() +{ +} + void DataView::updateView() { setAlternatingRowColors(true); @@ -110,8 +115,8 @@ void DataView::openMshEditDialog() static_cast<MshModel*>(this->model())->getMesh(index); MshEditDialog meshEdit(mesh); - connect(&meshEdit, SIGNAL(mshEditFinished(MeshLib::CFEMesh*, std::string &)), - model, SLOT(addMesh(MeshLib::CFEMesh*, std::string &))); + connect(&meshEdit, SIGNAL(mshEditFinished(MeshLib::Mesh*)), + model, SLOT(addMesh(MeshLib::Mesh*))); meshEdit.exec(); } @@ -128,13 +133,23 @@ int DataView::writeMeshToFile() const static_cast<MshModel*>(this->model())->getMesh(index)->getName()); QString fileName = QFileDialog::getSaveFileName(NULL, "Save mesh as", settings.value("lastOpenedMeshFileDirectory").toString(), - "GeoSys mesh file (*.msh)"); + "VTK Unstructured Grid (*.vtu);;GeoSys legacy mesh file (*.msh)"); if (!fileName.isEmpty()) { - FileIO::MeshIO meshIO; - meshIO.setMesh(mesh); - meshIO.writeToFile(fileName.toStdString().c_str()); + QFileInfo fi(fileName); + if (fi.suffix().toLower() == "vtu") + { + FileIO::VTKInterface vtkIO; + vtkIO.setMesh(mesh); + vtkIO.writeToFile(fileName.toStdString().c_str()); + } + if (fi.suffix().toLower() == "msh") + { + FileIO::MeshIO meshIO; + meshIO.setMesh(mesh); + meshIO.writeToFile(fileName.toStdString().c_str()); + } QDir dir = QDir(fileName); settings.setValue("lastOpenedMeshFileDirectory", dir.absolutePath()); return 1; diff --git a/Gui/DataView/DataView.h b/Gui/DataView/DataView.h index 8ce62be874a549b6e907d184cf088d71a1e5ef01..60c558540938d7d2d92e3ebfc0d8afaf1166d112 100644 --- a/Gui/DataView/DataView.h +++ b/Gui/DataView/DataView.h @@ -15,13 +15,11 @@ #include "GeoType.h" #include <QTreeView> -class GridAdapter; class MshModel; class VtkMeshSource; -namespace MeshLib -{ -class CFEMesh; +namespace MeshLib { + class Mesh; } /* namespace GeoLib { @@ -38,6 +36,7 @@ class DataView : public QTreeView public: DataView(QWidget* parent = 0); + ~DataView(); public slots: void updateView(); diff --git a/Gui/DataView/DirectConditionGenerator.cpp b/Gui/DataView/DirectConditionGenerator.cpp index 38d8fcf95697841a2db523e7159bd3ac40f67b15..4f25983ca5210f81d649b08576e0cf638c5292b5 100644 --- a/Gui/DataView/DirectConditionGenerator.cpp +++ b/Gui/DataView/DirectConditionGenerator.cpp @@ -32,7 +32,7 @@ const std::vector< std::pair<size_t,double> >& DirectConditionGenerator::directT return _direct_values; } - const std::vector<GeoLib::PointWithID*> surface_nodes ( MshEditor::getSurfaceNodes(mesh) ); + const std::vector<GeoLib::PointWithID*> surface_nodes ( MeshLib::MshEditor::getSurfaceNodes(mesh) ); //std::vector<MeshLib::CNode*> nodes = mesh.nod_vector; const size_t nNodes(surface_nodes.size()); _direct_values.reserve(nNodes); diff --git a/Gui/DataView/MshEdit.ui b/Gui/DataView/MshEdit.ui index af36067029927f9fd365ff234b76dbe9d0ea27c9..354315f47270f59cda387207dbf3421b6b30969c 100644 --- a/Gui/DataView/MshEdit.ui +++ b/Gui/DataView/MshEdit.ui @@ -13,362 +13,59 @@ <property name="windowTitle"> <string>Dialog</string> </property> - <layout class="QVBoxLayout" name="verticalLayout_2"> + <layout class="QVBoxLayout" name="verticalLayout"> <item> - <widget class="QTabWidget" name="tabWidget"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="currentIndex"> - <number>0</number> - </property> - <widget class="QWidget" name="tab3DExtrusion"> - <attribute name="title"> - <string>3D Extrusion</string> - </attribute> - <layout class="QVBoxLayout" name="verticalLayout_3"> - <item> - <layout class="QVBoxLayout" name="vLayout3DExtrusion"> - <property name="spacing"> - <number>16</number> - </property> - <item> - <widget class="QLabel" name="label_4"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>50</height> - </size> - </property> - <property name="font"> - <font> - <pointsize>11</pointsize> - <weight>75</weight> - <bold>true</bold> - </font> - </property> - <property name="text"> - <string>Extrude Mesh-Elements to 3D</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="label"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Please specify the number of layers and their default thickness:</string> - </property> - <property name="margin"> - <number>0</number> - </property> - </widget> - </item> - <item> - <layout class="QGridLayout" name="gridLayout3DExtrusion"> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>15</number> - </property> - <property name="horizontalSpacing"> - <number>16</number> - </property> - <property name="verticalSpacing"> - <number>26</number> - </property> - <item row="0" column="0"> - <widget class="QLabel" name="labelNLayers"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>0</height> - </size> - </property> - <property name="text"> - <string>Number of Layers</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLineEdit" name="editNLayers"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>0</height> - </size> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="labelThickness"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>80</width> - <height>0</height> - </size> - </property> - <property name="text"> - <string>Thickness</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLineEdit" name="editThickness"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - <item row="0" column="2"> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="1" column="2"> - <spacer name="horizontalSpacer_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Expanding</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="2" column="1"> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Expanding</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - <item row="2" column="0"> - <spacer name="verticalSpacer_2"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Expanding</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - <item row="2" column="2"> - <spacer name="verticalSpacer_3"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Expanding</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - </layout> - </item> - </layout> - </widget> - <widget class="QWidget" name="tabLayerMapping"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <attribute name="title"> - <string>Layer Mapping</string> - </attribute> - <layout class="QVBoxLayout" name="verticalLayout_4"> - <property name="spacing"> - <number>0</number> + <layout class="QVBoxLayout" name="dialogLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>50</height> + </size> </property> - <property name="margin"> - <number>0</number> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>50</height> + </size> </property> - <item> - <widget class="QScrollArea" name="scrollArea"> - <property name="frameShadow"> - <enum>QFrame::Sunken</enum> - </property> - <property name="lineWidth"> - <number>0</number> - </property> - <property name="widgetResizable"> - <bool>true</bool> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> - </property> - <widget class="QWidget" name="scrollAreaWidgetContents"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>382</width> - <height>249</height> - </rect> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <property name="spacing"> - <number>6</number> - </property> - <property name="margin"> - <number>9</number> - </property> - <item> - <layout class="QVBoxLayout" name="vLayoutLayerMapping"> - <property name="spacing"> - <number>16</number> - </property> - <property name="margin"> - <number>0</number> - </property> - <item> - <widget class="QLabel" name="label_5"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>50</height> - </size> - </property> - <property name="font"> - <font> - <pointsize>11</pointsize> - <weight>75</weight> - <bold>true</bold> - </font> - </property> - <property name="text"> - <string>Map mesh layers by raster</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="label_2"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Please specify which rasterfile should used for each mesh layer:</string> - </property> - </widget> - </item> - <item> - <layout class="QGridLayout" name="gridLayoutLayerMapping"> - <property name="margin"> - <number>0</number> - </property> - </layout> - </item> - </layout> - </item> - </layout> - </widget> - </widget> - </item> - </layout> - </widget> - </widget> + <property name="font"> + <font> + <family>Verdana</family> + <pointsize>12</pointsize> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="text"> + <string>Create mesh layers by raster</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item> + <layout class="QGridLayout" name="gridLayoutLayerMapping"/> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> </item> <item> <widget class="QDialogButtonBox" name="buttonBox"> diff --git a/Gui/DataView/MshEditDialog.cpp b/Gui/DataView/MshEditDialog.cpp index b6cdd02bb3d78ceb55b77f8126be02467870c1e5..6cfcaae958bc6647fd6a32b6528a6c41eb7aebd6 100644 --- a/Gui/DataView/MshEditDialog.cpp +++ b/Gui/DataView/MshEditDialog.cpp @@ -20,20 +20,59 @@ #include <QFileDialog> #include <QPushButton> #include <QSettings> +#include <QLineEdit> MshEditDialog::MshEditDialog(const MeshLib::Mesh* mesh, QDialog* parent) - : QDialog(parent), _msh(mesh), _noDataDeleteBox(NULL) + : QDialog(parent), _msh(mesh), _noDataDeleteBox(NULL), + _nLayerLabel (new QLabel("Please specify the number of layers to add:")), + _selectLabel(NULL), + _layerEdit (new QLineEdit("0")), + _nextButton (new QPushButton("Next")) { setupUi(this); -/* TODO6 - this->gridLayoutLayerMapping->setMargin(5); + + this->gridLayoutLayerMapping->addWidget(_nLayerLabel, 0, 0, 1, 2); + this->gridLayoutLayerMapping->addWidget(_layerEdit, 0, 2); + this->gridLayoutLayerMapping->addWidget(_nextButton, 0, 3); + connect(_nextButton, SIGNAL(pressed()), this, SLOT(nextButtonPressed())); +} + +MshEditDialog::~MshEditDialog() +{ + + delete _nLayerLabel; + delete _selectLabel; + delete _layerEdit; + delete _nextButton; + delete _noDataDeleteBox; + + for (int i = 0; i < _labels.size(); i++) + { + delete _labels[i]; + delete _edits[i]; + delete _buttons[i]; + } + +} + +void MshEditDialog::nextButtonPressed() +{ + _layerEdit->setEnabled(false); + _nextButton->setEnabled(false); + const size_t nLayers = _layerEdit->text().toInt(); + const QString selectText = (nLayers>0) ? + "Please specify a raster file for mapping each layer:" : + "Please specify which rasterfile surface mapping:"; + _selectLabel = new QLabel(selectText); + _selectLabel->setMargin(20); + this->gridLayoutLayerMapping->addWidget(_selectLabel, 1, 0, 1, 4); + + this->gridLayoutLayerMapping->setMargin(10); this->gridLayoutLayerMapping->setColumnMinimumWidth(2,10); this->gridLayoutLayerMapping->setColumnStretch(0, 80); this->gridLayoutLayerMapping->setColumnStretch(1, 200); this->gridLayoutLayerMapping->setColumnStretch(2, 10); - - size_t nLayers = mesh->getNumberOfMeshLayers(); - + for (size_t i = 0; i <= nLayers+1; i++) { QString text(""); @@ -50,9 +89,9 @@ MshEditDialog::MshEditDialog(const MeshLib::Mesh* mesh, QDialog* parent) _fileButtonMap.insert(button, edit); connect(button, SIGNAL(clicked()), this, SLOT(getFileName())); - this->gridLayoutLayerMapping->addWidget(_labels[i], i, 0); - this->gridLayoutLayerMapping->addWidget(_edits[i], i, 1); - this->gridLayoutLayerMapping->addWidget(_buttons[i], i, 2); + this->gridLayoutLayerMapping->addWidget(_labels[i], i+2, 0); + this->gridLayoutLayerMapping->addWidget(_edits[i], i+2, 1, 1, 2); + this->gridLayoutLayerMapping->addWidget(_buttons[i], i+2, 3); if (nLayers==0) break; // don't add bottom layer if mesh contains only surface } @@ -63,88 +102,73 @@ MshEditDialog::MshEditDialog(const MeshLib::Mesh* mesh, QDialog* parent) if (nLayers == 0) { _noDataDeleteBox->setEnabled(true); - this->gridLayoutLayerMapping->addWidget(_noDataDeleteBox, 2, 1); - } - */ -} - -MshEditDialog::~MshEditDialog() -{ - delete _noDataDeleteBox; - - for (int i = 0; i < _labels.size(); i++) - { - delete _labels[i]; - delete _edits[i]; - delete _buttons[i]; + this->gridLayoutLayerMapping->addWidget(_noDataDeleteBox, 4, 1); } } void MshEditDialog::accept() { -/* TODO6 - int tabIndex = this->tabWidget->currentIndex(); - - if (tabIndex >= 0) + if (_labels.size()>0) { - MeshLib::CFEMesh* new_mesh = NULL; - - switch (tabIndex) - { - case 0: + bool all_paths_set (true); + if ((_labels.size()==1) && (_edits[0]->text().length()==0)) + all_paths_set = false; + else { - const int nLayers = atoi(this->editNLayers->text().toStdString().c_str()); - const double thickness = strtod(replaceString(",", ".", this->editThickness->text().toStdString()).c_str(), 0); - new_mesh = MshLayerMapper::CreateLayers(_msh, nLayers, thickness); - break; + for (unsigned i=1; i<_labels.size(); i++) + if (_edits[i]->text().length()==0) + all_paths_set = false; } - case 1: + + if (all_paths_set) { - new_mesh = new MeshLib::CFEMesh(*_msh); - const size_t nLayers = _msh->getNumberOfMeshLayers(); + const size_t nLayers = _layerEdit->text().toInt(); + MeshLib::Mesh* new_mesh (NULL); + if (nLayers==0) { + new_mesh = new MeshLib::Mesh(*_msh); const std::string imgPath ( this->_edits[0]->text().toStdString() ); if (!imgPath.empty()) MshLayerMapper::LayerMapping(new_mesh, imgPath, nLayers, 0, _noDataDeleteBox->isChecked()); } else { - for (size_t i = 1; i <= nLayers+1; i++) + new_mesh = MshLayerMapper::CreateLayers(_msh, nLayers, 100); + + for (size_t i = 0; i <= nLayers; i++) { const std::string imgPath ( this->_edits[i]->text().toStdString() ); if (!imgPath.empty()) { - int result = MshLayerMapper::LayerMapping(new_mesh, imgPath, nLayers, i-1, _noDataDeleteBox->isChecked()); + int result = MshLayerMapper::LayerMapping(new_mesh, imgPath, nLayers, i, _noDataDeleteBox->isChecked()); if (result==0) break; } } + + if (this->_edits[0]->text().length()>0) + { + MeshLib::Mesh* final_mesh = MshLayerMapper::blendLayersWithSurface(new_mesh, nLayers, this->_edits[0]->text().toStdString()); + delete new_mesh; + new_mesh = final_mesh; + } } - if (nLayers>0 && this->_edits[0]->text().length()>0) + + if (new_mesh) { - MeshLib::CFEMesh* final_mesh = MshLayerMapper::blendLayersWithSurface(new_mesh, nLayers, this->_edits[0]->text().toStdString()); - delete new_mesh; - new_mesh = final_mesh; + new_mesh->setName("NewMesh"); + emit mshEditFinished(new_mesh); } - break; - } - default: - std::cout << - "Error in MshEditDialog::accept() - No instructions found for selected tab..." - << std::endl; - } - if (new_mesh) - { - std::string mshname("NewMesh"); - emit mshEditFinished(new_mesh, mshname); + else + OGSError::box("Error creating mesh"); + + this->done(QDialog::Accepted); } else - OGSError::box("Error creating mesh"); + OGSError::box("Please specifiy raster files for all layers."); } else - std::cout << "Error in MshEditDialog::accept() - No tab selected... " << std::endl; - this->done(QDialog::Accepted); -*/ + OGSError::box("Please specifiy the number of\n layers and press \"Next\""); } void MshEditDialog::reject() @@ -156,11 +180,8 @@ void MshEditDialog::getFileName() { QPushButton* button = dynamic_cast<QPushButton*>(this->sender()); QSettings settings("UFZ", "OpenGeoSys-5"); - QString filename = QFileDialog::getOpenFileName(this, - "Select raster file to open", - settings.value( - "lastOpenedFileDirectory").toString( - ), + QString filename = QFileDialog::getOpenFileName(this, "Select raster file to open", + settings.value("lastOpenedFileDirectory").toString(), "ASCII raster files (*.asc);;All files (* *.*)"); _fileButtonMap[button]->setText(filename); QDir dir = QDir(filename); diff --git a/Gui/DataView/MshEditDialog.h b/Gui/DataView/MshEditDialog.h index f006a2dd7d40be89d4a5356ece42f4c51925334d..50e6591ff2cca9faec4d48e3c8c513e61678e262 100644 --- a/Gui/DataView/MshEditDialog.h +++ b/Gui/DataView/MshEditDialog.h @@ -44,9 +44,16 @@ private: QVector<QPushButton*> _buttons; QCheckBox* _noDataDeleteBox; + QLabel* _nLayerLabel; + QLabel* _selectLabel; + QLineEdit* _layerEdit; + QPushButton* _nextButton; + private slots: void getFileName(); + void nextButtonPressed(); + /// Instructions if the OK-Button has been pressed. void accept(); @@ -54,7 +61,7 @@ private slots: void reject(); signals: - void mshEditFinished(MeshLib::Mesh*, std::string&); + void mshEditFinished(MeshLib::Mesh*); }; #endif //MSHEDITDIALOG_H diff --git a/Gui/DataView/MshLayerMapper.cpp b/Gui/DataView/MshLayerMapper.cpp index 43503b6cb18938f84fa819f010157a647029f41a..6716b972e473b9d11a953e03de4f849d89ccb8d5 100644 --- a/Gui/DataView/MshLayerMapper.cpp +++ b/Gui/DataView/MshLayerMapper.cpp @@ -9,97 +9,86 @@ * Created on 2010-11-01 by Karsten Rink */ -/* TODO6 #include "MshLayerMapper.h" #include "VtkRaster.h" +#include "Mesh.h" +#include "Node.h" +#include "Elements/Element.h" +#include "Elements/Hex.h" +#include "Elements/Prism.h" #include "MshEditor.h" -#include "matrix_class.h" -#include "msh_mesh.h" +#include "MathTools.h" #include <QImage> -MeshLib::CFEMesh* MshLayerMapper::CreateLayers(const MeshLib::CFEMesh* mesh, - size_t nLayers, - double thickness) +MeshLib::Mesh* MshLayerMapper::CreateLayers(const MeshLib::Mesh* mesh, size_t nLayers, double thickness) { - if (nLayers < 1 || thickness <= 0) + if (nLayers < 1 || thickness <= 0 || mesh->getDimension() != 2) { - std::cout << - "Error in MshLayerMapper::CreateLayers() - Invalid parameter: nLayers > 0 and thickness > 0 are required." - << std::endl; + std::cout << "Error in MshLayerMapper::CreateLayers() - A 2D mesh with nLayers>0 and thickness>0 is required as input." << std::endl; return NULL; } - - MeshLib::CFEMesh* new_mesh ( new MeshLib::CFEMesh() ); - const size_t nNodes = mesh->nod_vector.size(); - const size_t nElems = mesh->ele_vector.size(); + const size_t nNodes = mesh->getNNodes(); + const size_t nElems = mesh->getNElements(); + const std::vector<MeshLib::Node*> nodes = mesh->getNodes(); + const std::vector<MeshLib::Element*> elems = mesh->getElements(); + std::vector<MeshLib::Node*> new_nodes(nNodes + (nLayers * nNodes)); + std::vector<MeshLib::Element*> new_elems(nElems * nLayers); for (size_t layer_id = 0; layer_id <= nLayers; layer_id++) { // add nodes for new layer - size_t node_offset ( nNodes * layer_id ); - const double z_offset ( layer_id*thickness ); + unsigned node_offset (nNodes * layer_id); + const double z_offset (layer_id * thickness); for (size_t i = 0; i < nNodes; i++) { - const double* coords = mesh->nod_vector[i]->getData(); - new_mesh->nod_vector.push_back( new MeshLib::CNode(node_offset + i, - coords[0], - coords[1], - coords[2]-z_offset) ); + const double* coords = nodes[i]->getCoords(); + new_nodes[i] = new MeshLib::Node(coords[0], coords[1], coords[2]-z_offset, node_offset+i); } - if (layer_id > 0) // starting with the 2nd layer prism (or hex) elements can be created + // starting with 2nd layer create prism or hex elements connecting the last layer with the current one + if (layer_id > 0) { - // create prism elements connecting the last layer with the current one - node_offset = (layer_id - 1) * nNodes; + node_offset -= nNodes; + const unsigned mat_id (nLayers - layer_id); + for (size_t i = 0; i < nElems; i++) { - const MeshLib::CElem* sfc_elem( mesh->ele_vector[i] ); - MeshLib::CElem* elem( new MeshLib::CElem() ); - size_t nElemNodes = sfc_elem->getNodeIndices().Size(); - if (sfc_elem->GetElementType() == MshElemType::TRIANGLE) - elem->setElementProperties(MshElemType::PRISM); // extrude triangles to prism - else if (sfc_elem->GetElementType() == MshElemType::QUAD) - elem->setElementProperties(MshElemType::HEXAHEDRON); // extrude quads to hexes - else if (sfc_elem->GetElementType() == MshElemType::LINE) - continue; // line elements are ignored and not duplicated - else + const MeshLib::Element* sfc_elem( elems[i] ); + if (sfc_elem->getDimension() == 2) { - std::cout << "Error in MshLayerMapper::CreateLayers() - Method can only handle 2D mesh elements ..." << std::endl; - std::cout << "Element " << i << " is of type \"" << MshElemType2String(sfc_elem->GetElementType()) << "\"." << std::endl; - delete new_mesh; - return NULL; + const unsigned nElemNodes(sfc_elem->getNNodes()); + MeshLib::Node** e_nodes = new MeshLib::Node*[2*nElemNodes]; + + for (size_t j=0; j<nElemNodes; j++) + { + const unsigned node_id = sfc_elem->getNode(j)->getID() + node_offset; + e_nodes[j] = new_nodes[node_id]; + e_nodes[j+nElemNodes] = new_nodes[node_id+nNodes]; + } + if (sfc_elem->getType() == MshElemType::TRIANGLE) // extrude triangles to prism + new_elems.push_back(new MeshLib::Prism(e_nodes, mat_id)); + else if (sfc_elem->getType() == MshElemType::QUAD) // extrude quads to hexes + new_elems.push_back(new MeshLib::Hex(e_nodes, mat_id)); + + delete e_nodes; } - elem->SetPatchIndex(nLayers - layer_id); - elem->SetNodesNumber(2 * nElemNodes); - elem->getNodeIndices().resize(2 * nElemNodes); - for (size_t j = 0; j < nElemNodes; j++) + else { - long idx = sfc_elem->GetNodeIndex(j); - elem->SetNodeIndex(nElemNodes-j-1, node_offset + idx); - elem->SetNodeIndex(nElemNodes-j-1 + nElemNodes, node_offset + nNodes + idx); + std::cout << "Warning in MshLayerMapper::CreateLayers() - Method can only handle 2D mesh elements ..." << std::endl; + std::cout << "Skipping Element " << i << " of type \"" << MshElemType2String(sfc_elem->getType()) << "\"." << std::endl; } - new_mesh->ele_vector.push_back(elem); } } } - new_mesh->setNumberOfNodesFromNodesVectorSize (); - new_mesh->setNumberOfMeshLayers(nLayers); - - new_mesh->ConstructGrid(); - new_mesh->FillTransformMatrix(); - - return new_mesh; + return new MeshLib::Mesh("NewMesh", new_nodes, new_elems); } -int MshLayerMapper::LayerMapping(MeshLib::CFEMesh* new_mesh, - const std::string &rasterfile, - const size_t nLayers, - const size_t layer_id, - bool removeNoDataValues) +int MshLayerMapper::LayerMapping(MeshLib::Mesh* new_mesh, const std::string &rasterfile, + const size_t nLayers, const size_t layer_id, bool removeNoDataValues) { if (new_mesh == NULL) { @@ -109,7 +98,7 @@ int MshLayerMapper::LayerMapping(MeshLib::CFEMesh* new_mesh, return 0; } - if (new_mesh->getNumberOfMeshLayers() >= layer_id) + if (nLayers >= layer_id) { double x0(0), y0(0), delta(1); size_t width(1), height(1); @@ -130,7 +119,7 @@ int MshLayerMapper::LayerMapping(MeshLib::CFEMesh* new_mesh, return 0; } - const size_t nNodes = new_mesh->nod_vector.size(); + const size_t nNodes = new_mesh->getNNodes(); const size_t nNodesPerLayer = nNodes / (nLayers+1); const size_t firstNode = layer_id * nNodesPerLayer; @@ -138,9 +127,10 @@ int MshLayerMapper::LayerMapping(MeshLib::CFEMesh* new_mesh, std::vector<size_t> noData_nodes; const double half_delta = 0.5*delta; + const std::vector<MeshLib::Node*> nodes = new_mesh->getNodes(); for(size_t i = firstNode; i < lastNode; i++) { - const double* coords = new_mesh->nod_vector[i]->getData(); + const double* coords = nodes[i]->getCoords(); // position in raster const double xPos ((coords[0] - xDim.first) / delta); const double yPos ((coords[1] - yDim.first) / delta); @@ -173,32 +163,33 @@ int MshLayerMapper::LayerMapping(MeshLib::CFEMesh* new_mesh, double ome[4]; double xi = 1-fabs(xShift); double eta = 1-fabs(xShift); - MPhi2D(ome, xi, eta); + MathLib::MPhi2D(ome, xi, eta); double z(0.0); for(size_t j = 0; j < 4; j++) z += ome[j] * locZ[j]; - new_mesh->nod_vector[i]->SetZ(z); - new_mesh->nod_vector[i]->SetMark(true); + const double* coords (nodes[i]->getCoords()); + nodes[i]->updateCoordinates(coords[0], coords[1], z); + //nodes[i]->SetMark(true); } else { - new_mesh->nod_vector[i]->SetZ(0); - new_mesh->nod_vector[i]->SetMark(false); + const double* coords (nodes[i]->getCoords()); + nodes[i]->updateCoordinates(coords[0], coords[1], 0); + //nodes[i]->SetMark(false); noData_nodes.push_back(i); } } if ((nLayers == 0) && removeNoDataValues) { - if (noData_nodes.size() < (new_mesh->nod_vector.size() - 2)) + if (noData_nodes.size() < (nNodes - 2)) { - std::cout << "Warning: Removing " << noData_nodes.size() << - " mesh nodes at NoData values ... " << std::endl; - MeshLib::CFEMesh* red_mesh = MshEditor::removeMeshNodes( - new_mesh, - noData_nodes); - if (!new_mesh->ele_vector.empty()) + std::cout << "Warning: Removing " << noData_nodes.size() + << " mesh nodes at NoData values ... " << std::endl; + MeshLib::MshEditor msh_editor; + MeshLib::Mesh* red_mesh = msh_editor.removeMeshNodes(new_mesh, noData_nodes); + if (new_mesh->getNElements() == 0) { delete new_mesh; new_mesh = red_mesh; @@ -217,27 +208,27 @@ int MshLayerMapper::LayerMapping(MeshLib::CFEMesh* new_mesh, return 1; } else - std::cout << "Error in MshLayerMapper::LayerMapping() - Mesh has only " << - new_mesh->getNumberOfMeshLayers() << " Layers, cannot assign layer " << layer_id << - "..." << std::endl; + std::cout << "Error in MshLayerMapper::LayerMapping() - Mesh has only " + << nLayers << " Layers, cannot assign layer " << layer_id + << "..." << std::endl; return 0; } -// KR, based on code by WW (Note: this method has not been tested yet and will probably fail miserably!) -bool MshLayerMapper::meshFitsImage(const MeshLib::CFEMesh* msh, +bool MshLayerMapper::meshFitsImage(const MeshLib::Mesh* msh, const std::pair<double, double> &xDim, const std::pair<double, double> &yDim) { - double const* pnt (msh->nod_vector[0]->getData()); - double xMin(pnt[0]); - double yMin(pnt[1]); - double xMax(pnt[0]); - double yMax(pnt[1]); - - size_t nNodes = msh->nod_vector.size(); + const size_t nNodes = msh->getNNodes(); + const std::vector<MeshLib::Node*> nodes = msh->getNodes(); + const double* pnt; + double xMin(std::numeric_limits<double>::max()); + double yMin(std::numeric_limits<double>::max()); + double xMax(std::numeric_limits<double>::min()); + double yMax(std::numeric_limits<double>::min()); + for (size_t i = 1; i < nNodes; i++) { - pnt = msh->nod_vector[i]->getData(); + pnt = nodes[i]->getCoords(); if (xMin > pnt[0]) xMin = pnt[0]; else if (xMax < pnt[0]) @@ -257,10 +248,11 @@ bool MshLayerMapper::meshFitsImage(const MeshLib::CFEMesh* msh, return true; } -MeshLib::CFEMesh* MshLayerMapper::blendLayersWithSurface(MeshLib::CFEMesh* mesh, const size_t nLayers, const std::string &dem_raster) +MeshLib::Mesh* MshLayerMapper::blendLayersWithSurface(MeshLib::Mesh* mesh, const size_t nLayers, const std::string &dem_raster) { +/* // construct surface mesh from DEM - MeshLib::CFEMesh* dem = MshEditor::getMeshSurface(*mesh); + MeshLib::Mesh* dem = MshEditor::getMeshSurface(*mesh); MshLayerMapper::LayerMapping(dem, dem_raster, 0, 0); const size_t nNodes = mesh->nod_vector.size(); @@ -410,6 +402,9 @@ MeshLib::CFEMesh* MshLayerMapper::blendLayersWithSurface(MeshLib::CFEMesh* mesh, grid.setElements(elements); MeshLib::CFEMesh* struct_mesh = new MeshLib::CFEMesh(*grid.getCFEMesh()); return struct_mesh; +*/ + return new MeshLib::Mesh(*mesh); } -*/ + + diff --git a/Gui/DataView/MshLayerMapper.h b/Gui/DataView/MshLayerMapper.h index 424cace187a7a7f5f4a00a514f6812f3d71f0f69..391035d974310b5b9dbfda4b89e57acdc9677a9c 100644 --- a/Gui/DataView/MshLayerMapper.h +++ b/Gui/DataView/MshLayerMapper.h @@ -16,9 +16,8 @@ class QImage; -namespace MeshLib -{ -class CFEMesh; +namespace MeshLib { + class Mesh; } /** @@ -37,23 +36,18 @@ public: * \param thickness The thickness of each of these newly added layers * \return A mesh with the requested number of layers of prism/hex elements */ - static MeshLib::CFEMesh* CreateLayers(const MeshLib::CFEMesh* mesh, - size_t nLayers, - double thickness); + static MeshLib::Mesh* CreateLayers(const MeshLib::Mesh* mesh, size_t nLayers, double thickness); /// Maps the z-values of nodes in the designated layer of the given mesh according to the given raster. - static int LayerMapping(MeshLib::CFEMesh* msh, - const std::string &rasterfile, - const size_t nLayers, - const size_t layer_id, - bool removeNoDataValues = false); + static int LayerMapping(MeshLib::Mesh* msh, const std::string &rasterfile, + const size_t nLayers, const size_t layer_id, bool removeNoDataValues = false); /// Blends a mesh with the surface given by dem_raster. Nodes and elements above the surface are either removed or adapted to fit the surface. - static MeshLib::CFEMesh* blendLayersWithSurface(MeshLib::CFEMesh* mesh, const size_t nLayers, const std::string &dem_raster); + static MeshLib::Mesh* blendLayersWithSurface(MeshLib::Mesh* mesh, const size_t nLayers, const std::string &dem_raster); private: /// Checks if the given mesh is within the dimensions given by xDim and yDim. - static bool meshFitsImage(const MeshLib::CFEMesh* msh, + static bool meshFitsImage(const MeshLib::Mesh* msh, const std::pair<double, double> &xDim, const std::pair<double, double> &yDim); }; diff --git a/Gui/DataView/StationTreeView.cpp b/Gui/DataView/StationTreeView.cpp index 633404365ca481cce04d158b613719ea52753a08..2cb476f23697fbe040c5ae2aa6eae15e4efd97f5 100644 --- a/Gui/DataView/StationTreeView.cpp +++ b/Gui/DataView/StationTreeView.cpp @@ -13,9 +13,8 @@ #include <QMenu> #include <iostream> -//TODO6 #include "GMSInterface.h" +#include "GMSInterface.h" #include "Station.h" -//TODO6 #include "StationIO.h" #include "DiagramPrefsDialog.h" #include "ModelTreeItem.h" @@ -178,14 +177,12 @@ void StationTreeView::exportStation() QString temp_name; std::vector<std::string> temp_soil_names; temp_soil_names.push_back(""); // soil name vector needs to be initialised - /* TODO6 GMSInterface::writeBoreholeToGMS(static_cast<GeoLib::StationBorehole*>(static_cast< StationTreeModel *>( model())->stationFromIndex(index, temp_name)), fileName.toStdString(), temp_soil_names); - */ } } diff --git a/Gui/VtkVis/CMakeLists.txt b/Gui/VtkVis/CMakeLists.txt index 1e94ce27c6b47bded7a3709ad0aaacba20c039f3..5b48f3692c31a586c03006d74b67dd616007a1e8 100644 --- a/Gui/VtkVis/CMakeLists.txt +++ b/Gui/VtkVis/CMakeLists.txt @@ -132,6 +132,7 @@ INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/Gui/VtkAct ${CMAKE_BINARY_DIR}/Gui/VtkVis ${CMAKE_SOURCE_DIR}/BaseLib + ${CMAKE_BINARY_DIR}/BaseLib ${CMAKE_SOURCE_DIR}/FemLib ${CMAKE_SOURCE_DIR}/GeoLib ${CMAKE_SOURCE_DIR}/MathLib diff --git a/Gui/VtkVis/VtkMeshConverter.h b/Gui/VtkVis/VtkMeshConverter.h index b233dde5a61224e754df3716011b13d3be6c04ed..57188c963f7909b93942b1d3d6df7c4fd4791dcc 100644 --- a/Gui/VtkVis/VtkMeshConverter.h +++ b/Gui/VtkVis/VtkMeshConverter.h @@ -62,7 +62,7 @@ public: MshElemType::type elem_type, UseIntensityAs::type intensity_type); - /// Converts a vtkUnstructuredGrid object to a CFEMesh + /// Converts a vtkUnstructuredGrid object to a Mesh static MeshLib::Mesh* convertUnstructuredGrid(vtkUnstructuredGrid* grid); private: diff --git a/Gui/VtkVis/VtkRaster.cpp b/Gui/VtkVis/VtkRaster.cpp index c9ffd2e17b9148be5b2554f9c9f446810e765ac1..79aefde775256fc0d12eb5fc380a36cc3d4768df 100644 --- a/Gui/VtkVis/VtkRaster.cpp +++ b/Gui/VtkVis/VtkRaster.cpp @@ -402,7 +402,7 @@ vtkImageImport* VtkRaster::loadImageFromTIFF(const std::string &fileName, _TIFFfree(pixVal); GTIFFree(geoTiff); XTIFFClose(tiff); - return false; + return NULL; } // check for colormap diff --git a/Gui/VtkVis/VtkVisPipeline.h b/Gui/VtkVis/VtkVisPipeline.h index 07fc57acc08f2cbb3f8b437008bbe1b0c3d786c6..129f013c6ac5c0365bb838b69bb6ebbe1b322434 100644 --- a/Gui/VtkVis/VtkVisPipeline.h +++ b/Gui/VtkVis/VtkVisPipeline.h @@ -14,7 +14,6 @@ // ** INCLUDES ** #include "Color.h" -//TODO6 #include "Configure.h" #include "FEMCondition.h" #include "GeoType.h" #include "MSHEnums.h" diff --git a/Gui/VtkVis/VtkVisPipelineItem.h b/Gui/VtkVis/VtkVisPipelineItem.h index a98488e514cae3b8fea54c4f07326e5f12d32d4f..3c0eeb5aa3e581b5dc67a39ed90b8120b7ff291b 100644 --- a/Gui/VtkVis/VtkVisPipelineItem.h +++ b/Gui/VtkVis/VtkVisPipelineItem.h @@ -13,7 +13,7 @@ #define VTKVISPIPELINEITEM_H // ** INCLUDES ** -//TODO6 #include "Configure.h" +#include "BuildInfo.h" #include "TreeItem.h" #include <QList> diff --git a/Gui/VtkVis/VtkVisPipelineView.cpp b/Gui/VtkVis/VtkVisPipelineView.cpp index 3ef57039066ee80061cbba7dc3a1edc75aeb69df..aa7011617bcff4a3ce0c4dbbf727e70b7965669c 100644 --- a/Gui/VtkVis/VtkVisPipelineView.cpp +++ b/Gui/VtkVis/VtkVisPipelineView.cpp @@ -94,11 +94,11 @@ void VtkVisPipelineView::contextMenuEvent( QContextMenuEvent* event ) connect(addLUTAction, SIGNAL(triggered()), this, SLOT(addColorTable())); } - QAction* addConvertToCFEMeshAction(NULL); + QAction* addConvertToMeshAction(NULL); if (objectType == VTK_UNSTRUCTURED_GRID) { - addConvertToCFEMeshAction = menu.addAction("Convert to Mesh..."); - connect(addConvertToCFEMeshAction, SIGNAL(triggered()), this, + addConvertToMeshAction = menu.addAction("Convert to Mesh..."); + connect(addConvertToMeshAction, SIGNAL(triggered()), this, SLOT(convertVTKToOGSMesh())); } menu.addSeparator(); diff --git a/Gui/VtkVis/VtkVisPipelineView.h b/Gui/VtkVis/VtkVisPipelineView.h index 87a28134cd653c597af15849f579b1c7668b1518..c3d6870b811597de42f28c9215929241704cf678 100644 --- a/Gui/VtkVis/VtkVisPipelineView.h +++ b/Gui/VtkVis/VtkVisPipelineView.h @@ -22,9 +22,8 @@ class VtkVisPipelineItem; class vtkProp3D; class vtkDataObject; -namespace MeshLib -{ -class CFEMesh; +namespace MeshLib { + class Mesh; } /** diff --git a/Gui/VtkVis/VtkVisPointSetItem.cpp b/Gui/VtkVis/VtkVisPointSetItem.cpp index ed1a8c3f8442f75270f0933cf7ee1745aef1e068..663d34c207745ea9dcb55bf46d15e4ca37baeb4c 100644 --- a/Gui/VtkVis/VtkVisPointSetItem.cpp +++ b/Gui/VtkVis/VtkVisPointSetItem.cpp @@ -270,6 +270,7 @@ void VtkVisPointSetItem::SetActiveAttribute( const QString& name ) _algorithm->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, charName); _mapper->SetScalarModeToUsePointData(); pointData->GetArray(_activeArrayName.c_str())->GetRange(range); + pointData->GetArray(charName)->GetRange(range); } else { @@ -290,6 +291,7 @@ void VtkVisPointSetItem::SetActiveAttribute( const QString& name ) _algorithm->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_CELLS, charName); _mapper->SetScalarModeToUseCellData(); cellData->GetArray(_activeArrayName.c_str())->GetRange(range); + cellData->GetArray(charName)->GetRange(range); } else { @@ -340,6 +342,11 @@ bool VtkVisPointSetItem::activeAttributeExists(vtkDataSetAttributes* data, std:: { data->SetActiveAttribute(name.c_str(), vtkDataSetAttributes::SCALARS); return true; + int i = data->SetActiveAttribute(name.c_str(), vtkDataSetAttributes::SCALARS); + if (i < 0) + return false; + else + return true; } else return false; diff --git a/Gui/mainwindow.cpp b/Gui/mainwindow.cpp index 31e5642eede9d57b04b8c89ccf8b28d7c4eb1660..7375b7b88c64857eb2c7e61c814be4e14ca4b76d 100644 --- a/Gui/mainwindow.cpp +++ b/Gui/mainwindow.cpp @@ -62,7 +62,7 @@ #include "MeshIO/GMSHInterface.h" // TODO6 #include "MeshIO/TetGenInterface.h" #include "PetrelInterface.h" -// TODO6 #include "StationIO.h" +#include "XmlIO/VTKInterface.h" #include "XmlIO/XmlCndInterface.h" #include "XmlIO/XmlGmlInterface.h" #include "XmlIO/XmlGspInterface.h" @@ -74,7 +74,6 @@ #include "Mesh.h" #include "Node.h" #include "MshEditor.h" -//TODO6 #include "ExtractMeshNodes.h" // Qt includes #include <QDesktopWidget> @@ -331,6 +330,7 @@ MainWindow::MainWindow(QWidget* parent /* = 0*/) MainWindow::~MainWindow() { + delete _signal_mapper; delete _import_files_menu; delete _vtkVisPipeline; delete _meshModels; @@ -393,7 +393,7 @@ void MainWindow::open(int file_type) ImportFileType::type t = static_cast<ImportFileType::type>(file_type); QString type_str = QString::fromStdString((ImportFileType::convertImportFileTypeToString(t))); QString fileName = QFileDialog::getOpenFileName(this, - "Select " + type_str + " file to import", + "Select " + type_str + " file to import", settings.value("lastOpenedFileDirectory").toString(), QString::fromStdString(ImportFileType::getFileSuffixString(t))); if (!fileName.isEmpty()) @@ -478,19 +478,12 @@ void MainWindow::loadFile(ImportFileType::type t, const QString &fileName) { if (fi.suffix().toLower() == "gli") { -#ifndef NDEBUG - QTime myTimer0; - myTimer0.start(); -#endif std::string unique_name; std::vector<std::string> errors; if (! readGLIFileV4(fileName.toStdString(), _geoModels, unique_name, errors)) { for (size_t k(0); k<errors.size(); k++) OGSError::box(QString::fromStdString(errors[k])); } -#ifndef NDEBUG - std::cout << myTimer0.elapsed() << " ms" << std::endl; -#endif } else if (fi.suffix().toLower() == "gsp") { @@ -516,20 +509,31 @@ void MainWindow::loadFile(ImportFileType::type t, const QString &fileName) // OpenGeoSys mesh files else if (fi.suffix().toLower() == "msh") { +#ifndef NDEBUG QTime myTimer0; myTimer0.start(); - +#endif FileIO::MeshIO meshIO; std::string name = fileName.toStdString(); MeshLib::Mesh* msh = meshIO.loadMeshFromFile(name); if (msh) { _meshModels->addMesh(msh); +#ifndef NDEBUG std::cout << "Total mesh loading time: " << myTimer0.elapsed() << " ms" << std::endl; +#endif } else OGSError::box("Failed to load a mesh file."); } + else if (fi.suffix().toLower() == "vtu") + { + MeshLib::Mesh* msh = FileIO::VTKInterface::readVTUFile(fileName.toStdString()); + if (msh) + _meshModels->addMesh(msh); + else + OGSError::box("Failed to load a mesh file."); + } else if (fi.suffix().toLower() == "cnd") { this->loadFEMConditionsFromFile(fileName); @@ -537,6 +541,7 @@ void MainWindow::loadFile(ImportFileType::type t, const QString &fileName) } else if (t == ImportFileType::FEFLOW) { + OGSError::box("Interface not yet integrated"); /* TODO6 FEFLOWInterface feflowIO(_geoModels); MeshLib::Mesh* msh = feflowIO.readFEFLOWModelFile(fileName.toStdString()); @@ -550,13 +555,12 @@ void MainWindow::loadFile(ImportFileType::type t, const QString &fileName) updateDataViews(); } else - OGSError::box("Failed to load a FEFLOW file."); + OGSError::box("Failed to load a FEFLOW file."); */ } else if (t == ImportFileType::GMS) { - // GMS borehole files - if (fi.suffix().toLower() == "txt") + if (fi.suffix().toLower() == "txt") // GMS borehole files { std::vector<GeoLib::Point*>* boreholes = new std::vector<GeoLib::Point*>(); std::string name = fi.baseName().toStdString(); @@ -566,8 +570,7 @@ void MainWindow::loadFile(ImportFileType::type t, const QString &fileName) else OGSError::box("Error reading GMS file."); } - // GMS mesh files - else if (fi.suffix().toLower() == "3dm") + else if (fi.suffix().toLower() == "3dm") // GMS mesh files { std::string name = fileName.toStdString(); MeshLib::Mesh* mesh = GMSInterface::readGMS3DMMesh(name); @@ -577,16 +580,20 @@ void MainWindow::loadFile(ImportFileType::type t, const QString &fileName) } else if (t == ImportFileType::GMSH) { - // TODO6 + std::string msh_name (fileName.toStdString()); + if (FileIO::GMSHInterface::isGMSHMeshFile (msh_name)) + { + MeshLib::Mesh* mesh = FileIO::GMSHInterface::readGMSHMesh(msh_name); + if (mesh) + _meshModels->addMesh(mesh); + return; + } } - else if (t == ImportFileType::NETCDF) + else if (t == ImportFileType::NETCDF) // CH 01.2012 { - // NetCDF files - // CH 01.2012 - std::string name = fileName.toStdString(); MeshLib::Mesh* mesh (NULL); - NetCdfConfigureDialog dlg(name); + NetCdfConfigureDialog dlg(fileName.toStdString()); dlg.exec(); if (dlg.getMesh() != NULL) { @@ -635,6 +642,7 @@ void MainWindow::loadFile(ImportFileType::type t, const QString &fileName) "TetGen element files (*.ele);;"); if (!fileName.isEmpty() && !element_fname.isEmpty()) { + OGSError::box("Interface not yet integrated"); /* TODO6 FileIO::TetGenInterface tetgen; MeshLib::Mesh* msh (tetgen.readTetGenMesh(node_fname.toStdString(), element_fname.toStdString())); @@ -646,7 +654,7 @@ void MainWindow::loadFile(ImportFileType::type t, const QString &fileName) OGSError::box("Failed to load a TetGen mesh."); settings.setValue("lastOpenedTetgenFileDirectory", QDir(node_fname).absolutePath()); */ - } + } } else if (t == ImportFileType::VTK) { @@ -746,9 +754,9 @@ QMenu* MainWindow::createImportFilesMenu() QAction* vtkFiles = importFiles->addAction("&VTK Files..."); connect( vtkFiles, SIGNAL(triggered()), _signal_mapper, SLOT(map()) ); _signal_mapper->setMapping(vtkFiles, ImportFileType::VTK); - + connect(_signal_mapper, SIGNAL(mapped(int)), this, SLOT(open(int))); - + return importFiles; } diff --git a/MathLib/MathTools.cpp b/MathLib/MathTools.cpp index c332c4ebf06f24f550db2577554101a6ed31ce9a..66db48c65d6a91c0ddbafb268580c81d9f3cc216 100644 --- a/MathLib/MathTools.cpp +++ b/MathLib/MathTools.cpp @@ -1,4 +1,4 @@ -/** + /** * Copyright (c) 2012, OpenGeoSys Community (http://www.opengeosys.com) * Distributed under a Modified BSD License. * See accompanying file LICENSE.txt or @@ -99,4 +99,14 @@ double calcTetrahedronVolume(const double* x1, const double* x2, const double* x + (x1[2] - x4[2]) * ((x2[0] - x4[0]) * (x3[1] - x4[1]) - (x2[1] - x4[1]) * (x3[0] - x4[0]))) / 6.0; } +void MPhi2D(double* vf, double r, double s) +{ + vf[0] = (1.0 + r) * (1.0 + s); + vf[1] = (1.0 - r) * (1.0 + s); + vf[2] = (1.0 - r) * (1.0 - s); + vf[3] = (1.0 + r) * (1.0 - s); + for (unsigned i=0; i<4; i++) + vf[i] *= 0.25; +} + } // namespace diff --git a/MathLib/MathTools.h b/MathLib/MathTools.h index ad83ef5618b9aecbe10617b0cf21176a21d33154..a44cbe32b680397041610e0264668c6839e1743d 100644 --- a/MathLib/MathTools.h +++ b/MathLib/MathTools.h @@ -159,6 +159,9 @@ T fastpow (T base, size_t exp) return result; } +/// 2D linear interpolation function (TODO adopted from geo_mathlib) +void MPhi2D(double* vf, double r, double s); + } // namespace #endif /* MATHTOOLS_H_ */ diff --git a/MeshLib/Elements/Cell.h b/MeshLib/Elements/Cell.h index 9bf62bf064cbbd98916da916aea5ff222d12a20e..e14797f487ae5b08755d53e4195a6b60a61743b6 100644 --- a/MeshLib/Elements/Cell.h +++ b/MeshLib/Elements/Cell.h @@ -54,9 +54,6 @@ protected: /// Constructor for a generic mesh element without an array of mesh nodes. Cell(unsigned value = 0); - /// Calculate the volume of this 3d element. - virtual double computeVolume() = 0; - double _volume; }; /* class */ diff --git a/MeshLib/Elements/Edge.cpp b/MeshLib/Elements/Edge.cpp index a5db2266f985feb9e6bb1d0d53a4488d481f4139..ed49b9095429a2a627f3804ff19836abc38f8b90 100644 --- a/MeshLib/Elements/Edge.cpp +++ b/MeshLib/Elements/Edge.cpp @@ -21,7 +21,7 @@ Edge::Edge(Node* nodes[2], unsigned value) : Element(value) { _nodes = nodes; - this->_length = this->computeLength(); + this->_length = this->computeVolume(); } Edge::Edge(Node* n0, Node* n1, unsigned value) @@ -31,7 +31,7 @@ Edge::Edge(Node* n0, Node* n1, unsigned value) _nodes[0] = n0; _nodes[1] = n1; - this->_length = this->computeLength(); + this->_length = this->computeVolume(); } Edge::Edge(const Edge &edge) @@ -47,7 +47,7 @@ Edge::~Edge() { } -double Edge::computeLength() +double Edge::computeVolume() { return sqrt(MathLib::sqrDist(_nodes[0]->getCoords(), _nodes[1]->getCoords())); } diff --git a/MeshLib/Elements/Edge.h b/MeshLib/Elements/Edge.h index 5a4461d0b7a7576bf305fc223412f91f2e537fd0..dcb0898e5ab2435b4c0d80dc435a54287d671d53 100644 --- a/MeshLib/Elements/Edge.h +++ b/MeshLib/Elements/Edge.h @@ -13,6 +13,8 @@ #ifndef EDGE_H_ #define EDGE_H_ +#include <limits> + #include "Element.h" namespace MeshLib { @@ -84,15 +86,16 @@ public: virtual Element* reviseElement() const; protected: - /// Calculate the length of this 1d element. - double computeLength(); - + double computeVolume(); /// 1D elements have no edges. Node const* getEdgeNode(unsigned edge_id, unsigned node_id) const { (void)edge_id; (void)node_id; return NULL; }; /// 1D elements have no faces. Node* getFaceNode(unsigned face_id, unsigned node_id) const { (void)face_id; (void)node_id; return NULL; }; + /// Returns the ID of a face given an array of nodes (but is not applicable for edges!). + unsigned identifyFace(Node* [3]/*nodes[3]*/) const { return std::numeric_limits<unsigned>::max(); }; + double _length; }; /* class */ diff --git a/MeshLib/Elements/Element.cpp b/MeshLib/Elements/Element.cpp index c751a180e46254e6c197d678022153be1c142ee9..bf356f8ccca68fb418dacb8dd10359b2ff4b57a6 100644 --- a/MeshLib/Elements/Element.cpp +++ b/MeshLib/Elements/Element.cpp @@ -36,9 +36,11 @@ Element::~Element() bool Element::addNeighbor(Element* e) { - unsigned n(0); + if (e == this) + return false; + unsigned nNeighbors (this->getNNeighbors()); - for (n=0; n<nNeighbors; n++) + for (unsigned n=0; n<nNeighbors; n++) { if (this->_neighbors[n] == e) return false; @@ -46,24 +48,26 @@ bool Element::addNeighbor(Element* e) break; } - if (n<nNeighbors) - { - const unsigned nNodes (this->getNNodes()); - const unsigned eNodes (e->getNNodes()); - const Node* const* e_nodes = e->getNodes(); - unsigned count(0); - const unsigned dim (this->getDimension()); - for (unsigned i(0); i<nNodes; i++) - for (unsigned j(0); j<eNodes; j++) - if (_nodes[i] == e_nodes[j]) - //std::cout << _nodes[i]->getID() << " == " << e_nodes[j]->getID() << std::endl; - // increment shared nodes counter and check if enough nodes are similar to be sure e is a neighbour of this - if ((++count)>=dim) - { - _neighbors[n]=e; - return true; - } - } + Node* face_nodes[3]; + const unsigned nNodes (this->getNNodes()); + const unsigned eNodes (e->getNNodes()); + const Node* const* e_nodes = e->getNodes(); + unsigned count(0); + const unsigned dim (this->getDimension()); + for (unsigned i(0); i<nNodes; i++) + for (unsigned j(0); j<eNodes; j++) + if (_nodes[i] == e_nodes[j]) + { + face_nodes[count] = _nodes[i]; + //std::cout << _nodes[i]->getID() << " == " << e_nodes[j]->getID() << std::endl; + // increment shared nodes counter and check if enough nodes are similar to be sure e is a neighbour of this + if ((++count)>=dim) + { + _neighbors[ this->identifyFace(face_nodes) ] = e; + return true; + } + } + return false; } diff --git a/MeshLib/Elements/Element.h b/MeshLib/Elements/Element.h index 20dd2b8b994fac02e3a9e4a95ba5e09eaa6b3481..ae08aad2398a4f7ecf464367c5a76bcde2846354 100644 --- a/MeshLib/Elements/Element.h +++ b/MeshLib/Elements/Element.h @@ -131,6 +131,13 @@ public: */ virtual Element* reviseElement() const = 0; + /** + * Computes the length / area / volumen of this element. This is automatically + * done at initalisation time but can be repeated by calling this function at any time. + */ + virtual double computeVolume() = 0; + + protected: /// Constructor for a generic mesh element without an array of mesh nodes. Element(unsigned value = 0); @@ -138,6 +145,9 @@ protected: /// Return a specific edge node. virtual Node const* getEdgeNode(unsigned edge_id, unsigned node_id) const = 0; + /// Returns the ID of a face given an array of nodes. + virtual unsigned identifyFace(Node* nodes[3]) const = 0; + Node** _nodes; unsigned _value; Element** _neighbors; diff --git a/MeshLib/Elements/Face.h b/MeshLib/Elements/Face.h index b0aa82cec56b63ae8913bfda3c8be4d64f4289cb..3fb1a126084cd0d6c86131da3db463dc206d81f0 100644 --- a/MeshLib/Elements/Face.h +++ b/MeshLib/Elements/Face.h @@ -63,9 +63,6 @@ protected: /// Constructor for a generic mesh element without an array of mesh nodes. Face(unsigned value = 0); - /// Calculate the area of this 2d element. - virtual double computeArea() = 0; - double _area; private: diff --git a/MeshLib/Elements/Hex.cpp b/MeshLib/Elements/Hex.cpp index b12fd76501bb10cf3c3e5f204997ad8b2f2da2de..8cdda69b6953f35b843c5aca37b698927b0868c0 100644 --- a/MeshLib/Elements/Hex.cpp +++ b/MeshLib/Elements/Hex.cpp @@ -120,6 +120,21 @@ Element* Hex::clone() const return new Hex(*this); } +unsigned Hex::identifyFace(Node* nodes[3]) const +{ + for (unsigned i=0; i<6; i++) + { + unsigned flag(0); + for (unsigned j=0; j<4; j++) + for (unsigned k=0; k<3; k++) + if (_nodes[_face_nodes[i][j]] == nodes[k]) + flag++; + if (flag==3) + return i; + } + return std::numeric_limits<unsigned>::max(); +} + Element* Hex::reviseElement() const { std::vector<size_t> collapsed_edges; diff --git a/MeshLib/Elements/Hex.h b/MeshLib/Elements/Hex.h index 172c9200604f1ccf1f906563a687cd1415074228..c214f54917521091d22b3aefd84e86331d498116 100644 --- a/MeshLib/Elements/Hex.h +++ b/MeshLib/Elements/Hex.h @@ -100,6 +100,9 @@ protected: /// Return a specific edge node. inline Node const* getEdgeNode(unsigned edge_id, unsigned node_id) const { return _nodes[_edge_nodes[edge_id][node_id]]; }; + /// Returns the ID of a face given an array of nodes. + unsigned identifyFace(Node* nodes[3]) const; + static const unsigned _face_nodes[6][4]; static const unsigned _edge_nodes[12][2]; diff --git a/MeshLib/Elements/Prism.cpp b/MeshLib/Elements/Prism.cpp index dde1cd3193d573678aa27273a59c8ad1cb91faf5..58f719059f945e5446ce189f70544dec5a709926 100644 --- a/MeshLib/Elements/Prism.cpp +++ b/MeshLib/Elements/Prism.cpp @@ -125,6 +125,21 @@ Element* Prism::clone() const return new Prism(*this); } +unsigned Prism::identifyFace(Node* nodes[3]) const +{ + for (unsigned i=0; i<5; i++) + { + unsigned flag(0); + for (unsigned j=0; j<4; j++) + for (unsigned k=0; k<3; k++) + if (_face_nodes[i][j] != 99 && _nodes[_face_nodes[i][j]] == nodes[k]) + flag++; + if (flag==3) + return i; + } + return std::numeric_limits<unsigned>::max(); +} + Element* Prism::reviseElement() const { // try to create Pyramid diff --git a/MeshLib/Elements/Prism.h b/MeshLib/Elements/Prism.h index 7649559424aabd8c46268d1cea297938f9b13bfb..0aa4dd0f4fc29013fdef72827dea86ce4b51c5a7 100644 --- a/MeshLib/Elements/Prism.h +++ b/MeshLib/Elements/Prism.h @@ -104,6 +104,9 @@ protected: /// Return a specific edge node. inline Node const* getEdgeNode(unsigned edge_id, unsigned node_id) const { return _nodes[_edge_nodes[edge_id][node_id]]; }; + /// Returns the ID of a face given an array of nodes. + unsigned identifyFace(Node* nodes[3]) const; + static const unsigned _face_nodes[5][4]; static const unsigned _edge_nodes[9][2]; static const unsigned _n_face_nodes[5]; diff --git a/MeshLib/Elements/Pyramid.cpp b/MeshLib/Elements/Pyramid.cpp index 55b1cf0edbf07e0ff9c2e80b176c4d7cc61c2e40..adf4cf3604b61711a0aabf5aa36aecfef089ffa3 100644 --- a/MeshLib/Elements/Pyramid.cpp +++ b/MeshLib/Elements/Pyramid.cpp @@ -124,6 +124,21 @@ Element* Pyramid::clone() const return new Pyramid(*this); } +unsigned Pyramid::identifyFace(Node* nodes[3]) const +{ + for (unsigned i=0; i<5; i++) + { + unsigned flag(0); + for (unsigned j=0; j<4; j++) + for (unsigned k=0; k<3; k++) + if (_face_nodes[i][j] != 99 && _nodes[_face_nodes[i][j]] == nodes[k]) + flag++; + if (flag==3) + return i; + } + return std::numeric_limits<unsigned>::max(); +} + Element* Pyramid::reviseElement() const { // try to create tetrahedron diff --git a/MeshLib/Elements/Pyramid.h b/MeshLib/Elements/Pyramid.h index 4345d8bd3d0f9c9f0e6f16aec6bad1a052001012..4c87b52ee87444a006aab7b44f00d9fafdbff6c1 100644 --- a/MeshLib/Elements/Pyramid.h +++ b/MeshLib/Elements/Pyramid.h @@ -102,6 +102,9 @@ protected: /// Return a specific edge node. inline Node const* getEdgeNode(unsigned edge_id, unsigned node_id) const { return _nodes[_edge_nodes[edge_id][node_id]]; }; + /// Returns the ID of a face given an array of nodes. + unsigned identifyFace(Node* nodes[3]) const; + static const unsigned _face_nodes[5][4]; static const unsigned _edge_nodes[8][2]; static const unsigned _n_face_nodes[5]; diff --git a/MeshLib/Elements/Quad.cpp b/MeshLib/Elements/Quad.cpp index 922871ddbee54da7015e137f04d08dbbc75e3991..3bec55469fc4ad8d4aeeebf6a63726501ae6feeb 100644 --- a/MeshLib/Elements/Quad.cpp +++ b/MeshLib/Elements/Quad.cpp @@ -35,7 +35,7 @@ Quad::Quad(Node* nodes[4], unsigned value) _neighbors = new Element*[4]; for (unsigned i=0; i<4; i++) _neighbors[i] = NULL; - this->_area = this->computeArea(); + this->_area = this->computeVolume(); } Quad::Quad(Node* n0, Node* n1, Node* n2, Node* n3, unsigned value) @@ -49,7 +49,7 @@ Quad::Quad(Node* n0, Node* n1, Node* n2, Node* n3, unsigned value) _neighbors = new Element*[4]; for (unsigned i=0; i<4; i++) _neighbors[i] = NULL; - this->_area = this->computeArea(); + this->_area = this->computeVolume(); } Quad::Quad(const Quad &quad) @@ -69,7 +69,7 @@ Quad::~Quad() { } -double Quad::computeArea() +double Quad::computeVolume() { return MathLib::calcTriangleArea(_nodes[0]->getCoords(), _nodes[1]->getCoords(), _nodes[2]->getCoords()) + MathLib::calcTriangleArea(_nodes[2]->getCoords(), _nodes[3]->getCoords(), _nodes[0]->getCoords()); @@ -80,6 +80,20 @@ Element* Quad::clone() const return new Quad(*this); } +unsigned Quad::identifyFace(Node* nodes[3]) const +{ + for (unsigned i=0; i<4; i++) + { + unsigned flag(0); + for (unsigned j=0; j<2; j++) + for (unsigned k=0; k<2; k++) + if (_nodes[_edge_nodes[i][j]] == nodes[k]) + flag++; + if (flag==2) + return i; + } + return std::numeric_limits<unsigned>::max(); +} Element* Quad::reviseElement() const { if (_nodes[0] == _nodes[1] || _nodes[1] == _nodes[2]) { diff --git a/MeshLib/Elements/Quad.h b/MeshLib/Elements/Quad.h index 2dfef14ab9ad8e27589d2a809bf163fd2dce1a49..5f9d55d0a9291003f006bd184a1346921321f6d2 100644 --- a/MeshLib/Elements/Quad.h +++ b/MeshLib/Elements/Quad.h @@ -81,11 +81,15 @@ public: protected: /// Calculates the area of a convex quadliteral by dividing it into two triangles. - double computeArea(); + double computeVolume(); +protected: /// Return a specific edge node. inline Node const* getEdgeNode(unsigned edge_id, unsigned node_id) const { return _nodes[_edge_nodes[edge_id][node_id]]; }; + /// Returns the ID of a face given an array of nodes. + unsigned identifyFace(Node* nodes[3]) const; + static const unsigned _edge_nodes[4][2]; }; /* class */ diff --git a/MeshLib/Elements/Tet.cpp b/MeshLib/Elements/Tet.cpp index 966ec3cfb5c7522c5d7d9c11b49e8f9135aa3406..ce57084ec1c697506625ba53d43584cf9835fd58 100644 --- a/MeshLib/Elements/Tet.cpp +++ b/MeshLib/Elements/Tet.cpp @@ -37,7 +37,6 @@ const unsigned Tet::_edge_nodes[6][2] = {2, 3} // Edge 5 }; - Tet::Tet(Node* nodes[4], unsigned value) : Cell(value) { @@ -111,6 +110,20 @@ Element* Tet::clone() const return new Tet(*this); } +unsigned Tet::identifyFace(Node* nodes[3]) const +{ + for (unsigned i=0; i<4; i++) + { + unsigned flag(0); + for (unsigned j=0; j<3; j++) + for (unsigned k=0; k<3; k++) + if (_nodes[_face_nodes[i][j]] == nodes[k]) + flag++; + if (flag==3) + return i; + } + return std::numeric_limits<unsigned>::max(); +} Element* Tet::reviseElement() const { if (_nodes[0] == _nodes[1] || _nodes[1] == _nodes[2]) { diff --git a/MeshLib/Elements/Tet.h b/MeshLib/Elements/Tet.h index 6a8ac29f00882916f8889df97ca0ac967761c31d..f77af5faad8fa31e6bdb359ff8fa86129d352bbb 100644 --- a/MeshLib/Elements/Tet.h +++ b/MeshLib/Elements/Tet.h @@ -106,6 +106,10 @@ protected: */ inline Node const* getEdgeNode(unsigned edge_id, unsigned node_id) const { return _nodes[_edge_nodes[edge_id][node_id]]; }; + /// Returns the ID of a face given an array of nodes. + unsigned identifyFace(Node* nodes[3]) const; + + static const unsigned _face_nodes[4][3]; static const unsigned _edge_nodes[6][2]; diff --git a/MeshLib/Elements/Tri.cpp b/MeshLib/Elements/Tri.cpp index 653343ca2a3c43d63876252fa971f87d7262516a..316e09394ccc8576dcd24e939260b0c6061486da 100644 --- a/MeshLib/Elements/Tri.cpp +++ b/MeshLib/Elements/Tri.cpp @@ -34,7 +34,7 @@ Tri::Tri(Node* nodes[3], unsigned value) _neighbors = new Element*[3]; for (unsigned i=0; i<3; i++) _neighbors[i] = NULL; - this->_area = this->computeArea(); + this->_area = this->computeVolume(); } Tri::Tri(Node* n0, Node* n1, Node* n2, unsigned value) @@ -47,7 +47,7 @@ Tri::Tri(Node* n0, Node* n1, Node* n2, unsigned value) _neighbors = new Element*[3]; for (unsigned i=0; i<3; i++) _neighbors[i] = NULL; - this->_area = this->computeArea(); + this->_area = this->computeVolume(); } Tri::Tri(const Tri &tri) @@ -72,11 +72,26 @@ Element* Tri::clone() const return new Tri(*this); } -double Tri::computeArea() +double Tri::computeVolume() { return MathLib::calcTriangleArea(_nodes[0]->getCoords(), _nodes[1]->getCoords(), _nodes[2]->getCoords()); } +unsigned Tri::identifyFace(Node* nodes[3]) const +{ + for (unsigned i=0; i<3; i++) + { + unsigned flag(0); + for (unsigned j=0; j<2; j++) + for (unsigned k=0; k<2; k++) + if (_nodes[_edge_nodes[i][j]] == nodes[k]) + flag++; + if (flag==2) + return i; + } + return std::numeric_limits<unsigned>::max(); +} + Element* Tri::reviseElement() const { // try to create an edge diff --git a/MeshLib/Elements/Tri.h b/MeshLib/Elements/Tri.h index d6ebcfce0538de9b3b5b02368fc9274ab536382f..b14a9847184fce4634e265a71dd0d1b4853e4135 100644 --- a/MeshLib/Elements/Tri.h +++ b/MeshLib/Elements/Tri.h @@ -82,11 +82,15 @@ public: protected: /// Calculates the area of the triangle by returning half of the area of the corresponding parallelogram. - double computeArea(); + double computeVolume(); +protected: /// Return a specific edge node. inline Node const* getEdgeNode(unsigned edge_id, unsigned node_id) const { return _nodes[_edge_nodes[edge_id][node_id]]; }; + /// Returns the ID of a face given an array of nodes. + unsigned identifyFace(Node* nodes[3]) const; + static const unsigned _edge_nodes[3][2]; }; /* class */ diff --git a/MeshLib/Mesh.cpp b/MeshLib/Mesh.cpp index 87f1466ebe650ca9048458ec222c658f5175030c..e6117acb8ae1e834fa68df7d7ebb4f74fc327d3b 100644 --- a/MeshLib/Mesh.cpp +++ b/MeshLib/Mesh.cpp @@ -23,19 +23,36 @@ namespace MeshLib { Mesh::Mesh(const std::string &name, const std::vector<Node*> &nodes, const std::vector<Element*> &elements) - : _name(name), _nodes(nodes), _elements(elements) + : _mesh_dimension(0), _name(name), _nodes(nodes), _elements(elements) { this->resetNodeIDs(); // reset node ids so they match the node position in the vector _edge_length[0] = 0; _edge_length[1] = 0; this->makeNodesUnique(); + this->setDimension(); this->setElementInformationForNodes(); this->setNeighborInformationForElements(); } Mesh::Mesh(const Mesh &mesh) - : _name(mesh.getName()), _nodes(mesh.getNodes()), _elements(mesh.getElements()) + : _mesh_dimension(mesh.getDimension()), _name(mesh.getName()), _nodes(mesh.getNodes()), _elements(mesh.getElements()) { + const std::vector<Node*> nodes (mesh.getNodes()); + const size_t nNodes (nodes.size()); + for (unsigned i=0; i<nNodes; i++) + _nodes[i] = new Node(*nodes[i]); + + const std::vector<Element*> elements (mesh.getElements()); + const size_t nElements (elements.size()); + for (unsigned i=0; i<nElements; i++) + { + const size_t nElemNodes = elements[i]->getNNodes(); + _elements[i] = elements[i]->clone(); + for (unsigned j=0; j<nElemNodes; j++) + _elements[i]->_nodes[j] = _nodes[elements[i]->getNode(j)->getID()]; + } + + if (_mesh_dimension==0) this->setDimension(); this->setElementInformationForNodes(); this->setNeighborInformationForElements(); } @@ -91,6 +108,14 @@ void Mesh::resetNodeIDs() _nodes[i]->setID(i); } +void Mesh::setDimension() +{ + const size_t nElements (_elements.size()); + for (unsigned i=0; i<nElements; i++) + if (_elements[i]->getDimension() > _mesh_dimension) + _mesh_dimension = _elements[i]->getDimension(); +} + void Mesh::setElementInformationForNodes() { const size_t nElements (_elements.size()); @@ -100,6 +125,13 @@ void Mesh::setElementInformationForNodes() for (unsigned j=0; j<nNodes; j++) _elements[i]->_nodes[j]->addElement(_elements[i]); } +#ifdef NDEBUG + // search for nodes that are not part of any element + const size_t nNodes (_nodes.size()); + for (unsigned i=0; i<nNodes; i++) + if (_nodes[i]->getNElements() == 0) + std::cout << "Warning: Node " << i << " is not part of any element." << std::endl; +#endif } void Mesh::setEdgeLengthRange(const double &min_length, const double &max_length) @@ -110,32 +142,40 @@ void Mesh::setEdgeLengthRange(const double &min_length, const double &max_length _edge_length[1] = max_length; } else - std::cerr << "Error in MeshLib::Mesh::setEdgeLengthRange() - min length < max length." << std::endl; + std::cerr << "Error in MeshLib::Mesh::setEdgeLengthRange() - min length > max length." << std::endl; } void Mesh::setNeighborInformationForElements() { const size_t nElements = _elements.size(); - for (unsigned m(0); m<nElements; m++) +#ifdef _OPENMP + OPENMP_LOOP_TYPE m; + #pragma omp parallel for +#else + unsigned m(0); +#endif + for (m=0; m<nElements; m++) { // create vector with all elements connected to current element (includes lots of doubles!) std::vector<Element*> neighbors; Element *const element (_elements[m]); - const size_t nNodes (element->getNNodes()); - for (unsigned n(0); n<nNodes; n++) + if (element->getType() != MshElemType::EDGE) { - std::vector<Element*> const& conn_elems ((element->getNode(n)->getElements())); - neighbors.insert(neighbors.end(), conn_elems.begin(), conn_elems.end()); - } + const size_t nNodes (element->getNNodes()); + for (unsigned n(0); n<nNodes; n++) + { + std::vector<Element*> const& conn_elems ((element->getNode(n)->getElements())); + neighbors.insert(neighbors.end(), conn_elems.begin(), conn_elems.end()); + } - const unsigned nNeighbors ( neighbors.size() ); + const unsigned nNeighbors ( neighbors.size() ); - // check if connected element is indeed a neighbour and mark all doubles of that element as 'done' - for (unsigned i(0); i<nNeighbors; i++) - { - if (element->addNeighbor(neighbors[i])) + for (unsigned i(0); i<nNeighbors; i++) { - neighbors[i]->addNeighbor(element); + if (element->addNeighbor(neighbors[i]) && neighbors[i]->getType() != MshElemType::EDGE) + { + neighbors[i]->addNeighbor(element); + } } } } diff --git a/MeshLib/Mesh.h b/MeshLib/Mesh.h index dee3618aa3f2502a3f519090ffd82297c8ed0195..02f9923d030878b9566378586909799843c365d1 100644 --- a/MeshLib/Mesh.h +++ b/MeshLib/Mesh.h @@ -44,6 +44,9 @@ public: /// Add an element to the mesh. void addElement(Element* elem); + /// Returns the dimension of the mesh (determinded by the maximum dimension over all elements). + unsigned getDimension() const { return _mesh_dimension; }; + /// Get the minimum edge length over all elements of the mesh. double getMinEdgeLength() { return _edge_length[0]; }; @@ -94,12 +97,16 @@ protected: /// Checks the coordinates of all mesh nodes and removes identical nodes. Elements are adapted accordingly. void makeNodesUnique(); + /// Sets the dimension of the mesh. + void setDimension(); + /// Fills in the neighbor-information for nodes (i.e. which element each node belongs to). void setElementInformationForNodes(); /// Fills in the neighbor-information for elements. void setNeighborInformationForElements(); + unsigned _mesh_dimension; double _edge_length[2]; std::string _name; std::vector<Node*> _nodes; diff --git a/MeshLib/MshEditor.cpp b/MeshLib/MshEditor.cpp index e282c2e3454bdadd93c5886904c91cd0ef8affc0..bad87b43686c0e43c8fd0e645acff7542a58c838 100644 --- a/MeshLib/MshEditor.cpp +++ b/MeshLib/MshEditor.cpp @@ -12,74 +12,104 @@ #include "MshEditor.h" #include "PointWithID.h" #include "Mesh.h" +#include "Node.h" +#include "Elements/Element.h" +#include "Elements/Face.h" +#include "Elements/Cell.h" +#include "Elements/Tri.h" +#include "Elements/Quad.h" +#include "MathTools.h" + +namespace MeshLib { + +void MshEditor::getSurfaceAreaForNodes(const MeshLib::Mesh* mesh, std::vector<double> &node_area_vec) +{ + if (mesh->getDimension() == 2) + { + double total_area (0); + + // for each node, a vector containing all the element idget every element + std::vector<MeshLib::Node*> nodes = mesh->getNodes(); + const size_t nNodes ( mesh->getNNodes() ); + for (size_t n=0; n<nNodes; n++) + { + double node_area (0); + + std::vector<MeshLib::Element*> conn_elems = nodes[n]->getElements(); + const size_t nConnElems (conn_elems.size()); + + for (size_t i=0; i<nConnElems;i++) + { + const MeshLib::Element* elem (conn_elems[i]); + const unsigned nElemParts = (elem->getType() == MshElemType::TRIANGLE) ? 3 : 4; + const double area = conn_elems[i]->getContent() / nElemParts; + node_area += area; + total_area += area; + } + + node_area_vec.push_back(node_area); + } + + std::cout<< "Total surface Area: " << total_area << std::endl; + } + else + std::cout << "Error in MshEditor::getSurfaceAreaForNodes() - Given mesh is no surface mesh (dimension != 2)." << std::endl; +} MeshLib::Mesh* MshEditor::removeMeshNodes(MeshLib::Mesh* mesh, const std::vector<size_t> &nodes) { MeshLib::Mesh* new_mesh (new MeshLib::Mesh(*mesh)); - /* TODO6 // delete nodes and their connected elements and replace them with null pointers - size_t delNodes = nodes.size(); + const size_t delNodes = nodes.size(); + std::vector<MeshLib::Node*> mesh_nodes = new_mesh->getNodes(); for (size_t i = 0; i < delNodes; i++) { const MeshLib::Node* node = new_mesh->getNode(i); - std::vector<size_t> conn_elems = node->getConnectedElementIDs(); + std::vector<MeshLib::Element*> conn_elems = node->getElements(); + for (size_t j = 0; j < conn_elems.size(); j++) { - delete new_mesh->ele_vector[conn_elems[j]]; - new_mesh->ele_vector[conn_elems[j]] = NULL; + delete conn_elems[j]; + conn_elems[j] = NULL; } - delete new_mesh->nod_vector[nodes[i]]; - new_mesh->nod_vector[nodes[i]] = NULL; + delete mesh_nodes[i]; + mesh_nodes[i] = NULL; } // create map to adjust node indices in element vector - size_t nNodes = new_mesh->nod_vector.size(); - std::vector<int> id_map; - size_t count = 0; + const size_t nNodes = new_mesh->getNNodes(); + std::vector<int> id_map(nNodes, -1); + size_t count(0); for (size_t i = 0; i < nNodes; i++) { - if (new_mesh->nod_vector[i]) + if (mesh_nodes[i]) { - new_mesh->nod_vector[i]->SetIndex(count); - id_map.push_back(count); - count++; + mesh_nodes[i]->setID(count); + id_map.push_back(count++); } - else - id_map.push_back(-1); } // erase null pointers from node- and element vectors - for (std::vector<MeshLib::CElem*>::iterator it = new_mesh->ele_vector.begin(); - it != new_mesh->ele_vector.end(); ) + std::vector<MeshLib::Element*> elements = new_mesh->getElements(); + for (std::vector<MeshLib::Element*>::iterator it = elements.begin(); it != elements.end(); ) { if (*it) ++it; else - it = new_mesh->ele_vector.erase(it); + it = elements.erase(it); } - for (std::vector<MeshLib::CNode*>::iterator it = new_mesh->nod_vector.begin(); - it != new_mesh->nod_vector.end(); ) + for (std::vector<MeshLib::Node*>::iterator it = mesh_nodes.begin(); it != mesh_nodes.end(); ) { if (*it) ++it; else - it = new_mesh->nod_vector.erase(it); + it = mesh_nodes.erase(it); } - // re-adjust node indices - size_t nElems = new_mesh->ele_vector.size(); - for (size_t i = 0; i < nElems; i++) - { - MeshLib::CElem* elem = new_mesh->ele_vector[i]; - size_t nElemNodes = elem->GetNodesNumber(false); - for (size_t j = 0; j < nElemNodes; j++) - elem->SetNodeIndex(j, id_map[elem->GetNodeIndex(j)]); - } - */ return new_mesh; } @@ -117,67 +147,85 @@ std::vector<GeoLib::PointWithID*> MshEditor::getSurfaceNodes(const MeshLib::Mesh return surface_pnts; } -MeshLib::Mesh* MshEditor::getMeshSurface(const MeshLib::Mesh &mesh) +MeshLib::Mesh* MshEditor::getMeshSurface(const MeshLib::Mesh &mesh, const double* dir) { - /* TODO6 std::cout << "Extracting mesh surface..." << std::endl; - GridAdapter surface; - const std::vector<GeoLib::PointWithID*> sfc_points = MshEditor::getSurfaceNodes(mesh); - const size_t nSurfacePoints (sfc_points.size()); - std::vector<GridAdapter::Element*> *elements = new std::vector<GridAdapter::Element*>; + const std::vector<MeshLib::Element*> elements = mesh.getElements(); + std::vector<MeshLib::Element*> new_elements; + const size_t nElements (mesh.getNElements()); - const size_t nElements = mesh.ele_vector.size(); - for (size_t j=0; j<nElements; j++) + bool complete_surface = ((dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2]) == 0) ? true : false; + + // 2D meshes + if (mesh.getDimension() == 2 ) { - MeshLib::CElem* elem (mesh.ele_vector[j]); - std::vector<size_t> elem_nodes; - bool is_surface (true); - for (size_t i=0; i<4; i++) + if (complete_surface) return new MeshLib::Mesh(mesh); // simply copy the mesh + else // check only surface normal directions of all elements { - size_t node_index = elem->GetNodeIndex(i); - bool node_found(false), one_node(true); - for (size_t k=0; k<nSurfacePoints; k++) + for (unsigned i=0; i<nElements; i++) { - if (sfc_points[k]->getID() == node_index) - { - node_found=true; - elem_nodes.push_back(k); - break; - } + MeshLib::Face* face = dynamic_cast<MeshLib::Face*>(elements[i]); + double normal[3]; + face->getSurfaceNormal(normal); + if (MathLib::scpr(normal, dir, 3) > 0) + new_elements.push_back(static_cast<MeshLib::Element*>(face)); } - if (!node_found) + } + } + // 3D meshes + else if (mesh.getDimension() == 3) // + { + for (unsigned i=0; i<nElements; i++) + { + if (const MeshLib::Cell* cell = dynamic_cast<MeshLib::Cell*>(elements[i])) { - if (one_node == true) - one_node = false; - else + if (cell->isOnSurface()) { - is_surface = false; - break; + const unsigned nFaces (cell->getNFaces()); + for (unsigned j=0; j<nFaces; j++) + { + if (cell->getNeighbor(i) == NULL) + { + const MeshLib::Face* face = static_cast<const MeshLib::Face*>(cell->getFace(i)); + if (!complete_surface) + { + double normal[3]; + face->getSurfaceNormal(normal); + if (MathLib::scpr<double,3>(normal, dir) <= 0) + continue; + } + + if (face->getType() == MshElemType::TRIANGLE) + new_elements.push_back(new MeshLib::Tri(*static_cast<const MeshLib::Tri*>(face))); + else + new_elements.push_back(new MeshLib::Quad(*static_cast<const MeshLib::Quad*>(face))); + } + } } } } - if (is_surface) + + // now copy nodes + const size_t nNewElements (new_elements.size()); + std::vector<const MeshLib::Node*> tmp_nodes(mesh.getNNodes(), NULL); + const size_t nNodes (tmp_nodes.size()); + for (unsigned i=0; i<nNewElements; i++) { - GridAdapter::Element* element = new GridAdapter::Element; - element->material = 0; - element->type = MshElemType::TRIANGLE; - element->nodes = elem_nodes; - elements->push_back(element); + const MeshLib::Element* elem (new_elements[i]); + for (unsigned j=0; j<elem->getNNodes(); j++) + { + const MeshLib::Node* node (elem->getNode(i)); + tmp_nodes[node->getID()] = node; + } } + std::vector<MeshLib::Node*> new_nodes; + for (unsigned i=0; i<nNodes; i++) + if (tmp_nodes[i]) + new_nodes.push_back(new MeshLib::Node(tmp_nodes[i]->getCoords())); } - std::vector<GeoLib::Point*> *nodes = new std::vector<GeoLib::Point*>(nSurfacePoints); - for (size_t j=0; j<nSurfacePoints; j++) - //(*nodes)[sfc_points[j]->getID()]=sfc_points[j]; - (*nodes)[j] = sfc_points[j]; - surface.setNodeVector(nodes); - surface.setElements(elements); - - MeshLib::Mesh* sfc_mesh = new MeshLib::Mesh(*surface.getMesh()); - return sfc_mesh; - */ - return new MeshLib::Mesh(mesh); } +} // end namespace MeshLib diff --git a/MeshLib/MshEditor.h b/MeshLib/MshEditor.h index a7c082649ee87207668b6f96c0208c117d13a51e..3c3323e049aafd2376d009f0bbe6ffa6b6bbc348 100644 --- a/MeshLib/MshEditor.h +++ b/MeshLib/MshEditor.h @@ -15,16 +15,16 @@ #include <cstddef> #include <vector> +#include "Point.h" + namespace GeoLib { class PointWithID; } -namespace MeshLib -{ +namespace MeshLib { +// forward declarations class Mesh; -} - -class GridAdapter; +class Element; /** * \brief A set of tools for manipulating existing meshes @@ -35,14 +35,21 @@ public: MshEditor() {} ~MshEditor() {} - static MeshLib::Mesh* removeMeshNodes(MeshLib::Mesh* mesh, - const std::vector<size_t> &nodes); + /// Returns the area assigned to each node on a surface mesh. + static void getSurfaceAreaForNodes(const MeshLib::Mesh* mesh, std::vector<double> &node_area_vec); + + /// Removes the mesh nodes (and connected elements) given in the nodes-list from the mesh. + static MeshLib::Mesh* removeMeshNodes(MeshLib::Mesh* mesh, const std::vector<size_t> &nodes); + /// Returns the surface nodes of a layered mesh. static std::vector<GeoLib::PointWithID*> getSurfaceNodes(const MeshLib::Mesh &mesh); - static MeshLib::Mesh* getMeshSurface(const MeshLib::Mesh &mesh); + /// Returns the 2d-element mesh representing the surface of the given layered mesh. + static MeshLib::Mesh* getMeshSurface(const MeshLib::Mesh &mesh, const double* dir); private: }; +} // end namespace MeshLib + #endif //MSHEDITOR_H diff --git a/MeshLib/Node.cpp b/MeshLib/Node.cpp index dd2fe4979069da48c12867a1b753e4bf2fcbaa43..247d787e2476c14b06f82d113bac179a07dc5f9d 100644 --- a/MeshLib/Node.cpp +++ b/MeshLib/Node.cpp @@ -11,6 +11,7 @@ */ #include "Node.h" +#include "Elements/Element.h" namespace MeshLib { @@ -33,5 +34,17 @@ Node::~Node() { } + +void Node::updateCoordinates(double x, double y, double z) +{ + _x[0] = x; + _x[1] = y; + _x[2] = z; + + const size_t nElements (this->_elements.size()); + for (unsigned i=0; i<nElements; i++) + _elements[i]->computeVolume(); +} + } diff --git a/MeshLib/Node.h b/MeshLib/Node.h index 740c05bb58959020ebbab69226da01ec9b900759..05a50e56a94bca53b5dec66e64dfacb2a7c8b040 100644 --- a/MeshLib/Node.h +++ b/MeshLib/Node.h @@ -19,6 +19,7 @@ #include "PointWithID.h" #include "Mesh.h" +#include "MshEditor.h" namespace MeshLib { @@ -29,11 +30,12 @@ class Element; */ class Node : public GeoLib::PointWithID { + /* friend functions: */ + friend MeshLib::Mesh* MshEditor::removeMeshNodes(MeshLib::Mesh* mesh, const std::vector<size_t> &nodes); /* friend classes: */ - friend class Mesh;//void Mesh::setElementInformationForNodes(); + friend class Mesh; friend class MeshCoarsener; - //friend void Mesh::addElement(Element*); - + friend class MshLayerMapper; public: /// Constructor using a coordinate array @@ -67,6 +69,10 @@ protected: /// Sets the ID of a node to the given value. void setID(unsigned id) { this->_id = id; }; + /// Update coordinates of a node. + /// This method automatically also updates the areas/volumes of all connected elements. + virtual void updateCoordinates(double x, double y, double z); + std::vector<Element*> _elements; }; /* class */ diff --git a/SimpleTests/MeshTests/MeshRead.cpp b/SimpleTests/MeshTests/MeshRead.cpp index c58fc18f8a106fe93711b8db8c8f3725a33879b4..8e8554429ad61c21602df73e74472300349938d7 100644 --- a/SimpleTests/MeshTests/MeshRead.cpp +++ b/SimpleTests/MeshTests/MeshRead.cpp @@ -56,17 +56,17 @@ int main(int argc, char *argv[]) // std::cout << "time for reading: " << run_time.elapsed() << " s" << std::endl; INFO ("time for reading: %f s", run_time.elapsed()); -/* - unsigned elem_id = 1; + + unsigned elem_id = 25000; const MeshLib::Element* e = mesh->getElement(elem_id); const size_t nElems = mesh->getNElements(); for (unsigned i=0; i< e->getNNeighbors(); i++) { for (unsigned j=0; j< nElems; j++) if (mesh->getElement(j) == e->getNeighbor(i)) - std::cout << "neighbour of " << elem_id << " : " << j << std::endl; + std::cout << "neighbour of element " << elem_id << elem_id << " : " << j << std::endl; } -*/ + delete mesh; delete logogCout; LOGOG_SHUTDOWN(); diff --git a/scripts/cmake/Pack.cmake b/scripts/cmake/Pack.cmake new file mode 100644 index 0000000000000000000000000000000000000000..d23cf023d02dbb6514062ba713141c4ef54b56a8 --- /dev/null +++ b/scripts/cmake/Pack.cmake @@ -0,0 +1,67 @@ +#### Packaging setup for OGS-6 #### + +#INCLUDE(CMakeConfiguration/InstallRequiredSystemLibraries.cmake) + +SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "OGS-6") +SET(CPACK_PACKAGE_VENDOR "OpenGeoSys Community (http://www.opengeosys.com)") +SET(CPACK_PACKAGE_INSTALL_DIRECTORY "OGS-${OGS_VERSION_MAJOR}.${OGS_VERSION_MINOR}.${OGS_VERSION_PATCH}") +SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/README.md") +SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE.txt") +SET(CPACK_PACKAGE_VERSION_MAJOR "${OGS_VERSION_MAJOR}") +SET(CPACK_PACKAGE_VERSION_MINOR "${OGS_VERSION_MINOR}") +SET(CPACK_PACKAGE_VERSION_PATCH "${OGS_VERSION_PATCH}") +SET(CPACK_PACKAGE_FILE_NAME "ogs-${OGS_VERSION_MAJOR}.${OGS_VERSION_MINOR}.${OGS_VERSION_PATCH}-${CMAKE_SYSTEM}-x${BITS}") + +IF (OGS_PACKAGING_ZIP) + SET (CPACK_GENERATOR ZIP) + SET(CPACK_PACKAGE_FILE_NAME "ogs-6") +ELSE (OGS_PACKAGING_ZIP) + IF(WIN32) + SET(CPACK_GENERATOR NSIS) + # There is a bug in NSI that does not handle full unix paths properly. Make + # sure there is at least one set of four (4) backlasshes. + #SET(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/CMakeConfiguration\\\\OGS_Logo_Installer.bmp") + #SET(CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\MyExecutable.exe") + SET(CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}") + SET(CPACK_NSIS_HELP_LINK "https:\\\\\\\\www.opengeosys.com") + SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\www.opengeosys.com") + SET(CPACK_NSIS_CONTACT "lars.bilke@ufz.de") + SET(CPACK_NSIS_MODIFY_PATH ON) + #SET(CPACK_NSIS_MENU_LINKS "https://geosys.ufz.de/trac" "OGS Wiki") + MESSAGE (STATUS "Packaging set to NSIS") + ELSE(WIN32) + IF(UNIX) + SET(CPACK_GENERATOR TGZ) + ELSE(UNIX) + IF(APPLE) + SET(CPACK_GENERATOR TGZ) + ENDIF(APPLE) + ENDIF(UNIX) + #SET(CPACK_STRIP_FILES "bin/ogs") + #SET(CPACK_SOURCE_STRIP_FILES "") + ENDIF(WIN32) +ENDIF (OGS_PACKAGING_ZIP) + +# INCLUDE (FindMSVCRedist) +# IF (MSVC_REDIST) +# SET(CPACK_COMPONENTS_ALL msvc_redist) +# ENDIF () # MSVC_REDIST + +SET(CPACK_COMPONENT_OGS_DISPLAY_NAME "Executable") +SET(CPACK_COMPONENT_OGS_DESCRIPTION "The command line executable") +SET(CPACK_COMPONENT_MSVC_REDIST_DISPLAY_NAME "C++ Redistributable") +SET(CPACK_COMPONENT_MSVC_REDIST_DESCRIPTION "Microsoft Visual C++ Redistributable") + +SET(CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE 1) +IF (OGS_BUILD_GUI) + SET(CPACK_PACKAGE_EXECUTABLES "ogs-gui" "OGS User Interface") + SET(CPACK_COMPONENTS_ALL ${CPACK_COMPONENTS_ALL} ogs_gui Unspecified) + SET(CPACK_COMPONENT_OGS_GUI_DISPLAY_NAME "Data Explorer") + SET(CPACK_COMPONENT_OGS_GUI_DESCRIPTION "The graphical user interface for OpenGeoSys") + #SET(CPACK_COMPONENT_OGS_GUI_DEPENDS ogs) +ELSE () + # SET(CPACK_PACKAGE_EXECUTABLES "ogs" "OGS Command Line") + # SET(CPACK_COMPONENTS_ALL ${CPACK_COMPONENTS_ALL} ogs Unspecified) +ENDIF () + +INCLUDE (CPack)