From ac72c3a06940594d8086f6e41576f69ef30a6ae5 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 23 Apr 2019 15:49:33 +0200 Subject: [PATCH] Add stats to polygon_soup --- .../Polyhedron/Scene_polygon_soup_item.cpp | 168 ++++++++++++++++++ .../demo/Polyhedron/Scene_polygon_soup_item.h | 21 +++ Three/include/CGAL/Three/Scene_item.h | 2 +- 3 files changed, 190 insertions(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Scene_polygon_soup_item.cpp b/Polyhedron/demo/Polyhedron/Scene_polygon_soup_item.cpp index 5f50d54751e..8df409d7547 100644 --- a/Polyhedron/demo/Polyhedron/Scene_polygon_soup_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_polygon_soup_item.cpp @@ -33,6 +33,13 @@ #include "triangulate_primitive.h" #include +#include +#include +#include +#include +#include +#include + #include using namespace CGAL::Three; typedef Viewer_interface Vi; @@ -52,6 +59,7 @@ struct Scene_polygon_soup_item_priv{ nb_polys = 0; nb_lines = 0; nb_nm_edges = 0; + invalidate_stats(); } ~Scene_polygon_soup_item_priv() { @@ -63,6 +71,8 @@ struct Scene_polygon_soup_item_priv{ } void compute_normals_and_vertices(void) const; void triangulate_polygon(Polygons_iterator, int ) const; + void invalidate_stats(); + void compute_stats(); mutable QOpenGLShaderProgram *program; @@ -86,6 +96,10 @@ struct Scene_polygon_soup_item_priv{ mutable std::size_t nb_nm_edges; mutable std::size_t nb_polys; mutable std::size_t nb_lines; + bool is_triangle, is_quad, stats_computed; + double minl, maxl, meanl, midl, mini, maxi, ave; + std::size_t nb_null_edges, nb_degen_faces; + Scene_polygon_soup_item* item; }; @@ -624,6 +638,7 @@ Scene_polygon_soup_item::invalidateOpenGLBuffers() } getPointContainer(0)->reset_vbos(ALL); setBuffersFilled(false); + d->invalidate_stats(); } void Scene_polygon_soup_item::compute_bbox() const { @@ -844,3 +859,156 @@ void Scene_polygon_soup_item::repair(bool erase_dup, bool req_same_orientation) .require_same_orientation(req_same_orientation)); QApplication::restoreOverrideCursor(); } + +CGAL::Three::Scene_item::Header_data Scene_polygon_soup_item::header() const +{ + CGAL::Three::Scene_item::Header_data data; + //categories + + data.categories.append(std::pair(QString("Vertices"),1)); + data.categories.append(std::pair(QString("Polygons"),4)); + data.categories.append(std::pair(QString("Edges"),6)); + data.categories.append(std::pair(QString("Angles"),3)); + + + //titles + data.titles.append(QString("#Points")); + + data.titles.append(QString("#Polygons")); + data.titles.append(QString("Pure Triangle")); + data.titles.append(QString("Pure Quad")); + data.titles.append(QString("#Degenerate Polygons")); + + data.titles.append(QString("#Edges")); + data.titles.append(QString("Minimum Length")); + data.titles.append(QString("Maximum Length")); + data.titles.append(QString("Median Length")); + data.titles.append(QString("Mean Length")); + data.titles.append(QString("#Degenerate Edges")); + + data.titles.append(QString("Minimum")); + data.titles.append(QString("Maximum")); + data.titles.append(QString("Average")); + return data; +} + +QString Scene_polygon_soup_item::computeStats(int type) +{ + if(!d->stats_computed) + d->compute_stats(); + + switch(type) + { + case NB_VERTICES: + return QString::number(d->soup->points.size()); + case NB_FACETS: + return QString::number(d->soup->polygons.size()); + case NB_EDGES: + return QString::number(d->nb_lines/6); + + case NB_DEGENERATED_FACES: + { + if(d->is_triangle) + { + return QString::number(d->nb_degen_faces); + } + else + return QString("n/a"); + } + + case MIN_LENGTH: + return QString::number(d->minl); + case MAX_LENGTH: + return QString::number(d->maxl); + case MID_LENGTH: + return QString::number(d->midl); + case MEAN_LENGTH: + return QString::number(d->meanl); + case NB_NULL_LENGTH: + return QString::number(d->nb_null_edges); + + case MIN_ANGLE: + return QString::number(d->mini); + case MAX_ANGLE: + return QString::number(d->maxi); + case MEAN_ANGLE: + return QString::number(d->ave); + + case IS_PURE_TRIANGLE: + if(d->is_triangle) + return QString("yes"); + else + return QString("no"); + case IS_PURE_QUAD: + if (d->is_quad) + return QString("yes"); + else + return QString("no"); + } + return QString(); +} + +void +Scene_polygon_soup_item_priv:: +invalidate_stats() +{ + is_triangle = true; + is_quad = true; + minl=0; + maxl=0; + meanl=0; + midl=0; + mini=0; + maxi=0; + ave=0; + nb_null_edges=0; + nb_degen_faces=0; + stats_computed = false; +} + + +void +Scene_polygon_soup_item_priv::compute_stats() +{ + using namespace boost::accumulators; + accumulator_set< double, + features< tag::min, tag::max, tag::mean , tag::median> > edges_acc; + accumulator_set< double, + features< tag::min, tag::max, tag::mean > > angles_acc; + double rad_to_deg = 180. / CGAL_PI; + + + for(auto poly : soup->polygons) + { + if(poly.size() != 3) + is_triangle = false; + if(poly.size() != 4) + is_quad = false; + for(std::size_t i = 0; i< poly.size(); ++i) + { + Polygon_soup::Point_3 a(soup->points[poly[i]]), + b(soup->points[poly[(i+1)%poly.size()]]), + c(soup->points[poly[(i+2)%poly.size()]]); + if (a == b) + ++nb_null_edges; + edges_acc(CGAL::sqrt(CGAL::squared_distance(a, b))); + typename Traits::Vector_3 ba(b, a); + typename Traits::Vector_3 bc(b, c); + double cos_angle = (ba * bc) + / std::sqrt(ba.squared_length() * bc.squared_length()); + if(cos_angle == CGAL_PI || cos_angle == 0) + ++nb_degen_faces; + angles_acc(std::acos(cos_angle) * rad_to_deg); + } + } + + minl = extract_result< tag::min >(edges_acc); + maxl = extract_result< tag::max >(edges_acc); + meanl = extract_result< tag::mean >(edges_acc); + midl = extract_result< tag::median >(edges_acc); + mini = extract_result< tag::min >(angles_acc); + maxi = extract_result< tag::max >(angles_acc); + ave = extract_result< tag::mean >(angles_acc); + + stats_computed = true; +} diff --git a/Polyhedron/demo/Polyhedron/Scene_polygon_soup_item.h b/Polyhedron/demo/Polyhedron/Scene_polygon_soup_item.h index 0fbfccdf58e..fe223f318d6 100644 --- a/Polyhedron/demo/Polyhedron/Scene_polygon_soup_item.h +++ b/Polyhedron/demo/Polyhedron/Scene_polygon_soup_item.h @@ -152,6 +152,27 @@ public: const Edges& non_manifold_edges() const; void initializeBuffers(CGAL::Three::Viewer_interface *) const Q_DECL_OVERRIDE; void computeElements() const Q_DECL_OVERRIDE; + //statistics + enum STATS { + NB_VERTICES = 0, + NB_FACETS, + IS_PURE_TRIANGLE, + IS_PURE_QUAD, + NB_DEGENERATED_FACES, + NB_EDGES, + MIN_LENGTH, + MAX_LENGTH, + MID_LENGTH, + MEAN_LENGTH, + NB_NULL_LENGTH, + MIN_ANGLE, + MAX_ANGLE, + MEAN_ANGLE + }; + + bool has_stats()const Q_DECL_OVERRIDE{return true;} + QString computeStats(int type)Q_DECL_OVERRIDE; + CGAL::Three::Scene_item::Header_data header() const Q_DECL_OVERRIDE; public Q_SLOTS: void shuffle_orientations(); bool orient(); diff --git a/Three/include/CGAL/Three/Scene_item.h b/Three/include/CGAL/Three/Scene_item.h index cc1da66cf4b..1bc24219479 100644 --- a/Three/include/CGAL/Three/Scene_item.h +++ b/Three/include/CGAL/Three/Scene_item.h @@ -298,7 +298,7 @@ public: * | |_______|_____| * |General Info | #Edges|12 | * |_____________|_______|_____| - * compute stats(0) should return "Cube" and computeStats(1) should return QString::number(12); + * ComputeStats(0) should return "Cube" and computeStats(1) should return QString::number(12); * The numbers must be coherent with the order of declaration of the titles in the header. * \endverbatim *