From a4d1dbe5f054a10ecee12fc2a1d907e04760b7be Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 11 Oct 2015 00:18:53 +0200 Subject: [PATCH] + rework BoundingBox class and its Python binding --- src/App/PreCompiled.h | 1 + src/Base/BoundBox.h | 1442 +++++++++-------- src/Base/BoundBoxPy.xml | 68 +- src/Base/BoundBoxPyImp.cpp | 327 +++- src/Base/PreCompiled.h | 1 + src/Base/Tools2D.h | 18 +- src/Gui/CommandView.cpp | 2 +- src/Gui/GLPainter.h | 1 + src/Gui/SoFCSelection.h | 1 + src/Gui/SoFCUnifiedSelection.h | 1 + src/Mod/Draft/Draft.py | 2 +- src/Mod/Draft/DraftGeomUtils.py | 2 +- src/Mod/Drawing/Gui/TaskOrthoViews.cpp | 6 +- src/Mod/Drawing/Gui/ViewProviderPage.cpp | 3 - src/Mod/Drawing/Gui/ViewProviderView.cpp | 3 - src/Mod/Inspection/App/InspectionFeature.cpp | 6 +- src/Mod/Inspection/Gui/PreCompiled.h | 4 + src/Mod/Mesh/App/Core/Algorithm.cpp | 8 +- src/Mod/Mesh/App/Core/Elements.cpp | 4 +- src/Mod/Mesh/App/Core/Grid.cpp | 6 +- src/Mod/Mesh/App/Core/Grid.h | 6 +- src/Mod/Mesh/App/Core/MeshKernel.cpp | 18 +- src/Mod/Mesh/App/Core/Projection.cpp | 2 +- src/Mod/Mesh/App/Core/TopoAlgorithm.cpp | 2 +- src/Mod/Mesh/Gui/Command.cpp | 2 +- src/Mod/Mesh/Gui/SoFCMeshObject.cpp | 14 +- .../Gui/ViewProviderTransformDemolding.cpp | 2 +- src/Mod/Part/App/PreCompiled.h | 2 + src/Mod/Part/Gui/CrossSections.cpp | 10 +- src/Mod/Part/Gui/PreCompiled.h | 8 +- src/Mod/Part/Gui/ViewProviderMirror.cpp | 2 +- src/Mod/Points/App/PointsGrid.cpp | 12 +- src/Mod/Points/Gui/PreCompiled.h | 4 + src/Mod/Points/Gui/ViewProvider.cpp | 3 - .../ReverseEngineering/App/ApproxSurface.cpp | 2 +- src/Mod/Sandbox/Gui/Command.cpp | 2 + src/Mod/Sketcher/App/PreCompiled.h | 1 + src/Mod/Spreadsheet/App/PreCompiled.h | 1 + src/Mod/Test/BaseTests.py | 10 + 39 files changed, 1167 insertions(+), 842 deletions(-) diff --git a/src/App/PreCompiled.h b/src/App/PreCompiled.h index d6fd57b3a..7b59f2108 100644 --- a/src/App/PreCompiled.h +++ b/src/App/PreCompiled.h @@ -47,6 +47,7 @@ #ifdef FC_OS_WIN32 #include #define WIN32_LEAN_AND_MEAN +#define NOMINMAX #include #include #endif diff --git a/src/Base/BoundBox.h b/src/Base/BoundBox.h index 1e6d24d64..dd086a4b8 100644 --- a/src/Base/BoundBox.h +++ b/src/Base/BoundBox.h @@ -28,9 +28,8 @@ #include "Matrix.h" #include "ViewProj.h" #include "Tools2D.h" - -// Checks if point K lies on the ray [A,B[ -#define IS_ON_RAY(A,B,K) (((A) <= (K)) && ((B) > (K))) +#include +#include namespace Base { @@ -40,166 +39,228 @@ class ViewProjMethod; template class BoundBox3 { + // helper function + static bool isOnRayW(_Precision, _Precision, _Precision); + static bool isOnRayS(_Precision, _Precision, _Precision); + public: - typedef _Precision num_type; - typedef float_traits traits_type; + typedef _Precision num_type; + typedef float_traits traits_type; - /** Public attributes */ - //@{ - _Precision MinX; - _Precision MinY; - _Precision MinZ; - _Precision MaxX; - _Precision MaxY; - _Precision MaxZ; - //@} - - /** Builds box from pairs of x,y,z values. */ - inline explicit BoundBox3 ( _Precision fMinX = FLOAT_MAX, _Precision fMinY = FLOAT_MAX, - _Precision fMinZ = FLOAT_MAX, _Precision fMaxX = -FLOAT_MAX, - _Precision fMaxY = -FLOAT_MAX, _Precision fMaxZ = -FLOAT_MAX ); - BoundBox3 (const BoundBox3<_Precision> &rcBB) { *this = rcBB; } - /** Builds box from an array of points. */ - inline BoundBox3 (const Vector3<_Precision> *pclVect, unsigned long ulCt); + /** Public attributes */ + //@{ + _Precision MinX; + _Precision MinY; + _Precision MinZ; + _Precision MaxX; + _Precision MaxY; + _Precision MaxZ; + //@} - /** Defines a bounding box around the center \a rcCnt with the - * distances \a fDistance in each coordinate. - */ - BoundBox3 (const Vector3<_Precision> &rcCnt, _Precision fDistance); - ~BoundBox3 (); - - /// Assignment operator - inline BoundBox3<_Precision>& operator = (const BoundBox3<_Precision> &rcBound); - - /** Methods for intersection, cuttíng and union of bounding boxes */ - //@{ - /** Checks for intersection. */ - inline bool operator && (const BoundBox3<_Precision> &rcBB) const; - /** Checks for intersection. */ - inline bool operator && (const BoundBox2D &rcBB) const; - /** Computes the intersection between two bounding boxes. - * The result is also a bounding box. - */ - BoundBox3<_Precision> operator & (const BoundBox3<_Precision> &rcBB) const; - /** Appends the point to the box. The box can grow but not shrink. */ - inline BoundBox3<_Precision>& operator &= (const Vector3<_Precision> &rclVect); - /** The union of two bounding boxes. */ - BoundBox3<_Precision> operator | (const BoundBox3<_Precision> &rcBB) const; - /** Appends the point to the box. The box can grow but not shrink. - * This method does the same as the &= operator unless that it nothing returns. - */ - inline void Add (const Vector3<_Precision> &rclVect); - /** Appends the bounding box to this box. The box can grow but not shrink. */ - inline void Add (const BoundBox3<_Precision> &rcBB); - //@} - - /** Test methods */ - //@{ - /** Checks if this point lies inside the box. */ - inline bool IsInBox (const Vector3<_Precision> &rcVct) const; - /** Checks if this 3D box lies inside the box. */ - inline bool IsInBox (const BoundBox3<_Precision> &rcBB) const; - /** Checks if this 2D box lies inside the box. */ - inline bool IsInBox (const BoundBox2D &rcbb) const; - /** Checks whether the bounding box is valid. */ - bool IsValid (void) const; - //@} + /** Builds box from pairs of x,y,z values. */ + inline explicit BoundBox3 (_Precision fMinX = std::numeric_limits<_Precision>::max(), + _Precision fMinY = std::numeric_limits<_Precision>::max(), + _Precision fMinZ = std::numeric_limits<_Precision>::max(), + _Precision fMaxX = -std::numeric_limits<_Precision>::max(), + _Precision fMaxY = -std::numeric_limits<_Precision>::max(), + _Precision fMaxZ = -std::numeric_limits<_Precision>::max()); + BoundBox3 (const BoundBox3<_Precision> &rcBB) { *this = rcBB; } + /** Builds box from an array of points. */ + inline BoundBox3 (const Vector3<_Precision> *pclVect, unsigned long ulCt); - enum OCTANT {OCT_LDB = 0, OCT_RDB, OCT_LUB, OCT_RUB, - OCT_LDF, OCT_RDF, OCT_LUF, OCT_RUF}; - bool GetOctantFromVector (const Vector3<_Precision> &rclVct, OCTANT &rclOctant) const; - BoundBox3<_Precision> CalcOctant (typename BoundBox3<_Precision>::OCTANT Octant) const; + /** Defines a bounding box around the center \a rcCnt with the + * distances \a fDistance in each coordinate. + */ + BoundBox3 (const Vector3<_Precision> &rcCnt, _Precision fDistance); + ~BoundBox3 (); - enum SIDE { LEFT =0, RIGHT=1, TOP=2, BOTTOM=3, FRONT=4, BACK=5, INVALID=255 }; + /// Assignment operator + inline BoundBox3<_Precision>& operator = (const BoundBox3<_Precision> &rcBound); - /** - * Returns the corner point \a usPoint. - * 0: front,bottom,left 1: front,bottom,right - * 2: front,top,right 3: front,top,left - * 4: back,bottom,left 5: back,bottom,right - * 6: back,top,right 7: back,top,left - */ - inline Vector3<_Precision> CalcPoint (unsigned short usPoint) const; - /** Returns the plane of the given side. */ - void CalcPlane (unsigned short usPlane, Vector3<_Precision>& rBase, Vector3<_Precision>& rNormal ) const; - /** Calculates the two points of an edge. - * 0. edge P0-P1 1. edge P1-P2 2. edge P2-P3 - * 3. edge P3-P0 4. edge P4-P5 5. edge P5-P6 - * 6. edge P6-P7 7. edge P7-P4 8. edge P0-P4 - * 9. edge P1-P5 10. edge P2-P6 11. edge P3-P7 - */ - bool CalcDistance (unsigned short usEdge, Vector3<_Precision>& rcP0, Vector3<_Precision>& rcP1) const; - /** Intersection point of an inner search ray with the bounding box, built of - * the base \a rcVct and the direction \a rcVctDir. \a rcVct must lie inside the - * bounding box. - */ - bool IntersectionPoint (const Vector3<_Precision> &rcVct, const Vector3<_Precision> &rcVctDir, Vector3<_Precision>& cVctRes, _Precision epsilon) const; - /** Checks for intersection with line incl. search tolerance. */ - bool IsCutLine ( const Vector3<_Precision>& rcBase, const Vector3<_Precision>& rcDir, _Precision fTolerance = 0.0f) const; - /** Checks if this plane specified by (point,normal) cuts this box. */ - inline bool IsCutPlane (const Vector3<_Precision> &rclBase, const Vector3<_Precision> &rclNormal) const; - /** Computes the intersection points of line and bounding box. */ - bool IntersectWithLine (const Vector3<_Precision>& rcBase, const Vector3<_Precision>& rcDir, Vector3<_Precision>& rcP0, Vector3<_Precision>& rcP1) const; - /** Computes the intersection point of line and a plane of the bounding box. */ - bool IntersectPlaneWithLine (unsigned short usSide, const Vector3<_Precision>& rcBase, const Vector3<_Precision>& rcDir, - Vector3<_Precision>& rcP0) const; - /** Returns the side of the bounding box the ray exits. */ - typename BoundBox3<_Precision>::SIDE GetSideFromRay (const Vector3<_Precision> &rclPt, const Vector3<_Precision> &rclDir) const; - /** Returns the side of the bounding box the ray exits. */ - typename BoundBox3<_Precision>::SIDE GetSideFromRay (const Vector3<_Precision> &rclPt, const Vector3<_Precision> &rclDir, Vector3<_Precision>& rcInt) const; - - /** - * Searches for the nearest point of the bounding box. - * \note Point must be inside the bounding box. - */ - Vector3<_Precision> NearestPoint (const Vector3<_Precision> &rclPt) const; - /** Projects the box onto a plane and returns a 2D box. */ - BoundBox2D ProjectBox(const ViewProjMethod *rclP) const; - BoundBox3<_Precision> Transformed(const Matrix4D& mat) const; + /** Methods for intersection, cuttíng and union of bounding boxes */ + //@{ + /** Checks for intersection. */ + inline bool Intersect (const BoundBox3<_Precision> &rcBB) const; + /** Checks for intersection. */ + inline bool operator && (const BoundBox3<_Precision> &rcBB) const; + /** Checks for intersection. */ + inline bool Intersect (const BoundBox2D &rcBB) const; + /** Checks for intersection. */ + inline bool operator && (const BoundBox2D &rcBB) const; + /** Computes the intersection between two bounding boxes. + * The result is also a bounding box. + */ + BoundBox3<_Precision> Intersected (const BoundBox3<_Precision> &rcBB) const; + /** The union of two bounding boxes. */ + BoundBox3<_Precision> United (const BoundBox3<_Precision> &rcBB) const; + /** Appends the point to the box. The box can grow but not shrink. */ + inline void Add (const Vector3<_Precision> &rclVect); + /** Appends the bounding box to this box. The box can grow but not shrink. */ + inline void Add (const BoundBox3<_Precision> &rcBB); + //@} - /** Returns the center.of the box. */ - inline Vector3<_Precision> CalcCenter (void) const; - inline _Precision CalcDiagonalLength (void) const; - void Flush (void); - - /** Enlarges the box with factor \a fLen. */ - inline void Enlarge (_Precision fLen); - /** Shrinks the box with factor \a fLen. */ - inline void Shrink (_Precision fLen); + /** Test methods */ + //@{ + /** Checks if this point lies inside the box. + * @note It's up to the client programmer to make sure that this bounding box is valid. + */ + inline bool IsInBox (const Vector3<_Precision> &rcVct) const; + /** Checks if this 3D box lies inside the box. + * @note It's up to the client programmer to make sure that both bounding boxes are valid. + */ + inline bool IsInBox (const BoundBox3<_Precision> &rcBB) const; + /** Checks if this 2D box lies inside the box. + * @note It's up to the client programmer to make sure that both bounding boxes are valid. + */ + inline bool IsInBox (const BoundBox2D &rcbb) const; + /** Checks whether the bounding box is valid. */ + bool IsValid (void) const; + //@} - /** Calculates expansion in x-direction. */ - inline _Precision LengthX (void) const; - /** Calculates expansion in y-direction. */ - inline _Precision LengthY (void) const; - /** Calculates expansion in z-direction. */ - inline _Precision LengthZ (void) const; - /** Moves in x-direction. */ - inline void MoveX (_Precision f); - /** Moves in y-direction. */ - inline void MoveY (_Precision f); - /** Moves in z-direction. */ - inline void MoveZ (_Precision f); - /** Scales in x-direction. */ - inline void ScaleX (_Precision f); - /** Scales in y-direction. */ - inline void ScaleY (_Precision f); - /** Scales in z-direction. */ - inline void ScaleZ (_Precision f); - - /** Prints the values to stdout. */ - void Print (void); + enum OCTANT {OCT_LDB = 0, OCT_RDB, OCT_LUB, OCT_RUB, + OCT_LDF, OCT_RDF, OCT_LUF, OCT_RUF}; + bool GetOctantFromVector (const Vector3<_Precision> &rclVct, OCTANT &rclOctant) const; + BoundBox3<_Precision> CalcOctant (typename BoundBox3<_Precision>::OCTANT Octant) const; + + enum SIDE { LEFT =0, RIGHT=1, TOP=2, BOTTOM=3, FRONT=4, BACK=5, INVALID=255 }; + + /** + * Returns the corner point \a usPoint. + * 0: front,bottom,left 1: front,bottom,right + * 2: front,top,right 3: front,top,left + * 4: back,bottom,left 5: back,bottom,right + * 6: back,top,right 7: back,top,left + */ + inline Vector3<_Precision> CalcPoint (unsigned short usPoint) const; + /** Returns the plane of the given side. */ + void CalcPlane (unsigned short usPlane, Vector3<_Precision>& rBase, Vector3<_Precision>& rNormal ) const; + /** Calculates the two points of an edge. + * 0. edge P0-P1 1. edge P1-P2 2. edge P2-P3 + * 3. edge P3-P0 4. edge P4-P5 5. edge P5-P6 + * 6. edge P6-P7 7. edge P7-P4 8. edge P0-P4 + * 9. edge P1-P5 10. edge P2-P6 11. edge P3-P7 + */ + bool CalcEdge (unsigned short usEdge, Vector3<_Precision>& rcP0, Vector3<_Precision>& rcP1) const; + /** Intersection point of an inner search ray with the bounding box, built of + * the base \a rcVct and the direction \a rcVctDir. \a rcVct must lie inside the + * bounding box. + */ + bool IntersectionPoint (const Vector3<_Precision> &rcVct, const Vector3<_Precision> &rcVctDir, Vector3<_Precision>& cVctRes, _Precision epsilon) const; + /** Checks for intersection with line incl. search tolerance. */ + bool IsCutLine ( const Vector3<_Precision>& rcBase, const Vector3<_Precision>& rcDir, _Precision fTolerance = 0.0f) const; + /** Checks if this plane specified by (point,normal) cuts this box. + * @note It's up to the client programmer to make sure that this bounding box is valid. + */ + inline bool IsCutPlane (const Vector3<_Precision> &rclBase, const Vector3<_Precision> &rclNormal) const; + /** Computes the intersection points of line and bounding box. */ + bool IntersectWithLine (const Vector3<_Precision>& rcBase, const Vector3<_Precision>& rcDir, Vector3<_Precision>& rcP0, Vector3<_Precision>& rcP1) const; + /** Computes the intersection point of line and a plane of the bounding box. */ + bool IntersectPlaneWithLine (unsigned short usSide, const Vector3<_Precision>& rcBase, const Vector3<_Precision>& rcDir, + Vector3<_Precision>& rcP0) const; + /** Returns the side of the bounding box the ray exits. */ + typename BoundBox3<_Precision>::SIDE GetSideFromRay (const Vector3<_Precision> &rclPt, const Vector3<_Precision> &rclDir) const; + /** Returns the side of the bounding box the ray exits. */ + typename BoundBox3<_Precision>::SIDE GetSideFromRay (const Vector3<_Precision> &rclPt, const Vector3<_Precision> &rclDir, Vector3<_Precision>& rcInt) const; + + /** + * Searches for the closest point of the bounding box. + */ + Vector3<_Precision> ClosestPoint (const Vector3<_Precision> &rclPt) const; + /** Projects the box onto a plane and returns a 2D box. */ + BoundBox2D ProjectBox(const ViewProjMethod *rclP) const; + /** Transform the corners of this box with the given matrix and create a new bounding box. + * @note It's up to the client programmer to make sure that this bounding box is valid. + */ + BoundBox3<_Precision> Transformed(const Matrix4D& mat) const; + + /** Returns the center.of the box. */ + inline Vector3<_Precision> GetCenter (void) const; + /** Compute the diagonal length of this bounding box. + * @note It's up to the client programmer to make sure that this bounding box is valid. + */ + inline _Precision CalcDiagonalLength (void) const; + void SetVoid (void); + + /** Enlarges the box with factor \a fLen. */ + inline void Enlarge (_Precision fLen); + /** Shrinks the box with factor \a fLen. */ + inline void Shrink (_Precision fLen); + + /** Calculates expansion in x-direction. */ + inline _Precision LengthX (void) const; + /** Calculates expansion in y-direction. */ + inline _Precision LengthY (void) const; + /** Calculates expansion in z-direction. */ + inline _Precision LengthZ (void) const; + /** Moves in x-direction. */ + inline void MoveX (_Precision f); + /** Moves in y-direction. */ + inline void MoveY (_Precision f); + /** Moves in z-direction. */ + inline void MoveZ (_Precision f); + /** Scales in x-direction. */ + inline void ScaleX (_Precision f); + /** Scales in y-direction. */ + inline void ScaleY (_Precision f); + /** Scales in z-direction. */ + inline void ScaleZ (_Precision f); + + /** Prints the values to stream. */ + void Print (std::ostream&) const; }; +template +bool BoundBox3<_Precision>::isOnRayW(_Precision A, _Precision B, _Precision K) +{ + // Checks if point K lies on the ray [A,B] + return ((A <= K) && (K <= B)); +} + +template +bool BoundBox3<_Precision>::isOnRayS(_Precision A, _Precision B, _Precision K) +{ + // Checks if point K lies on the ray [A,B[ + return ((A <= K) && (K < B)); +} + +template +inline BoundBox3<_Precision>::BoundBox3 (_Precision fMinX, _Precision fMinY, _Precision fMinZ, + _Precision fMaxX, _Precision fMaxY, _Precision fMaxZ) + : MinX(fMinX), MinY(fMinY), MinZ(fMinZ), + MaxX(fMaxX), MaxY(fMaxY), MaxZ(fMaxZ) +{ +} + +template +inline BoundBox3<_Precision>::BoundBox3 (const Vector3<_Precision> *pclVect, unsigned long ulCt) + : MinX( std::numeric_limits<_Precision>::max()) + , MinY( std::numeric_limits<_Precision>::max()) + , MinZ( std::numeric_limits<_Precision>::max()) + , MaxX(-std::numeric_limits<_Precision>::max()) + , MaxY(-std::numeric_limits<_Precision>::max()) + , MaxZ(-std::numeric_limits<_Precision>::max()) +{ + const Vector3<_Precision> *pI, *pEnd = pclVect + ulCt; + for (pI = pclVect; pI < pEnd; ++pI) { + MinX = std::min<_Precision>(MinX, pI->x); + MinY = std::min<_Precision>(MinY, pI->y); + MinZ = std::min<_Precision>(MinZ, pI->z); + MaxX = std::max<_Precision>(MaxX, pI->x); + MaxY = std::max<_Precision>(MaxY, pI->y); + MaxZ = std::max<_Precision>(MaxZ, pI->z); + } +} + template inline BoundBox3<_Precision>::BoundBox3 (const Vector3<_Precision> &rcVector, _Precision fDistance) { - MinX = rcVector.x - fDistance; - MaxX = rcVector.x + fDistance; - MinY = rcVector.y - fDistance; - MaxY = rcVector.y + fDistance; - MinZ = rcVector.z - fDistance; - MaxZ = rcVector.z + fDistance; + MinX = rcVector.x - fDistance; + MaxX = rcVector.x + fDistance; + MinY = rcVector.y - fDistance; + MaxY = rcVector.y + fDistance; + MinZ = rcVector.z - fDistance; + MaxZ = rcVector.z + fDistance; } template @@ -208,298 +269,329 @@ inline BoundBox3<_Precision>::~BoundBox3 () } template -inline BoundBox3<_Precision> BoundBox3<_Precision>::operator & (const BoundBox3<_Precision> &rcBB) const +inline BoundBox3<_Precision>& BoundBox3<_Precision>::operator = (const BoundBox3<_Precision> &rcBound) { - BoundBox3<_Precision> cBBRes; - - cBBRes.MinX = std::max<_Precision> (MinX, rcBB.MinX); - cBBRes.MaxX = std::min<_Precision> (MaxX, rcBB.MaxX); - cBBRes.MinY = std::max<_Precision> (MinY, rcBB.MinY); - cBBRes.MaxY = std::min<_Precision> (MaxY, rcBB.MaxY); - cBBRes.MinZ = std::max<_Precision> (MinZ, rcBB.MinZ); - cBBRes.MaxZ = std::min<_Precision> (MaxZ, rcBB.MaxZ); - - return cBBRes; + MinX = rcBound.MinX; + MinY = rcBound.MinY; + MinZ = rcBound.MinZ; + MaxX = rcBound.MaxX; + MaxY = rcBound.MaxY; + MaxZ = rcBound.MaxZ; + return *this; } template -inline BoundBox3<_Precision> BoundBox3<_Precision>::operator | (const BoundBox3<_Precision> &rcBB) const +inline bool BoundBox3<_Precision>::Intersect (const BoundBox3<_Precision> &rcBB) const { - BoundBox3<_Precision> cBBRes; + if (rcBB.MaxX < this->MinX || rcBB.MinX > this->MaxX) + return false; + if (rcBB.MaxY < this->MinY || rcBB.MinY > this->MaxY) + return false; + if (rcBB.MaxZ < this->MinZ || rcBB.MinZ > this->MaxZ) + return false; + return true; +} - cBBRes.MinX = std::min<_Precision> (MinX, rcBB.MinX); - cBBRes.MaxX = std::max<_Precision> (MaxX, rcBB.MaxX); - cBBRes.MinY = std::min<_Precision> (MinY, rcBB.MinY); - cBBRes.MaxY = std::max<_Precision> (MaxY, rcBB.MaxY); - cBBRes.MinZ = std::min<_Precision> (MinZ, rcBB.MinZ); - cBBRes.MaxZ = std::max<_Precision> (MaxZ, rcBB.MaxZ); +template +bool BoundBox3<_Precision>::operator && (const BoundBox3<_Precision> &rcBB) const +{ + return Intersect(rcBB); +} - return cBBRes; +template +inline bool BoundBox3<_Precision>::Intersect (const BoundBox2D &rcBB) const +{ + if (rcBB.fMaxX < this->MinX || rcBB.fMinX > this->MaxX) + return false; + if (rcBB.fMaxY < this->MinY || rcBB.fMinY > this->MaxY) + return false; + return true; +} + +template +inline bool BoundBox3<_Precision>::operator && (const BoundBox2D &rcBB) const +{ + return Intersect(rcBB); +} + +template +inline BoundBox3<_Precision> BoundBox3<_Precision>::Intersected(const BoundBox3<_Precision> &rcBB) const +{ + BoundBox3<_Precision> cBBRes; + + cBBRes.MinX = std::max<_Precision> (MinX, rcBB.MinX); + cBBRes.MaxX = std::min<_Precision> (MaxX, rcBB.MaxX); + cBBRes.MinY = std::max<_Precision> (MinY, rcBB.MinY); + cBBRes.MaxY = std::min<_Precision> (MaxY, rcBB.MaxY); + cBBRes.MinZ = std::max<_Precision> (MinZ, rcBB.MinZ); + cBBRes.MaxZ = std::min<_Precision> (MaxZ, rcBB.MaxZ); + + return cBBRes; +} + +template +inline BoundBox3<_Precision> BoundBox3<_Precision>::United(const BoundBox3<_Precision> &rcBB) const +{ + BoundBox3<_Precision> cBBRes; + + cBBRes.MinX = std::min<_Precision> (MinX, rcBB.MinX); + cBBRes.MaxX = std::max<_Precision> (MaxX, rcBB.MaxX); + cBBRes.MinY = std::min<_Precision> (MinY, rcBB.MinY); + cBBRes.MaxY = std::max<_Precision> (MaxY, rcBB.MaxY); + cBBRes.MinZ = std::min<_Precision> (MinZ, rcBB.MinZ); + cBBRes.MaxZ = std::max<_Precision> (MaxZ, rcBB.MaxZ); + + return cBBRes; } template inline void BoundBox3<_Precision>::Add (const Vector3<_Precision> &rclVect) { - this->MinX = std::min<_Precision>(this->MinX, rclVect.x); - this->MinY = std::min<_Precision>(this->MinY, rclVect.y); - this->MinZ = std::min<_Precision>(this->MinZ, rclVect.z); - this->MaxX = std::max<_Precision>(this->MaxX, rclVect.x); - this->MaxY = std::max<_Precision>(this->MaxY, rclVect.y); - this->MaxZ = std::max<_Precision>(this->MaxZ, rclVect.z); + this->MinX = std::min<_Precision>(this->MinX, rclVect.x); + this->MinY = std::min<_Precision>(this->MinY, rclVect.y); + this->MinZ = std::min<_Precision>(this->MinZ, rclVect.z); + this->MaxX = std::max<_Precision>(this->MaxX, rclVect.x); + this->MaxY = std::max<_Precision>(this->MaxY, rclVect.y); + this->MaxZ = std::max<_Precision>(this->MaxZ, rclVect.z); } template inline void BoundBox3<_Precision>::Add (const BoundBox3<_Precision> &rcBB) { - this->MinX = std::min<_Precision> (this->MinX, rcBB.MinX); - this->MaxX = std::max<_Precision> (this->MaxX, rcBB.MaxX); - this->MinY = std::min<_Precision> (this->MinY, rcBB.MinY); - this->MaxY = std::max<_Precision> (this->MaxY, rcBB.MaxY); - this->MinZ = std::min<_Precision> (this->MinZ, rcBB.MinZ); - this->MaxZ = std::max<_Precision> (this->MaxZ, rcBB.MaxZ); + this->MinX = std::min<_Precision> (this->MinX, rcBB.MinX); + this->MaxX = std::max<_Precision> (this->MaxX, rcBB.MaxX); + this->MinY = std::min<_Precision> (this->MinY, rcBB.MinY); + this->MaxY = std::max<_Precision> (this->MaxY, rcBB.MaxY); + this->MinZ = std::min<_Precision> (this->MinZ, rcBB.MinZ); + this->MaxZ = std::max<_Precision> (this->MaxZ, rcBB.MaxZ); } template -inline bool BoundBox3<_Precision>::IsCutLine ( const Vector3<_Precision>& rcBase, const Vector3<_Precision>& rcDir, _Precision fTolerance) const +inline bool BoundBox3<_Precision>::IsInBox (const Vector3<_Precision> &rcVct) const { - _Precision fDist; - - // zuerst nur grobe und schnelle Pruefung, indem der - // Abstand der Linie zum Mittelpunkt der BB berechnet wird - // und mit der maximalen Diagonalenlaenge + fTolerance - // verglichen wird. - - // Distanz zwischen Mittelpunkt und Linie - fDist = (rcDir % (CalcCenter() - rcBase)).Length() / rcDir.Length(); + if (rcVct.x < this->MinX || rcVct.x > this->MaxX) + return false; + if (rcVct.y < this->MinY || rcVct.y > this->MaxY) + return false; + if (rcVct.z < this->MinZ || rcVct.z > this->MaxZ) + return false; + return true; +} - if (fDist > (CalcDiagonalLength() + fTolerance)) - return false; - else // hier genauerer Test - { - unsigned char i; - Vector3<_Precision> clVectRes; - - // schneide jede Seitenflaeche mit der Linie - for (i = 0; i < 6; i++) - { - - if (IntersectPlaneWithLine(i, rcBase, rcDir, clVectRes) == true) - { - // pruefe, ob Schnittpunkt innerhalb BB-Grenzen + Toleranz - switch (i) - { - case 0 : // linke und rechte Ebene - case 1 : - if ((IS_ON_RAY (MinY - fTolerance, MaxY + fTolerance, clVectRes.y) && - IS_ON_RAY (MinZ - fTolerance, MaxZ + fTolerance, clVectRes.z)) == true) - return true; - break; - case 2 : // obere und untere Ebene - case 3 : - if ((IS_ON_RAY (MinX - fTolerance, MaxX + fTolerance, clVectRes.x) && - IS_ON_RAY (MinZ - fTolerance, MaxZ + fTolerance, clVectRes.z))== true) - return true; - break; - case 4 : // vordere und hintere Ebene - case 5 : - if ((IS_ON_RAY (MinX - fTolerance, MaxX + fTolerance, clVectRes.x) && - IS_ON_RAY (MinY - fTolerance, MaxY + fTolerance, clVectRes.y)) == true) - return true; - break; - } - } - } - } - - return false; -} +template +inline bool BoundBox3<_Precision>::IsInBox (const BoundBox3<_Precision> &rcBB) const +{ + if (rcBB.MinX < this->MinX || rcBB.MaxX > this->MaxX) + return false; + if (rcBB.MinY < this->MinY || rcBB.MaxY > this->MaxY) + return false; + if (rcBB.MinZ < this->MinZ || rcBB.MaxZ > this->MaxZ) + return false; + return true; +} + +template +inline bool BoundBox3<_Precision>::IsInBox (const BoundBox2D &rcBB) const +{ + if (rcBB.fMinX < this->MinX || rcBB.fMaxX > this->MaxX) + return false; + if (rcBB.fMinY < this->MinY || rcBB.fMaxY > this->MaxY) + return false; + return true; +} template inline bool BoundBox3<_Precision>::IsValid (void) const { - return ((MinX <= MaxX) && (MinY <= MaxY) && (MinZ <= MaxZ)); + return ((MinX <= MaxX) && (MinY <= MaxY) && (MinZ <= MaxZ)); } -#define HALF(A,B) ((A)+((B-A)/2)) - template inline bool BoundBox3<_Precision>::GetOctantFromVector (const Vector3<_Precision> &rclVct, OCTANT &rclOctant) const { - if (!IsInBox (rclVct)) - return false; - - unsigned short usNdx = 0; - if (IS_ON_RAY (HALF (MinX, MaxX), MaxX, rclVct.x)) // left/RIGHT - usNdx |= 1; - if (IS_ON_RAY (HALF (MinY, MaxY), MaxY, rclVct.y)) // down/UP - usNdx |= 2; - if (IS_ON_RAY (HALF (MinZ, MaxZ), MaxZ, rclVct.z)) // back/FRONT - usNdx |= 4; - rclOctant = (OCTANT) usNdx; - return true; + if (!IsInBox (rclVct)) + return false; + + unsigned short usNdx = 0; + if (isOnRayS ((MinX + MaxX)/2, MaxX, rclVct.x)) // left/RIGHT + usNdx |= 1; + if (isOnRayS ((MinY + MaxY)/2, MaxY, rclVct.y)) // down/UP + usNdx |= 2; + if (isOnRayS ((MinZ + MaxZ)/2, MaxZ, rclVct.z)) // back/FRONT + usNdx |= 4; + rclOctant = (OCTANT) usNdx; + return true; } template inline BoundBox3<_Precision> BoundBox3<_Precision>::CalcOctant (typename BoundBox3< _Precision >::OCTANT Octant) const { - BoundBox3<_Precision> cOct (*this); + BoundBox3<_Precision> cOct (*this); - switch (Octant) - { + switch (Octant) { case OCT_LDB: - cOct.MaxX = HALF (cOct.MinX, cOct.MaxX); - cOct.MaxY = HALF (cOct.MinY, cOct.MaxY); - cOct.MaxZ = HALF (cOct.MinZ, cOct.MaxZ); - break; + cOct.MaxX = (cOct.MinX + cOct.MaxX)/2; + cOct.MaxY = (cOct.MinY + cOct.MaxY)/2; + cOct.MaxZ = (cOct.MinZ + cOct.MaxZ)/2; + break; case OCT_RDB: - cOct.MinX = HALF (cOct.MinX, cOct.MaxX); - cOct.MaxY = HALF (cOct.MinY, cOct.MaxY); - cOct.MaxZ = HALF (cOct.MinZ, cOct.MaxZ); - break; + cOct.MinX = (cOct.MinX + cOct.MaxX)/2; + cOct.MaxY = (cOct.MinY + cOct.MaxY)/2; + cOct.MaxZ = (cOct.MinZ + cOct.MaxZ)/2; + break; case OCT_LUB: - cOct.MaxX = HALF (cOct.MinX, cOct.MaxX); - cOct.MinY = HALF (cOct.MinY, cOct.MaxY); - cOct.MaxZ = HALF (cOct.MinZ, cOct.MaxZ); - break; + cOct.MaxX = (cOct.MinX + cOct.MaxX)/2; + cOct.MinY = (cOct.MinY + cOct.MaxY)/2; + cOct.MaxZ = (cOct.MinZ + cOct.MaxZ)/2; + break; case OCT_RUB: - cOct.MinX = HALF (cOct.MinX, cOct.MaxX); - cOct.MinY = HALF (cOct.MinY, cOct.MaxY); - cOct.MaxZ = HALF (cOct.MinZ, cOct.MaxZ); - break; + cOct.MinX = (cOct.MinX + cOct.MaxX)/2; + cOct.MinY = (cOct.MinY + cOct.MaxY)/2; + cOct.MaxZ = (cOct.MinZ + cOct.MaxZ)/2; + break; case OCT_LDF: - cOct.MaxX = HALF (cOct.MinX, cOct.MaxX); - cOct.MaxY = HALF (cOct.MinY, cOct.MaxY); - cOct.MinZ = HALF (cOct.MinZ, cOct.MaxZ); - break; + cOct.MaxX = (cOct.MinX + cOct.MaxX)/2; + cOct.MaxY = (cOct.MinY + cOct.MaxY)/2; + cOct.MinZ = (cOct.MinZ + cOct.MaxZ)/2; + break; case OCT_RDF: - cOct.MinX = HALF (cOct.MinX, cOct.MaxX); - cOct.MaxY = HALF (cOct.MinY, cOct.MaxY); - cOct.MinZ = HALF (cOct.MinZ, cOct.MaxZ); - break; + cOct.MinX = (cOct.MinX + cOct.MaxX)/2; + cOct.MaxY = (cOct.MinY + cOct.MaxY)/2; + cOct.MinZ = (cOct.MinZ + cOct.MaxZ)/2; + break; case OCT_LUF: - cOct.MaxX = HALF (cOct.MinX, cOct.MaxX); - cOct.MinY = HALF (cOct.MinY, cOct.MaxY); - cOct.MinZ = HALF (cOct.MinZ, cOct.MaxZ); - break; + cOct.MaxX = (cOct.MinX + cOct.MaxX)/2; + cOct.MinY = (cOct.MinY + cOct.MaxY)/2; + cOct.MinZ = (cOct.MinZ + cOct.MaxZ)/2; + break; case OCT_RUF: - cOct.MinX = HALF (cOct.MinX, cOct.MaxX); - cOct.MinY = HALF (cOct.MinY, cOct.MaxY); - cOct.MinZ = HALF (cOct.MinZ, cOct.MaxZ); - break; - } - return cOct; -} - -#undef HALF - -template -inline void BoundBox3<_Precision>::CalcPlane (unsigned short usPlane, Vector3<_Precision>& rBase, Vector3<_Precision>& rNormal ) const -{ - switch (usPlane) - { - //links - case 0: - rBase.Set(MinX, MinY, MaxZ); - rNormal.Set(1.0f, 0.0f, 0.0f); - break; - - // rechts - case 1: - rBase.Set(MaxX, MinY, MaxZ); - rNormal.Set(1.0f, 0.0f, 0.0f); - break; - - // oben - case 2: - rBase.Set(MinX, MaxY, MaxZ); - rNormal.Set(0.0f, 1.0f, 0.0f); - break; - - // unten - case 3: - rBase.Set(MinX, MinY, MaxZ); - rNormal.Set(0.0f, 1.0f, 0.0f); - break; - - // vorne - case 4: - rBase.Set(MinX, MinY, MaxZ); - rNormal.Set(0.0f, 0.0f, 1.0f); - break; - - // hinten - default: - rBase.Set(MinX, MinY, MinZ); - rNormal.Set(0.0f, 0.0f, 1.0f); - break; - } + cOct.MinX = (cOct.MinX + cOct.MaxX)/2; + cOct.MinY = (cOct.MinY + cOct.MaxY)/2; + cOct.MinZ = (cOct.MinZ + cOct.MaxZ)/2; + break; + } + return cOct; } template -inline bool BoundBox3<_Precision>::CalcDistance (unsigned short usEdge, Vector3<_Precision>& rcP0, Vector3<_Precision>& rcP1) const +inline Vector3<_Precision> BoundBox3<_Precision>::CalcPoint (unsigned short usPoint) const { - switch (usEdge) - { - case 0: - rcP0 = CalcPoint(0); - rcP1 = CalcPoint(1); - break; - case 1: - rcP0 = CalcPoint(1); - rcP1 = CalcPoint(2); - break; - case 2: - rcP0 = CalcPoint(2); - rcP1 = CalcPoint(3); - break; - case 3: - rcP0 = CalcPoint(3); - rcP1 = CalcPoint(0); - break; - case 4: - rcP0 = CalcPoint(4); - rcP1 = CalcPoint(5); - break; - case 5: - rcP0 = CalcPoint(5); - rcP1 = CalcPoint(6); - break; - case 6: - rcP0 = CalcPoint(6); - rcP1 = CalcPoint(7); - break; - case 7: - rcP0 = CalcPoint(7); - rcP1 = CalcPoint(4); - break; - case 8: - rcP0 = CalcPoint(0); - rcP1 = CalcPoint(4); - break; - case 9: - rcP0 = CalcPoint(1); - rcP1 = CalcPoint(5); - break; - case 10: - rcP0 = CalcPoint(2); - rcP1 = CalcPoint(6); - break; - case 11: - rcP0 = CalcPoint(3); - rcP1 = CalcPoint(7); - break; - default: - return false; // undefined - } + switch (usPoint) { + case 0: return Vector3<_Precision>(MinX, MinY, MaxZ); + case 1: return Vector3<_Precision>(MaxX, MinY, MaxZ); + case 2: return Vector3<_Precision>(MaxX, MaxY, MaxZ); + case 3: return Vector3<_Precision>(MinX, MaxY, MaxZ); + case 4: return Vector3<_Precision>(MinX, MinY, MinZ); + case 5: return Vector3<_Precision>(MaxX, MinY, MinZ); + case 6: return Vector3<_Precision>(MaxX, MaxY, MinZ); + case 7: return Vector3<_Precision>(MinX, MaxY, MinZ); + } - return true; + return Vector3<_Precision>(); +} + +template +inline void BoundBox3<_Precision>::CalcPlane (unsigned short usPlane, Vector3<_Precision>& rBase, Vector3<_Precision>& rNormal) const +{ + switch (usPlane) { + case LEFT: + rBase.Set(MinX, MinY, MaxZ); + rNormal.Set(1.0f, 0.0f, 0.0f); + break; + + case RIGHT: + rBase.Set(MaxX, MinY, MaxZ); + rNormal.Set(1.0f, 0.0f, 0.0f); + break; + + case TOP: + rBase.Set(MinX, MaxY, MaxZ); + rNormal.Set(0.0f, 1.0f, 0.0f); + break; + + case BOTTOM: + rBase.Set(MinX, MinY, MaxZ); + rNormal.Set(0.0f, 1.0f, 0.0f); + break; + + case FRONT: + rBase.Set(MinX, MinY, MaxZ); + rNormal.Set(0.0f, 0.0f, 1.0f); + break; + + case BACK: + rBase.Set(MinX, MinY, MinZ); + rNormal.Set(0.0f, 0.0f, 1.0f); + break; + default: + break; + } +} + +template +inline bool BoundBox3<_Precision>::CalcEdge (unsigned short usEdge, Vector3<_Precision>& rcP0, Vector3<_Precision>& rcP1) const +{ + switch (usEdge) { + case 0: + rcP0 = CalcPoint(0); + rcP1 = CalcPoint(1); + break; + case 1: + rcP0 = CalcPoint(1); + rcP1 = CalcPoint(2); + break; + case 2: + rcP0 = CalcPoint(2); + rcP1 = CalcPoint(3); + break; + case 3: + rcP0 = CalcPoint(3); + rcP1 = CalcPoint(0); + break; + case 4: + rcP0 = CalcPoint(4); + rcP1 = CalcPoint(5); + break; + case 5: + rcP0 = CalcPoint(5); + rcP1 = CalcPoint(6); + break; + case 6: + rcP0 = CalcPoint(6); + rcP1 = CalcPoint(7); + break; + case 7: + rcP0 = CalcPoint(7); + rcP1 = CalcPoint(4); + break; + case 8: + rcP0 = CalcPoint(0); + rcP1 = CalcPoint(4); + break; + case 9: + rcP0 = CalcPoint(1); + rcP1 = CalcPoint(5); + break; + case 10: + rcP0 = CalcPoint(2); + rcP1 = CalcPoint(6); + break; + case 11: + rcP0 = CalcPoint(3); + rcP1 = CalcPoint(7); + break; + default: + return false; // undefined + } + + return true; } template @@ -532,447 +624,372 @@ inline bool BoundBox3<_Precision>::IntersectionPoint (const Vector3<_Precision> } template -inline bool BoundBox3<_Precision>::IntersectPlaneWithLine (unsigned short usSide, const Vector3<_Precision>& rcBase, - const Vector3<_Precision>& rcDir, Vector3<_Precision>& rcP0) const +inline bool BoundBox3<_Precision>::IsCutLine (const Vector3<_Precision>& rcBase, const Vector3<_Precision>& rcDir, _Precision fTolerance) const { - _Precision k; - Vector3<_Precision> cBase, cNormal; - Vector3<_Precision> cDir(rcDir); - CalcPlane(usSide, cBase, cNormal); + _Precision fDist; - if ((cNormal * cDir) == 0.0f) - return false; // no point of intersection - else - { - k = (cNormal * (cBase - rcBase)) / (cNormal * cDir); - cDir.Scale(k, k, k); - rcP0 = rcBase + cDir; + // zuerst nur grobe und schnelle Pruefung, indem der + // Abstand der Linie zum Mittelpunkt der BB berechnet wird + // und mit der maximalen Diagonalenlaenge + fTolerance + // verglichen wird. - return true; - } + // Distanz zwischen Mittelpunkt und Linie + fDist = (rcDir % (GetCenter() - rcBase)).Length() / rcDir.Length(); + + if (fDist > (CalcDiagonalLength() + fTolerance)) { + return false; + } + else { // hier genauerer Test + unsigned char i; + Vector3<_Precision> clVectRes; + + // schneide jede Seitenflaeche mit der Linie + for (i = 0; i < 6; i++) { + if (IntersectPlaneWithLine(i, rcBase, rcDir, clVectRes)) { + // pruefe, ob Schnittpunkt innerhalb BB-Grenzen + Toleranz + switch (i) { + case LEFT : // linke und rechte Ebene + case RIGHT : + if ((isOnRayW (MinY - fTolerance, MaxY + fTolerance, clVectRes.y) && + isOnRayW (MinZ - fTolerance, MaxZ + fTolerance, clVectRes.z))) + return true; + break; + case TOP : // obere und untere Ebene + case BOTTOM : + if ((isOnRayW (MinX - fTolerance, MaxX + fTolerance, clVectRes.x) && + isOnRayW (MinZ - fTolerance, MaxZ + fTolerance, clVectRes.z))) + return true; + break; + case FRONT : // vordere und hintere Ebene + case BACK : + if ((isOnRayW (MinX - fTolerance, MaxX + fTolerance, clVectRes.x) && + isOnRayW (MinY - fTolerance, MaxY + fTolerance, clVectRes.y))) + return true; + break; + } + } + } + } + + return false; } template -inline bool BoundBox3<_Precision>::IntersectWithLine ( const Vector3<_Precision> & rcBase, const Vector3<_Precision>& rcDir, - Vector3<_Precision>& rcP0, Vector3<_Precision>& rcP1 ) const +inline bool BoundBox3<_Precision>::IsCutPlane (const Vector3<_Precision> &rclBase, const Vector3<_Precision> &rclNormal) const { - Vector3<_Precision> clVectRes, clVect[6]; - unsigned short i, j; - - j = 0; - // schneide jede Seitenflaeche mit der Linie - for (i = 0; i < 6; i++) - { + if (fabs(GetCenter().DistanceToPlane(rclBase, rclNormal)) < CalcDiagonalLength()) { + _Precision fD = CalcPoint(0).DistanceToPlane(rclBase, rclNormal); + for (unsigned short i = 1; i < 8; i++) { + if ((CalcPoint(i).DistanceToPlane(rclBase, rclNormal) * fD) <= 0.0f) + return true; + } + } + return false; +} - if ( IntersectPlaneWithLine(i, rcBase, rcDir, clVectRes ) ) - { - // pruefe, ob Schnittpunkt innerhalb BB-Grenzen - switch (i) - { - case 0 : // linke und rechte Ebene - case 1 : - if ((IS_ON_RAY(MinY, MaxY, clVectRes.y) && - IS_ON_RAY(MinZ, MaxZ, clVectRes.z)) == true) - { - clVect[j] = clVectRes; - j++; - } - break; - case 2 : // obere und untere Ebene - case 3 : - if ((IS_ON_RAY(MinX, MaxX, clVectRes.x) && - IS_ON_RAY(MinZ, MaxZ, clVectRes.z))== true) - { - clVect[j] = clVectRes; - j++; - } - break; - case 4 : // vordere und hintere Ebene - case 5 : - if ((IS_ON_RAY(MinX, MaxX, clVectRes.x) && - IS_ON_RAY(MinY, MaxY, clVectRes.y)) == true) - { - clVect[j] = clVectRes; - j++; - } - break; - } +template +inline bool BoundBox3<_Precision>::IntersectWithLine (const Vector3<_Precision> & rcBase, const Vector3<_Precision>& rcDir, + Vector3<_Precision>& rcP0, Vector3<_Precision>& rcP1) const +{ + Vector3<_Precision> clVectRes, clVect[6]; + + unsigned short numIntersect = 0; + // cut each face with the line + for (unsigned short i = 0; i < 6; i++) { + if (IntersectPlaneWithLine(i, rcBase, rcDir, clVectRes)) { + // check if intersection point is inside + switch (i) { + case LEFT : // left and right plane + case RIGHT : + if ((isOnRayS(MinY, MaxY, clVectRes.y) && + isOnRayS(MinZ, MaxZ, clVectRes.z))) { + clVect[numIntersect] = clVectRes; + numIntersect++; + } break; + case TOP : // top and bottom plane + case BOTTOM : + if ((isOnRayS(MinX, MaxX, clVectRes.x) && + isOnRayS(MinZ, MaxZ, clVectRes.z))) { + clVect[numIntersect] = clVectRes; + numIntersect++; + } break; + case FRONT : // front and back plane + case BACK : + if ((isOnRayS(MinX, MaxX, clVectRes.x) && + isOnRayS(MinY, MaxY, clVectRes.y))) { + clVect[numIntersect] = clVectRes; + numIntersect++; + } break; + } + } } - } - - if (j == 2) - { - rcP0 = clVect[0]; - rcP1 = clVect[1]; - return true; - } - else if (j > 2) // suche 2 unterschiedliche Schnittpunkte - { - for (i = 1; i < j; i++) - { - if (clVect[i] != clVect[0]) - { + + if (numIntersect == 2) { rcP0 = clVect[0]; - rcP1 = clVect[i]; + rcP1 = clVect[1]; + return true; + } + else if (numIntersect > 2) { // search two different intersection points + for (unsigned short i = 1; i < numIntersect; i++) { + if (clVect[i] != clVect[0]) { + rcP0 = clVect[0]; + rcP1 = clVect[i]; + return true; + } + } + } + + return false; +} + +template +inline bool BoundBox3<_Precision>::IntersectPlaneWithLine (unsigned short usSide, const Vector3<_Precision>& rcBase, + const Vector3<_Precision>& rcDir, Vector3<_Precision>& rcP0) const +{ + _Precision k; + Vector3<_Precision> cBase, cNormal; + Vector3<_Precision> cDir(rcDir); + CalcPlane(usSide, cBase, cNormal); + + if ((cNormal * cDir) == 0.0f) { + return false; // no point of intersection + } + else { + k = (cNormal * (cBase - rcBase)) / (cNormal * cDir); + cDir.Scale(k, k, k); + rcP0 = rcBase + cDir; return true; - } } - } - - return false; } template inline typename BoundBox3<_Precision>::SIDE BoundBox3<_Precision>::GetSideFromRay (const Vector3<_Precision> &rclPt, const Vector3<_Precision> &rclDir) const { - Vector3<_Precision> cIntersection; - return GetSideFromRay( rclPt, rclDir, cIntersection); + Vector3<_Precision> cIntersection; + return GetSideFromRay( rclPt, rclDir, cIntersection); } template inline typename BoundBox3<_Precision>::SIDE BoundBox3<_Precision>::GetSideFromRay (const Vector3<_Precision> &rclPt, const Vector3<_Precision> &rclDir, Vector3<_Precision>& rcInt) const { - Vector3<_Precision> cP0, cP1; - if ( IntersectWithLine(rclPt, rclDir, cP0, cP1) == false ) - return INVALID; + Vector3<_Precision> cP0, cP1; + if (IntersectWithLine(rclPt, rclDir, cP0, cP1) == false) + return INVALID; - Vector3<_Precision> cOut; - // same orientation - if ( (cP1-cP0)*rclDir > 0.0f ) - cOut = cP1; - else - cOut = cP0; + Vector3<_Precision> cOut; + // same orientation + if ((cP1-cP0)*rclDir > 0) + cOut = cP1; + else + cOut = cP0; - rcInt = cOut; + rcInt = cOut; - _Precision fMax = 1.0e-3f; - SIDE tSide = INVALID; + _Precision fMax = 1.0e-3f; + SIDE tSide = INVALID; - if (fabs(cOut.x - MinX) < fMax) // linke Ebene - { - fMax = _Precision(fabs(cOut.x - MinX)); - tSide = LEFT; - } + if (fabs(cOut.x - MinX) < fMax) { // left plane + fMax = _Precision(fabs(cOut.x - MinX)); + tSide = LEFT; + } - if (fabs(cOut.x - MaxX) < fMax) // rechte Ebene - { - fMax = _Precision(fabs(cOut.x - MaxX)); - tSide = RIGHT; - } + if (fabs(cOut.x - MaxX) < fMax) { // right plane + fMax = _Precision(fabs(cOut.x - MaxX)); + tSide = RIGHT; + } - if (fabs(cOut.y - MinY) < fMax) // untere Ebene - { - fMax = _Precision(fabs(cOut.y - MinY)); - tSide = BOTTOM; - } + if (fabs(cOut.y - MinY) < fMax) { // bottom plane + fMax = _Precision(fabs(cOut.y - MinY)); + tSide = BOTTOM; + } - if (fabs(cOut.y - MaxY) < fMax) // obere Ebene - { - fMax = _Precision(fabs(cOut.y - MaxY)); - tSide = TOP; - } + if (fabs(cOut.y - MaxY) < fMax) { // top plane + fMax = _Precision(fabs(cOut.y - MaxY)); + tSide = TOP; + } - if (fabs(cOut.z - MinZ) < fMax) // vordere Ebene - { - fMax = _Precision(fabs(cOut.z - MinZ)); - tSide = FRONT; - } + if (fabs(cOut.z - MinZ) < fMax) { // front plane + fMax = _Precision(fabs(cOut.z - MinZ)); + tSide = FRONT; + } - if (fabs(cOut.z - MaxZ) < fMax) // hintere Ebene - { - fMax = _Precision(fabs(cOut.z - MaxZ)); - tSide = BACK; - } + if (fabs(cOut.z - MaxZ) < fMax) { // back plane + fMax = _Precision(fabs(cOut.z - MaxZ)); + tSide = BACK; + } - return tSide; + return tSide; } template -inline void BoundBox3<_Precision>::Flush (void) +inline Vector3<_Precision> BoundBox3<_Precision>::ClosestPoint (const Vector3<_Precision> &rclPt) const { - MinX = MinY = MinZ = FLOAT_MAX; - MaxX = MaxY = MaxZ = -FLOAT_MAX; -} +#if 0 + // Get the nearest point of the bb, point MUST be inside the bb! + _Precision fMinDist = std::numeric_limits<_Precision>::max(); + Vector3<_Precision> cBase, cNormal, clRet; -template -inline void BoundBox3<_Precision>::Print (void) -{ - printf ("X1 : %5.2f Y1 : %5.2f Z1 : %5.2f\n", MinX, MinY, MinZ); - printf ("X2 : %5.2f Y2 : %5.2f Z2 : %5.2f\n", MaxX, MaxY, MaxZ); + for (int i = 0; i < 6; i++) { + Vector3<_Precision> clTemp = rclPt; + CalcPlane(i, cBase, cNormal); + clTemp.ProjToPlane(cBase, cNormal); + _Precision fDist = (clTemp - rclPt).Length(); + if (fDist < fMinDist) { + fMinDist = fDist; + clRet = clTemp; + } + } + + return clRet; +#else + Vector3<_Precision> closest = rclPt; + + Vector3<_Precision> center = GetCenter(); + _Precision devx = closest.x - center.x; + _Precision devy = closest.y - center.y; + _Precision devz = closest.z - center.z; + + _Precision halfwidth = (MaxX - MinX) / 2; + _Precision halfheight = (MaxY - MinY) / 2; + _Precision halfdepth = (MaxZ - MinZ) / 2; + + // Move point to be on the nearest plane of the box. + if ((fabs(devx) > fabs(devy)) && (fabs(devx) > fabs(devz))) + closest.x = center.x + halfwidth * ((devx < 0.0) ? -1.0 : 1.0); + else if (fabs(devy) > fabs(devz)) + closest.y = center.y + halfheight * ((devy < 0.0) ? -1.0 : 1.0); + else + closest.z = center.z + halfdepth * ((devz < 0.0) ? -1.0 : 1.0); + + // Clamp to be inside box. + closest.x = std::min<_Precision>(std::max<_Precision>(closest.x, MinX), MaxX); + closest.y = std::min<_Precision>(std::max<_Precision>(closest.y, MinY), MaxY); + closest.z = std::min<_Precision>(std::max<_Precision>(closest.z, MinZ), MaxZ); + + return closest; +#endif } template inline BoundBox2D BoundBox3<_Precision>::ProjectBox(const ViewProjMethod *pclP) const { - BoundBox2D clBB2D; + BoundBox2D clBB2D; + clBB2D.SetVoid(); - clBB2D.SetVoid(); + for (int i = 0; i < 8; i++) { + Vector3<_Precision> clTrsPt = (*pclP)(CalcPoint(i)); + clBB2D.Add(Vector2D(clTrsPt.x, clTrsPt.y)); + } - for (int i = 0; i < 8; i++) - { - Vector3<_Precision> clTrsPt = (*pclP)(CalcPoint(i)); - clBB2D &= Vector2D(clTrsPt.x, clTrsPt.y); - } - - return clBB2D; + return clBB2D; } template inline BoundBox3<_Precision> BoundBox3<_Precision>::Transformed(const Matrix4D& mat) const { - BoundBox3<_Precision> bbox; - for (int i=0; i<8; i++) - bbox.Add(mat * CalcPoint(i)); - return bbox; + BoundBox3<_Precision> bbox; + for (int i=0; i<8; i++) + bbox.Add(mat * CalcPoint(i)); + return bbox; } template -inline Vector3<_Precision> BoundBox3<_Precision>::NearestPoint (const Vector3<_Precision> &rclPt) const +inline Vector3<_Precision> BoundBox3<_Precision>::GetCenter (void) const { - // Suche naechsten Punkt auf der BB, !!! Punkt MUSS innerhalb BB liegen !!! - _Precision fMinDist = FLOAT_MAX; - Vector3<_Precision> cBase, cNormal, clRet; - - for (int i = 0; i < 6; i++) - { - Vector3<_Precision> clTemp = rclPt; - CalcPlane(i, cBase, cNormal); - clTemp.ProjToPlane(cBase, cNormal); - _Precision fDist = (clTemp - rclPt).Length(); - if (fDist < fMinDist) - { - fMinDist = fDist; - clRet = clTemp; - } - } - - return clRet; -} - - -template -inline BoundBox3<_Precision>::BoundBox3 (_Precision fMinX, _Precision fMinY, _Precision fMinZ, - _Precision fMaxX, _Precision fMaxY, _Precision fMaxZ) -: MinX(fMinX), MinY(fMinY), MinZ(fMinZ), - MaxX(fMaxX), MaxY(fMaxY), MaxZ(fMaxZ) -{ -} - -template -inline BoundBox3<_Precision>::BoundBox3 (const Vector3<_Precision> *pclVect, unsigned long ulCt) -: MinX(FLOAT_MAX), MinY(FLOAT_MAX), MinZ(FLOAT_MAX), - MaxX(-FLOAT_MAX), MaxY(-FLOAT_MAX), MaxZ(-FLOAT_MAX) -{ - const Vector3<_Precision> *pI, *pEnd = pclVect + ulCt; - for (pI = pclVect; pI < pEnd; ++pI) - { - MinX = std::min<_Precision>(MinX, pI->x); - MinY = std::min<_Precision>(MinY, pI->y); - MinZ = std::min<_Precision>(MinZ, pI->z); - MaxX = std::max<_Precision>(MaxX, pI->x); - MaxY = std::max<_Precision>(MaxY, pI->y); - MaxZ = std::max<_Precision>(MaxZ, pI->z); - } -} - -template -inline BoundBox3<_Precision>& BoundBox3<_Precision>::operator = (const BoundBox3<_Precision> &rcBound) -{ - MinX = rcBound.MinX; - MinY = rcBound.MinY; - MinZ = rcBound.MinZ; - MaxX = rcBound.MaxX; - MaxY = rcBound.MaxY; - MaxZ = rcBound.MaxZ; - return *this; -} - -template -inline BoundBox3<_Precision>& BoundBox3<_Precision>::operator &= (const Vector3<_Precision> &rclVect) -{ - MinX = std::min<_Precision>(MinX, rclVect.x); - MinY = std::min<_Precision>(MinY, rclVect.y); - MinZ = std::min<_Precision>(MinZ, rclVect.z); - MaxX = std::max<_Precision>(MaxX, rclVect.x); - MaxY = std::max<_Precision>(MaxY, rclVect.y); - MaxZ = std::max<_Precision>(MaxZ, rclVect.z); - return *this; -} - -template -inline bool BoundBox3<_Precision>::operator && (const BoundBox3<_Precision> &rcBB) const -{ - return (IS_ON_RAY (MinX, MaxX, rcBB.MinX) || - IS_ON_RAY (MinX, MaxX, rcBB.MaxX) || - IS_ON_RAY (rcBB.MinX, rcBB.MaxX, MinX) || - IS_ON_RAY (rcBB.MinX, rcBB.MaxX, MaxX)) && - (IS_ON_RAY (MinY, MaxY, rcBB.MinY) || - IS_ON_RAY (MinY, MaxY, rcBB.MaxY) || - IS_ON_RAY (rcBB.MinY, rcBB.MaxY, MinY) || - IS_ON_RAY (rcBB.MinY, rcBB.MaxY, MaxY)) && - (IS_ON_RAY (MinZ, MaxZ, rcBB.MinZ) || - IS_ON_RAY (MinZ, MaxZ, rcBB.MaxZ) || - IS_ON_RAY (rcBB.MinZ, rcBB.MaxZ, MinZ) || - IS_ON_RAY (rcBB.MinZ, rcBB.MaxZ, MaxZ)); -} - -template -inline bool BoundBox3<_Precision>::operator && (const BoundBox2D &rcBB) const -{ - return (IS_ON_RAY (MinX, MaxX, rcBB.fMinX) || - IS_ON_RAY (MinX, MaxX, rcBB.fMaxX) || - IS_ON_RAY (rcBB.fMinX, rcBB.fMaxX, MinX) || - IS_ON_RAY (rcBB.fMinX, rcBB.fMaxX, MaxX)) && - (IS_ON_RAY (MinY, MaxY, rcBB.fMinY) || - IS_ON_RAY (MinY, MaxY, rcBB.fMaxY) || - IS_ON_RAY (rcBB.fMinY, rcBB.fMaxY, MinY) || - IS_ON_RAY (rcBB.fMinY, rcBB.fMaxY, MaxY) ); -} - -template -inline Vector3<_Precision> BoundBox3<_Precision>::CalcPoint (unsigned short usPoint) const -{ - switch (usPoint) - { - case 0: return Vector3<_Precision>(MinX, MinY, MaxZ); - case 1: return Vector3<_Precision>(MaxX, MinY, MaxZ); - case 2: return Vector3<_Precision>(MaxX, MaxY, MaxZ); - case 3: return Vector3<_Precision>(MinX, MaxY, MaxZ); - case 4: return Vector3<_Precision>(MinX, MinY, MinZ); - case 5: return Vector3<_Precision>(MaxX, MinY, MinZ); - case 6: return Vector3<_Precision>(MaxX, MaxY, MinZ); - case 7: return Vector3<_Precision>(MinX, MaxY, MinZ); - } - - return Vector3<_Precision>(); -} - -template -inline Vector3<_Precision> BoundBox3<_Precision>::CalcCenter (void) const -{ - return Vector3<_Precision>(MinX + (MaxX - MinX) / 2.0f, - MinY + (MaxY - MinY) / 2.0f, - MinZ + (MaxZ - MinZ) / 2.0f); + return Vector3<_Precision>((MaxX + MinX) / 2, + (MaxY + MinY) / 2, + (MaxZ + MinZ) / 2); } template inline _Precision BoundBox3<_Precision>::CalcDiagonalLength (void) const { - return (_Precision)sqrt (((MaxX - MinX) * (MaxX - MinX)) + - ((MaxY - MinY) * (MaxY - MinY)) + - ((MaxZ - MinZ) * (MaxZ - MinZ))); + return static_cast<_Precision>(sqrt (((MaxX - MinX) * (MaxX - MinX)) + + ((MaxY - MinY) * (MaxY - MinY)) + + ((MaxZ - MinZ) * (MaxZ - MinZ)))); } template -inline bool BoundBox3<_Precision>::IsCutPlane (const Vector3<_Precision> &rclBase, const Vector3<_Precision> &rclNormal) const +inline void BoundBox3<_Precision>::SetVoid (void) { - if (fabs(CalcCenter().DistanceToPlane(rclBase, rclNormal)) < CalcDiagonalLength()) - { - _Precision fD = CalcPoint(0).DistanceToPlane(rclBase, rclNormal); - for (unsigned short i = 1; i < 8; i++) - { - if ((CalcPoint(i).DistanceToPlane(rclBase, rclNormal) * fD) < 0.0f) - return true; - } - } - return false; + MinX = MinY = MinZ = std::numeric_limits<_Precision>::max(); + MaxX = MaxY = MaxZ = -std::numeric_limits<_Precision>::max(); } template inline void BoundBox3<_Precision>::Enlarge (_Precision fLen) { - MinX -= fLen; MinY -= fLen; MinZ -= fLen; - MaxX += fLen; MaxY += fLen; MaxZ += fLen; + MinX -= fLen; MinY -= fLen; MinZ -= fLen; + MaxX += fLen; MaxY += fLen; MaxZ += fLen; } template inline void BoundBox3<_Precision>::Shrink (_Precision fLen) { - MinX += fLen; MinY += fLen; MinZ += fLen; - MaxX -= fLen; MaxY -= fLen; MaxZ -= fLen; -} - -template -inline bool BoundBox3<_Precision>::IsInBox (const Vector3<_Precision> &rcVct) const -{ - return (IS_ON_RAY (MinX, MaxX, rcVct.x) && - IS_ON_RAY (MinY, MaxY, rcVct.y) && - IS_ON_RAY (MinZ, MaxZ, rcVct.z)); -} - -template -inline bool BoundBox3<_Precision>::IsInBox (const BoundBox3<_Precision> &rcBB) const -{ - return (IS_ON_RAY (MinX, MaxX, rcBB.MinX) && - IS_ON_RAY (MinX, MaxX, rcBB.MaxX) && - IS_ON_RAY (MinY, MaxY, rcBB.MinY) && - IS_ON_RAY (MinY, MaxY, rcBB.MaxY) && - IS_ON_RAY (MinZ, MaxZ, rcBB.MinZ) && - IS_ON_RAY (MinZ, MaxZ, rcBB.MaxZ)); -} - -template -inline bool BoundBox3<_Precision>::IsInBox (const BoundBox2D &rcBB) const -{ - return ( IS_ON_RAY (MinX, MaxX, rcBB.fMinX) && - IS_ON_RAY (MinX, MaxX, rcBB.fMaxX) && - IS_ON_RAY (MinY, MaxY, rcBB.fMinY) && - IS_ON_RAY (MinY, MaxY, rcBB.fMaxY) ); + MinX += fLen; MinY += fLen; MinZ += fLen; + MaxX -= fLen; MaxY -= fLen; MaxZ -= fLen; } template inline _Precision BoundBox3<_Precision>::LengthX (void) const { - return MaxX - MinX; + return MaxX - MinX; } template inline _Precision BoundBox3<_Precision>::LengthY (void) const { - return MaxY - MinY; + return MaxY - MinY; } template inline _Precision BoundBox3<_Precision>::LengthZ (void) const { - return MaxZ - MinZ; + return MaxZ - MinZ; } template inline void BoundBox3<_Precision>::MoveX (_Precision f) { - MinX += f; MaxX += f; + MinX += f; MaxX += f; } template inline void BoundBox3<_Precision>::MoveY (_Precision f) { - MinY += f; MaxY += f; + MinY += f; MaxY += f; } template inline void BoundBox3<_Precision>::MoveZ (_Precision f) { - MinZ += f; MaxZ += f; + MinZ += f; MaxZ += f; } template inline void BoundBox3<_Precision>::ScaleX (_Precision f) { - MinX *= f; MaxX *= f; + MinX *= f; MaxX *= f; } template inline void BoundBox3<_Precision>::ScaleY (_Precision f) { - MinY *= f; MaxY *= f; + MinY *= f; MaxY *= f; } template inline void BoundBox3<_Precision>::ScaleZ (_Precision f) { - MinZ *= f; MaxZ *= f; + MinZ *= f; MaxZ *= f; +} + +template +inline void BoundBox3<_Precision>::Print (std::ostream& out) const +{ + out << "X1 : " << MinX << " Y1 : " << MinY << " Z1 : " << MinZ << std::endl; + out << "X2 : " << MaxX << " Y2 : " << MaxY << " Z2 : " << MaxZ << std::endl; } typedef BoundBox3 BoundBox3f; @@ -980,6 +997,17 @@ typedef BoundBox3 BoundBox3d; } // namespace Base +inline std::ostream& operator << (std::ostream& out, const Base::BoundBox3f& bb) +{ + bb.Print(out); + return out; +} + +inline std::ostream& operator << (std::ostream& out, const Base::BoundBox3d& bb) +{ + bb.Print(out); + return out; +} #endif // BASE_BOUNDBOX_H diff --git a/src/Base/BoundBoxPy.xml b/src/Base/BoundBoxPy.xml index afa16c55f..43f3c7ca2 100644 --- a/src/Base/BoundBoxPy.xml +++ b/src/Base/BoundBoxPy.xml @@ -27,22 +27,68 @@ App.BoundBox(Vector, Vector) App.BoundBox(BoundBox) + + + method setVoid() +Invalidate the bounding box + + + + + method isValid() +Checks if the bounding box is valid + + method add(BoundBox) Add (enlarge) the given BoundBox - + - method isIntersection(Vector|BoundBox|Vector Base, Vector Dir) + method getPoint(Int) +Get the point of the given index. The index must be in the range of [0,7] + + + + + + method getEdge(Int) +Get the edge points of the given index. The index must be in the range of [0,11] + + + + + + method closestPoint(Vector) +Get the closest point of the bounding box to the given point + + + + + + method intersect(BoundBox|Vector Base, Vector Dir) Checks if the given object intersects with the BoundBox. That can be: -- A Vector (Point) - Another BoundBox - A line, specified by Base and Dir + + + method intersected(BoundBox) +Returns the intersection of this and the given bounding box. + + + + + + method united(BoundBox) +Returns the union of this and the given bounding box. + + + method enlarge(Float) @@ -62,11 +108,25 @@ exception is thrown. - method getIntersectionPoint(Vector) + method move(Vector) Move the BoundBox by the given vector + + + method scale(x,y,z) +Scale the BoundBox by the given values in x, y and z + + + + + + method transformed(Matrix) +Return a new bounding box with the transformed corner of this bounding box + + + method bool isCutPlane(Vector Base, Vector Normal) diff --git a/src/Base/BoundBoxPyImp.cpp b/src/Base/BoundBoxPyImp.cpp index d78f11418..de0b12e7b 100644 --- a/src/Base/BoundBoxPyImp.cpp +++ b/src/Base/BoundBoxPyImp.cpp @@ -26,6 +26,7 @@ #include "Base/BoundBox.h" // inclusion of the generated files (generated out of BoundBoxPy.xml) +#include "MatrixPy.h" #include "VectorPy.h" #include "GeometryPyCXX.h" #include "BoundBoxPy.h" @@ -104,6 +105,23 @@ int BoundBoxPy::PyInit(PyObject* args, PyObject* /*kwd*/) return -1; } +PyObject* BoundBoxPy::setVoid(PyObject *args) +{ + if (!PyArg_ParseTuple(args,"")) + return 0; + + getBoundBoxPtr()->SetVoid(); + Py_Return; +} + +PyObject* BoundBoxPy::isValid(PyObject *args) +{ + if (!PyArg_ParseTuple(args,"")) + return 0; + + return PyBool_FromLong(getBoundBoxPtr()->IsValid() ? 1 : 0); +} + PyObject* BoundBoxPy::add(PyObject *args) { double x,y,z; @@ -135,42 +153,150 @@ PyObject* BoundBoxPy::add(PyObject *args) return 0; } -PyObject* BoundBoxPy::isIntersection(PyObject *args) +PyObject* BoundBoxPy::getPoint(PyObject *args) { - double x,y,z; - PyObject *object,*object2; - Py::Boolean retVal; - if (PyArg_ParseTuple(args, "ddd", &x,&y,&z)) { - retVal = getBoundBoxPtr()->IsInBox(Vector3d(x,y,z)); - } - else if (PyArg_ParseTuple(args,"O!",&PyTuple_Type, &object)) { - PyErr_Clear(); - retVal = getBoundBoxPtr()->IsInBox(getVectorFromTuple(object)); - } - else if (PyArg_ParseTuple(args,"O!",&(Base::VectorPy::Type), &object)) { - PyErr_Clear(); - retVal = getBoundBoxPtr()->IsInBox(*(static_cast(object)->getVectorPtr())); - } - else if (PyArg_ParseTuple(args,"O!O!",&(Base::VectorPy::Type), &object, - &(Base::VectorPy::Type), &object2)) { - PyErr_Clear(); - retVal = getBoundBoxPtr()->IsCutLine( - *(static_cast(object )->getVectorPtr()), - *(static_cast(object2)->getVectorPtr())); - } - else if (PyArg_ParseTuple(args,"O!;Need vector, bounding box or three floats as argument", - &(Base::BoundBoxPy::Type), &object)) { - PyErr_Clear(); - retVal = getBoundBoxPtr()->IsInBox(*(static_cast(object)->getBoundBoxPtr())); - } - else { - PyErr_SetString(PyExc_TypeError, "Either three floats, Vector(s) or BoundBox expected"); + int index; + if (!PyArg_ParseTuple(args,"i",&index)) + return 0; + + if (index < 0 || index > 7) { + PyErr_SetString (PyExc_IndexError, "Invalid bounding box"); return 0; } + Base::Vector3d pnt = getBoundBoxPtr()->CalcPoint(index); + return new Base::VectorPy(new Base::Vector3d(pnt)); +} + +PyObject* BoundBoxPy::getEdge(PyObject *args) +{ + int index; + if (!PyArg_ParseTuple(args,"i",&index)) + return 0; + + if (index < 0 || index > 11) { + PyErr_SetString (PyExc_IndexError, "Invalid bounding box"); + return 0; + } + + Base::Vector3d pnt1, pnt2; + getBoundBoxPtr()->CalcEdge(index, pnt1, pnt2); + Py::Tuple tuple(2); + tuple.setItem(0, Py::Vector(pnt1)); + tuple.setItem(1, Py::Vector(pnt2)); + return Py::new_reference_to(tuple); +} + +PyObject* BoundBoxPy::closestPoint(PyObject *args) +{ + double x,y,z; + PyObject *object; + + Base::Vector3d vec; + + do { + if (PyArg_ParseTuple(args, "ddd", &x,&y,&z)) { + vec = Vector3d(x,y,z); + break; + } + + PyErr_Clear(); + if (PyArg_ParseTuple(args,"O!",&PyTuple_Type, &object)) { + vec = getVectorFromTuple(object); + break; + } + + PyErr_Clear(); + if (PyArg_ParseTuple(args,"O!",&(Base::VectorPy::Type), &object)) { + vec = *(static_cast(object)->getVectorPtr()); + break; + } + else { + PyErr_SetString(PyExc_TypeError, "Either three floats or vector expected"); + return 0; + } + } + while(false); + + Base::Vector3d point = getBoundBoxPtr()->ClosestPoint(vec); + return new Base::VectorPy(new Base::Vector3d(point)); +} + +PyObject* BoundBoxPy::intersect(PyObject *args) +{ + PyObject *object,*object2; + Py::Boolean retVal; + + if (!getBoundBoxPtr()->IsValid()) { + PyErr_SetString (PyExc_FloatingPointError, "Invalid bounding box"); + return 0; + } + + do { + if (PyArg_ParseTuple(args,"O!O!",&(Base::VectorPy::Type), &object, + &(Base::VectorPy::Type), &object2)) { + retVal = getBoundBoxPtr()->IsCutLine( + *(static_cast(object )->getVectorPtr()), + *(static_cast(object2)->getVectorPtr())); + break; + } + + PyErr_Clear(); + if (PyArg_ParseTuple(args,"O!",&(Base::BoundBoxPy::Type), &object)) { + if (!static_cast(object)->getBoundBoxPtr()->IsValid()) { + PyErr_SetString (PyExc_FloatingPointError, "Invalid bounding box argument"); + return 0; + } + retVal = getBoundBoxPtr()->Intersect(*(static_cast(object)->getBoundBoxPtr())); + break; + } + + PyErr_SetString(PyExc_TypeError, "Either BoundBox or two Vectors expected"); + return 0; + } + while(false); + return Py::new_reference_to(retVal); } +PyObject* BoundBoxPy::intersected(PyObject *args) +{ + if (!getBoundBoxPtr()->IsValid()) { + PyErr_SetString (PyExc_FloatingPointError, "Invalid bounding box"); + return 0; + } + + PyObject *object; + if (!PyArg_ParseTuple(args,"O!",&(Base::BoundBoxPy::Type), &object)) + return 0; + if (!static_cast(object)->getBoundBoxPtr()->IsValid()) { + PyErr_SetString (PyExc_FloatingPointError, "Invalid bounding box argument"); + return 0; + } + + Base::BoundBox3d bbox = getBoundBoxPtr()->Intersected(*static_cast(object)->getBoundBoxPtr()); + return new Base::BoundBoxPy(new Base::BoundBox3d(bbox)); +} + +PyObject* BoundBoxPy::united(PyObject *args) +{ + if (!getBoundBoxPtr()->IsValid()) { + PyErr_SetString (PyExc_FloatingPointError, "Invalid bounding box"); + return 0; + } + + PyObject *object; + if (!PyArg_ParseTuple(args,"O!",&(Base::BoundBoxPy::Type), &object)) + return 0; + if (!static_cast(object)->getBoundBoxPtr()->IsValid()) { + PyErr_SetString (PyExc_FloatingPointError, "Invalid bounding box argument"); + return 0; + } + + Base::BoundBox3d bbox = getBoundBoxPtr()->United(*static_cast(object)->getBoundBoxPtr()); + return new Base::BoundBoxPy(new Base::BoundBox3d(bbox)); +} + PyObject* BoundBoxPy::enlarge(PyObject *args) { double s; @@ -191,7 +317,6 @@ PyObject* BoundBoxPy::getIntersectionPoint(PyObject *args) *(static_cast(object)->getVectorPtr()), *(static_cast(object2)->getVectorPtr()), point, epsilon); - // IsInBox() doesn't handle border points correctly if (ok) { return new VectorPy(point); } @@ -206,26 +331,34 @@ PyObject* BoundBoxPy::getIntersectionPoint(PyObject *args) PyObject* BoundBoxPy::move(PyObject *args) { - double x,y,z; + double x,y,z; PyObject *object; Base::Vector3d vec; - if (PyArg_ParseTuple(args, "ddd", &x,&y,&z)) { - vec = Vector3d(x,y,z); - } - else if (PyArg_ParseTuple(args,"O!:Need vector to move",&PyTuple_Type, &object)) { + do { + if (PyArg_ParseTuple(args, "ddd", &x,&y,&z)) { + vec = Vector3d(x,y,z); + break; + } + PyErr_Clear(); - vec = getVectorFromTuple(object); - } - else if (PyArg_ParseTuple(args,"O!:Need vector to move",&(Base::VectorPy::Type), &object)) { + if (PyArg_ParseTuple(args,"O!:Need vector to move",&PyTuple_Type, &object)) { + vec = getVectorFromTuple(object); + break; + } + PyErr_Clear(); - vec = *(static_cast(object)->getVectorPtr()); - } - else { - PyErr_SetString(PyExc_TypeError, "Either three floats or vector expected"); - return 0; + if (PyArg_ParseTuple(args,"O!:Need vector to move",&(Base::VectorPy::Type), &object)) { + vec = *(static_cast(object)->getVectorPtr()); + break; + } + else { + PyErr_SetString(PyExc_TypeError, "Either three floats or vector expected"); + return 0; + } } + while(false); getBoundBoxPtr()->MoveX(vec.x); getBoundBoxPtr()->MoveY(vec.y); @@ -234,11 +367,67 @@ PyObject* BoundBoxPy::move(PyObject *args) Py_Return; } +PyObject* BoundBoxPy::scale(PyObject *args) +{ + double x,y,z; + PyObject *object; + + Base::Vector3d vec; + + do { + if (PyArg_ParseTuple(args, "ddd", &x,&y,&z)) { + vec = Vector3d(x,y,z); + break; + } + + PyErr_Clear(); + if (PyArg_ParseTuple(args,"O!:Need vector to scale",&PyTuple_Type, &object)) { + vec = getVectorFromTuple(object); + break; + } + + PyErr_Clear(); + if (PyArg_ParseTuple(args,"O!:Need vector to scale",&(Base::VectorPy::Type), &object)) { + vec = *(static_cast(object)->getVectorPtr()); + break; + } + else { + PyErr_SetString(PyExc_TypeError, "Either three floats or vector expected"); + return 0; + } + } + while(false); + + getBoundBoxPtr()->ScaleX(vec.x); + getBoundBoxPtr()->ScaleY(vec.y); + getBoundBoxPtr()->ScaleZ(vec.z); + + Py_Return; +} + +PyObject* BoundBoxPy::transformed(PyObject *args) +{ + PyObject *mat; + + if (!PyArg_ParseTuple(args,"O!", &(Base::MatrixPy::Type), &mat)) + return 0; + + if (!getBoundBoxPtr()->IsValid()) + throw Py::FloatingPointError("Cannot transform invalid bounding box"); + Base::BoundBox3d bbox = getBoundBoxPtr()->Transformed(*static_cast(mat)->getMatrixPtr()); + return new Base::BoundBoxPy(new Base::BoundBox3d(bbox)); +} + PyObject* BoundBoxPy::isCutPlane(PyObject *args) { PyObject *object,*object2; Py::Boolean retVal; + if (!getBoundBoxPtr()->IsValid()) { + PyErr_SetString (PyExc_FloatingPointError, "Invalid bounding box"); + return 0; + } + if (PyArg_ParseTuple(args,"O!O!:Need base and normal vector of a plane", &(Base::VectorPy::Type), &object,&(Base::VectorPy::Type), &object2)) retVal = getBoundBoxPtr()->IsCutPlane( @@ -252,30 +441,54 @@ PyObject* BoundBoxPy::isCutPlane(PyObject *args) PyObject* BoundBoxPy::isInside(PyObject *args) { + double x,y,z; PyObject *object; Py::Boolean retVal; - if (!PyArg_ParseTuple(args,"O", &object)) - return 0; - if (PyObject_TypeCheck(object, &(Base::VectorPy::Type))) { - Base::VectorPy *vec = static_cast(object); - retVal = getBoundBoxPtr()->IsInBox(*vec->getVectorPtr()); - } - else if (PyObject_TypeCheck(object, &(Base::BoundBoxPy::Type))) { - Base::BoundBoxPy *box = static_cast(object); - retVal = getBoundBoxPtr()->IsInBox(*box->getBoundBoxPtr()); - } - else { - PyErr_SetString(PyExc_TypeError, "Either a Vector or BoundBox object expected"); + if (!getBoundBoxPtr()->IsValid()) { + PyErr_SetString (PyExc_FloatingPointError, "Invalid bounding box"); return 0; } + do { + if (PyArg_ParseTuple(args, "ddd", &x,&y,&z)) { + retVal = getBoundBoxPtr()->IsInBox(Vector3d(x,y,z)); + break; + } + + PyErr_Clear(); + if (PyArg_ParseTuple(args,"O!",&PyTuple_Type, &object)) { + retVal = getBoundBoxPtr()->IsInBox(getVectorFromTuple(object)); + break; + } + + PyErr_Clear(); + if (PyArg_ParseTuple(args,"O!",&(Base::VectorPy::Type), &object)) { + retVal = getBoundBoxPtr()->IsInBox(*(static_cast(object)->getVectorPtr())); + break; + } + + PyErr_Clear(); + if (PyArg_ParseTuple(args,"O!",&(Base::BoundBoxPy::Type), &object)) { + if (!static_cast(object)->getBoundBoxPtr()->IsValid()) { + PyErr_SetString (PyExc_FloatingPointError, "Invalid bounding box argument"); + return 0; + } + retVal = getBoundBoxPtr()->IsInBox(*(static_cast(object)->getBoundBoxPtr())); + break; + } + + PyErr_SetString(PyExc_TypeError, "Either three floats, Vector(s) or BoundBox expected"); + return 0; + } + while(false); + return Py::new_reference_to(retVal); } Py::Object BoundBoxPy::getCenter(void) const { - return Py::Vector(getBoundBoxPtr()->CalcCenter()); + return Py::Vector(getBoundBoxPtr()->GetCenter()); } Py::Float BoundBoxPy::getXMax(void) const @@ -355,6 +568,8 @@ Py::Float BoundBoxPy::getZLength(void) const Py::Float BoundBoxPy::getDiagonalLength(void) const { + if (!getBoundBoxPtr()->IsValid()) + throw Py::FloatingPointError("Cannot deterine diagonal length of invalid bounding box"); return Py::Float(getBoundBoxPtr()->CalcDiagonalLength()); } diff --git a/src/Base/PreCompiled.h b/src/Base/PreCompiled.h index 68e61c0b3..8dda7676a 100644 --- a/src/Base/PreCompiled.h +++ b/src/Base/PreCompiled.h @@ -46,6 +46,7 @@ #ifdef FC_OS_WIN32 #include #define WIN32_LEAN_AND_MEAN +#define NOMINMAX #include #include #include diff --git a/src/Base/Tools2D.h b/src/Base/Tools2D.h index b61a8981c..7f56d2dfc 100644 --- a/src/Base/Tools2D.h +++ b/src/Base/Tools2D.h @@ -92,7 +92,7 @@ public: bool operator|| (const Line2D &rclLine) const; bool operator|| (const BoundBox2D &rclBB) const; bool operator|| (const Polygon2D &rclPoly) const; - inline void operator &= (const Vector2D &rclVct); + inline void Add(const Vector2D &rclVct); void SetVoid (void) { fMinX = fMinY = DOUBLE_MAX; fMaxX = fMaxY = -DOUBLE_MAX; } @@ -164,14 +164,6 @@ private: /** INLINES ********************************************/ -inline void BoundBox2D::operator &= (const Vector2D &rclVct) -{ - fMinX = std::min(fMinX, rclVct.fX); - fMinY = std::min(fMinY, rclVct.fY); - fMaxX = std::max(fMaxX, rclVct.fX); - fMaxY = std::max(fMaxY, rclVct.fY); -} - inline Vector2D::Vector2D (void) : fX(0.0), fY(0.0) { @@ -380,6 +372,14 @@ inline bool BoundBox2D::operator== (const BoundBox2D& rclBB) const (fMaxY == rclBB.fMaxY); } +inline void BoundBox2D::Add(const Vector2D &rclVct) +{ + fMinX = std::min(fMinX, rclVct.fX); + fMinY = std::min(fMinY, rclVct.fY); + fMaxX = std::max(fMaxX, rclVct.fX); + fMaxY = std::max(fMaxY, rclVct.fY); +} + } // namespace Base #endif // BASE_TOOLS2D_H diff --git a/src/Gui/CommandView.cpp b/src/Gui/CommandView.cpp index c6d525538..4ea0710dc 100644 --- a/src/Gui/CommandView.cpp +++ b/src/Gui/CommandView.cpp @@ -2182,7 +2182,7 @@ static void selectionCallback(void * ud, SoEventCallback * cb) App::PropertyGeometry* prop = static_cast(*jt); Base::BoundBox3d bbox = prop->getBoundingBox(); Base::Vector3d pt2d; - pt2d = proj(bbox.CalcCenter()); + pt2d = proj(bbox.GetCenter()); if (polygon.Contains(Base::Vector2D(pt2d.x, pt2d.y))) { Gui::Selection().addSelection(doc->getName(), (*it)->getNameInDocument()); } diff --git a/src/Gui/GLPainter.h b/src/Gui/GLPainter.h index 256c2f4e4..f297fe725 100644 --- a/src/Gui/GLPainter.h +++ b/src/Gui/GLPainter.h @@ -25,6 +25,7 @@ #define GUI_GLPAINTER_H #ifdef FC_OS_WIN32 +#define NOMINMAX #include #endif #ifdef FC_OS_MACOSX diff --git a/src/Gui/SoFCSelection.h b/src/Gui/SoFCSelection.h index 96aefd944..656f3ccdf 100644 --- a/src/Gui/SoFCSelection.h +++ b/src/Gui/SoFCSelection.h @@ -27,6 +27,7 @@ # include # else # ifdef FC_OS_WIN32 +# define NOMINMAX # include # endif # include diff --git a/src/Gui/SoFCUnifiedSelection.h b/src/Gui/SoFCUnifiedSelection.h index acada3ff0..894ab1c8c 100644 --- a/src/Gui/SoFCUnifiedSelection.h +++ b/src/Gui/SoFCUnifiedSelection.h @@ -27,6 +27,7 @@ # include # else # ifdef FC_OS_WIN32 +# define NOMINMAX # include # endif # include diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index d29ed0750..c31bb1c12 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -4624,7 +4624,7 @@ class _Shape2DView(_DraftObject): if cutv: if sh.Volume < 0: sh.reverse() - #if cutv.BoundBox.isIntersection(sh.BoundBox): + #if cutv.BoundBox.intersect(sh.BoundBox): # c = sh.cut(cutv) #else: # c = sh.copy() diff --git a/src/Mod/Draft/DraftGeomUtils.py b/src/Mod/Draft/DraftGeomUtils.py index 2391a2f80..fb74b7f2c 100755 --- a/src/Mod/Draft/DraftGeomUtils.py +++ b/src/Mod/Draft/DraftGeomUtils.py @@ -284,7 +284,7 @@ def findIntersection(edge1,edge2,infinite1=False,infinite2=False,ex1=False,ex2=F # First, try to use distToShape if possible if dts and isinstance(edge1,Part.Edge) and isinstance(edge2,Part.Edge) \ and (not infinite1) and (not infinite2) and \ - edge1.BoundBox.isIntersection(edge2.BoundBox): + edge1.BoundBox.intersect(edge2.BoundBox): dist, pts, geom = edge1.distToShape(edge2) sol = [] for p in pts: diff --git a/src/Mod/Drawing/Gui/TaskOrthoViews.cpp b/src/Mod/Drawing/Gui/TaskOrthoViews.cpp index 8098dcb25..91154e8ae 100644 --- a/src/Mod/Drawing/Gui/TaskOrthoViews.cpp +++ b/src/Mod/Drawing/Gui/TaskOrthoViews.cpp @@ -142,9 +142,9 @@ orthoview::orthoview(App::Document * parent, App::DocumentObject * part, App::Do parent_doc = parent; myname = parent_doc->getUniqueObjectName("Ortho"); - cx = partbox->CalcCenter().x; - cy = partbox->CalcCenter().y; - cz = partbox->CalcCenter().z; + cx = partbox->GetCenter().x; + cy = partbox->GetCenter().y; + cz = partbox->GetCenter().z; this_view = static_cast (parent_doc->addObject("Drawing::FeatureViewPart", myname.c_str())); static_cast(page)->addObject(this_view); diff --git a/src/Mod/Drawing/Gui/ViewProviderPage.cpp b/src/Mod/Drawing/Gui/ViewProviderPage.cpp index f6d4cd32f..c0f088137 100644 --- a/src/Mod/Drawing/Gui/ViewProviderPage.cpp +++ b/src/Mod/Drawing/Gui/ViewProviderPage.cpp @@ -24,9 +24,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# ifdef FC_OS_WIN32 -# include -# endif # include # include # include diff --git a/src/Mod/Drawing/Gui/ViewProviderView.cpp b/src/Mod/Drawing/Gui/ViewProviderView.cpp index 52d2606ce..2eb3b0ad8 100644 --- a/src/Mod/Drawing/Gui/ViewProviderView.cpp +++ b/src/Mod/Drawing/Gui/ViewProviderView.cpp @@ -24,9 +24,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# ifdef FC_OS_WIN32 -# include -# endif #endif /// Here the FreeCAD includes sorted by Base,App,Gui...... diff --git a/src/Mod/Inspection/App/InspectionFeature.cpp b/src/Mod/Inspection/App/InspectionFeature.cpp index f8cd42774..cdebaae2f 100644 --- a/src/Mod/Inspection/App/InspectionFeature.cpp +++ b/src/Mod/Inspection/App/InspectionFeature.cpp @@ -182,9 +182,9 @@ namespace Inspection { unsigned long ulX1, ulY1, ulZ1, ulX2, ulY2, ulZ2; Base::BoundBox3f clBB; - clBB &= rclFacet._aclPoints[0]; - clBB &= rclFacet._aclPoints[1]; - clBB &= rclFacet._aclPoints[2]; + clBB.Add(rclFacet._aclPoints[0]); + clBB.Add(rclFacet._aclPoints[1]); + clBB.Add(rclFacet._aclPoints[2]); Pos(Base::Vector3f(clBB.MinX,clBB.MinY,clBB.MinZ), ulX1, ulY1, ulZ1); Pos(Base::Vector3f(clBB.MaxX,clBB.MaxY,clBB.MaxZ), ulX2, ulY2, ulZ2); diff --git a/src/Mod/Inspection/Gui/PreCompiled.h b/src/Mod/Inspection/Gui/PreCompiled.h index 0379531be..1ccb50dc4 100644 --- a/src/Mod/Inspection/Gui/PreCompiled.h +++ b/src/Mod/Inspection/Gui/PreCompiled.h @@ -39,6 +39,10 @@ # define InspectionGuiExport #endif +#ifdef FC_OS_WIN32 +# define NOMINMAX +#endif + #ifdef _PreComp_ // standard diff --git a/src/Mod/Mesh/App/Core/Algorithm.cpp b/src/Mod/Mesh/App/Core/Algorithm.cpp index aec610185..35d3710e2 100644 --- a/src/Mod/Mesh/App/Core/Algorithm.cpp +++ b/src/Mod/Mesh/App/Core/Algorithm.cpp @@ -1237,7 +1237,7 @@ void MeshAlgorithm::SearchFacetsFromPolyline (const std::vector // BB eines Polyline-Segments BoundBox3f clSegmBB(rclP0.x, rclP0.y, rclP0.z, rclP0.x, rclP0.y, rclP0.z); - clSegmBB &= rclP1; + clSegmBB.Add(rclP1); clSegmBB.Enlarge(fRadius); // BB um Suchradius vergroessern std::vector aclBBFacets; @@ -1663,9 +1663,9 @@ bool MeshAlgorithm::Distance (const Base::Vector3f &rclPt, unsigned long ulFacet const unsigned long *pulIdx = rclFAry[ulFacetIdx]._aulPoints; BoundBox3f clBB; - clBB &= rclPAry[*(pulIdx++)]; - clBB &= rclPAry[*(pulIdx++)]; - clBB &= rclPAry[*pulIdx]; + clBB.Add(rclPAry[*(pulIdx++)]); + clBB.Add(rclPAry[*(pulIdx++)]); + clBB.Add(rclPAry[*pulIdx]); clBB.Enlarge(fMaxDistance); if (clBB.IsInBox(rclPt) == false) diff --git a/src/Mod/Mesh/App/Core/Elements.cpp b/src/Mod/Mesh/App/Core/Elements.cpp index 6b18e4561..9553e45c0 100644 --- a/src/Mod/Mesh/App/Core/Elements.cpp +++ b/src/Mod/Mesh/App/Core/Elements.cpp @@ -204,7 +204,7 @@ bool MeshGeomEdge::IntersectBoundingBox (const Base::BoundBox3f &rclBB) const Segment3 akSeg(p, n, 0.5f*len); - Base::Vector3f clCenter = rclBB.CalcCenter(); + Base::Vector3f clCenter = rclBB.GetCenter(); Vector3 center(clCenter.x, clCenter.y, clCenter.z); Vector3 axis0(1.0f, 0.0f, 0.0f); Vector3 axis1(0.0f, 1.0f, 0.0f); @@ -473,7 +473,7 @@ bool MeshGeomFacet::IntersectBoundingBox ( const Base::BoundBox3f &rclBB ) const Segment3 akSeg2(p2, d2, len2/2.0f); // Build up the box - Base::Vector3f clCenter = rclBB.CalcCenter(); + Base::Vector3f clCenter = rclBB.GetCenter(); Vector3 center(clCenter.x, clCenter.y, clCenter.z); Vector3 axis0(1.0f, 0.0f, 0.0f); Vector3 axis1(0.0f, 1.0f, 0.0f); diff --git a/src/Mod/Mesh/App/Core/Grid.cpp b/src/Mod/Mesh/App/Core/Grid.cpp index 752c037e2..ce89f0eca 100644 --- a/src/Mod/Mesh/App/Core/Grid.cpp +++ b/src/Mod/Mesh/App/Core/Grid.cpp @@ -189,7 +189,7 @@ unsigned long MeshGrid::Inside (const Base::BoundBox3f &rclBB, std::vector &rclFAry) unsigned long MeshKernel::AddFacets(const std::vector &rclFAry, const std::vector& rclPAry) { for (std::vector::const_iterator it = rclPAry.begin(); it != rclPAry.end(); ++it) - _clBoundBox &= *it; + _clBoundBox.Add(*it); this->_aclPointArray.insert(this->_aclPointArray.end(), rclPAry.begin(), rclPAry.end()); return this->AddFacets(rclFAry); } @@ -367,7 +367,7 @@ void MeshKernel::Merge(const MeshPointArray& rPoints, const MeshFacetArray& rFac *it = index++; const MeshPoint& rPt = rPoints[it-increments.begin()]; this->_aclPointArray.push_back(rPt); - _clBoundBox &= rPt; + _clBoundBox.Add(rPt); } } @@ -394,7 +394,7 @@ void MeshKernel::Clear (void) MeshPointArray().swap(_aclPointArray); MeshFacetArray().swap(_aclFacetArray); - _clBoundBox.Flush(); + _clBoundBox.SetVoid(); } bool MeshKernel::DeleteFacet (const MeshFacetIterator &rclIter) @@ -908,10 +908,10 @@ void MeshKernel::Transform (const Base::Matrix4D &rclMat) MeshPointArray::_TIterator clPIter = _aclPointArray.begin(), clPEIter = _aclPointArray.end(); Base::Matrix4D clMatrix(rclMat); - _clBoundBox.Flush(); + _clBoundBox.SetVoid(); while (clPIter < clPEIter) { *clPIter *= clMatrix; - _clBoundBox &= *clPIter; + _clBoundBox.Add(*clPIter); clPIter++; } } @@ -923,9 +923,9 @@ void MeshKernel::Smooth(int iterations, float stepsize) void MeshKernel::RecalcBoundBox (void) { - _clBoundBox.Flush(); + _clBoundBox.SetVoid(); for (MeshPointArray::_TConstIterator pI = _aclPointArray.begin(); pI != _aclPointArray.end(); pI++) - _clBoundBox &= *pI; + _clBoundBox.Add(*pI); } std::vector MeshKernel::CalcVertexNormals() const diff --git a/src/Mod/Mesh/App/Core/Projection.cpp b/src/Mod/Mesh/App/Core/Projection.cpp index 042eaa2e5..b55837fa3 100644 --- a/src/Mod/Mesh/App/Core/Projection.cpp +++ b/src/Mod/Mesh/App/Core/Projection.cpp @@ -287,7 +287,7 @@ bool MeshProjection::bboxInsideRectangle(const Base::BoundBox3f& bbox, if (bbox.IsCutPlane(base, normal)) { dir.Normalize(); - Base::Vector3f cnt(bbox.CalcCenter()); + Base::Vector3f cnt(bbox.GetCenter()); return (fabs(cnt.DistanceToPlane(p1, dir)) + fabs(cnt.DistanceToPlane(p2, dir))) <= (bbox.CalcDiagonalLength() + (p2 - p1).Length()); diff --git a/src/Mod/Mesh/App/Core/TopoAlgorithm.cpp b/src/Mod/Mesh/App/Core/TopoAlgorithm.cpp index 658467142..b559c9ed9 100644 --- a/src/Mod/Mesh/App/Core/TopoAlgorithm.cpp +++ b/src/Mod/Mesh/App/Core/TopoAlgorithm.cpp @@ -1324,7 +1324,7 @@ void MeshTopoAlgorithm::FillupHoles(int level, AbstractPolygonTriangulator& cTri // insert new points and faces into the mesh structure _rclMesh._aclPointArray.insert(_rclMesh._aclPointArray.end(), newPoints.begin(), newPoints.end()); for (MeshPointArray::_TIterator it = newPoints.begin(); it != newPoints.end(); ++it) - _rclMesh._clBoundBox &= *it; + _rclMesh._clBoundBox.Add(*it); if (!newFacets.empty()) { // Do some checks for invalid point indices MeshFacetArray addFacets; diff --git a/src/Mod/Mesh/Gui/Command.cpp b/src/Mod/Mesh/Gui/Command.cpp index c09c0e5ca..cd9ac8f19 100644 --- a/src/Mod/Mesh/Gui/Command.cpp +++ b/src/Mod/Mesh/Gui/Command.cpp @@ -973,7 +973,7 @@ void CmdMeshTrimByPlane::activated(int iMsg) Base::BoundBox3d bbox = mesh->getBoundBox(); double len = bbox.CalcDiagonalLength(); // project center of bbox onto plane and use this as base point - Base::Vector3d cnt = bbox.CalcCenter(); + Base::Vector3d cnt = bbox.GetCenter(); double dist = (cnt-base)*normal; base = cnt - normal * dist; diff --git a/src/Mod/Mesh/Gui/SoFCMeshObject.cpp b/src/Mod/Mesh/Gui/SoFCMeshObject.cpp index 81dd2763f..61828924c 100644 --- a/src/Mod/Mesh/Gui/SoFCMeshObject.cpp +++ b/src/Mod/Mesh/Gui/SoFCMeshObject.cpp @@ -1096,7 +1096,7 @@ void SoFCMeshObjectShape::computeBBox(SoAction *action, SbBox3f &box, SbVec3f &c Base::BoundBox3f cBox = mesh->getKernel().GetBoundBox(); box.setBounds(SbVec3f(cBox.MinX,cBox.MinY,cBox.MinZ), SbVec3f(cBox.MaxX,cBox.MaxY,cBox.MaxZ)); - Base::Vector3f mid = cBox.CalcCenter(); + Base::Vector3f mid = cBox.GetCenter(); center.setValue(mid.x,mid.y,mid.z); } else { @@ -1503,14 +1503,14 @@ void SoFCMeshSegmentShape::computeBBox(SoAction *action, SbBox3f &box, SbVec3f & for (std::vector::const_iterator it = indices.begin(); it != indices.end(); ++it) { const MeshCore::MeshFacet& face = rFaces[*it]; - cBox &= rPoint[face._aulPoints[0]]; - cBox &= rPoint[face._aulPoints[1]]; - cBox &= rPoint[face._aulPoints[2]]; + cBox.Add(rPoint[face._aulPoints[0]]); + cBox.Add(rPoint[face._aulPoints[1]]); + cBox.Add(rPoint[face._aulPoints[2]]); } box.setBounds(SbVec3f(cBox.MinX,cBox.MinY,cBox.MinZ), SbVec3f(cBox.MaxX,cBox.MaxY,cBox.MaxZ)); - Base::Vector3f mid = cBox.CalcCenter(); + Base::Vector3f mid = cBox.GetCenter(); center.setValue(mid.x,mid.y,mid.z); } } @@ -1653,10 +1653,10 @@ void SoFCMeshObjectBoundary::computeBBox(SoAction *action, SbBox3f &box, SbVec3f if (rPoints.size() > 0) { Base::BoundBox3f cBox; for (MeshCore::MeshPointArray::_TConstIterator it = rPoints.begin(); it != rPoints.end(); ++it) - cBox &= (*it); + cBox.Add(*it); box.setBounds(SbVec3f(cBox.MinX,cBox.MinY,cBox.MinZ), SbVec3f(cBox.MaxX,cBox.MaxY,cBox.MaxZ)); - Base::Vector3f mid = cBox.CalcCenter(); + Base::Vector3f mid = cBox.GetCenter(); center.setValue(mid.x,mid.y,mid.z); } else { diff --git a/src/Mod/Mesh/Gui/ViewProviderTransformDemolding.cpp b/src/Mod/Mesh/Gui/ViewProviderTransformDemolding.cpp index f026068b7..f788ecf40 100644 --- a/src/Mod/Mesh/Gui/ViewProviderTransformDemolding.cpp +++ b/src/Mod/Mesh/Gui/ViewProviderTransformDemolding.cpp @@ -122,7 +122,7 @@ void ViewProviderMeshTransformDemolding::attach(App::DocumentObject *pcFeat) calcNormalVector(); calcMaterialIndex(SbRotation()); // geting center point - center = dynamic_cast(pcObject)->Mesh.getValue().getKernel().GetBoundBox().CalcCenter(); + center = dynamic_cast(pcObject)->Mesh.getValue().getKernel().GetBoundBox().GetCenter(); //SoGetBoundingBoxAction boxAction; //pcHighlight->getBoundingBox(&boxAction); diff --git a/src/Mod/Part/App/PreCompiled.h b/src/Mod/Part/App/PreCompiled.h index 1570284b3..67c8bc391 100644 --- a/src/Mod/Part/App/PreCompiled.h +++ b/src/Mod/Part/App/PreCompiled.h @@ -77,6 +77,8 @@ #include "OpenCascadeAll.h" #elif defined(FC_OS_WIN32) +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX #include #endif //_PreComp_ diff --git a/src/Mod/Part/Gui/CrossSections.cpp b/src/Mod/Part/Gui/CrossSections.cpp index be3402125..89025c2a9 100644 --- a/src/Mod/Part/Gui/CrossSections.cpp +++ b/src/Mod/Part/Gui/CrossSections.cpp @@ -129,7 +129,7 @@ CrossSections::CrossSections(const Base::BoundBox3d& bb, QWidget* parent, Qt::WF ui->distance->setDecimals(Base::UnitsApi::getDecimals()); vp = new ViewProviderCrossSections(); - Base::Vector3d c = bbox.CalcCenter(); + Base::Vector3d c = bbox.GetCenter(); calcPlane(CrossSections::XY, c.z); ui->position->setValue(c.z); @@ -269,7 +269,7 @@ void CrossSections::apply() void CrossSections::on_xyPlane_clicked() { - Base::Vector3d c = bbox.CalcCenter(); + Base::Vector3d c = bbox.GetCenter(); ui->position->setValue(c.z); if (!ui->sectionsBox->isChecked()) { calcPlane(CrossSections::XY, c.z); @@ -285,7 +285,7 @@ void CrossSections::on_xyPlane_clicked() void CrossSections::on_xzPlane_clicked() { - Base::Vector3d c = bbox.CalcCenter(); + Base::Vector3d c = bbox.GetCenter(); ui->position->setValue(c.y); if (!ui->sectionsBox->isChecked()) { calcPlane(CrossSections::XZ, c.y); @@ -301,7 +301,7 @@ void CrossSections::on_xzPlane_clicked() void CrossSections::on_yzPlane_clicked() { - Base::Vector3d c = bbox.CalcCenter(); + Base::Vector3d c = bbox.GetCenter(); ui->position->setValue(c.x); if (!ui->sectionsBox->isChecked()) { calcPlane(CrossSections::YZ, c.x); @@ -332,7 +332,7 @@ void CrossSections::on_sectionsBox_toggled(bool b) } else { CrossSections::Plane type = plane(); - Base::Vector3d c = bbox.CalcCenter(); + Base::Vector3d c = bbox.GetCenter(); double value = 0; switch (type) { case CrossSections::XY: diff --git a/src/Mod/Part/Gui/PreCompiled.h b/src/Mod/Part/Gui/PreCompiled.h index 53d5e31cc..0e6285e70 100644 --- a/src/Mod/Part/Gui/PreCompiled.h +++ b/src/Mod/Part/Gui/PreCompiled.h @@ -35,6 +35,11 @@ # define PartGuiExport #endif +#ifdef FC_OS_WIN32 +# define NOMINMAX +#endif + + #ifdef _PreComp_ // here get the warnings of too long specifiers disabled (needed for VC6) #ifdef _MSC_VER @@ -43,9 +48,6 @@ # pragma warning( disable : 4786 ) // specifier longer then 255 chars #endif - - - // standard #include //#include diff --git a/src/Mod/Part/Gui/ViewProviderMirror.cpp b/src/Mod/Part/Gui/ViewProviderMirror.cpp index b021928ec..944afc9fb 100644 --- a/src/Mod/Part/Gui/ViewProviderMirror.cpp +++ b/src/Mod/Part/Gui/ViewProviderMirror.cpp @@ -88,7 +88,7 @@ bool ViewProviderMirror::setEdit(int ModNum) float len = (float)bbox.CalcDiagonalLength(); Base::Vector3d base = mf->Base.getValue(); Base::Vector3d norm = mf->Normal.getValue(); - Base::Vector3d cent = bbox.CalcCenter(); + Base::Vector3d cent = bbox.GetCenter(); base = cent.ProjToPlane(base, norm); // setup the graph for editing the mirror plane diff --git a/src/Mod/Points/App/PointsGrid.cpp b/src/Mod/Points/App/PointsGrid.cpp index 1c13b99f3..962ade82e 100644 --- a/src/Mod/Points/App/PointsGrid.cpp +++ b/src/Mod/Points/App/PointsGrid.cpp @@ -81,7 +81,7 @@ PointsGrid::PointsGrid (const PointKernel &rclM, double fGridLen) { Base::BoundBox3d clBBPts;// = _pclPoints->GetBoundBox(); for (PointKernel::const_iterator it = _pclPoints->begin(); it != _pclPoints->end(); ++it ) - clBBPts &= (*it); + clBBPts.Add(*it); Rebuild(std::max((unsigned long)(clBBPts.LengthX() / fGridLen), 1), std::max((unsigned long)(clBBPts.LengthY() / fGridLen), 1), std::max((unsigned long)(clBBPts.LengthZ() / fGridLen), 1)); @@ -138,7 +138,7 @@ void PointsGrid::InitGrid (void) { Base::BoundBox3d clBBPts;// = _pclPoints->GetBoundBox(); for (PointKernel::const_iterator it = _pclPoints->begin(); it != _pclPoints->end(); ++it ) - clBBPts &= (*it); + clBBPts.Add(*it); double fLengthX = clBBPts.LengthX(); double fLengthY = clBBPts.LengthY(); @@ -222,7 +222,7 @@ unsigned long PointsGrid::InSide (const Base::BoundBox3d &rclBB, std::vectorGetBoundBox(); for (PointKernel::const_iterator it = _pclPoints->begin(); it != _pclPoints->end(); ++it ) - clBBPtsEnlarged &= (*it); + clBBPtsEnlarged.Add(*it); double fVolElem; if (_ulCtElements > (ulMaxGrids * ulCtGrid)) @@ -316,7 +316,7 @@ void PointsGrid::CalculateGridLength (int iCtGridPerAxis) // bzw. max Grids sollten 10000 nicht ueberschreiten Base::BoundBox3d clBBPts;// = _pclPoints->GetBoundBox(); for (PointKernel::const_iterator it = _pclPoints->begin(); it != _pclPoints->end(); ++it ) - clBBPts &= (*it); + clBBPts.Add(*it); double fLenghtX = clBBPts.LengthX(); double fLenghtY = clBBPts.LengthY(); @@ -464,7 +464,7 @@ void PointsGrid::SearchNearestFromPoint (const Base::Vector3d &rclPt, std::set -# endif # include # include # include diff --git a/src/Mod/ReverseEngineering/App/ApproxSurface.cpp b/src/Mod/ReverseEngineering/App/ApproxSurface.cpp index 76e9c5215..12c7ce259 100644 --- a/src/Mod/ReverseEngineering/App/ApproxSurface.cpp +++ b/src/Mod/ReverseEngineering/App/ApproxSurface.cpp @@ -682,7 +682,7 @@ bool ParameterCorrection::GetUVParameters(double fSizeFactor) (*_pvcPoints)(ii).Y(), (*_pvcPoints)(ii).Z())); vcProjPts.push_back(Base::Vector2D(clProjPnt.X(), clProjPnt.Y())); - clBBox &= (Base::Vector2D(clProjPnt.X(), clProjPnt.Y())); + clBBox.Add(Base::Vector2D(clProjPnt.X(), clProjPnt.Y())); } if ((clBBox.fMaxX == clBBox.fMinX) || (clBBox.fMaxY == clBBox.fMinY)) diff --git a/src/Mod/Sandbox/Gui/Command.cpp b/src/Mod/Sandbox/Gui/Command.cpp index 2104a97fe..1e2bf3637 100644 --- a/src/Mod/Sandbox/Gui/Command.cpp +++ b/src/Mod/Sandbox/Gui/Command.cpp @@ -24,6 +24,8 @@ #include "PreCompiled.h" #ifndef _PreComp_ # ifdef FC_OS_WIN32 +# define WIN32_LEAN_AND_MEAN +# define NOMINMAX # include # endif # include diff --git a/src/Mod/Sketcher/App/PreCompiled.h b/src/Mod/Sketcher/App/PreCompiled.h index b0e980bfb..0ea5baa48 100644 --- a/src/Mod/Sketcher/App/PreCompiled.h +++ b/src/Mod/Sketcher/App/PreCompiled.h @@ -54,6 +54,7 @@ #include #elif defined(FC_OS_WIN32) +#define NOMINMAX #include #endif // _PreComp_ #endif diff --git a/src/Mod/Spreadsheet/App/PreCompiled.h b/src/Mod/Spreadsheet/App/PreCompiled.h index fc3124c29..bfc8f37a6 100644 --- a/src/Mod/Spreadsheet/App/PreCompiled.h +++ b/src/Mod/Spreadsheet/App/PreCompiled.h @@ -40,6 +40,7 @@ // here get the warnings of too long specifiers disabled (needed for VC6) #ifdef _MSC_VER # pragma warning( disable : 4251 ) +# pragma warning( disable : 4275 ) # pragma warning( disable : 4503 ) # pragma warning( disable : 4786 ) // specifier longer then 255 chars #endif diff --git a/src/Mod/Test/BaseTests.py b/src/Mod/Test/BaseTests.py index 22c36aad0..3b059dde5 100644 --- a/src/Mod/Test/BaseTests.py +++ b/src/Mod/Test/BaseTests.py @@ -170,6 +170,16 @@ class ParameterTestCase(unittest.TestCase): self.failUnless(m2==m3*m4 ,"Wrong multiplication order") self.failUnless(not m2==m4*m3,"Wrong multiplication order") + def testBounding(self): + b=FreeCAD.BoundBox() + b.setVoid() + self.failUnless(not b.isValid(),"Bbox is not invalid") + b.add(0,0,0) + self.failUnless(b.isValid(),"Bbox is invalid") + self.failUnless(b.XLength==0,"X length > 0") + self.failUnless(b.YLength==0,"Y length > 0") + self.failUnless(b.ZLength==0,"Z length > 0") + def testNesting(self): # Parameter testing #FreeCAD.Console.PrintLog("Base::ParameterTestCase::testNesting\n")