Salome HOME
28409b10369afe3b465a92bb9c0876571bcd7609
[modules/geom.git] / src / GEOMAlgo / GEOMAlgo_ClsfQuad.cxx
1 // Copyright (C) 2007-2023  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // File:        GEOMAlgo_ClsfQuad.cxx
24 // Created:     Fri Feb 13 16:03:19 2015
25 // Author:      Sergey KHROMOV
26 //
27
28
29 #include <GEOMAlgo_ClsfQuad.hxx>
30 #include <GEOMAlgo_SurfaceTools.hxx>
31
32 #include <Geom_Plane.hxx>
33
34 IMPLEMENT_STANDARD_RTTIEXT(GEOMAlgo_ClsfQuad, GEOMAlgo_Clsf)
35
36 //=======================================================================
37 //function :
38 //purpose  :
39 //=======================================================================
40 GEOMAlgo_ClsfQuad::GEOMAlgo_ClsfQuad()
41 : GEOMAlgo_Clsf(),
42   myQuadNormal(0., 0., 0.)
43 {
44 }
45 //=======================================================================
46 //function : ~
47 //purpose  :
48 //=======================================================================
49 GEOMAlgo_ClsfQuad::~GEOMAlgo_ClsfQuad()
50 {
51 }
52 //=======================================================================
53 //function : SetCorners
54 //purpose  :
55 //=======================================================================
56 void GEOMAlgo_ClsfQuad::SetCorners(const gp_Pnt &theTopLeftPoint,
57                                    const gp_Pnt &theTopRightPoint,
58                                    const gp_Pnt &theBottomLeftPoint,
59                                    const gp_Pnt &theBottomRightPoint)
60 {
61   myPoints.resize(6);
62   myPoints[0] = theTopLeftPoint;
63   myPoints[1] = theTopRightPoint;
64   myPoints[2] = theBottomRightPoint;
65   myPoints[3] = theBottomLeftPoint;
66   myPoints[4] = myPoints[0];
67   myPoints[5] = myPoints[1];
68
69   // Find plane normal defined by corner points, it will be used to define
70   // a plane for each quadrangle side.
71   myQuadNormal.SetCoord (0., 0., 0.);
72
73   for ( int i = 1; i <= 4; ++i ) {
74     myQuadNormal +=
75       gp_Vec(myPoints[i], myPoints[i+1]) ^ gp_Vec(myPoints[i], myPoints[i-1]);
76   }
77
78   if (myQuadNormal.SquareMagnitude() <= DBL_MIN) {
79     return;
80   }
81
82   // detect concave quadrangle sides
83   myConcaveQuad = false;
84   myConcaveSide.resize (4, false);
85
86   for ( int i = 1; i <= 4; ++i ) {
87     gp_Vec localQN =
88       gp_Vec(myPoints[i], myPoints[i+1]) ^ gp_Vec(myPoints[i], myPoints[i-1]);
89
90     if (myQuadNormal * localQN < 0) {
91       myConcaveSide[i-1] = myConcaveSide[i] = myConcaveQuad = true;
92     }
93   }
94
95   // loop on quadrangle sides
96   myPlanes.reserve( 4 );
97
98   for ( int i = 0; i < 4; ++i ) {
99     // point1 -> point2 vector
100     gp_Vec aSideVec( myPoints[ i ], myPoints[ i + 1 ]);
101
102     // plane normal
103     gp_Vec aSideNorm = aSideVec ^ myQuadNormal;
104     if (aSideNorm.SquareMagnitude() <= DBL_MIN) {
105       continue;
106     }
107
108     // make plane
109     Handle(Geom_Plane) aPlane = new Geom_Plane(myPoints[i], aSideNorm);
110
111     myPlanes.push_back(GeomAdaptor_Surface());
112     myPlanes.back().Load( aPlane );
113   }
114 }
115
116   //=======================================================================
117 //function : GetCorners
118 //purpose  :
119 //=======================================================================
120 void GEOMAlgo_ClsfQuad::GetCorners(gp_Pnt &theTopLeftPoint,
121                                    gp_Pnt &theTopRightPoint,
122                                    gp_Pnt &theBottomLeftPoint,
123                                    gp_Pnt &theBottomRightPoint) const
124 {
125   if (myPoints.size() == 6) {
126     theTopLeftPoint     = myPoints[0];
127     theTopRightPoint    = myPoints[1];
128     theBottomLeftPoint  = myPoints[3];
129     theBottomRightPoint = myPoints[2];
130   }
131 }
132
133 //=======================================================================
134 //function : CheckData
135 //purpose  :
136 //=======================================================================
137 void GEOMAlgo_ClsfQuad::CheckData()
138 {
139   myErrorStatus = 0;
140
141   if (myQuadNormal.SquareMagnitude() <= DBL_MIN) {
142     myErrorStatus = 10; // undefined quadrangle normal.
143     return;
144   }
145 }
146 //=======================================================================
147 //function : Perform
148 //purpose  :
149 //=======================================================================
150 void GEOMAlgo_ClsfQuad::Perform()
151 {
152   myErrorStatus=0;
153   //
154   // Return IN if aP has TopAbs_IN with all sides.
155   // In the case of concave quadrangle, return IN if
156   // aP is OUT of only one concave side
157   double nbIn = 0.;
158
159   for (size_t i = 0; i < myPlanes.size(); ++i) {
160     TopAbs_State aSt;
161
162     GEOMAlgo_SurfaceTools::GetState(myPnt, myPlanes[i], myTolerance, aSt);
163
164     if (aSt == TopAbs_IN) {
165       nbIn += myConcaveSide[i] ? 0.5 : 1.0;
166     } else if (aSt == TopAbs_ON) {
167       // check that aP is between quadrangle corners
168       Handle(Geom_Plane) aSidePlane =
169         Handle(Geom_Plane)::DownCast(myPlanes[i].Surface());
170       gp_Vec aSideNorm = aSidePlane->Axis().Direction();
171       gp_Vec aSideVec = myQuadNormal ^ aSideNorm;
172       gp_Vec c1p (myPoints[i], myPnt);
173       gp_Vec pc2 (myPnt, myPoints[i+1]);
174
175       if (aSideVec * c1p >= 0. && aSideVec * pc2 >= 0.) {
176         myState = TopAbs_ON;
177         return;
178       }
179       // consider to be IN (???????????)
180       //nbIn += myConcaveSide[i] ? 0.5 : 1.0;
181     }
182   }
183
184   Standard_Real inThreshold = myPlanes.size(); // usually 4.0
185
186   if (myConcaveQuad) {
187     inThreshold = 2.5; // 1.0 + 1.0 + 0.5
188   }
189
190   if (nbIn >= inThreshold) {
191     myState = TopAbs_IN;
192   } else {
193     myState = TopAbs_OUT;
194   }
195 }
196 //=======================================================================
197 //function : CanBeON
198 //purpose  :
199 //=======================================================================
200   Standard_Boolean GEOMAlgo_ClsfQuad::CanBeON(const Handle(Geom_Curve)& aC) const
201 {
202   return GEOMAlgo_Clsf::CanBeON(aC);
203 }
204 //=======================================================================
205 //function : CanBeON
206 //purpose  :
207 //=======================================================================
208   Standard_Boolean GEOMAlgo_ClsfQuad::CanBeON(const Handle(Geom_Surface)& aS1) const
209 {
210   GeomAdaptor_Surface aGAS1;
211
212   aGAS1.Load(aS1);
213
214   GeomAbs_SurfaceType aST1 = aGAS1.GetType();
215   Standard_Boolean    bRet = (aST1 == GeomAbs_Plane);
216
217   return bRet;
218 }