0033661: Data Exchange, Step Import - Tessellated GDTs are not imported
[occt.git] / src / BVH / BVH_Box.hxx
CommitLineData
3c4e78f2 1// Created on: 2013-12-20
2// Created by: Denis BOGOLEPOV
d5f74e42 3// Copyright (c) 2013-2014 OPEN CASCADE SAS
3c4e78f2 4//
5// This file is part of Open CASCADE Technology software library.
6//
d5f74e42 7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
3c4e78f2 9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
12//
13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
15
5bd54bef 16#ifndef BVH_Box_HeaderFile
17#define BVH_Box_HeaderFile
3c4e78f2 18
f5b72419 19#include <BVH_Constants.hxx>
3c4e78f2 20#include <BVH_Types.hxx>
bc73b006 21#include <Standard_Macro.hxx>
0904aa63 22#include <Standard_Dump.hxx>
bc73b006 23#include <Standard_ShortReal.hxx>
3c4e78f2 24
0bb09048 25#include <limits>
26
2b5a58a3 27//! Base class for BVH_Box (CRTP idiom is used).
28//! @tparam T Numeric data type
29//! @tparam N Vector dimension
30//! @tparam TheDerivedBox Template of derived class that defined axis aligned bounding box.
31template <class T, int N, template <class /*T*/, int /*N*/> class TheDerivedBox>
32class BVH_BaseBox {};
33
34// forward declaration
35template <class T, int N> class BVH_Box;
36
37//! Partial template specialization for BVH_Box when N = 3.
38template <class T>
39class BVH_BaseBox<T, 3, BVH_Box>
40{
41public:
42
43 //! Transforms this box with given transformation.
44 void Transform (const NCollection_Mat4<T>& theTransform)
45 {
46 if (theTransform.IsIdentity())
47 {
48 return;
49 }
50
51 BVH_Box<T, 3> *aThis = static_cast<BVH_Box<T, 3>*>(this);
52 if (!aThis->IsValid())
53 {
54 return;
55 }
56
57 BVH_Box<T, 3> aBox = Transformed (theTransform);
58
59 aThis->CornerMin() = aBox.CornerMin();
60 aThis->CornerMax() = aBox.CornerMax();
61 }
62
63 //! Returns a box which is the result of applying the
64 //! given transformation to this box.
65 BVH_Box<T, 3> Transformed (const NCollection_Mat4<T>& theTransform) const
66 {
3453354e 67 const BVH_Box<T, 3> *aThis = static_cast<const BVH_Box<T, 3>*>(this);
2b5a58a3 68 if (theTransform.IsIdentity())
69 {
3453354e 70 return *aThis;
2b5a58a3 71 }
72
2b5a58a3 73 if (!aThis->IsValid())
74 {
3453354e 75 return *aThis;
2b5a58a3 76 }
77
3453354e 78 BVH_Box<T, 3> aResultBox;
2b5a58a3 79 for (size_t aX = 0; aX <= 1; ++aX)
80 {
81 for (size_t aY = 0; aY <= 1; ++aY)
82 {
83 for (size_t aZ = 0; aZ <= 1; ++aZ)
84 {
85 typename BVH::VectorType<T, 4>::Type aPnt =
86 theTransform * typename BVH::VectorType<T, 4>::Type (aX ? aThis->CornerMax().x() : aThis->CornerMin().x(),
87 aY ? aThis->CornerMax().y() : aThis->CornerMin().y(),
88 aZ ? aThis->CornerMax().z() : aThis->CornerMin().z(),
89 static_cast<T> (1.0));
90
91 aResultBox.Add (aPnt.xyz());
92 }
93 }
94 }
95 return aResultBox;
96 }
97};
98
679d3878 99//! Defines axis aligned bounding box (AABB) based on BVH vectors.
100//! \tparam T Numeric data type
101//! \tparam N Vector dimension
3c4e78f2 102template<class T, int N>
2b5a58a3 103class BVH_Box : public BVH_BaseBox<T, N, BVH_Box>
3c4e78f2 104{
105public:
106
3a7a7013 107 typedef typename BVH::VectorType<T, N>::Type BVH_VecNt;
3c4e78f2 108
109public:
110
111 //! Creates uninitialized bounding box.
679d3878 112 BVH_Box() : myIsInited (Standard_False) {}
3c4e78f2 113
114 //! Creates bounding box of given point.
115 BVH_Box (const BVH_VecNt& thePoint)
679d3878 116 : myMinPoint (thePoint),
117 myMaxPoint (thePoint),
118 myIsInited (Standard_True) {}
3c4e78f2 119
3c4e78f2 120 //! Creates bounding box from corner points.
121 BVH_Box (const BVH_VecNt& theMinPoint,
122 const BVH_VecNt& theMaxPoint)
679d3878 123 : myMinPoint (theMinPoint),
124 myMaxPoint (theMaxPoint),
125 myIsInited (Standard_True) {}
3c4e78f2 126
127public:
128
129 //! Clears bounding box.
e28f12b3 130 void Clear() { myIsInited = Standard_False; }
3c4e78f2 131
132 //! Is bounding box valid?
e28f12b3 133 Standard_Boolean IsValid() const { return myIsInited; }
3c4e78f2 134
135 //! Appends new point to the bounding box.
e28f12b3 136 void Add (const BVH_VecNt& thePoint)
137 {
138 if (!myIsInited)
139 {
140 myMinPoint = thePoint;
141 myMaxPoint = thePoint;
142 myIsInited = Standard_True;
143 }
144 else
145 {
146 myMinPoint = myMinPoint.cwiseMin (thePoint);
147 myMaxPoint = myMaxPoint.cwiseMax (thePoint);
148 }
149 }
3c4e78f2 150
151 //! Combines bounding box with another one.
e28f12b3 152 void Combine (const BVH_Box& theBox);
3c4e78f2 153
154 //! Returns minimum point of bounding box.
e28f12b3 155 const BVH_VecNt& CornerMin() const { return myMinPoint; }
3c4e78f2 156
157 //! Returns maximum point of bounding box.
e28f12b3 158 const BVH_VecNt& CornerMax() const { return myMaxPoint; }
3c4e78f2 159
160 //! Returns minimum point of bounding box.
e28f12b3 161 BVH_VecNt& CornerMin() { return myMinPoint; }
3c4e78f2 162
163 //! Returns maximum point of bounding box.
e28f12b3 164 BVH_VecNt& CornerMax() { return myMaxPoint; }
3c4e78f2 165
166 //! Returns surface area of bounding box.
0bb09048 167 //! If the box is degenerated into line, returns the perimeter instead.
3c4e78f2 168 T Area() const;
169
170 //! Returns diagonal of bounding box.
e28f12b3 171 BVH_VecNt Size() const { return myMaxPoint - myMinPoint; }
3c4e78f2 172
173 //! Returns center of bounding box.
e28f12b3 174 BVH_VecNt Center() const { return (myMinPoint + myMaxPoint) * static_cast<T> (0.5); }
3c4e78f2 175
679d3878 176 //! Returns center of bounding box along the given axis.
177 T Center (const Standard_Integer theAxis) const;
178
0904aa63 179 //! Dumps the content of me into the stream
bc73b006 180 void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const
0904aa63 181 {
182 (void)theDepth;
bc73b006 183 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsInited)
184
185 int n = Min (N, 3);
186 if (n == 1)
187 {
188 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMinPoint[0])
189 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMinPoint[0])
190 }
6b63dc83 191 else if (n == 2)
bc73b006 192 {
193 OCCT_DUMP_FIELD_VALUES_NUMERICAL (theOStream, "MinPoint", n, myMinPoint[0], myMinPoint[1])
194 OCCT_DUMP_FIELD_VALUES_NUMERICAL (theOStream, "MaxPoint", n, myMaxPoint[0], myMaxPoint[1])
195 }
6b63dc83 196 else if (n == 3)
bc73b006 197 {
198 OCCT_DUMP_FIELD_VALUES_NUMERICAL (theOStream, "MinPoint", n, myMinPoint[0], myMinPoint[1], myMinPoint[2])
199 OCCT_DUMP_FIELD_VALUES_NUMERICAL (theOStream, "MaxPoint", n, myMaxPoint[0], myMaxPoint[1], myMaxPoint[2])
200 }
0904aa63 201 }
202
6b63dc83 203 //! Inits the content of me from the stream
204 Standard_Boolean InitFromJson (const Standard_SStream& theSStream, Standard_Integer& theStreamPos)
205 {
206 Standard_Integer aPos = theStreamPos;
207
208 Standard_Integer anIsInited = 0;
209 TCollection_AsciiString aStreamStr = Standard_Dump::Text (theSStream);
210
211 OCCT_INIT_FIELD_VALUE_INTEGER (aStreamStr, aPos, anIsInited);
212 myIsInited = anIsInited != 0;
213
214 int n = Min (N, 3);
215 if (n == 1)
216 {
217 Standard_Real aValue;
218 OCCT_INIT_FIELD_VALUE_REAL (aStreamStr, aPos, aValue);
219 myMinPoint[0] = (T)aValue;
220 }
221 else if (n == 2)
222 {
223 Standard_Real aValue1, aValue2;
224 OCCT_INIT_VECTOR_CLASS (aStreamStr, "MinPoint", aPos, n, &aValue1, &aValue2);
225 myMinPoint[0] = (T)aValue1;
226 myMinPoint[1] = (T)aValue2;
227
228 OCCT_INIT_VECTOR_CLASS (aStreamStr, "MaxPoint", aPos, n, &aValue1, &aValue2);
229 myMaxPoint[0] = (T)aValue1;
230 myMaxPoint[1] = (T)aValue2;
231 }
232 else if (n == 3)
233 {
234 Standard_Real aValue1, aValue2, aValue3;
235 OCCT_INIT_VECTOR_CLASS (aStreamStr, "MinPoint", aPos, n, &aValue1, &aValue2, &aValue3);
236 myMinPoint[0] = (T)aValue1;
237 myMinPoint[1] = (T)aValue2;
238 myMinPoint[2] = (T)aValue3;
239
240 OCCT_INIT_VECTOR_CLASS (aStreamStr, "MaxPoint", aPos, n, &aValue1, &aValue2, &aValue3);
241 myMaxPoint[0] = (T)aValue1;
242 myMaxPoint[1] = (T)aValue2;
243 myMaxPoint[2] = (T)aValue3;
244 }
245
246 theStreamPos = aPos;
247 return Standard_True;
248 }
249
7c1a8210 250public:
251
252 //! Checks if the Box is out of the other box.
253 Standard_Boolean IsOut (const BVH_Box<T, N>& theOther) const
254 {
255 if (!theOther.IsValid())
256 return Standard_True;
257
258 return IsOut (theOther.myMinPoint, theOther.myMaxPoint);
259 }
260
261 //! Checks if the Box is out of the other box defined by two points.
262 Standard_Boolean IsOut (const BVH_VecNt& theMinPoint,
263 const BVH_VecNt& theMaxPoint) const
264 {
265 if (!IsValid())
266 return Standard_True;
267
268 int n = Min (N, 3);
269 for (int i = 0; i < n; ++i)
270 {
271 if (myMinPoint[i] > theMaxPoint[i] ||
272 myMaxPoint[i] < theMinPoint[i])
273 return Standard_True;
274 }
275 return Standard_False;
276 }
277
278 //! Checks if the Box fully contains the other box.
279 Standard_Boolean Contains (const BVH_Box<T, N>& theOther,
280 Standard_Boolean& hasOverlap) const
281 {
282 hasOverlap = Standard_False;
283 if (!theOther.IsValid())
284 return Standard_False;
285
286 return Contains (theOther.myMinPoint, theOther.myMaxPoint, hasOverlap);
287 }
288
289 //! Checks if the Box is fully contains the other box.
290 Standard_Boolean Contains (const BVH_VecNt& theMinPoint,
291 const BVH_VecNt& theMaxPoint,
292 Standard_Boolean& hasOverlap) const
293 {
294 hasOverlap = Standard_False;
295 if (!IsValid())
296 return Standard_False;
297
298 Standard_Boolean isInside = Standard_True;
299
300 int n = Min (N, 3);
301 for (int i = 0; i < n; ++i)
302 {
303 hasOverlap = (myMinPoint[i] <= theMaxPoint[i] &&
304 myMaxPoint[i] >= theMinPoint[i]);
305 if (!hasOverlap)
306 return Standard_False;
307
308 isInside = isInside && (myMinPoint[i] <= theMinPoint[i] &&
309 myMaxPoint[i] >= theMaxPoint[i]);
310 }
311 return isInside;
312 }
313
314 //! Checks if the Point is out of the box.
315 Standard_Boolean IsOut (const BVH_VecNt& thePoint) const
316 {
317 if (!IsValid())
318 return Standard_True;
319
320 int n = Min (N, 3);
321 for (int i = 0; i < n; ++i)
322 {
323 if (thePoint[i] < myMinPoint[i] ||
324 thePoint[i] > myMaxPoint[i])
325 return Standard_True;
326 }
327 return Standard_False;
328 }
329
330
3c4e78f2 331protected:
332
679d3878 333 BVH_VecNt myMinPoint; //!< Minimum point of bounding box
334 BVH_VecNt myMaxPoint; //!< Maximum point of bounding box
335 Standard_Boolean myIsInited; //!< Is bounding box initialized?
3c4e78f2 336
337};
338
679d3878 339namespace BVH
340{
341 //! Tool class for calculating box center along the given axis.
342 //! \tparam T Numeric data type
343 //! \tparam N Vector dimension
344 template<class T, int N>
345 struct CenterAxis
346 {
347 // Not implemented
348 };
349
350 template<class T>
351 struct CenterAxis<T, 2>
352 {
353 static T Center (const BVH_Box<T, 2>& theBox, const Standard_Integer theAxis)
354 {
355 if (theAxis == 0)
356 {
357 return (theBox.CornerMin().x() + theBox.CornerMax().x()) * static_cast<T> (0.5);
358 }
359 else if (theAxis == 1)
360 {
361 return (theBox.CornerMin().y() + theBox.CornerMax().y()) * static_cast<T> (0.5);
362 }
363 return static_cast<T> (0.0);
364 }
365 };
366
367 template<class T>
368 struct CenterAxis<T, 3>
369 {
370 static T Center (const BVH_Box<T, 3>& theBox, const Standard_Integer theAxis)
371 {
372 if (theAxis == 0)
373 {
374 return (theBox.CornerMin().x() + theBox.CornerMax().x()) * static_cast<T> (0.5);
375 }
376 else if (theAxis == 1)
377 {
378 return (theBox.CornerMin().y() + theBox.CornerMax().y()) * static_cast<T> (0.5);
379 }
380 else if (theAxis == 2)
381 {
382 return (theBox.CornerMin().z() + theBox.CornerMax().z()) * static_cast<T> (0.5);
383 }
384 return static_cast<T> (0.0);
385 }
386 };
387
388 template<class T>
389 struct CenterAxis<T, 4>
390 {
391 static T Center (const BVH_Box<T, 4>& theBox, const Standard_Integer theAxis)
392 {
393 if (theAxis == 0)
394 {
395 return (theBox.CornerMin().x() + theBox.CornerMax().x()) * static_cast<T> (0.5);
396 }
397 else if (theAxis == 1)
398 {
399 return (theBox.CornerMin().y() + theBox.CornerMax().y()) * static_cast<T> (0.5);
400 }
401 else if (theAxis == 2)
402 {
403 return (theBox.CornerMin().z() + theBox.CornerMax().z()) * static_cast<T> (0.5);
404 }
405 return static_cast<T> (0.0);
406 }
407 };
408
409 //! Tool class for calculating surface area of the box.
410 //! \tparam T Numeric data type
411 //! \tparam N Vector dimension
412 template<class T, int N>
413 struct SurfaceCalculator
414 {
415 // Not implemented
416 };
417
418 template<class T>
419 struct SurfaceCalculator<T, 2>
420 {
421 static T Area (const typename BVH_Box<T, 2>::BVH_VecNt& theSize)
422 {
0bb09048 423 const T anArea = theSize.x() * theSize.y();
424
425 if (anArea < std::numeric_limits<T>::epsilon())
426 {
427 return theSize.x() + theSize.y();
428 }
429
430 return anArea;
679d3878 431 }
432 };
433
434 template<class T>
435 struct SurfaceCalculator<T, 3>
436 {
437 static T Area (const typename BVH_Box<T, 3>::BVH_VecNt& theSize)
438 {
0bb09048 439 const T anArea = ( theSize.x() * theSize.y() +
440 theSize.x() * theSize.z() +
441 theSize.z() * theSize.y() ) * static_cast<T> (2.0);
442
443 if (anArea < std::numeric_limits<T>::epsilon())
444 {
445 return theSize.x() +
446 theSize.y() +
447 theSize.z();
448 }
449
450 return anArea;
679d3878 451 }
452 };
453
454 template<class T>
455 struct SurfaceCalculator<T, 4>
456 {
457 static T Area (const typename BVH_Box<T, 4>::BVH_VecNt& theSize)
458 {
0bb09048 459 const T anArea = ( theSize.x() * theSize.y() +
460 theSize.x() * theSize.z() +
461 theSize.z() * theSize.y() ) * static_cast<T> (2.0);
462
463 if (anArea < std::numeric_limits<T>::epsilon())
464 {
465 return theSize.x() +
466 theSize.y() +
467 theSize.z();
468 }
469
470 return anArea;
679d3878 471 }
472 };
473
474 //! Tool class for calculate component-wise vector minimum
475 //! and maximum (optimized version).
476 //! \tparam T Numeric data type
477 //! \tparam N Vector dimension
478 template<class T, int N>
479 struct BoxMinMax
480 {
481 typedef typename BVH::VectorType<T, N>::Type BVH_VecNt;
482
483 static void CwiseMin (BVH_VecNt& theVec1, const BVH_VecNt& theVec2)
484 {
485 theVec1.x() = Min (theVec1.x(), theVec2.x());
486 theVec1.y() = Min (theVec1.y(), theVec2.y());
487 theVec1.z() = Min (theVec1.z(), theVec2.z());
488 }
489
490 static void CwiseMax (BVH_VecNt& theVec1, const BVH_VecNt& theVec2)
491 {
492 theVec1.x() = Max (theVec1.x(), theVec2.x());
493 theVec1.y() = Max (theVec1.y(), theVec2.y());
494 theVec1.z() = Max (theVec1.z(), theVec2.z());
495 }
496 };
497
498 template<class T>
499 struct BoxMinMax<T, 2>
500 {
501 typedef typename BVH::VectorType<T, 2>::Type BVH_VecNt;
502
503 static void CwiseMin (BVH_VecNt& theVec1, const BVH_VecNt& theVec2)
504 {
505 theVec1.x() = Min (theVec1.x(), theVec2.x());
506 theVec1.y() = Min (theVec1.y(), theVec2.y());
507 }
508
509 static void CwiseMax (BVH_VecNt& theVec1, const BVH_VecNt& theVec2)
510 {
511 theVec1.x() = Max (theVec1.x(), theVec2.x());
512 theVec1.y() = Max (theVec1.y(), theVec2.y());
513 }
514 };
515}
516
e28f12b3 517// =======================================================================
518// function : Combine
519// purpose :
520// =======================================================================
521template<class T, int N>
522void BVH_Box<T, N>::Combine (const BVH_Box& theBox)
523{
524 if (theBox.myIsInited)
525 {
526 if (!myIsInited)
527 {
528 myMinPoint = theBox.myMinPoint;
529 myMaxPoint = theBox.myMaxPoint;
530 myIsInited = Standard_True;
531 }
532 else
533 {
534 BVH::BoxMinMax<T, N>::CwiseMin (myMinPoint, theBox.myMinPoint);
535 BVH::BoxMinMax<T, N>::CwiseMax (myMaxPoint, theBox.myMaxPoint);
536 }
537 }
538}
539
540// =======================================================================
541// function : Area
542// purpose :
543// =======================================================================
544template<class T, int N>
545T BVH_Box<T, N>::Area() const
546{
547 return !myIsInited ? static_cast<T> (0.0) : BVH::SurfaceCalculator<T, N>::Area (myMaxPoint - myMinPoint);
548}
549
550// =======================================================================
551// function : Center
552// purpose :
553// =======================================================================
554template<class T, int N>
555T BVH_Box<T, N>::Center (const Standard_Integer theAxis) const
556{
557 return BVH::CenterAxis<T, N>::Center (*this, theAxis);
558}
3c4e78f2 559
560#endif // _BVH_Box_Header