From 0ce8807a6a238210dbd153cc860373e7b51317cc Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 28 Feb 2017 13:01:43 +0100 Subject: [PATCH] Add faces statistics. --- .../demo/Polyhedron/Scene_polyhedron_item.cpp | 62 +++++++++++++++- .../demo/Polyhedron/Scene_polyhedron_item.h | 11 ++- .../include/CGAL/statistics_helpers.h | 71 +++++++++++++++++++ 3 files changed, 140 insertions(+), 4 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Scene_polyhedron_item.cpp b/Polyhedron/demo/Polyhedron/Scene_polyhedron_item.cpp index c9d37e43097..cc8ea327069 100644 --- a/Polyhedron/demo/Polyhedron/Scene_polyhedron_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_polyhedron_item.cpp @@ -941,7 +941,6 @@ invalidate_stats() volume = -std::numeric_limits::infinity(); area = -std::numeric_limits::infinity(); self_intersect = false; - } Scene_polyhedron_item* @@ -1447,6 +1446,32 @@ QString Scene_polyhedron_item::computeStats(int type) case MEAN_ANGLE: angles(d->poly, mini, maxi, ave); } + double min_area, max_area, med_area, mean_area; + switch (type) + { + case MIN_AREA: + case MAX_AREA: + case MEAN_AREA: + case MED_AREA: + if(!d->poly->is_pure_triangle()) + { + return QString("n/a"); + } + faces_area(d->poly, min_area, max_area, mean_area, med_area); + } + double min_altitude, min_ar, max_ar, mean_ar; + switch (type) + { + case MIN_ALTITUDE: + case MIN_ASPECT_RATIO: + case MAX_ASPECT_RATIO: + case MEAN_ASPECT_RATIO: + if(!d->poly->is_pure_triangle()) + { + return QString("n/a"); + } + faces_aspect_ratio(d->poly, min_altitude, min_ar, max_ar, mean_ar); + } switch(type) { @@ -1537,9 +1562,30 @@ QString Scene_polyhedron_item::computeStats(int type) return QString::number(maxi); case MEAN_ANGLE: return QString::number(ave); - case HOLES: return QString::number(nb_holes(d->poly)); + + case MIN_AREA: + return QString::number(min_area); + case MAX_AREA: + return QString::number(max_area); + case MED_AREA: + return QString::number(med_area); + case MEAN_AREA: + return QString::number(mean_area); + case MIN_ALTITUDE: + return QString::number(min_altitude); + case MIN_ASPECT_RATIO: + return QString::number(min_ar); + case MAX_ASPECT_RATIO: + return QString::number(max_ar); + case MEAN_ASPECT_RATIO: + return QString::number(mean_ar); + case IS_PURE_TRIANGLE: + if(d->poly->is_pure_triangle()) + return QString("yes"); + else + return QString("no"); } return QString(); } @@ -1549,20 +1595,30 @@ CGAL::Three::Scene_item::Header_data Scene_polyhedron_item::header() const CGAL::Three::Scene_item::Header_data data; //categories data.categories.append(std::pair(QString("Properties"),9)); + data.categories.append(std::pair(QString("Faces"),9)); data.categories.append(std::pair(QString("Edges"),6)); data.categories.append(std::pair(QString("Angles"),3)); //titles data.titles.append(QString("#Vertices")); - data.titles.append(QString("#Facets")); data.titles.append(QString("#Connected Components")); data.titles.append(QString("#Border Edges")); + data.titles.append(QString("Pure Triangle")); data.titles.append(QString("#Degenerated Faces")); data.titles.append(QString("Connected Components of the Boundary")); data.titles.append(QString("Area")); data.titles.append(QString("Volume")); data.titles.append(QString("Self-Intersecting")); + data.titles.append(QString("#Faces")); + data.titles.append(QString("Min Area")); + data.titles.append(QString("Max Area")); + data.titles.append(QString("Median Area")); + data.titles.append(QString("Mean Area")); + data.titles.append(QString("Min Altitude")); + data.titles.append(QString("Min Aspect-Ratio")); + data.titles.append(QString("Max Aspect-Ratio")); + data.titles.append(QString("Mean Aspect-Ratio")); data.titles.append(QString("#Edges")); data.titles.append(QString("Minimum Length")); data.titles.append(QString("Maximum Length")); diff --git a/Polyhedron/demo/Polyhedron/Scene_polyhedron_item.h b/Polyhedron/demo/Polyhedron/Scene_polyhedron_item.h index 5788f743746..c9a767449f9 100644 --- a/Polyhedron/demo/Polyhedron/Scene_polyhedron_item.h +++ b/Polyhedron/demo/Polyhedron/Scene_polyhedron_item.h @@ -26,14 +26,23 @@ class SCENE_POLYHEDRON_ITEM_EXPORT Scene_polyhedron_item public: enum STATS { NB_VERTICES = 0, - NB_FACETS, NB_CONNECTED_COMPOS, NB_BORDER_EDGES, + IS_PURE_TRIANGLE, NB_DEGENERATED_FACES, HOLES, AREA, VOLUME, SELFINTER, + NB_FACETS, + MIN_AREA, + MAX_AREA, + MED_AREA, + MEAN_AREA, + MIN_ALTITUDE, + MIN_ASPECT_RATIO, + MAX_ASPECT_RATIO, + MEAN_ASPECT_RATIO, NB_EDGES, MIN_LENGTH, MAX_LENGTH, diff --git a/Polyhedron/demo/Polyhedron/include/CGAL/statistics_helpers.h b/Polyhedron/demo/Polyhedron/include/CGAL/statistics_helpers.h index a79da775070..38a759eb91a 100644 --- a/Polyhedron/demo/Polyhedron/include/CGAL/statistics_helpers.h +++ b/Polyhedron/demo/Polyhedron/include/CGAL/statistics_helpers.h @@ -137,5 +137,76 @@ unsigned int nb_holes(Polyhedron* poly) return n; } +template +void faces_area(Polyhedron* poly, + double& mini, double& maxi, double& mean, double& mid) +{ + using namespace boost::accumulators; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + + accumulator_set< double, + features< tag::min, tag::max, tag::mean , tag::median> > acc; + + typename boost::property_map::type + vpmap = get(CGAL::vertex_point, *poly); + BOOST_FOREACH(face_descriptor f, faces(*poly)) + { + halfedge_descriptor h = halfedge(f, *poly); + typename Kernel::Point_3 a = get(vpmap, target(h, *poly)); + typename Kernel::Point_3 b = get(vpmap, target(next(h, *poly), *poly)); + typename Kernel::Point_3 c = get(vpmap, target(next(next(h, *poly), *poly), *poly)); + CGAL::squared_area(a,b,c); + acc(CGAL::sqrt(CGAL::squared_distance(a, b))); + } + + mini = extract_result< tag::min >(acc); + maxi = extract_result< tag::max >(acc); + mean = extract_result< tag::mean >(acc); + mid = extract_result< tag::median >(acc); +} + +template +void faces_aspect_ratio(Polyhedron* poly, + double& min_altitude, double& mini, double& maxi, double& mean) +{ + using namespace boost::accumulators; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + + + accumulator_set< double, + features< tag::min, tag::max, tag::mean> > acc; + + min_altitude = std::numeric_limits::infinity(); + typename boost::property_map::type + vpmap = get(CGAL::vertex_point, *poly); + BOOST_FOREACH(face_descriptor f, faces(*poly)) + { + halfedge_descriptor h = halfedge(f, *poly); + typename Kernel::Point_3 points[3]; + points[0] = get(vpmap, target(h, *poly)); + points[1] = get(vpmap, target(next(h, *poly), *poly)); + points[2] = get(vpmap, target(next(next(h, *poly), *poly), *poly)); + //Compute smallest altitude + double min_alt = std::numeric_limits::infinity(); + double longest_edge = 0; + for(int i=0; i<3; ++i) + { + double alt = CGAL::sqrt(CGAL::squared_distance(points[(0+i)%3], typename Kernel::Line_3(points[(1+i)%3], points[(2+i)%3]))); + double edge = CGAL::sqrt(CGAL::squared_distance(points[(1+i)%3], points[(2+i)%3])); + if(alt < min_alt) { min_alt = alt; } + if(edge > longest_edge) { longest_edge = edge; } + } + //compute aspect-ratio + acc(longest_edge/min_alt); + + if(min_alt < min_altitude) { min_altitude = min_alt; } + } + + mini = extract_result< tag::min >(acc); + maxi = extract_result< tag::max >(acc); + mean = extract_result< tag::mean >(acc); +} #endif // POLYHEDRON_DEMO_STATISTICS_HELPERS_H