]> SALOME platform Git repositories - tools/medcoupling.git/blob - src/INTERP_KERNEL/Geometric2D/Bounds.cxx
Salome HOME
Merge from BR_V5_DEV 16Feb09
[tools/medcoupling.git] / src / INTERP_KERNEL / Geometric2D / Bounds.cxx
1 //  Copyright (C) 2007-2008  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 #include "Bounds.hxx"
20 #include "InterpKernelException.hxx"
21 #include "EdgeArcCircle.hxx"
22 #include "Node.hxx"
23
24 using namespace INTERP_KERNEL;
25
26 const double& Bounds::operator[](int i) const
27 {
28   switch(i)
29     {
30     case 0:
31       return _x_min;
32     case 1:
33       return _x_max;
34     case 2:
35       return _y_min;
36     case 3:
37       return _y_max;
38     }
39   throw Exception("internal error occurs !");
40 }
41
42 double &Bounds::operator[](int i)
43 {
44   switch(i)
45     {
46     case 0:
47       return _x_min;
48     case 1:
49       return _x_max;
50     case 2:
51       return _y_min;
52     case 3:
53       return _y_max;
54     }
55   throw Exception("internal error occurs !");
56 }
57
58 double Bounds::getDiagonal() const
59 {
60   double a=_x_max-_x_min;
61   double b=_y_max-_y_min;
62   return sqrt(a*a+b*b);
63 }
64
65 /*!
66  * See Node::applySimilarity to see signification of params.
67  */
68 void Bounds::applySimilarity(double xBary, double yBary, double dimChar)
69 {
70   _x_min=(_x_min-xBary)/dimChar;
71   _x_max=(_x_max-xBary)/dimChar;
72   _y_min=(_y_min-yBary)/dimChar;
73   _y_max=(_y_max-yBary)/dimChar;
74 }
75
76 void Bounds::getBarycenter(double& xBary, double& yBary) const
77 {
78   xBary=(_x_min+_x_max)/2.;
79   yBary=(_y_max+_y_min)/2.;
80 }
81
82 void Bounds::prepareForAggregation()
83 {
84   _x_min=1e200; _x_max=-1e200; _y_min=1e200; _y_max=-1e200;
85 }
86
87 /*! 
88  * Given an arc defined by 'center', 'radius' and 'intrcptArcDelta' in radian, returns (by outputs intrcptArcAngle0 and intrcptArcDelta)
89  * the intercepted angle of 'this' from 'center' point of view.
90  * If diagonal of 'this' is the same order of 2*radius, intrcptArcAngle0 and intrcptArcDelta remains unchanged.
91  * @param center IN parameter.
92  * @param radius IN parameter.
93  * @param intrcptArcAngle0 OUT parameter.
94  * @param intrcptArcDelta IN/OUT parameter.
95  */
96 void Bounds::getInterceptedArc(const double *center, double radius, double& intrcptArcAngle0, double& intrcptArcDelta) const
97 {
98   double diag=getDiagonal();
99   if(diag<2.*radius)
100     {
101       double v1[2],v2[2],w1[2],w2[2];
102       v1[0]=_x_min-center[0]; v1[1]=_y_max-center[1]; v2[0]=_x_max-center[0]; v2[1]=_y_min-center[1];
103       w1[0]=v1[0]; w1[1]=_y_min-center[1];           w2[0]=v2[0]; w2[1]=_y_max-center[1];
104       double delta1=EdgeArcCircle::safeAsin(v1[0]*v2[1]-v1[1]*v2[0]);
105       double delta2=EdgeArcCircle::safeAsin(w1[0]*w2[1]-w1[1]*w2[0]);
106       double tmp;
107       if(fabs(delta1)>fabs(delta2))
108         {
109           intrcptArcDelta=delta1;
110           intrcptArcAngle0=EdgeArcCircle::getAbsoluteAngle(v1,tmp);
111         }
112       else
113         {
114           intrcptArcDelta=delta2;
115           intrcptArcAngle0=EdgeArcCircle::getAbsoluteAngle(w1,tmp);
116         }
117     }
118 }
119
120 double Bounds::fitXForXFigD(double val, int res) const
121 {
122   double delta=std::max(_x_max-_x_min,_y_max-_y_min)/2.;
123   double ret=val-(_x_max+_x_min)/2.+delta;
124   delta=11.1375*res/(2.*delta);
125   return ret*delta;
126 }
127
128 double Bounds::fitYForXFigD(double val, int res) const
129 {
130   double delta=std::max(_x_max-_x_min,_y_max-_y_min)/2.;
131   double ret=val-(_y_max+_y_min)/2.+delta;
132   delta=11.1375*res/(2.*delta);
133   return ret*delta;
134 }
135
136 Bounds *Bounds::nearlyAmIIntersectingWith(const Bounds& other) const
137 {
138   if( (other._x_min > _x_max+QUADRATIC_PLANAR::_precision) || (other._x_max < _x_min-QUADRATIC_PLANAR::_precision) || (other._y_min > _y_max+QUADRATIC_PLANAR::_precision) 
139       || (other._y_max < _y_min-QUADRATIC_PLANAR::_precision) )
140     return 0;
141   if( (other._x_min >= _x_max ) || (other._x_max <= _x_min) || (other._y_min >= _y_max) || (other._y_max <= _y_min) )
142     return new Bounds(std::max(_x_min-QUADRATIC_PLANAR::_precision,other._x_min),
143                       std::min(_x_max+QUADRATIC_PLANAR::_precision,other._x_max),
144                       std::max(_y_min-QUADRATIC_PLANAR::_precision,other._y_min),
145                       std::min(_y_max+QUADRATIC_PLANAR::_precision,other._y_max));//In approx cases.
146   else
147     return new Bounds(std::max(_x_min,other._x_min),std::min(_x_max,other._x_max),std::max(_y_min,other._y_min),std::min(_y_max,other._y_max));
148 }
149
150 Bounds *Bounds::amIIntersectingWith(const Bounds& other) const
151 {
152   if( (other._x_min > _x_max) || (other._x_max < _x_min) || (other._y_min > _y_max) || (other._y_max < _y_min) )
153     return 0;
154   return new Bounds(std::max(_x_min,other._x_min),std::min(_x_max,other._x_max),std::max(_y_min,other._y_min),std::min(_y_max,other._y_max));
155 }
156
157 Position Bounds::where(double x, double y) const
158 {
159   if((x>=_x_min && x<=_x_max) && (y>=_y_min && y<=_y_max))
160     return IN;
161   else
162     return OUT;
163 }
164
165 Position Bounds::nearlyWhere(double x, double y) const
166 {
167   bool thinX=Node::areDoubleEquals(_x_min,_x_max);
168   bool thinY=Node::areDoubleEquals(_y_min,_y_max);
169   if(!thinX)
170     {
171       if(Node::areDoubleEquals(x,_x_min) || Node::areDoubleEquals(x,_x_max) && (y<_y_max+QUADRATIC_PLANAR::_precision) && (y>_y_min-QUADRATIC_PLANAR::_precision))
172         return ON_BOUNDARY_POS;
173     }
174   else
175     if(!Node::areDoubleEquals(_x_min,x) && !Node::areDoubleEquals(_x_max,x))
176       return OUT;
177   if(!thinY)
178     {
179       if(Node::areDoubleEquals(y,_y_min) || Node::areDoubleEquals(y,_y_max) && (x<_x_max+QUADRATIC_PLANAR::_precision) && (x>_x_min-QUADRATIC_PLANAR::_precision))
180         return ON_BOUNDARY_POS;
181     }
182   else
183     if(!Node::areDoubleEquals(_y_min,y) && !Node::areDoubleEquals(_y_max,y))
184       return OUT;
185   if(thinX && thinY)
186     return ON_BOUNDARY_POS;
187   if((x>=_x_min && x<=_x_max) && (y>=_y_min && y<=_y_max))
188     return IN;
189   else
190     return OUT;
191 }
192
193 void Bounds::aggregate(const Bounds& other)
194 {
195   _x_min=std::min(_x_min,other._x_min); _x_max=std::max(_x_max,other._x_max);
196   _y_min=std::min(_y_min,other._y_min); _y_max=std::max(_y_max,other._y_max);
197 }