]> SALOME platform Git repositories - tools/medcoupling.git/blob - src/INTERP_KERNEL/Geometric2D/InterpKernelGeo2DBounds.cxx
Salome HOME
Refactoring QuadraticPlanar precision tuning. Fixes intersector bugs.
[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   double eps = QuadraticPlanarPrecision::getPrecision();
152   if( (other._x_min > _x_max+eps) || (other._x_max < _x_min-eps) || (other._y_min > _y_max+eps)
153       || (other._y_max < _y_min-eps) )
154     return 0;
155   if( (other._x_min >= _x_max ) || (other._x_max <= _x_min) || (other._y_min >= _y_max) || (other._y_max <= _y_min) )
156     {
157       return new Bounds(std::max(_x_min-eps,other._x_min),
158           std::min(_x_max+eps,other._x_max),
159           std::max(_y_min-eps,other._y_min),
160           std::min(_y_max+eps,other._y_max));//In approx cases.
161     }
162   else
163     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));
164 }
165
166 Bounds *Bounds::amIIntersectingWith(const Bounds& other) const
167 {
168   if( (other._x_min > _x_max) || (other._x_max < _x_min) || (other._y_min > _y_max) || (other._y_max < _y_min) )
169     return 0;
170   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));
171 }
172
173 Position Bounds::where(double x, double y) const
174 {
175   if((x>=_x_min && x<=_x_max) && (y>=_y_min && y<=_y_max))
176     return IN;
177   else
178     return OUT;
179 }
180
181 Position Bounds::nearlyWhere(double x, double y) const
182 {
183   bool thinX=Node::areDoubleEquals(_x_min,_x_max);
184   bool thinY=Node::areDoubleEquals(_y_min,_y_max);
185   if(!thinX)
186     {
187       if((Node::areDoubleEquals(x,_x_min) || Node::areDoubleEquals(x,_x_max)) && ((y<_y_max+QuadraticPlanarPrecision::getPrecision()) && (y>_y_min-QuadraticPlanarPrecision::getPrecision())))
188         return ON_BOUNDARY_POS;
189     }
190   else
191     if(!Node::areDoubleEquals(_x_min,x) && !Node::areDoubleEquals(_x_max,x))
192       return OUT;
193   if(!thinY)
194     {
195       if((Node::areDoubleEquals(y,_y_min) || Node::areDoubleEquals(y,_y_max)) && ((x<_x_max+QuadraticPlanarPrecision::getPrecision()) && (x>_x_min-QuadraticPlanarPrecision::getPrecision())))
196         return ON_BOUNDARY_POS;
197     }
198   else
199     if(!Node::areDoubleEquals(_y_min,y) && !Node::areDoubleEquals(_y_max,y))
200       return OUT;
201   if(thinX && thinY)
202     return ON_BOUNDARY_POS;
203   if((x>=_x_min && x<=_x_max) && (y>=_y_min && y<=_y_max))
204     return IN;
205   else
206     return OUT;
207 }
208
209 void Bounds::aggregate(const Bounds& other)
210 {
211   _x_min=std::min(_x_min,other._x_min); _x_max=std::max(_x_max,other._x_max);
212   _y_min=std::min(_y_min,other._y_min); _y_max=std::max(_y_max,other._y_max);
213 }