Salome HOME
Merge from V6_main 01/04/2013
[modules/med.git] / src / INTERP_KERNEL / BoundingBox.cxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "BoundingBox.hxx"
21
22 #include <iostream>
23 #include <algorithm>
24 #include <cassert>
25
26 namespace INTERP_KERNEL
27 {
28   
29   /**
30    * Constructor creating box from an array of the points corresponding
31    * to the vertices of the element.
32    * Each point is represented by an array of three doubles.
33    *
34    * @param pts     array of points 
35    * @param numPts  number of vertices
36    *
37    */
38   BoundingBox::BoundingBox(const double** pts, const unsigned numPts)
39     :_coords(new double[6])
40   {
41     assert(numPts > 1);     
42
43     // initialize with first two points
44     const double* pt1 = pts[0];
45     const double* pt2 = pts[1];
46
47     for(BoxCoord c = XMIN ; c <= ZMIN ; c = BoxCoord(c + 1))
48       {
49         _coords[c] = std::min(pt1[c], pt2[c]);
50         _coords[c + 3] = std::max(pt1[c], pt2[c]);
51       }
52
53     for(unsigned i = 2 ; i < numPts ; ++i)
54       {
55         updateWithPoint(pts[i]);
56       }
57   
58     assert(isValid());
59   }
60
61   /**
62    * Constructor creating box from union of two boxes, resulting in a box that encloses both of them
63    *
64    * @param  box1  the first box
65    * @param  box2  the second box
66    */
67   BoundingBox::BoundingBox(const BoundingBox& box1, const BoundingBox& box2) 
68     : _coords(new double[6])
69   {
70     assert(_coords != 0);
71
72     for(BoxCoord c = XMIN ; c <= ZMIN ; c = BoxCoord(c + 1))
73       {
74         _coords[c] = std::min(box1._coords[c], box2._coords[c]);
75         _coords[c + 3] = std::max(box1._coords[c + 3], box2._coords[c + 3]);
76       }
77     
78     assert(isValid());
79   }
80
81   /**
82    * Destructor
83    *
84    */
85   BoundingBox::~BoundingBox()
86   {
87     delete[] _coords;
88   }
89
90   /**
91    * Determines if the intersection with a given box is empty
92    * 
93    * @param    box   BoundingBox with which intersection is tested
94    * @return  true if intersection between boxes is empty, false if not
95    */
96   bool BoundingBox::isDisjointWith(const BoundingBox& box) const
97   {
98     for(BoxCoord c = XMIN ; c <= ZMIN ; c = BoxCoord(c + 1))
99       {
100         const double otherMinCoord = box.getCoordinate(c);
101         const double otherMaxCoord = box.getCoordinate(BoxCoord(c + 3));
102        
103         // boxes are disjoint if there exists a direction in which the 
104         // minimum coordinate of one is greater than the maximum coordinate of the other
105
106         // more stable version ?
107         // const double tol = 1.0e-2*_coords[c];
108         // if(_coords[c] > otherMaxCoord + tol 
109         //   || _coords[c + 3] < otherMinCoord - tol)
110        
111        
112         if(_coords[c] > otherMaxCoord 
113            || _coords[c + 3] < otherMinCoord)
114        
115           {
116             return true;
117           }
118        
119       }
120     return false;
121   }
122     
123   
124
125   /**
126    * Updates the bounding box to include a given point
127    * 
128    * @param pt    point to be included
129    *
130    */
131   void BoundingBox::updateWithPoint(const double* pt)
132   {
133     for(BoxCoord c = XMIN ; c <= ZMIN ; c = BoxCoord(c + 1))
134       {
135         const double ptVal = pt[c];
136
137         // update min and max coordinates
138         _coords[c] = std::min(_coords[c], ptVal);
139         _coords[c + 3] = std::max(_coords[c + 3], ptVal);
140
141       }
142   }
143   
144   /**
145    * Checks if the box is valid, which it is if its minimum coordinates are
146    * smaller than its maximum coordinates in all directions.
147    *
148    * @return  true if the box is valid, false if not
149    */
150   bool BoundingBox::isValid() const
151   {
152     bool valid = true;
153     for(BoxCoord c = XMIN ; c < ZMIN ; c = BoxCoord(c + 1))
154       {
155         if(_coords[c] > _coords[c + 3])
156           {
157             std::cout << "+++ Error in  BoundingBox |: coordinate " << c << " is invalid : "
158                       <<_coords[c] << " > " << _coords[c+3] << std::endl;
159             valid = false;
160           }
161       }
162     return valid;
163   }
164
165 }