stats.hh 2.97 KB
Newer Older
1
2
#pragma once

3
#include <sstream>
4

5
6
#include <polymesh/Mesh.hh>
#include <polymesh/fields.hh>
7

8
#include <polymesh/properties.hh>
Philip Trettner's avatar
Philip Trettner committed
9
#include "components.hh"
10
11
12
13
14
15
16

namespace polymesh
{
/// Prints statistics for the given mesh, including:
/// - number of primitives
/// - components
/// - aabb
17
18
template <class Vec3 = void, class OutStream>
void print_stats(OutStream& out, Mesh const& m, vertex_attribute<Vec3> const* position = nullptr);
19

Philip Trettner's avatar
Philip Trettner committed
20
// ======== IMPLEMENTATION ========
21
22
template <class Vec3, class OutStream>
void print_stats(OutStream& out, Mesh const& m, vertex_attribute<Vec3> const* position)
23
24
25
{
    auto ln = "\n";

Philip Trettner's avatar
Philip Trettner committed
26
    auto to_string = [&](auto const& v) {
27
28
29
30
31
        std::stringstream ss;
        ss << "(" << v[0] << ", " << v[1] << ", " << v[2] << ")";
        return ss.str();
    };

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
    out << "[Mesh]:" << ln;

    // # verts, faces, edges, hedges
    out << "  Vertices: " << m.vertices().size();
    if (m.vertices().size() != m.all_vertices().size())
        out << " (" << m.all_vertices().size() - m.vertices().size() << " removed)";
    out << ln;
    out << "  Faces: " << m.faces().size();
    if (m.faces().size() != m.all_faces().size())
        out << " (" << m.all_faces().size() - m.faces().size() << " removed)";
    out << ln;
    out << "  Edges: " << m.edges().size();
    if (m.edges().size() != m.all_edges().size())
        out << " (" << m.all_edges().size() - m.edges().size() << " removed)";
    out << ln;
    out << "  Half-edges: " << m.halfedges().size();
    if (m.halfedges().size() != m.all_halfedges().size())
        out << " (" << m.all_halfedges().size() - m.halfedges().size() << " removed)";
    out << ln;

    if (m.vertices().empty())
        return; // no vertices, no further stats
    out << ln;

    // # isolated, components, boundaries, genus
    int face_comps;
    int vertex_comps;
    vertex_components(m, &vertex_comps);
    face_components(m, &face_comps);
    out << "  Vertex Components: " << vertex_comps << ln;
    out << "  Face Components: " << face_comps << ln;
    // TODO: genus
    // TODO: boundaries
    // TODO: isolated verts, edges
66
67
    out << "  Isolated Vertices: " << m.vertices().count(is_vertex_isolated);
    out << "  Isolated Edges: " << m.edges().count(is_edge_isolated);
68
69
70
71
72
73
74
75
76
77

    if (position)
    {
        out << ln;

        auto const& pos = *position;

        auto aabb = m.vertices().aabb(pos);
        auto min = aabb.min;
        auto max = aabb.max;
78
79
80
        out << "  AABB Min:  " << to_string(min) << ln;
        out << "  AABB Max:  " << to_string(max) << ln;
        out << "  AABB Size: " << to_string(max - min) << ln;
81
82

        auto avg = m.vertices().avg(pos);
83
        out << "  Vertex Centroid: " << to_string(avg) << ln;
84
85
86
87

        auto el_minmax = m.edges().minmax([&](edge_handle e) { return edge_length(e, pos); });
        auto el_avg = m.edges().avg([&](edge_handle e) { return edge_length(e, pos); });
        out << "  Edge Lengths: " << el_minmax.min << " .. " << el_minmax.max << " (avg " << el_avg << ")" << ln;
88
89
    }
}
90
} // namespace polymesh