improve concept

This commit is contained in:
Sébastien Loriot 2023-11-20 11:28:50 +01:00
parent 730bbba98b
commit 37fb95b5cd
7 changed files with 48 additions and 45 deletions

View File

@ -16,6 +16,7 @@ class PMPSizingField{
public:
/// @name Types
/// These types are used for the documentation of the functions of the concept and not needed implementation wise.
/// @{
/// Vertex descriptor type
@ -38,27 +39,29 @@ typedef unspecified_type FT;
/// @name Functions
/// @{
/// a function that returns the sizing value at `v`.
FT at(const vertex_descriptor v) const;
/// returns the sizing value at `v` (used during tangential relaxation).
FT at(const vertex_descriptor v, const PolygonMesh& pmesh) const;
/// a function controlling edge split and edge collapse,
/// returning the ratio of the current edge length and the local target edge length between
/// the points of `va` and `vb` in case the current edge is too long, and `std::nullopt` otherwise.
/// returns the ratio of the current edge squared length and the local target edge squared length between
/// the points of `va` and `vb` in case the current edge is too long, and `std::nullopt` otherwise
/// (used for triggering edge splits and preventing some edge collapses).
std::optional<FT> is_too_long(const vertex_descriptor va,
const vertex_descriptor vb) const;
const vertex_descriptor vb,
const PolygonMesh& pmesh) const;
/// a function controlling edge collapse by returning the ratio of the squared length of `h` and the
/// local target edge length if it is too short, and `std::nullopt` otherwise.
/// returns the ratio of the squared length of `h` and the
/// local target edge squared length if it is too short, and `std::nullopt` otherwise
/// (used for triggering edge collapses).
std::optional<FT> is_too_short(const halfedge_descriptor h,
const PolygonMesh& pmesh) const;
/// a function returning the location of the split point of the edge of `h`.
/// returns the position of the new vertex created when splitting the edge of `h`.
Point_3 split_placement(const halfedge_descriptor h,
const PolygonMesh& pmesh) const;
/// a function that updates the sizing field value at the vertex `v`.
void update(const vertex_descriptor v,
const PolygonMesh& pmesh);
/// function called after the addition of the split vertex `v` in `pmesh`.
void register_split_vertex(const vertex_descriptor v,
const PolygonMesh& pmesh);
/// @}
};

View File

@ -19,14 +19,12 @@ struct My_sizing_field
{
double min_size, max_size;
double ymin, ymax;
const Mesh& mesh;
My_sizing_field(double min_size, double max_size, double ymin, double ymax, const Mesh& mesh)
My_sizing_field(double min_size, double max_size, double ymin, double ymax)
: min_size(min_size)
, max_size(max_size)
, ymin(ymin)
, ymax(ymax)
, mesh(mesh)
{}
double at(K::Point_3 p) const
@ -34,10 +32,11 @@ struct My_sizing_field
double y=p.y();
return CGAL::square( (y-ymin)/(ymax-ymin) * (min_size - max_size) + max_size );
}
double at(const Mesh::Vertex_index v) const { return at(mesh.point(v)); }
double at(const Mesh::Vertex_index v, const Mesh& mesh) const { return at(mesh.point(v)); }
std::optional<double> is_too_long(const Mesh::Vertex_index va,
const Mesh::Vertex_index vb) const
const Mesh::Vertex_index vb,
const Mesh& mesh) const
{
// TODO: no mesh as parameters?
K::Point_3 mp = CGAL::midpoint(mesh.point(va), mesh.point(vb));
@ -49,7 +48,7 @@ struct My_sizing_field
}
std::optional<double> is_too_short(const Mesh::Halfedge_index h,
const Mesh&) const
const Mesh& mesh) const
{
K::Point_3 mp = CGAL::midpoint(mesh.point(source(h, mesh)), mesh.point(target(h, mesh)));
double sql_at = at(mp);
@ -60,12 +59,12 @@ struct My_sizing_field
}
K::Point_3 split_placement(const Mesh::Halfedge_index h,
const Mesh&) const
const Mesh& mesh) const
{
return CGAL::midpoint(mesh.point(source(h, mesh)), mesh.point(target(h, mesh)));
}
void update(const Mesh::Vertex_index, const Mesh&) {}
void register_split_vertex(const Mesh::Vertex_index, const Mesh&) {}
};
@ -83,7 +82,7 @@ int main(int argc, char* argv[])
<< " (" << num_faces(mesh) << " faces)..." << std::endl;
CGAL::Bbox_3 bb = PMP::bbox(mesh);
My_sizing_field sizing_field(0.1, 30, bb.ymin(), bb.ymax(), mesh);
My_sizing_field sizing_field(0.1, 30, bb.ymin(), bb.ymax());
unsigned int nb_iter = 5;
PMP::isotropic_remeshing(

View File

@ -213,13 +213,13 @@ private:
}
public:
FT at(const vertex_descriptor v) const
FT at(const vertex_descriptor v, const PolygonMesh& /* pmesh */) const
{
CGAL_assertion(get(m_vertex_sizing_map, v));
return get(m_vertex_sizing_map, v);
}
std::optional<FT> is_too_long(const vertex_descriptor va, const vertex_descriptor vb) const
std::optional<FT> is_too_long(const vertex_descriptor va, const vertex_descriptor vb, const PolygonMesh& /* pmesh */) const
{
const FT sqlen = sqlength(va, vb);
FT sqtarg_len = CGAL::square(4./3. * (CGAL::min)(get(m_vertex_sizing_map, va),
@ -251,7 +251,7 @@ public:
get(m_vpmap, source(h, pmesh)));
}
void update(const vertex_descriptor v, const PolygonMesh& pmesh)
void register_split_vertex(const vertex_descriptor v, const PolygonMesh& pmesh)
{
// calculating it as the average of two vertices on other ends
// of halfedges as updating is done during an edge split

View File

@ -102,12 +102,12 @@ private:
}
public:
FT at(const vertex_descriptor /* v */) const
FT at(const vertex_descriptor /* v */, const PolygonMesh& /* pmesh */) const
{
return m_size;
}
std::optional<FT> is_too_long(const vertex_descriptor va, const vertex_descriptor vb) const
std::optional<FT> is_too_long(const vertex_descriptor va, const vertex_descriptor vb, const PolygonMesh& /* pmesh */) const
{
const FT sqlen = sqlength(va, vb);
if (sqlen > m_sq_long)
@ -133,7 +133,7 @@ public:
get(m_vpmap, source(h, pmesh)));
}
void update(const vertex_descriptor /* v */, const PolygonMesh& /* pmesh */)
void register_split_vertex(const vertex_descriptor /* v */, const PolygonMesh& /* pmesh */)
{}
private:

View File

@ -246,7 +246,7 @@ namespace internal {
get(ecmap, e) ||
get(fpm, face(h,pmesh))!=get(fpm, face(opposite(h,pmesh),pmesh)) )
{
if (sizing.is_too_long(source(h, pmesh), target(h, pmesh)))
if (sizing.is_too_long(source(h, pmesh), target(h, pmesh), pmesh))
{
return false;
}
@ -400,7 +400,7 @@ namespace internal {
for(edge_descriptor e : edge_range)
{
const halfedge_descriptor he = halfedge(e, mesh_);
std::optional<double> sqlen = sizing.is_too_long(source(he, mesh_), target(he, mesh_));
std::optional<double> sqlen = sizing.is_too_long(source(he, mesh_), target(he, mesh_), mesh_);
if(sqlen != std::nullopt)
long_edges.emplace(he, sqlen.value());
}
@ -433,16 +433,16 @@ namespace internal {
std::cout << " refinement point : " << refinement_point << std::endl;
#endif
//update sizing field with the new point
sizing.update(vnew, mesh_);
sizing.register_split_vertex(vnew, mesh_);
//check sub-edges
//if it was more than twice the "long" threshold, insert them
std::optional<double> sqlen_new = sizing.is_too_long(source(hnew, mesh_), target(hnew, mesh_));
std::optional<double> sqlen_new = sizing.is_too_long(source(hnew, mesh_), target(hnew, mesh_), mesh_);
if(sqlen_new != std::nullopt)
long_edges.emplace(hnew, sqlen_new.value());
const halfedge_descriptor hnext = next(hnew, mesh_);
sqlen_new = sizing.is_too_long(source(hnext, mesh_), target(hnext, mesh_));
sqlen_new = sizing.is_too_long(source(hnext, mesh_), target(hnext, mesh_), mesh_);
if (sqlen_new != std::nullopt)
long_edges.emplace(hnext, sqlen_new.value());
@ -500,7 +500,7 @@ namespace internal {
if (!is_split_allowed(e))
continue;
const halfedge_descriptor he = halfedge(e, mesh_);
std::optional<double> sqlen = sizing.is_too_long(source(he, mesh_), target(he, mesh_));
std::optional<double> sqlen = sizing.is_too_long(source(he, mesh_), target(he, mesh_), mesh_);
if(sqlen != std::nullopt)
long_edges.emplace(halfedge(e, mesh_), sqlen.value());
}
@ -550,16 +550,16 @@ namespace internal {
halfedge_added(hnew_opp, status(opposite(he, mesh_)));
//update sizing field with the new point
sizing.update(vnew, mesh_);
sizing.register_split_vertex(vnew, mesh_);
//check sub-edges
//if it was more than twice the "long" threshold, insert them
std::optional<double> sqlen_new = sizing.is_too_long(source(hnew, mesh_), target(hnew, mesh_));
std::optional<double> sqlen_new = sizing.is_too_long(source(hnew, mesh_), target(hnew, mesh_), mesh_);
if(sqlen_new != std::nullopt)
long_edges.emplace(hnew, sqlen_new.value());
const halfedge_descriptor hnext = next(hnew, mesh_);
sqlen_new = sizing.is_too_long(source(hnext, mesh_), target(hnext, mesh_));
sqlen_new = sizing.is_too_long(source(hnext, mesh_), target(hnext, mesh_), mesh_);
if (sqlen_new != std::nullopt)
long_edges.emplace(hnext, sqlen_new.value());
@ -580,7 +580,7 @@ namespace internal {
if (snew == PATCH)
{
std::optional<double> sql = sizing.is_too_long(source(hnew2, mesh_), target(hnew2, mesh_));
std::optional<double> sql = sizing.is_too_long(source(hnew2, mesh_), target(hnew2, mesh_), mesh_);
if(sql != std::nullopt)
long_edges.emplace(hnew2, sql.value());
}
@ -603,7 +603,7 @@ namespace internal {
if (snew == PATCH)
{
std::optional<double> sql = sizing.is_too_long(source(hnew2, mesh_), target(hnew2, mesh_));
std::optional<double> sql = sizing.is_too_long(source(hnew2, mesh_), target(hnew2, mesh_), mesh_);
if (sql != std::nullopt)
long_edges.emplace(hnew2, sql.value());
}
@ -747,7 +747,7 @@ namespace internal {
for(halfedge_descriptor ha : halfedges_around_target(va, mesh_))
{
vertex_descriptor va_i = source(ha, mesh_);
std::optional<double> sqha = sizing.is_too_long(vb, va_i);
std::optional<double> sqha = sizing.is_too_long(vb, va_i, mesh_);
if (sqha != std::nullopt)
{
collapse_ok = false;

View File

@ -60,13 +60,14 @@ public:
typedef typename K::FT FT;
public:
virtual FT at(const vertex_descriptor v) const = 0;
virtual FT at(const vertex_descriptor v, const PolygonMesh&) const = 0;
virtual std::optional<FT> is_too_long(const vertex_descriptor va,
const vertex_descriptor vb) const = 0;
const vertex_descriptor vb,
const PolygonMesh&) const = 0;
virtual std::optional<FT> is_too_short(const halfedge_descriptor h,
const PolygonMesh& pmesh) const = 0;
virtual Point_3 split_placement(const halfedge_descriptor h, const PolygonMesh& pmesh) const = 0;
virtual void update(const vertex_descriptor v, const PolygonMesh& pmesh) = 0;
virtual void register_split_vertex(const vertex_descriptor v, const PolygonMesh& pmesh) = 0;
};

View File

@ -288,9 +288,9 @@ void tangential_relaxation(const VertexRange& vertices,
const double tri_area = gt_area(get(vpm, v), get(vpm, v1), get(vpm, v2));
const double face_weight = tri_area
/ (1. / 3. * (sizing.at(v)
+ sizing.at(v1)
+ sizing.at(v2)));
/ (1. / 3. * (sizing.at(v, tm)
+ sizing.at(v1, tm)
+ sizing.at(v2, tm)));
weight += face_weight;
const Point_3 centroid = gt_centroid(get(vpm, v), get(vpm, v1), get(vpm, v2));