8#include <kernel/geometry/atlas/chart.hpp>
9#include <kernel/geometry/conformal_mesh.hpp>
10#include <kernel/geometry/index_calculator.hpp>
12#include <kernel/util/math.hpp>
49 template<
typename Mesh_>
51 public ChartCRTP<SurfaceMesh<Mesh_>, Mesh_, SurfaceMeshTraits>
84 explicit SurfaceMesh(std::unique_ptr<SurfaceMeshType> surf_mesh) :
104 virtual std::size_t
bytes()
const override
109 return std::size_t(0);
115 return "SurfaceMesh";
128 for(
Index i(0); i < vtx.get_num_vertices(); ++i)
130 tmp = vtx[i] - origin;
131 vtx[i].set_mat_vec_mult(rot, tmp) += offset;
136 virtual void write(std::ostream& os,
const String& sindent)
const override
140 os << indent <<
"<SurfaceMesh";
141 os <<
" verts=\" " <<
_surface_mesh->get_num_entities(0) <<
"\"";
146 indent.resize(indent.size()+2,
' ');
150 os << indent <<
"<Vertices>\n";
151 indent.resize(indent.size()+2,
' ');
153 for(
Index i(0); i < vtx.get_num_vertices(); ++i)
155 const auto& v = vtx[i];
156 os << indent << v[0];
162 indent.resize(indent.size()-2);
163 os << indent <<
"</Vertices>\n";
166 const auto& idx =
_surface_mesh->template get_index_set<ShapeType::dimension, 0>();
168 os << indent <<
"<Triangles>\n";
169 indent.resize(indent.size()+2,
' ');
171 for(
Index i(0); i < idx.get_num_entities(); ++i)
173 const auto& idx_loc = idx[i];
174 os << indent << idx_loc[0];
175 for(
int j(1); j < idx.num_indices; ++j)
176 os <<
' ' << idx_loc[j];
180 indent.resize(indent.size()-2);
181 os << indent <<
"</Triangles>\n";
183 indent.resize(indent.size()-2);
184 os << indent <<
"</SurfaceMesh>";
220 const auto& idx(
_surface_mesh->template get_index_set<SurfaceMeshType::shape_dim, 0>());
231 CoordType acceptable_distance(Math::huge<CoordType>());
250 Index i(idx(best_facet, j+1));
251 projected_point += coeffs[j]*vtx[i];
255 projected_point += coeff0*vtx[idx(best_facet,
Index(0))];
257 grad_distance = (projected_point - point);
261 if(signed_distance < Math::eps<CoordType>())
265 grad_distance.normalize();
270 point = projected_point;
290 const auto& idx(
_surface_mesh->template get_index_set<SurfaceMeshType::shape_dim, 0>());
297 Index i0(idx(facet, 0));
298 Index i1(idx(facet, 1));
299 Index i2(idx(facet, 2));
301 coords[0] = vtx[i1] - vtx[i0];
302 coords[1] = vtx[i2] - vtx[i0];
304 for(
int i(0); i < coords.
m; ++i)
306 for(
int j(0); j < coords.
n; ++j)
307 coords_transpose(j,i) = coords(i,j);
334 XASSERTM(meshpart.get_topology() !=
nullptr,
"The meshpart needs a topology for SurfaceMesh::project()!");
340 if(num_facets ==
Index(0))
346 const auto& ts_verts(meshpart.template get_target_set<0>());
349 const auto& idx_sm(
_surface_mesh->template get_index_set<SurfaceMeshType::shape_dim, 0>());
354 const auto& idx_mp(meshpart.template get_index_set<SurfaceMeshType::shape_dim, 0>());
358 const auto& facet_idx_mp(meshpart.template get_index_set
366 Geometry::Intern::FacetNeighbors::compute(neigh_mp, facet_idx_mp);
369 auto& vtx(mesh.get_vertex_set());
376 bool* vert_todo(
new bool[num_verts]);
377 for(
Index i(0); i < num_verts; ++i)
381 bool* facet_todo(
new bool[num_facets]);
382 for(
Index i(0); i < num_facets; ++i)
383 facet_todo[i] =
true;
388 for(
Index i(0); i < num_facets; ++i)
389 guesses[i] =
Index(0);
392 std::deque<Index> facet_stack;
393 facet_stack.push_front(0);
396 while(!facet_stack.empty())
399 Index current_facet(facet_stack.front());
402 Index facet_sm(guesses[current_facet]);
404 facet_stack.pop_front();
405 facet_todo[current_facet] =
false;
414 for(
int j(0); j < idx_mp.num_indices-1; ++j)
416 Index i0(idx_mp(current_facet, 0));
417 Index i_mp(idx_mp(current_facet, j+1));
418 acceptable_distance *= ((vtx[i_mp] - vtx[i0]).norm_euclid());
424 for(
int j(0); j < idx_mp.num_indices; ++j)
427 Index i_mp(idx_mp(current_facet, j));
431 vert_todo[i_mp] =
false;
432 const auto& x(vtx[ts_verts[i_mp]]);
438 guesses[current_facet] = facet_sm;
441 Index i_parent(ts_verts[i_mp]);
449 Index i_sm(idx_sm(facet_sm, i+1));
450 vtx[i_parent] += coeffs[i]*vtx_sm[i_sm];
453 vtx[i_parent] += coeff0*vtx_sm[idx_sm(facet_sm, 0)];
459 for(
int l(0); l < neigh_mp.num_indices; ++l)
461 Index k(neigh_mp(current_facet, l));
462 if(k != ~
Index(0) && facet_todo[k])
464 facet_todo[k] =
false;
465 facet_stack.push_back(k);
468 guesses[k] = facet_sm;
492 project_point(projected_point, signed_distance, grad_distance);
509 project_point(projected_point, signed_distance, grad_distance);
511 return signed_distance;
551 template<
int world_dim,
int sc_,
int sx_>
568 for(
Index cell(0); cell < num_cells; ++cell)
574 static constexpr int num_vert_loc = VertAtCellIdxType::num_indices;
576 const VertAtCellIdxType& idx(mesh.template get_index_set<SurfaceMeshType::shape_dim, 0>());
578 const auto& facet_idx(mesh.template
579 get_index_set<SurfaceMeshType::shape_dim, SurfaceMeshType::shape_dim-1>());
590 std::deque<Index> cell_stack;
592 cell_stack.push_front(guess);
597 CoordType best_approx_dist(Math::huge<CoordType>());
602 while(!cell_stack.empty())
605 Index current(cell_stack.front());
606 cell_stack.pop_front();
612 Index i(idx(current, j));
618 compute_inverse_coeffs(current_coeffs, x, coords);
631 if(success && !find_best_approx)
633 best_approx_cell = current;
634 coeffs = current_coeffs;
638 else if(success && find_best_approx)
640 if(ortho_dist < best_approx_dist)
642 best_approx_dist = ortho_dist;
643 best_approx_cell = current;
644 coeffs = current_coeffs;
653 Index n(neigh(current, l));
657 Index facet(facet_idx(current,l));
662 cell_stack.push_front(n);
664 cell_stack.push_back(n);
677 return best_approx_cell;
730 template<
typename DT_,
int n_,
int sn_,
int sb_>
734 for(
int j(0); j < n_-1; ++j)
736 bary(0) -= coeffs(j);
737 bary(j+1) = coeffs(j);
807 template<
typename DT_,
int n_,
int sn_,
typename IdxType_>
810 DT_ acceptable_distance,
812 const IdxType_& facet_idx,
815 static const DT_ tol =
Math::sqrt(Math::eps<DT_>());
819 if(ortho_dist > acceptable_distance)
824 for(
int l(0); l < n_; ++l)
828 Index facet(facet_idx[l]);
837 traversed[facet] =
true;
854 template<
typename DT_,
int sb_,
int sp_,
int smx_,
int snx_>
855 void compute_inverse_coeffs(
865 for(
int i(0); i < 3; ++i)
867 for(
int j(0); j < 2; ++j)
868 A(i,j) = x(j+1,i) - x(0,i);
878 for(
int i(0); i < 3; ++i)
886 coeffs = Ainv*(point - x[0]);
894 template<
typename DT_,
int world_dim,
int sc_,
int sp_,
int smx_,
int snx_>
895 void compute_inverse_coeffs(
901 "world dim has to be 2 or 3 for complementary barycentric coordinates");
903 auto tmp = x[1]-x[0];
907 tmp = point - (x[0] + coeffs[0]*(x[1]-x[0]));
914 template<
typename Mesh_>
915 class SurfaceMeshVertsParser :
916 public Xml::MarkupParser
919 typedef typename Mesh_::CoordType CoordType;
920 typedef VertexSet<3, CoordType> VertexSetType;
923 VertexSetType& _vertex_set;
927 explicit SurfaceMeshVertsParser(VertexSetType& vertex_set) :
928 _vertex_set(vertex_set),
933 virtual bool attribs(std::map<String,bool>&)
const override
938 virtual void create(
int iline,
const String& sline,
const String&,
const std::map<String, String>&,
bool closed)
override
941 throw Xml::GrammarError(iline, sline,
"Invalid closed markup");
944 virtual void close(
int iline,
const String& sline)
override
947 if(_read < _vertex_set.get_num_vertices())
948 throw Xml::GrammarError(iline, sline,
"Invalid terminator; expected point");
951 virtual std::shared_ptr<MarkupParser> markup(
int,
const String&,
const String&)
override
957 virtual bool content(
int iline,
const String& sline)
override
960 if(_read >= _vertex_set.get_num_vertices())
961 throw Xml::ContentError(iline, sline,
"Invalid content; expected terminator");
964 std::deque<String> scoords = sline.split_by_whitespaces();
967 if(scoords.size() != std::size_t(3))
968 throw Xml::ContentError(iline, sline,
"Invalid number of coordinates");
971 auto& vtx = _vertex_set[_read];
972 for(
int i(0); i < 3; ++i)
974 if(!scoords.at(std::size_t(i)).parse(vtx[i]))
975 throw Xml::ContentError(iline, sline,
"Failed to parse vertex coordinate");
985 template<
typename Mesh_>
986 class SurfaceMeshTriasParser :
987 public Xml::MarkupParser
990 typedef IndexSet<3> IndexSetType;
993 IndexSetType& _index_set;
997 explicit SurfaceMeshTriasParser(IndexSetType& index_set) :
998 _index_set(index_set),
1003 virtual bool attribs(std::map<String,bool>&)
const override
1008 virtual void create(
int iline,
const String& sline,
const String&,
const std::map<String, String>&,
bool closed)
override
1011 throw Xml::GrammarError(iline, sline,
"Invalid closed markup");
1014 virtual void close(
int iline,
const String& sline)
override
1017 if(_read < _index_set.get_num_entities())
1018 throw Xml::GrammarError(iline, sline,
"Invalid terminator; expected triangle indices");
1021 virtual std::shared_ptr<MarkupParser> markup(
int,
const String&,
const String&)
override
1027 virtual bool content(
int iline,
const String& sline)
override
1030 if(_read >= _index_set.get_num_entities())
1031 throw Xml::ContentError(iline, sline,
"Invalid content; exprected terminator");
1034 std::deque<String> sidx = sline.split_by_whitespaces();
1037 if(sidx.size() != std::size_t(3))
1038 throw Xml::ContentError(iline, sline,
"Invalid number of indices");
1041 auto& idx = _index_set[_read];
1042 for(
int i(0); i < 3; ++i)
1044 if(!sidx.at(std::size_t(i)).parse(idx[i]))
1045 throw Xml::ContentError(iline, sline,
"Failed to parse vertex index");
1055 template<
typename Mesh_,
bool enable_ = (Mesh_::shape_dim > 2)>
1056 class SurfaceMeshChartParser :
1057 public Xml::DummyParser
1060 explicit SurfaceMeshChartParser(std::unique_ptr<ChartBase<Mesh_>>&)
1062 XABORTM(
"Thou shall not arrive here");
1066 template<
typename Mesh_>
1067 class SurfaceMeshChartParser<Mesh_, true> :
1068 public Xml::MarkupParser
1071 typedef typename SurfaceMesh<Mesh_>::SurfaceMeshType SurfaceMeshType;
1072 std::unique_ptr<ChartBase<Mesh_>>& _chart;
1073 std::unique_ptr<SurfaceMeshType> _surfmesh;
1074 Index _nverts, _ntrias;
1075 bool _have_verts, _have_trias;
1078 explicit SurfaceMeshChartParser(std::unique_ptr<ChartBase<Mesh_>>& chart) :
1083 _have_verts(false), _have_trias(false)
1087 virtual bool attribs(std::map<String,bool>& attrs)
const override
1089 attrs.emplace(
"verts",
true);
1090 attrs.emplace(
"trias",
true);
1094 virtual void create(
1096 const String& sline,
1098 const std::map<String, String>& attrs,
1099 bool closed)
override
1103 throw Xml::GrammarError(iline, sline,
"Invalid closed SurfaceMesh markup");
1106 if(!attrs.find(
"verts")->second.parse(_nverts))
1107 throw Xml::GrammarError(iline, sline,
"Failed to parse number of vertices");
1108 if(!attrs.find(
"trias")->second.parse(_ntrias))
1109 throw Xml::GrammarError(iline, sline,
"Failed to parse number of triangles");
1112 Index num_entities[3] = {_nverts, 0, _ntrias};
1113 _surfmesh.reset(
new SurfaceMeshType(num_entities));
1116 virtual void close(
int iline,
const String& sline)
override
1119 throw Xml::GrammarError(iline, sline,
"Vertices of SurfaceMesh are missing");
1121 throw Xml::GrammarError(iline, sline,
"Triangles of SurfaceMesh are missing");
1124 _surfmesh->deduct_topology_from_top();
1127 _chart.reset(
new SurfaceMesh<Mesh_>(std::move(_surfmesh)));
1130 virtual bool content(
int,
const String&)
override
1135 virtual std::shared_ptr<Xml::MarkupParser> markup(
int,
const String&,
const String& name)
override
1137 if(name ==
"Vertices")
1140 return std::make_shared<SurfaceMeshVertsParser<Mesh_>>(_surfmesh->get_vertex_set());
1142 if(name ==
"Triangles")
1145 return std::make_shared<SurfaceMeshTriasParser<Mesh_>>(_surfmesh->template get_index_set<2,0>());
#define XABORTM(msg)
Abortion macro definition with custom message.
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Chart CRTP base-class template.
static constexpr int world_dim
the world dimension of this chart
BaseClass::WorldPoint WorldPoint
our world point type
VertexSetType::CoordType CoordType
coordinate type
Boundary description by a surface mesh in 3d.
SurfaceMesh()=delete
Explicitly delete empty default constructor.
CoordType compute_dist(const WorldPoint &point, WorldPoint &grad_distance) const
Computes the distance of a point to this chart.
void project_meshpart(Mesh_ &mesh, const MeshPart< Mesh_ > &meshpart) const
Orthogonally projects all vertices at facets of a MeshPart.
virtual void transform(const WorldPoint &origin, const WorldPoint &angles, const WorldPoint &offset) override
std::unique_ptr< SurfaceMeshType > _surface_mesh
Pointer to the surface mesh object.
bool * _edge_marker
Marker for edges.
virtual void write(std::ostream &os, const String &sindent) const override
Writes the Chart into a stream in XML format.
WorldPoint get_normal_on_tria(const Index facet, const Tiny::Vector< CoordType, SurfaceMeshType::shape_dim+1 > coeffs) const
Computes the outer normal on a triangle for a single point.
virtual ~SurfaceMesh()
Virtual destructor.
BaseClass::CoordType CoordType
Floating point type for coordinates.
virtual std::size_t bytes() const override
SurfaceMesh(std::unique_ptr< SurfaceMeshType > surf_mesh)
Constructor getting an object.
ConformalMesh< ShapeType, 3, CoordType > SurfaceMeshType
The type for the mesh defining the discrete surface.
void project_point(WorldPoint &point, CoordType &signed_distance, WorldPoint &grad_distance) const
Projects a single point to the surface given by the surface mesh.
Shape::Simplex< 2 > ShapeType
The shape type is always Simplex<2>
BaseClass::WorldPoint WorldPoint
Vector type for world points.
Index find_cell(Tiny::Vector< CoordType, SurfaceMeshType::shape_dim+1, sc_ > &coeffs, const Tiny::Vector< CoordType, world_dim, sx_ > &x, Index guess, CoordType acceptable_distance, const SurfaceMeshType &mesh, bool find_best_approx) const
Finds the cell in the surface mesh that contains a specific point.
virtual String get_type() const override
Writes the type as String.
bool * _cell_marker
Marker for triangles.
static DT_ compute_bary_and_dist(Tiny::Vector< DT_, n_, sb_ > &bary, const Tiny::Vector< DT_, n_, sn_ > &coeffs)
For given reference cell coordinates, this computes the barycentric coordinates and the distance.
static bool determine_success(DT_ ortho_dist, DT_ acceptable_distance, Tiny::Vector< DT_, n_, sn_ > &bary, const IdxType_ &facet_idx, bool *traversed)
Determines the success of the point search.
CoordType compute_signed_dist(const WorldPoint &point) const
Computes the signed distance of a point to this chart.
CoordType compute_signed_dist(const WorldPoint &point, WorldPoint &grad_distance) const
Computes the signed distance of a point to this chart.
CoordType compute_dist(const WorldPoint &point) const
Computes the distance of a point to this chart.
void project_point(WorldPoint &point) const
Projects a single point to the surface given by the surface mesh.
ChartCRTP< SurfaceMesh< Mesh_ >, Mesh_, SurfaceMeshTraits > BaseClass
The CRTP base class.
SurfaceMesh(SurfaceMeshType &&)=delete
Explicitly delete move constructor.
Conformal Index-Set class template.
Class template for partial meshes.
Index get_num_entities(int dim) const
Returns the number of entities.
String class implementation.
Tiny Matrix class template.
static constexpr int n
the column count of the matrix
static constexpr int m
the row count of the matrix
CUDA_HOST_DEVICE Matrix & set_rotation_3d(T_ yaw, T_ pitch, T_ roll)
Sets this matrix to a 3D yaw-pitch-roll rotation matrix.
Tiny Vector class template.
CUDA_HOST_DEVICE void format(DataType alpha=DataType(0))
Formats the vector.
CUDA_HOST_DEVICE Vector & normalize()
Normalizes this vector.
CUDA_HOST_DEVICE DataType norm_euclid() const
Computes the euclid norm of this vector.
T_ sqrt(T_ x)
Returns the square-root of a value.
T_ abs(T_ x)
Returns the absolute value.
T_ pow(T_ x, T_ y)
Returns x raised to the power of y.
T_ sqr(T_ x)
Returns the square of a value.
T_ min(T_ a, T_ b)
Returns the minimum of two values.
T_ signum(T_ x)
Returns the sign of a value.
T_ max(T_ a, T_ b)
Returns the maximum of two values.
CUDA_HOST_DEVICE T_ dot(const T_ &a, const T_ &b)
Computes the dot-product of two scalars.
CUDA_HOST_DEVICE void orthogonal_3x2(Vector< T_, mx_, smx_ > &nu, const Matrix< T_, ma_, na_, sm_, sn_ > &tau)
Computes the positively oriented orthogonal vector to the columns of a 3x2 matrix.
Vector< T_, m_ > orthogonal(const Matrix< T_, m_, m_-1, sm_, sn_ > &tau)
Computes the positively oriented orthogonal vector to the columns of a m_ x (m_-1) Matrix.
String stringify(const T_ &item)
Converts an item into a String.
std::uint64_t Index
Index data type.
static constexpr bool is_explicit
No explicit map is available in general.
static constexpr bool is_implicit
We support implicit projection.
static constexpr int param_dim
If there was a parametrization, it would be the object's shape dim.
static constexpr int world_dim
This is a world_dim dimensional object.
Simplex shape tag struct template.
static constexpr int dimension
Simplex dimension.