Salome HOME
Copyright update 2020
[tools/medcoupling.git] / src / INTERP_KERNEL / BoundingBox.cxx
1 // Copyright (C) 2007-2020  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, or (at your option) any later version.
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 > 0);     
42
43     // initialize with first two points
44     const double *pt0(pts[0]);
45
46     for(BoxCoord c = XMIN ; c <= ZMIN ; c = BoxCoord(c + 1))
47       {
48         _coords[c] = pt0[c];
49         _coords[c + 3] = pt0[c];
50       }
51
52     for(unsigned i = 1 ; i < numPts ; ++i)
53       {
54         updateWithPoint(pts[i]);
55       }
56   
57     assert(isValid());
58   }
59
60   /**
61    * Constructor creating box from union of two boxes, resulting in a box that encloses both of them
62    *
63    * @param  box1  the first box
64    * @param  box2  the second box
65    */
66   BoundingBox::BoundingBox(const BoundingBox& box1, const BoundingBox& box2) 
67     : _coords(new double[6])
68   {
69     assert(_coords != 0);
70
71     for(BoxCoord c = XMIN ; c <= ZMIN ; c = BoxCoord(c + 1))
72       {
73         _coords[c] = std::min(box1._coords[c], box2._coords[c]);
74         _coords[c + 3] = std::max(box1._coords[c + 3], box2._coords[c + 3]);
75       }
76     
77     assert(isValid());
78   }
79
80   /**
81    * Destructor
82    *
83    */
84   BoundingBox::~BoundingBox()
85   {
86     delete [] _coords;
87   }
88
89   /**
90    * Determines if the intersection with a given box is empty
91    * 
92    * @param    box   BoundingBox with which intersection is tested
93    * @return  true if intersection between boxes is empty, false if not
94    */
95   bool BoundingBox::isDisjointWith(const BoundingBox& box) const
96   {
97     for(BoxCoord c = XMIN ; c <= ZMIN ; c = BoxCoord(c + 1))
98       {
99         const double otherMinCoord = box.getCoordinate(c);
100         const double otherMaxCoord = box.getCoordinate(BoxCoord(c + 3));
101        
102         // boxes are disjoint if there exists a direction in which the 
103         // minimum coordinate of one is greater than the maximum coordinate of the other
104
105         // more stable version ?
106         // const double tol = 1.0e-2*_coords[c];
107         // if(_coords[c] > otherMaxCoord + tol 
108         //   || _coords[c + 3] < otherMinCoord - tol)
109        
110        
111         if(_coords[c] > otherMaxCoord 
112            || _coords[c + 3] < otherMinCoord)
113        
114           {
115             return true;
116           }
117        
118       }
119     return false;
120   }
121     
122   
123
124   /**
125    * Updates the bounding box to include a given point
126    * 
127    * @param pt    point to be included
128    *
129    */
130   void BoundingBox::updateWithPoint(const double* pt)
131   {
132     for(BoxCoord c = XMIN ; c <= ZMIN ; c = BoxCoord(c + 1))
133       {
134         const double ptVal = pt[c];
135
136         // update min and max coordinates
137         _coords[c] = std::min(_coords[c], ptVal);
138         _coords[c + 3] = std::max(_coords[c + 3], ptVal);
139
140       }
141   }
142   
143   /**
144    * Checks if the box is valid, which it is if its minimum coordinates are
145    * smaller than its maximum coordinates in all directions.
146    *
147    * @return  true if the box is valid, false if not
148    */
149   bool BoundingBox::isValid() const
150   {
151     bool valid = true;
152     for(BoxCoord c = XMIN ; c < ZMIN ; c = BoxCoord(c + 1))
153       {
154         if(_coords[c] > _coords[c + 3])
155           {
156             std::cout << "+++ Error in  BoundingBox |: coordinate " << c << " is invalid : "
157                       <<_coords[c] << " > " << _coords[c+3] << std::endl;
158             valid = false;
159           }
160       }
161     return valid;
162   }
163
164   void BoundingBox::toCompactData(double data[6]) const
165   {
166     data[0]=_coords[XMIN];
167     data[1]=_coords[XMAX];
168     data[2]=_coords[YMIN];
169     data[3]=_coords[YMAX];
170     data[4]=_coords[ZMIN];
171     data[5]=_coords[ZMAX];
172   }
173
174 }