OpenVDB 12.1.0
Loading...
Searching...
No Matches
PrincipalComponentAnalysis.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: MPL-2.0
3
4/// @author Richard Jones, Nick Avramoussis
5///
6/// @file PrincipalComponentAnalysis.h
7///
8/// @brief Provides methods to perform principal component analysis (PCA) over
9/// a point set to compute rotational and affine transformations for each
10/// point that represent a their neighborhoods anisotropy. The techniques
11/// and algorithms used here are described in:
12/// [Reconstructing Surfaces of Particle-Based Fluids Using Anisotropic
13/// Kernel - Yu Turk 2010].
14/// The parameters and results of these methods can be combines with the
15/// ellipsoidal surfacing technique found in PointRasterizeSDF.h.
16
17#ifndef OPENVDB_POINTS_POINT_PRINCIPAL_COMPONENT_ANALYSIS_HAS_BEEN_INCLUDED
18#define OPENVDB_POINTS_POINT_PRINCIPAL_COMPONENT_ANALYSIS_HAS_BEEN_INCLUDED
19
20#include <openvdb/openvdb.h>
21#include <openvdb/Grid.h>
22#include <openvdb/Types.h>
23#include <openvdb/math/Coord.h>
24#include <openvdb/thread/Threading.h>
26#include <openvdb/util/Assert.h>
31
32#include <string>
33#include <vector>
34#include <memory>
35#include <limits>
36#include <cmath> // std::cbrt
37
38namespace openvdb {
40namespace OPENVDB_VERSION_NAME {
41namespace points {
42
43struct PcaSettings;
44struct PcaAttributes;
45
46/// @brief Calculate ellipsoid transformations from the local point
47/// distributions as described in Yu and Turk's 'Reconstructing Fluid Surfaces
48/// with Anisotropic Kernels'. The results are stored on the attributes
49/// pointed to by the PcaAttributes. See the PcaSettings and PcaAttributes
50/// structs for more details.
51/// @warning This method will throw if the 'strech', 'rotation' or 'pws'
52/// attributes already exist on this input point set.
53/// @param points The point data grid to analyses
54/// @param settings The PCA settings for controlling the behavior of the
55/// neighborhood searches and the resulting ellipsoidal values
56/// @param attrs The PCA attributes to create
57template <typename PointDataGridT>
58inline void
59pca(PointDataGridT& points,
60 const PcaSettings& settings,
61 const PcaAttributes& attrs);
62
63
64/// @brief Various settings for the neighborhood analysis of point
65/// distributions.
67{
68 /// @param searchRadius the world space search radius of the neighborhood
69 /// around each point. Increasing this value will result in points
70 /// including more of their neighbors into their ellipsoidal calculations.
71 /// This may or may not be desirable depending on the point set's
72 /// distribution and can be tweaked as necessary. Note however that large
73 /// values will cause the PCA calculation to become exponentially more
74 /// expensive and should be used in conjunction with the max point per
75 /// voxel settings below.
76 /// @warning Valid range is [0, inf). Behaviour is undefined when outside
77 /// this range.
78 float searchRadius = 1.0f;
79 /// @param allowedAnisotropyRatio the maximum allowed ratio between the
80 /// components in each ellipse' stretch coefficients such that:
81 /// @code
82 /// const auto s = stretch.sorted();
83 /// assert(s[0]/s[2] >= allowedAnisotropyRatio);
84 /// @endcode
85 /// This parameter effectively clamps the allowed anisotropy, with a
86 /// value of 1.0f resulting in uniform stretch values (representing a
87 /// sphere). Values tending towards zero will allow for greater
88 /// anisotropy i.e. much more exaggerated stretches along the computed
89 /// principal axis and corresponding squashes along the others to
90 /// compensate.
91 /// @note Very small values may cause very thing ellipses to be produced,
92 /// so a reasonable minimum should be set. Valid range is (0, 1].
93 /// Behaviour is undefined when outside this range.
95 /// @param nonAnisotropicStretch The stretch coefficient that should be
96 /// used for points which have no anisotropic neighbourhood (due to
97 /// being isolated or not having enough neighbours to reach the
98 /// specified @sa neighbourThreshold).
100 /// @param neighbourThreshold number of points in a given neighbourhood
101 /// that target points must have to be classified as having an elliptical
102 /// distribution. Points with less neighbours than this will end up with
103 /// uniform stretch values of nonAnisotropicStretch and an identity
104 /// rotation matrix.
105 /// @note This number can include the target point itself.
106 /// @warning Changing this value does not change the size or number of
107 /// point neighborhood lookups. As such, increasing this value only
108 /// speeds up the number of calculated covariance matrices. Valid range
109 /// is [0, inf], where 0 effectively disables all covariance calculations
110 /// and 1 enables them for every point.
112 /// @param The maximum number of source points to gather for contributions
113 /// to each target point, per voxel. When a voxel contains more points
114 /// than this value, source point are trivially stepped over, with the
115 /// step size calculated as max(1, ppv / neighbourThreshold).
116 /// @note There is no prioritisation of nearest points; for example, voxels
117 /// which partially overlap the search radius may end up selecting point
118 /// ids which all lie outside. This is rarely an issue in practice and
119 /// choosing an appropriate value for this setting can significantly
120 /// increase performance without a large impact to the results.
121 /// @warning Valid range is [1, inf). Behaviour is undefined if this value
122 /// is set to zero.
124 /// @param The maximum number of target points to write anisotropy values
125 /// to. When a voxel contains more points than this value, target point
126 /// are trivially stepped over, with the step size calculated as:
127 /// max(1, ppv / maxTargetPointsPerVoxel).
128 /// default behaviour is to compute for all points. Any points skipped
129 /// will be treated as being isolated and receive an identity rotation
130 /// and nonAnisotropicStretch.
131 /// @note When using in conjuction with rasterizeSdf for ellipsoids,
132 /// consider choosing a lower value (e.g. same value as
133 /// maxSourcePointsPerVoxel) to speed up iterations and only
134 /// increase if necessary.
135 /// @warning Valid range is [1, inf). Behaviour is undefined if this value
136 /// is set to zero.
137 size_t maxTargetPointsPerVoxel = std::numeric_limits<size_t>::max();
138 /// @param averagePositions the amount (between 0 and 1) to average out
139 /// positions. All points, whether they end up as ellipses or not,
140 /// can have their positions smoothed to account for their neighbourhood
141 /// distribution. This will have no effect for points with no neighbours.
142 /// @warning This options does NOT modify the P attribute - instead, a
143 /// world space position attribute "pws" (default) is created and stores
144 /// the smoothed position.
145 /// @warning Valid range is [0, 1]. Behaviour is undefined when outside
146 /// this range.
147 float averagePositions = 1.0f;
148 /// @param interrupter optional interrupter
150};
151
152/// @brief The persistent attributes created by the PCA methods.
153/// @note These can be passed to points::rasterizeSdf with the
154/// EllipsoidSettings to perform ellipsoidal surface construction.
156{
157 /// @brief Settings for the "stretch" attribute, a floating point vector
158 /// attribute which represents the scaling components of each points
159 /// ellipse or (1.0,1.0,1.0) for isolated points.
161 std::string stretch = "stretch";
162
163 /// @brief Settings for the "rotation" attribute, a floating point matrix
164 /// attribute which represents the orthogonal rotation of each points
165 /// ellipse or the identity matrix for isolated points.
167 std::string rotation = "rotation";
168
169 /// @brief Settings for the world space position of every point. This may
170 /// end up being different to their actual position if the
171 /// PcaSettings::averagePositions value is not exactly 0. This attribute
172 /// is used in place of the point's actual position when calling
173 /// points::rasterizeSdf.
174 /// @note This should always be at least at double precision
176 std::string positionWS = "pws";
177
178 /// @brief A point group to create that represents points which have valid
179 /// ellipsoidal neighborhood. Points outside of this group will have
180 /// their stretch and rotation attributes set to describe a canonical
181 /// sphere. Note however that all points, regardless of this groups
182 /// membership flag, will still contribute to their neighbours and may
183 /// have their world space position deformed in relation to their
184 /// neighboring points.
185 std::string ellipses = "ellipsoids";
186};
187
188}
189}
190}
191
193
194#endif // OPENVDB_POINTS_POINT_PRINCIPAL_COMPONENT_ANALYSIS_HAS_BEEN_INCLUDED
Point attribute manipulation in a VDB Point Grid.
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
Point group manipulation in a VDB Point Grid.
Framework methods for rasterizing PointDataGrid data to Trees.
3x3 matrix class.
Definition Mat3.h:29
Definition Vec3.h:25
void pca(PointDataGridT &points, const PcaSettings &settings, const PcaAttributes &attrs)
Calculate ellipsoid transformations from the local point distributions as described in Yu and Turk's ...
Definition PrincipalComponentAnalysisImpl.h:548
Definition Exceptions.h:13
The persistent attributes created by the PCA methods.
Definition PrincipalComponentAnalysis.h:156
std::string rotation
Definition PrincipalComponentAnalysis.h:167
math::Vec3< float > StretchT
Settings for the "stretch" attribute, a floating point vector attribute which represents the scaling ...
Definition PrincipalComponentAnalysis.h:160
std::string positionWS
Definition PrincipalComponentAnalysis.h:176
std::string ellipses
A point group to create that represents points which have valid ellipsoidal neighborhood....
Definition PrincipalComponentAnalysis.h:185
math::Mat3< float > RotationT
Settings for the "rotation" attribute, a floating point matrix attribute which represents the orthogo...
Definition PrincipalComponentAnalysis.h:166
std::string stretch
Definition PrincipalComponentAnalysis.h:161
math::Vec3< double > PosWsT
Settings for the world space position of every point. This may end up being different to their actual...
Definition PrincipalComponentAnalysis.h:175
Various settings for the neighborhood analysis of point distributions.
Definition PrincipalComponentAnalysis.h:67
size_t neighbourThreshold
Definition PrincipalComponentAnalysis.h:111
float allowedAnisotropyRatio
Definition PrincipalComponentAnalysis.h:94
float averagePositions
Definition PrincipalComponentAnalysis.h:147
util::NullInterrupter * interrupter
Definition PrincipalComponentAnalysis.h:149
size_t maxTargetPointsPerVoxel
Definition PrincipalComponentAnalysis.h:137
size_t maxSourcePointsPerVoxel
Definition PrincipalComponentAnalysis.h:123
float nonAnisotropicStretch
Definition PrincipalComponentAnalysis.h:99
float searchRadius
Definition PrincipalComponentAnalysis.h:78
Base class for interrupters.
Definition NullInterrupter.h:26
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:218