Salome HOME
31f7622364c04cefa83b0334e63938d98296a688
[tools/medcoupling.git] / src / INTERP_KERNEL / Geometric2D / InterpKernelGeo2DNode.cxx
1 // Copyright (C) 2007-2019  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 "InterpKernelGeo2DNode.hxx"
22 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
23
24 using namespace INTERP_KERNEL;
25
26 Node::Node(double x, double y):_cnt(1),_loc(UNKNOWN)
27 {
28   _coords[0]=x; _coords[1]=y;
29 }
30
31 Node::Node(const double *coords):_cnt(1),_loc(UNKNOWN)
32 {
33   _coords[0]=coords[0];
34   _coords[1]=coords[1];
35 }
36
37 Node::Node(std::istream& stream):_cnt(1),_loc(UNKNOWN)
38 {
39   int tmp;
40   stream >> tmp;
41   _coords[0]=((double) tmp)/1e4;
42   stream >> tmp;
43   _coords[1]=((double) tmp)/1e4;
44 }
45
46 Node::~Node()
47 {
48 }
49
50 bool Node::decrRef()
51 {
52   bool ret=(--_cnt==0);
53   if(ret)
54     delete this;
55   return ret;
56 }
57
58 bool Node::isEqual(const Node& other) const
59 {
60   const unsigned SPACEDIM=2;
61   bool ret=true;
62   for(unsigned i=0;i<SPACEDIM;i++)
63     ret&=areDoubleEquals((*this)[i],other[i]);
64   return ret;
65 }
66
67 double Node::getSlope(const Node& other) const
68 {
69   return computeSlope(*this, other);
70 }
71
72 /*!
73  * Convenient method. Equivalent to isEqual method. In case of true is returned, '&other' is
74  * added in 'track' container.
75  */
76 bool Node::isEqualAndKeepTrack(const Node& other, std::vector<Node *>& track) const
77 {
78   bool ret=isEqual(other);
79   if(ret)
80     track.push_back(const_cast<Node *>(&other));
81   return ret;
82 }
83
84 void Node::dumpInXfigFile(std::ostream& stream, int resolution, const Bounds& box) const
85 {
86   stream << box.fitXForXFig(_coords[0],resolution) << " " << box.fitYForXFig(_coords[1],resolution) << " ";
87 }
88
89 double Node::distanceWithSq(const Node& other) const
90 {
91   return (_coords[0]-other._coords[0])*(_coords[0]-other._coords[0])+(_coords[1]-other._coords[1])*(_coords[1]-other._coords[1]);
92 }
93
94 /*!
95  * WARNING different from 'computeAngle' method ! The returned value are not in the same interval !
96  * Here in [0; Pi). Typically this method returns the same value by exchanging pt1 and pt2.
97  * Use in process of detection of a point in or not in polygon.
98  */
99 double Node::computeSlope(const double *pt1, const double *pt2)
100 {
101   double x=pt2[0]-pt1[0];
102   double y=pt2[1]-pt1[1];
103   double norm=sqrt(x*x+y*y);
104   double ret=EdgeArcCircle::SafeAcos(fabs(x)/norm);
105   if( (x>=0. && y>=0.) || (x<0. && y<0.) )
106     return ret;
107   else
108     return M_PI-ret;
109 }
110
111 /*!
112  * WARNING different from 'computeSlope' method. Here angle in -Pi;Pi is returned.
113  * This method is anti-symetric.
114  */
115 double Node::computeAngle(const double *pt1, const double *pt2)
116 {
117   double x=pt2[0]-pt1[0];
118   double y=pt2[1]-pt1[1];
119   double norm=sqrt(x*x+y*y);
120   return EdgeArcCircle::GetAbsoluteAngleOfNormalizedVect(x/norm,y/norm);
121 }
122
123 /*!
124  * apply a Similarity transformation on this.
125  * @param xBary is the opposite of the X translation to do.
126  * @param yBary is the opposite of the Y translation to do.
127  * @param dimChar is the reduction factor.
128  */
129 void Node::applySimilarity(double xBary, double yBary, double dimChar)
130 {
131   _coords[0]=(_coords[0]-xBary)/dimChar;
132   _coords[1]=(_coords[1]-yBary)/dimChar;
133 }
134
135 /*!
136  * apply the reverse Similarity transformation on this.
137  * This method is the opposite of Node::applySimilarity method to retrieve the initial state.
138  * @param xBary is the opposite of the X translation to do.
139  * @param yBary is the opposite of the Y translation to do.
140  * @param dimChar is the reduction factor.
141  */
142 void Node::unApplySimilarity(double xBary, double yBary, double dimChar)
143 {
144   _coords[0]=_coords[0]*dimChar+xBary;
145   _coords[1]=_coords[1]*dimChar+yBary;
146 }
147
148 /*!
149  * Called by QuadraticPolygon::splitAbs method.
150  */
151 void Node::fillGlobalInfoAbs(const std::map<INTERP_KERNEL::Node *,mcIdType>& mapThis, const std::map<INTERP_KERNEL::Node *,mcIdType>& mapOther, mcIdType offset1, mcIdType offset2, double fact, double baryX, double baryY,
152                              std::vector<double>& addCoo, std::map<INTERP_KERNEL::Node *,mcIdType>& mapAddCoo, mcIdType *nodeId) const
153 {
154   std::map<INTERP_KERNEL::Node *,mcIdType>::const_iterator it=mapOther.find(const_cast<Node *>(this));
155   if(it!=mapOther.end())     // order matters, try in mapOther first.
156     {
157       *nodeId=(*it).second+offset1;
158       return;
159     }
160   it=mapThis.find(const_cast<Node *>(this));
161   if(it!=mapThis.end())
162     {
163       *nodeId=(*it).second;
164       return;
165     }
166   it=mapAddCoo.find(const_cast<Node *>(this));
167   if(it!=mapAddCoo.end())
168     {
169       *nodeId=(*it).second;
170       return;
171     }
172   int id=(int)addCoo.size()/2;
173   addCoo.push_back(fact*_coords[0]+baryX);
174   addCoo.push_back(fact*_coords[1]+baryY);
175   *nodeId=offset2+id;
176   mapAddCoo[const_cast<Node *>(this)]=offset2+id;
177 }
178
179 /*!
180  * Called by QuadraticPolygon::splitAbs method.
181  */
182 void Node::fillGlobalInfoAbs2(const std::map<INTERP_KERNEL::Node *,mcIdType>& mapThis, const std::map<INTERP_KERNEL::Node *,mcIdType>& mapOther, mcIdType offset1, mcIdType offset2, double fact, double baryX, double baryY,
183                               std::vector<double>& addCoo, std::map<INTERP_KERNEL::Node *,mcIdType>& mapAddCoo, std::vector<mcIdType>& pointsOther) const
184 {
185   mcIdType tmp;
186   std::size_t sz1=addCoo.size();
187   fillGlobalInfoAbs(mapThis,mapOther,offset1,offset2,fact,baryX,baryY,addCoo,mapAddCoo,&tmp);
188   if(sz1!=addCoo.size()     // newly created point
189       || (tmp >= offset2    // or previously created point merged with a neighbour
190           && (pointsOther.size() == 0 || pointsOther.back() != tmp)))
191     {
192       pointsOther.push_back(tmp);
193       return ;
194     }
195   std::vector<mcIdType>::const_iterator it=std::find(pointsOther.begin(),pointsOther.end(),tmp);
196   if(it!=pointsOther.end())
197     return ;
198   pointsOther.push_back(tmp);
199 }