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