const std::vector< std::pair<size_t,double> >& DirectConditionGenerator::directWithSurfaceIntegration(MeshLib::Mesh &mesh, const std::string &filename, double scaling) { if (_direct_values.empty()) { GeoLib::Raster* raster (GeoLib::Raster::readRaster(filename)); if (!raster) { ERR("Error in DirectConditionGenerator::directWithSurfaceIntegration() - could not load raster file."); return _direct_values; } const MathLib::Vector3 dir(0,0,-1); MeshLib::Mesh* sfc_mesh (MeshLib::MeshSurfaceExtraction::getMeshSurface(mesh, dir, true)); std::vector<double> node_area_vec; MeshLib::MeshSurfaceExtraction::getSurfaceAreaForNodes(*sfc_mesh, node_area_vec); const std::vector<MeshLib::Node*> &surface_nodes (sfc_mesh->getNodes()); const size_t nNodes(sfc_mesh->getNNodes()); const double no_data (raster->getNoDataValue()); _direct_values.reserve(nNodes); for (size_t i=0; i<nNodes; ++i) { double val (raster->getValueAtPoint(*surface_nodes[i])); val = (val == no_data) ? 0 : ((val*node_area_vec[i])/scaling); _direct_values.push_back (std::pair<size_t, double>(surface_nodes[i]->getID(), val)); } delete raster; } else std::cout << "Error in DirectConditionGenerator::directWithSurfaceIntegration() - Data vector contains outdated values..." << std::endl; return _direct_values; }
void MshView::extractSurfaceMesh() { QModelIndex index = this->selectionModel()->currentIndex(); if (!index.isValid()) return; const MeshLib::Mesh* mesh = static_cast<MshModel*>(this->model())->getMesh(index); SurfaceExtractionDialog dlg; if (dlg.exec() != QDialog::Accepted) return; MathLib::Vector3 const& dir (dlg.getNormal()); int const tolerance (dlg.getTolerance()); MeshLib::Mesh* sfc_mesh (MeshLib::MeshSurfaceExtraction::getMeshSurface(*mesh, dir, tolerance)); if (sfc_mesh != nullptr) static_cast<MshModel*>(this->model())->addMesh(sfc_mesh); else OGSError::box(" No surfaces found to extract\n using the specified parameters."); }
MeshLib::Mesh* addLayerToMesh(MeshLib::Mesh const& mesh, double thickness, std::string const& name, bool on_top) { INFO("Extracting top surface of mesh \"%s\" ... ", mesh.getName().c_str()); int const flag = (on_top) ? -1 : 1; const MathLib::Vector3 dir(0, 0, flag); double const angle(90); std::unique_ptr<MeshLib::Mesh> sfc_mesh (nullptr); std::string const prop_name("OriginalSubsurfaceNodeIDs"); if (mesh.getDimension() == 3) sfc_mesh.reset(MeshLib::MeshSurfaceExtraction::getMeshSurface( mesh, dir, angle, prop_name)); else { sfc_mesh = (on_top) ? std::unique_ptr<MeshLib::Mesh>(new MeshLib::Mesh(mesh)) : std::unique_ptr<MeshLib::Mesh>(MeshLib::createFlippedMesh(mesh)); // add property storing node ids auto* const pv = sfc_mesh->getProperties().createNewPropertyVector<std::size_t>( prop_name, MeshLib::MeshItemType::Node, 1); if (pv) { pv->resize(sfc_mesh->getNumberOfNodes()); std::iota(pv->begin(), pv->end(), 0); } else { ERR("Could not create and initialize property."); return nullptr; } } INFO("done."); // *** add new surface nodes std::vector<MeshLib::Node*> subsfc_nodes = MeshLib::copyNodeVector(mesh.getNodes()); std::vector<MeshLib::Element*> subsfc_elements = MeshLib::copyElementVector(mesh.getElements(), subsfc_nodes); std::size_t const n_subsfc_nodes(subsfc_nodes.size()); std::vector<MeshLib::Node*> const& sfc_nodes(sfc_mesh->getNodes()); std::size_t const n_sfc_nodes(sfc_nodes.size()); // fetch subsurface node ids PropertyVector auto const* const node_id_pv = sfc_mesh->getProperties().getPropertyVector<std::size_t>(prop_name); if (!node_id_pv) { ERR( "Need subsurface node ids, but the property \"%s\" is not " "available.", prop_name.c_str()); return nullptr; } // *** copy sfc nodes to subsfc mesh node std::map<std::size_t, std::size_t> subsfc_sfc_id_map; for (std::size_t k(0); k<n_sfc_nodes; ++k) { std::size_t const subsfc_id((*node_id_pv)[k]); std::size_t const sfc_id(k+n_subsfc_nodes); subsfc_sfc_id_map.insert(std::make_pair(subsfc_id, sfc_id)); MeshLib::Node const& node(*sfc_nodes[k]); subsfc_nodes.push_back(new MeshLib::Node( node[0], node[1], node[2] - (flag * thickness), sfc_id)); } // *** insert new layer elements into subsfc_mesh std::vector<MeshLib::Element*> const& sfc_elements(sfc_mesh->getElements()); std::size_t const n_sfc_elements(sfc_elements.size()); for (std::size_t k(0); k<n_sfc_elements; ++k) subsfc_elements.push_back(extrudeElement( subsfc_nodes, *sfc_elements[k], *node_id_pv, subsfc_sfc_id_map)); auto new_mesh = new MeshLib::Mesh(name, subsfc_nodes, subsfc_elements); auto const* const opt_materials = mesh.getProperties().getPropertyVector<int>("MaterialIDs"); if (!opt_materials) { ERR("Could not copy the property \"MaterialIDs\" since the original " "mesh does not contain such a property."); return new_mesh; } auto* const new_materials = new_mesh->getProperties().createNewPropertyVector<int>( "MaterialIDs", MeshLib::MeshItemType::Cell, 1); if (!new_materials) { ERR("Can not set material properties for new layer"); return new_mesh; } new_materials->reserve(subsfc_elements.size()); int new_layer_id( *(std::max_element(opt_materials->cbegin(), opt_materials->cend())) + 1); std::copy(opt_materials->cbegin(), opt_materials->cend(), std::back_inserter(*new_materials)); auto const n_new_props(subsfc_elements.size() - mesh.getNumberOfElements()); std::fill_n(std::back_inserter(*new_materials), n_new_props, new_layer_id); return new_mesh; }
TEST(GeoLib, SurfaceIsPointInSurface) { std::vector<std::function<double(double, double)>> surface_functions; surface_functions.push_back(constant); surface_functions.push_back(coscos); for (auto f : surface_functions) { std::random_device rd; std::string name("Surface"); // generate ll and ur in random way std::mt19937 random_engine_mt19937(rd()); std::normal_distribution<> normal_dist_ll(-10, 2); std::normal_distribution<> normal_dist_ur(10, 2); MathLib::Point3d ll(std::array<double,3>({{ normal_dist_ll(random_engine_mt19937), normal_dist_ll(random_engine_mt19937), 0.0 } })); MathLib::Point3d ur(std::array<double,3>({{ normal_dist_ur(random_engine_mt19937), normal_dist_ur(random_engine_mt19937), 0.0 } })); for (std::size_t k(0); k<3; ++k) if (ll[k] > ur[k]) std::swap(ll[k], ur[k]); // random discretization of the domain std::default_random_engine re(rd()); std::uniform_int_distribution<std::size_t> uniform_dist(2, 25); std::array<std::size_t,2> n_steps = {{uniform_dist(re),uniform_dist(re)}}; std::unique_ptr<MeshLib::Mesh> sfc_mesh( MeshLib::MeshGenerator::createSurfaceMesh( name, ll, ur, n_steps, f ) ); // random rotation angles std::normal_distribution<> normal_dist_angles( 0, boost::math::double_constants::two_pi); std::array<double,3> euler_angles = {{ normal_dist_angles(random_engine_mt19937), normal_dist_angles(random_engine_mt19937), normal_dist_angles(random_engine_mt19937) } }; MathLib::DenseMatrix<double, std::size_t> rot_mat(getRotMat( euler_angles[0], euler_angles[1], euler_angles[2])); std::vector<MeshLib::Node*> const& nodes(sfc_mesh->getNodes()); GeoLib::rotatePoints<MeshLib::Node>(rot_mat, nodes); MathLib::Vector3 const normal(0,0,1.0); MathLib::Vector3 const surface_normal(rot_mat * normal); double const eps(1e-6); MathLib::Vector3 const displacement(eps * surface_normal); GeoLib::GEOObjects geometries; MeshLib::convertMeshToGeo(*sfc_mesh, geometries); std::vector<GeoLib::Surface*> const& sfcs(*geometries.getSurfaceVec(name)); GeoLib::Surface const*const sfc(sfcs.front()); std::vector<GeoLib::Point*> const& pnts(*geometries.getPointVec(name)); // test triangle edge point of the surface triangles for (auto const p : pnts) { EXPECT_TRUE(sfc->isPntInSfc(*p)); MathLib::Point3d q(*p); for (std::size_t k(0); k<3; ++k) q[k] += displacement[k]; EXPECT_FALSE(sfc->isPntInSfc(q)); } // test edge middle points of the triangles for (std::size_t k(0); k<sfc->getNTriangles(); ++k) { MathLib::Point3d p, q, r; std::tie(p,q,r) = getEdgeMiddlePoints(*(*sfc)[k]); EXPECT_TRUE(sfc->isPntInSfc(p)); EXPECT_TRUE(sfc->isPntInSfc(q)); EXPECT_TRUE(sfc->isPntInSfc(r)); } } }