HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
mapFunction.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_USD_PCP_MAP_FUNCTION_H
8 #define PXR_USD_PCP_MAP_FUNCTION_H
9 
10 #include "pxr/pxr.h"
11 #include "pxr/usd/pcp/api.h"
12 #include "pxr/usd/sdf/path.h"
15 
16 #include <atomic>
17 #include <memory>
18 
20 
21 /// \class PcpMapFunction
22 ///
23 /// A function that maps values from one namespace (and time domain) to
24 /// another. It represents the transformation that an arc such as a reference
25 /// arc applies as it incorporates values across the arc.
26 ///
27 /// Take the example of a reference arc, where a source path
28 /// </Model> is referenced as a target path, </Model_1>.
29 /// The source path </Model> is the source of the opinions;
30 /// the target path </Model_1> is where they are incorporated in the scene.
31 /// Values in the model that refer to paths relative to </Model> must be
32 /// transformed to be relative to </Model_1> instead.
33 /// The PcpMapFunction for the arc provides this service.
34 ///
35 /// Map functions have a specific \em domain, or set of values they can
36 /// operate on. Any values outside the domain cannot be mapped.
37 /// The domain precisely tracks what areas of namespace can be
38 /// referred to across various forms of arcs.
39 ///
40 /// Map functions can be chained to represent a series of map
41 /// operations applied in sequence. The map function represent the
42 /// cumulative effect as efficiently as possible. For example, in
43 /// the case of a chained reference from </Model> to </Model>
44 /// to </Model> to </Model_1>, this is effectively the same as
45 /// a mapping directly from </Model> to </Model_1>. Representing
46 /// the cumulative effect of arcs in this way is important for
47 /// handling larger scenes efficiently.
48 ///
49 /// Map functions can be \em inverted. Formally, map functions are
50 /// bijections (one-to-one and onto), which ensures that they can
51 /// be inverted. Put differently, no information is lost by applying
52 /// a map function to set of values within its domain; they retain
53 /// their distinct identities and can always be mapped back.
54 ///
55 /// One analogy that may or may not be helpful:
56 /// In the same way a geometric transform maps a model's points in its
57 /// rest space into the world coordinates for a particular instance,
58 /// a PcpMapFunction maps values about a referenced model into the
59 /// composed scene for a particular instance of that model. But rather
60 /// than translating and rotating points, the map function shifts the
61 /// values in namespace (and time).
62 ///
63 ///
65 {
66 public:
67  /// A mapping from path to path.
68  typedef std::map<SdfPath, SdfPath, SdfPath::FastLessThan> PathMap;
69  typedef std::pair<SdfPath, SdfPath> PathPair;
70  typedef std::vector<PathPair> PathPairVector;
71 
72  /// Construct a null function.
73  PcpMapFunction() = default;
74 
75  /// Constructs a map function with the given arguments.
76  /// Returns a null map function on error (see IsNull()).
77  ///
78  /// \param sourceToTargetMap The map from source paths to target paths.
79  /// \param offset The time offset to apply from source to target.
80  ///
81  PCP_API
82  static PcpMapFunction
83  Create(const PathMap &sourceToTargetMap,
84  const SdfLayerOffset &offset);
85 
86  /// Constructs a map function that is equivalent to
87  /// \code
88  /// transferFunc.Compose(classArc.Compose(transferFunc.Inverse))
89  /// \endcode
90  /// with an additional root identity mapping.
91  PCP_API
92  static PcpMapFunction
93  ImpliedClass(const PcpMapFunction& transferFunc,
94  const PcpMapFunction& classArc);
95 
96  /// Construct an identity map function.
97  PCP_API
98  static const PcpMapFunction &Identity();
99 
100  /// Returns an identity path mapping.
101  PCP_API
102  static const PathMap &IdentityPathMap();
103 
104  /// Swap the contents of this map function with \p map.
105  PCP_API
106  void Swap(PcpMapFunction &map);
107  void swap(PcpMapFunction &map) { Swap(map); }
108 
109  /// Equality.
110  PCP_API
111  bool operator==(const PcpMapFunction &map) const;
112 
113  /// Inequality.
114  PCP_API
115  bool operator!=(const PcpMapFunction &map) const;
116 
117  /// Return true if this map function is the null function.
118  /// For a null function, MapSourceToTarget() always returns an empty path.
119  PCP_API
120  bool IsNull() const;
121 
122  /// Return true if the map function is the identity function.
123  /// The identity function has an identity path mapping and time offset.
124  PCP_API
125  bool IsIdentity() const;
126 
127  /// Return true if the map function uses the identity path mapping.
128  /// If true, MapSourceToTarget() always returns the path unchanged.
129  /// However, this map function may have a non-identity time offset.
130  PCP_API
131  bool IsIdentityPathMapping() const;
132 
133  /// Return true if the map function maps the absolute root path to the
134  /// absolute root path, false otherwise.
135  bool HasRootIdentity() const { return _data.hasRootIdentity; }
136 
137  /// Map a path in the source namespace to the target.
138  /// If the path is not in the domain, returns an empty path.
139  PCP_API
140  SdfPath MapSourceToTarget(const SdfPath &path) const;
141 
142  /// Map a path in the target namespace to the source.
143  /// If the path is not in the co-domain, returns an empty path.
144  PCP_API
145  SdfPath MapTargetToSource(const SdfPath &path) const;
146 
147  /// Map all path pattern prefix paths and expression reference paths in the
148  /// source namespace to the target. For any references or patterns with
149  /// prefix paths that are not in the domain, replace with an
150  /// SdfPathPattern::Nothing() subexpression, to be simplified.
151  ///
152  /// For example, if the mapping specifies /Foo -> /World/Foo_1, and the
153  /// expression is '/Foo/Bar//Baz + /Something/Else//Entirely', the resulting
154  /// expression will be '/World/Foo_1/Bar//Baz', since the
155  /// /Something/Else prefix is outside the domain.
156  ///
157  /// If \p excludedPatterns and/or \p excludedReferences are supplied, they
158  /// are populated with those patterns & references that could not be
159  /// translated and were replaced with SdfPathPattern::Nothing().
160  PCP_API
163  const SdfPathExpression &pathExpr,
164  std::vector<SdfPathExpression::PathPattern>
165  *unmappedPatterns = nullptr,
166  std::vector<SdfPathExpression::ExpressionReference>
167  *unmappedRefs = nullptr
168  ) const;
169 
170  /// Map all path pattern prefix paths and expression reference paths in the
171  /// target namespace to the source. For any references or patterns with
172  /// prefix paths that are not in the co-domain, replace with an
173  /// SdfPathPattern::Nothing() subexpression, to be simplified.
174  ///
175  /// For example, if the mapping specifies /World/Foo_1 -> /Foo, and the
176  /// expression is '/World/Foo_1/Bar//Baz + /World/Bar//', the resulting
177  /// expression will be '/Foo/Bar//Baz', since the /World/Bar prefix is
178  /// outside the co-domain.
179  ///
180  /// If \p excludedPatterns and/or \p excludedReferences are supplied, they
181  /// are populated with those patterns & references that could not be
182  /// translated and were replaced with SdfPathPattern::Nothing().
183  PCP_API
186  const SdfPathExpression &pathExpr,
187  std::vector<SdfPathExpression::PathPattern>
188  *unmappedPatterns = nullptr,
189  std::vector<SdfPathExpression::ExpressionReference>
190  *unmappedRefs = nullptr
191  ) const;
192 
193  /// Compose this map over the given map function.
194  /// The result will represent the application of f followed by
195  /// the application of this function.
196  PCP_API
197  PcpMapFunction Compose(const PcpMapFunction &f) const;
198 
199  /// Compose this map function over a hypothetical map function that has an
200  /// identity path mapping and \p offset. This is equivalent to building
201  /// such a map function and invoking Compose(), but is faster.
202  PCP_API
203  PcpMapFunction ComposeOffset(const SdfLayerOffset &newOffset) const;
204 
205  /// Return the inverse of this map function.
206  /// This returns a true inverse \p inv: for any path p in this function's
207  /// domain that it maps to p', inv(p') -> p.
208  PCP_API
209  PcpMapFunction GetInverse() const;
210 
211  /// The set of path mappings, from source to target.
212  PCP_API
214 
215  /// The time offset of the mapping.
216  const SdfLayerOffset &GetTimeOffset() const { return _offset; }
217 
218  /// Returns a string representation of this mapping for debugging
219  /// purposes.
220  PCP_API
221  std::string GetString() const;
222 
223  /// Return a size_t hash for this map function.
224  PCP_API
225  size_t Hash() const;
226 
227 private:
228 
229  PCP_API
230  PcpMapFunction(PathPair const *sourceToTargetBegin,
231  PathPair const *sourceToTargetEnd,
233  bool hasRootIdentity);
234 
235  PCP_API
237  _MapPathExpressionImpl(
238  bool invert,
239  const SdfPathExpression &pathExpr,
240  std::vector<SdfPathExpression::PathPattern> *unmappedPatterns,
241  std::vector<SdfPathExpression::ExpressionReference> *unmappedRefs
242  ) const;
243 
244 private:
246 
247  static const int _MaxLocalPairs = 2;
248  struct _Data final {
249  _Data() {};
250 
251  _Data(PathPair const *begin, PathPair const *end, bool hasRootIdentity)
252  : numPairs(end-begin)
253  , hasRootIdentity(hasRootIdentity) {
254  if (numPairs == 0)
255  return;
256  if (numPairs <= _MaxLocalPairs) {
257  std::uninitialized_copy(begin, end, localPairs);
258  }
259  else {
260  new (&remotePairs) std::shared_ptr<PathPair>(
261  new PathPair[numPairs], std::default_delete<PathPair[]>());
262  std::copy(begin, end, remotePairs.get());
263  }
264  }
265 
266  _Data(_Data const &other)
267  : numPairs(other.numPairs)
268  , hasRootIdentity(other.hasRootIdentity) {
269  if (numPairs <= _MaxLocalPairs) {
270  std::uninitialized_copy(
271  other.localPairs,
272  other.localPairs + other.numPairs, localPairs);
273  }
274  else {
275  new (&remotePairs) std::shared_ptr<PathPair>(other.remotePairs);
276  }
277  }
278  _Data(_Data &&other)
279  : numPairs(other.numPairs)
280  , hasRootIdentity(other.hasRootIdentity) {
281  if (numPairs <= _MaxLocalPairs) {
282  PathPair *dst = localPairs;
283  PathPair *src = other.localPairs;
284  PathPair *srcEnd = other.localPairs + other.numPairs;
285  for (; src != srcEnd; ++src, ++dst) {
286  ::new (static_cast<void*>(std::addressof(*dst)))
287  PathPair(std::move(*src));
288  }
289  }
290  else {
291  new (&remotePairs)
292  std::shared_ptr<PathPair>(std::move(other.remotePairs));
293  }
294  }
295  _Data &operator=(_Data const &other) {
296  if (this != &other) {
297  this->~_Data();
298  new (this) _Data(other);
299  }
300  return *this;
301  }
302  _Data &operator=(_Data &&other) {
303  if (this != &other) {
304  this->~_Data();
305  new (this) _Data(std::move(other));
306  }
307  return *this;
308  }
309  ~_Data() {
310  if (numPairs <= _MaxLocalPairs) {
311  for (PathPair *p = localPairs; numPairs--; ++p) {
312  p->~PathPair();
313  }
314  }
315  else {
316  remotePairs.~shared_ptr<PathPair>();
317  }
318  }
319 
320  bool IsNull() const {
321  return numPairs == 0 && !hasRootIdentity;
322  }
323 
324  PathPair const *begin() const {
325  return numPairs <= _MaxLocalPairs ? localPairs : remotePairs.get();
326  }
327 
328  PathPair const *end() const {
329  return begin() + numPairs;
330  }
331 
332  bool operator==(_Data const &other) const {
333  return numPairs == other.numPairs &&
334  hasRootIdentity == other.hasRootIdentity &&
335  std::equal(begin(), end(), other.begin());
336  }
337 
338  bool operator!=(_Data const &other) const {
339  return !(*this == other);
340  }
341 
342  template <class HashState>
343  friend void TfHashAppend(HashState &h, _Data const &data){
344  h.Append(data.hasRootIdentity);
345  h.Append(data.numPairs);
346  h.AppendRange(std::begin(data), std::end(data));
347  }
348 
349  union {
350  PathPair localPairs[_MaxLocalPairs > 0 ? _MaxLocalPairs : 1];
351  std::shared_ptr<PathPair> remotePairs;
352  };
353  typedef int PairCount;
354  PairCount numPairs = 0;
355  bool hasRootIdentity = false;
356  };
357 
358  // Specialize TfHashAppend for PcpMapFunction.
359  template <typename HashState>
360  friend inline
361  void TfHashAppend(HashState& h, const PcpMapFunction& x){
362  h.Append(x._data);
363  h.Append(x._offset);
364  }
365 
366  _Data _data;
367  SdfLayerOffset _offset;
368 };
369 
370 // Specialize hash_value for PcpMapFunction.
371 inline
373 {
374  return TfHash{}(x);
375 }
376 
378 
379 #endif // PXR_USD_PCP_MAP_FUNCTION_H
PCP_API size_t Hash() const
Return a size_t hash for this map function.
PCP_API bool IsIdentityPathMapping() const
PCP_API PathMap GetSourceToTargetMap() const
The set of path mappings, from source to target.
static PCP_API const PcpMapFunction & Identity()
Construct an identity map function.
GLboolean invert
Definition: glcorearb.h:549
PCP_API bool IsIdentity() const
#define PXR_NAMESPACE_OPEN_SCOPE
Definition: pxr.h:73
static PCP_API const PathMap & IdentityPathMap()
Returns an identity path mapping.
GLsizei const GLchar *const * path
Definition: glcorearb.h:3341
PCP_API bool operator!=(const PcpMapFunction &map) const
Inequality.
PCP_API SdfPath MapSourceToTarget(const SdfPath &path) const
static PCP_API PcpMapFunction Create(const PathMap &sourceToTargetMap, const SdfLayerOffset &offset)
friend PcpMapFunction * Pcp_MakeIdentity()
IMATH_HOSTDEVICE constexpr bool equal(T1 a, T2 b, T3 t) IMATH_NOEXCEPT
Definition: ImathFun.h:105
PCP_API bool operator==(const PcpMapFunction &map) const
Equality.
const SdfLayerOffset & GetTimeOffset() const
The time offset of the mapping.
Definition: mapFunction.h:216
Definition: hash.h:472
GLfloat f
Definition: glcorearb.h:1926
GLintptr offset
Definition: glcorearb.h:665
friend void TfHashAppend(HashState &h, const PcpMapFunction &x)
Definition: mapFunction.h:361
std::map< SdfPath, SdfPath, SdfPath::FastLessThan > PathMap
A mapping from path to path.
Definition: mapFunction.h:68
std::pair< SdfPath, SdfPath > PathPair
Definition: mapFunction.h:69
GLuint GLuint end
Definition: glcorearb.h:475
Definition: path.h:280
GLint GLenum GLint x
Definition: glcorearb.h:409
void swap(PcpMapFunction &map)
Definition: mapFunction.h:107
std::vector< PathPair > PathPairVector
Definition: mapFunction.h:70
PCP_API PcpMapFunction Compose(const PcpMapFunction &f) const
PCP_API void Swap(PcpMapFunction &map)
Swap the contents of this map function with map.
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:2002
GLenum GLenum dst
Definition: glcorearb.h:1793
PCP_API PcpMapFunction GetInverse() const
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.
Definition: node.h:587
PcpMapFunction()=default
Construct a null function.
LeafData & operator=(const LeafData &)=delete
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
bool HasRootIdentity() const
Definition: mapFunction.h:135
static PCP_API PcpMapFunction ImpliedClass(const PcpMapFunction &transferFunc, const PcpMapFunction &classArc)
size_t hash_value(const PcpMapFunction &x)
Definition: mapFunction.h:372
PCP_API std::string GetString() const
PCP_API SdfPath MapTargetToSource(const SdfPath &path) const
PCP_API bool IsNull() const
PCP_API PcpMapFunction ComposeOffset(const SdfLayerOffset &newOffset) const
Definition: format.h:1821
#define PCP_API
Definition: api.h:23
GLenum src
Definition: glcorearb.h:1793