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