OpenVDB 13.0.1
Loading...
Searching...
No Matches
PrincipalComponentAnalysis.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: Apache-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>
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', 'xform' 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 /// @note This value is used to normalize, so you should not use maximum
77 /// limit values to try and include all points. If, for example, you
78 /// want include every point against eachother, consider computing the
79 /// extents of the grid and using that as the searchRadius.
80 /// @warning Valid range is [0, inf). Behaviour is undefined when outside
81 /// this range.
82 float searchRadius = 1.0f;
83 /// @param allowedAnisotropyRatio the maximum allowed ratio between the
84 /// components in each ellipse' stretch coefficients such that:
85 /// @code
86 /// const auto s = stretch.sorted();
87 /// assert(s[0]/s[2] >= allowedAnisotropyRatio);
88 /// @endcode
89 /// This parameter effectively clamps the allowed anisotropy, with a
90 /// value of 1.0f resulting in uniform stretch values (representing a
91 /// sphere). Values tending towards zero will allow for greater
92 /// anisotropy i.e. much more exaggerated stretches along the computed
93 /// principal axis and corresponding squashes along the others to
94 /// compensate.
95 /// @note Very small values may cause very thing ellipses to be produced,
96 /// so a reasonable minimum should be set. Valid range is (0, 1].
97 /// Behaviour is undefined when outside this range.
99 /// @param nonAnisotropicStretch The stretch coefficient that should be
100 /// used for points which have no anisotropic neighbourhood (due to
101 /// being isolated or not having enough neighbours to reach the
102 /// specified @sa neighbourThreshold).
104 /// @param neighbourThreshold number of points in a given neighbourhood
105 /// that target points must have to be classified as having an elliptical
106 /// distribution. Points with less neighbours than this will end up with
107 /// uniform stretch values of nonAnisotropicStretch and an identity
108 /// transformation.
109 /// @note This number can include the target point itself.
110 /// @warning Changing this value does not change the size or number of
111 /// point neighborhood lookups. As such, increasing this value only
112 /// speeds up the number of calculated covariance matrices. Valid range
113 /// is [0, inf], where 0 effectively disables all covariance calculations
114 /// and 1 enables them for every point.
116 /// @param The maximum number of source points to gather for contributions
117 /// to each target point, per voxel. When a voxel contains more points
118 /// than this value, source point are trivially stepped over, with the
119 /// step size calculated as max(1, ppv / neighbourThreshold).
120 /// @note There is no prioritisation of nearest points; for example, voxels
121 /// which partially overlap the search radius may end up selecting point
122 /// ids which all lie outside. This is rarely an issue in practice and
123 /// choosing an appropriate value for this setting can significantly
124 /// increase performance without a large impact to the results.
125 /// @warning Valid range is [1, inf). Behaviour is undefined if this value
126 /// is set to zero.
128 /// @param The maximum number of target points to write anisotropy values
129 /// to. When a voxel contains more points than this value, target point
130 /// are trivially stepped over, with the step size calculated as:
131 /// max(1, ppv / maxTargetPointsPerVoxel).
132 /// default behaviour is to compute for all points. Any points skipped
133 /// will be treated as being isolated and receive an identity transform
134 /// and nonAnisotropicStretch.
135 /// @note When using in conjuction with rasterizeSdf for ellipsoids,
136 /// consider choosing a lower value (e.g. same value as
137 /// maxSourcePointsPerVoxel) to speed up iterations and only
138 /// increase if necessary.
139 /// @warning Valid range is [1, inf). Behaviour is undefined if this value
140 /// is set to zero.
141 size_t maxTargetPointsPerVoxel = std::numeric_limits<size_t>::max();
142 /// @param averagePositions the amount (between 0 and 1) to average out
143 /// positions. All points, whether they end up as ellipses or not,
144 /// can have their positions smoothed to account for their neighbourhood
145 /// distribution. This will have no effect for points with no neighbours.
146 /// @warning This options does NOT modify the P attribute - instead, a
147 /// world space position attribute "pws" (default) is created and stores
148 /// the smoothed position.
149 /// @warning Valid range is [0, 1]. Behaviour is undefined when outside
150 /// this range.
151 float averagePositions = 1.0f;
152 /// @param interrupter optional interrupter
154};
155
156// Suppress spurious warnings on compiler emitted methods (constructors, etc)
157// due to deprecated members. Accessing said members still generates the warning.
159
160/// @brief The persistent attributes created by the PCA methods.
161/// @note These can be passed to points::rasterizeSdf with the
162/// EllipsoidSettings to perform ellipsoidal surface construction.
164{
165 enum class XformOutput
166 {
167 // When selected, the "stretch" output attribute won't be created.
168 // Instead, only a 3x3 affine unitary "xform" attribute will be
169 // created with the combined stretch and rotational transformations
171 // When selected, both the "stretch" vector and "xform" output
172 // attributes will be created. The xform will take the form of a
173 // quaternion representing the rotation.
175 // When selected, both the "stretch" vector and "xform" output
176 // attributes will be created. The xform will take the form of an
177 // orthogonal 3x3 matrix representing the rotation OR a pure
178 // reflection.
180 };
181
183
184 /// @brief Settings for the "stretch" attribute, a floating point vector
185 /// attribute which represents the scaling components of each points
186 /// ellipse or (1.0,1.0,1.0) for isolated points.
187 /// @note This will only be created if the XformOutput is set to
188 /// STRETCH_AND_QUATERNION or STRETCH_AND_UNITARY_MATRIX.
190 std::string stretch = "stretch";
191
192 /// @brief Settings for the "xform" attribute, either a floating point
193 /// matrix or quaternion attribute. See the `xformOutput` setting and
194 /// XformOutput enum above for details.
197 std::string xform = "xform";
198
199 /// @brief Settings for the world space position of every point. This may
200 /// end up being different to their actual position if the
201 /// PcaSettings::averagePositions value is not exactly 0. This attribute
202 /// is used in place of the point's actual position when calling
203 /// points::rasterizeSdf.
204 /// @note This should always be at least at double precision
206 std::string positionWS = "pws";
207
208 /// @brief A point group to create that represents points which have valid
209 /// ellipsoidal neighborhood. Points outside of this group will have
210 /// their stretch and xform attributes set to describe a canonical sphere
211 /// Note however that all points, regardless of this groups membership
212 /// flag, will still contribute to their neighbours and may have their
213 /// world space position deformed in relation to their neighboring points.
214 std::string ellipses = "ellipsoids";
215
216 /// Old style "xform" attribute which has since been renamed and ONLY
217 /// supported rotation. If set, both the above "xform" and this attribute
218 /// will be created. This attribute only ever holds rotation, regardless
219 /// of the xformOutput specified. This will be removed and should not be
220 /// used.
221 OPENVDB_DEPRECATED_MESSAGE("Use PcaAttributes::xform") std::string rotation = "";
222};
223
225
226}
227}
228}
229
230#include "impl/PrincipalComponentAnalysisImpl.h"
231
232#endif // OPENVDB_POINTS_POINT_PRINCIPAL_COMPONENT_ANALYSIS_HAS_BEEN_INCLUDED
#define OPENVDB_NO_DEPRECATION_WARNING_END
Definition Platform.h:218
#define OPENVDB_NO_DEPRECATION_WARNING_BEGIN
Bracket code with OPENVDB_NO_DEPRECATION_WARNING_BEGIN/_END, to inhibit warnings about deprecated cod...
Definition Platform.h:217
#define OPENVDB_DEPRECATED_MESSAGE(msg)
Definition Platform.h:171
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 Quat.h:80
Definition Vec3.h:25
Definition AttributeArray.h:42
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 Exceptions.h:13
Definition Coord.h:590
The persistent attributes created by the PCA methods.
Definition PrincipalComponentAnalysis.h:164
std::string rotation
Definition PrincipalComponentAnalysis.h:221
math::Vec3< float > StretchT
Settings for the "stretch" attribute, a floating point vector attribute which represents the scaling ...
Definition PrincipalComponentAnalysis.h:189
std::string positionWS
Definition PrincipalComponentAnalysis.h:206
std::string ellipses
A point group to create that represents points which have valid ellipsoidal neighborhood....
Definition PrincipalComponentAnalysis.h:214
math::Mat3< float > RotationT
Settings for the "xform" attribute, either a floating point matrix or quaternion attribute....
Definition PrincipalComponentAnalysis.h:195
std::string stretch
Definition PrincipalComponentAnalysis.h:190
math::Quat< float > QuatT
Definition PrincipalComponentAnalysis.h:196
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:205
XformOutput xformOutput
Definition PrincipalComponentAnalysis.h:182
std::string xform
Definition PrincipalComponentAnalysis.h:197
XformOutput
Definition PrincipalComponentAnalysis.h:166
@ STRETCH_AND_UNITARY_MATRIX
Definition PrincipalComponentAnalysis.h:179
@ COMBINED_TRANSFORM
Definition PrincipalComponentAnalysis.h:170
@ STRETCH_AND_QUATERNION
Definition PrincipalComponentAnalysis.h:174
Various settings for the neighborhood analysis of point distributions.
Definition PrincipalComponentAnalysis.h:67
size_t neighbourThreshold
Definition PrincipalComponentAnalysis.h:115
float allowedAnisotropyRatio
Definition PrincipalComponentAnalysis.h:98
float averagePositions
Definition PrincipalComponentAnalysis.h:151
util::NullInterrupter * interrupter
Definition PrincipalComponentAnalysis.h:153
size_t maxTargetPointsPerVoxel
Definition PrincipalComponentAnalysis.h:141
size_t maxSourcePointsPerVoxel
Definition PrincipalComponentAnalysis.h:127
float nonAnisotropicStretch
Definition PrincipalComponentAnalysis.h:103
float searchRadius
Definition PrincipalComponentAnalysis.h:82
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