Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PMP::longest_edge() #6496

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ The page \ref bgl_namedparameters "Named Parameters" describes their usage.
- \link PMP_measure_grp `CGAL::Polygon_mesh_processing::area()` \endlink
- \link PMP_measure_grp `CGAL::Polygon_mesh_processing::volume()` \endlink
- \link PMP_measure_grp `CGAL::Polygon_mesh_processing::face_border_length()` \endlink
- \link PMP_measure_grp `CGAL::Polygon_mesh_processing::longest_edge()` \endlink
- \link PMP_measure_grp `CGAL::Polygon_mesh_processing::longest_border()` \endlink
- \link PMP_measure_grp `CGAL::Polygon_mesh_processing::centroid()` \endlink
- \link PMP_measure_grp `CGAL::Polygon_mesh_processing::match_faces()` \endlink
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,82 @@ average_edge_length(const PolygonMesh& pmesh,
return avg_edge_length;
}

/**
* \ingroup PMP_measure_grp
*
* returns the longest edge of a given polygon mesh.
*
* @tparam PolygonMesh a model of `HalfedgeListGraph`
* @tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters"
*
* @param pmesh the polygon mesh in which the longest edge is searched for
* @param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below
*
* \cgalNamedParamsBegin
* \cgalParamNBegin{vertex_point_map}
* \cgalParamDescription{a property map associating points to the vertices of `pmesh`}
* \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits<PolygonMesh>::%vertex_descriptor`
* as key type and `%Point_3` as value type}
* \cgalParamDefault{`boost::get(CGAL::vertex_point, pmesh)`}
* \cgalParamNEnd
*
* \cgalParamNBegin{geom_traits}
* \cgalParamDescription{an instance of a geometric traits class}
* \cgalParamType{The traits class must provide the nested functor `Compare_squared_distance_3`
* to compare the lengths of two edges given by their end points:
* `CGAL::Comparison_result operator()(%Point_3 src1, %Point_3 tgt1, %Point_3 src2, %Point_3 tgt2)`,
* and a function `Compare_squared_distance_3 compare_squared_distance_3_object()`.}
* \cgalParamDefault{a \cgal Kernel deduced from the point type, using `CGAL::Kernel_traits`}
* \cgalParamExtra{The geometric traits class must be compatible with the vertex point type.}
* \cgalParamNEnd
* \cgalNamedParamsEnd
*
* @return the longest edge in `pmesh`. The return type is an `edge_descriptor`.
*
* @sa `squared_edge_length()`
*/
template<typename PolygonMesh,
typename NamedParameters = parameters::Default_named_parameters>
inline typename boost::graph_traits<PolygonMesh>::edge_descriptor
longest_edge(const PolygonMesh& pmesh,
const NamedParameters& np = parameters::default_values())
{
using parameters::choose_parameter;
using parameters::get_parameter;

using edge_iterator = typename boost::graph_traits<PolygonMesh>::edge_iterator;

using Geom_traits = typename GetGeomTraits<PolygonMesh, NamedParameters>::type;
Geom_traits gt = choose_parameter<Geom_traits>(get_parameter(np, internal_np::geom_traits));

typename GetVertexPointMap<PolygonMesh, NamedParameters>::const_type
vpm = choose_parameter(get_parameter(np, internal_np::vertex_point),
get_const_property_map(CGAL::vertex_point, pmesh));

const auto& edge_range = edges(pmesh);

// if mesh has no edges
edge_iterator first = std::cbegin(edge_range), beyond = std::cend(edge_range);
if(first == beyond)
return { };

edge_iterator le_pos = first, eit = first;
while(++eit != beyond)
{
if(gt.compare_squared_distance_3_object()(get(vpm, source(*eit, pmesh)),
get(vpm, target(*eit, pmesh)),
get(vpm, source(*le_pos, pmesh)),
get(vpm, target(*le_pos, pmesh))) == LARGER)
{
le_pos = eit;
}
}

CGAL_assertion(le_pos != beyond);

return *le_pos;
}

/**
* \ingroup PMP_measure_grp
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,19 @@ void test_pmesh(const Mesh& pmesh)
std::cout << "mesh area (NP) = " << mesh_area_np << std::endl;
assert(mesh_area_np > 0);

edge_descriptor longest_edge = PMP::longest_edge(pmesh);
assert(longest_edge != typename boost::graph_traits<Mesh>::edge_descriptor());
FT le_sq_length = PMP::squared_edge_length(longest_edge, pmesh);
std::cout << "longest edge is: " << get(CGAL::vertex_point, pmesh, source(longest_edge, pmesh))
<< " -> " << get(CGAL::vertex_point, pmesh, target(longest_edge, pmesh))
<< ", length = " << PMP::edge_length(longest_edge, pmesh) << std::endl;
for(edge_descriptor e : edges(pmesh))
{
// this could be wrong due to numerical errors, but the tested meshes are gentle enough
// such that we don't need a predicate... right?
assert(le_sq_length >= PMP::squared_edge_length(e, pmesh));
}

std::pair<halfedge_descriptor, FT> res = PMP::longest_border(pmesh);
if(res.first == boost::graph_traits<Mesh>::null_halfedge()){
std::cout << "mesh has no border" << std::endl;
Expand Down
Loading