0026173: Wrong result of ChFi3d_ChBuilder algorithm: incorrect processing of G1 junct...
[occt.git] / src / ChFi3d / ChFi3d.cxx
1 // Created on: 1993-12-21
2 // Created by: Isabelle GRIGNON
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <BRep_Tool.hxx>
19 #include <BRepAdaptor_Curve.hxx>
20 #include <BRepAdaptor_Curve2d.hxx>
21 #include <BRepAdaptor_Surface.hxx>
22 #include <ChFi3d.hxx>
23 #include <ChFi3d_Builder_0.hxx>
24 #include <gp_Pnt.hxx>
25 #include <gp_Pnt2d.hxx>
26 #include <gp_Vec.hxx>
27 #include <gp_Vec2d.hxx>
28 #include <Precision.hxx>
29 #include <TopExp_Explorer.hxx>
30 #include <TopoDS.hxx>
31 #include <TopoDS_Edge.hxx>
32
33 //=======================================================================
34 //function : ConcaveSide
35 //purpose  : calculate the concave face at the neighborhood of the border of
36 //           2 faces.
37 //=======================================================================
38 Standard_Integer ChFi3d::ConcaveSide(const BRepAdaptor_Surface& S1, 
39                                      const BRepAdaptor_Surface& S2, 
40                                      const TopoDS_Edge& E, 
41                                      TopAbs_Orientation& Or1, 
42                                      TopAbs_Orientation& Or2)
43
44 {
45   Standard_Integer ChoixConge;
46   Or1 = Or2 = TopAbs_FORWARD;
47   BRepAdaptor_Curve CE(E);
48   Standard_Real first = CE.FirstParameter();
49   Standard_Real last = CE.LastParameter();
50   Standard_Real par = 0.691254*first + 0.308746*last;
51
52   gp_Pnt pt, pt1, pt2; gp_Vec tgE, tgE1, tgE2, ns1, ns2, dint1, dint2;
53   TopoDS_Face F1 = S1.Face();
54   TopoDS_Face F2 = S2.Face();
55   //F1.Orientation(TopAbs_FORWARD);
56   //F2.Orientation(TopAbs_FORWARD);
57   
58   CE.D1(par,pt,tgE);
59   tgE.Normalize();
60   tgE2 = tgE1 = tgE;
61   if(E.Orientation() == TopAbs_REVERSED) tgE.Reverse();
62
63   TopoDS_Edge E1 = E, E2 = E;
64   E1.Orientation(TopAbs_FORWARD);
65   E2.Orientation(TopAbs_FORWARD);
66
67   if(F1.IsSame(F2) && BRep_Tool::IsClosed(E,F1)) {
68     E2.Orientation(TopAbs_REVERSED);
69     tgE2.Reverse();
70   }
71   else {
72     TopExp_Explorer Exp;
73     Standard_Boolean found = 0;
74     for (Exp.Init(F1,TopAbs_EDGE); 
75          Exp.More() && !found; 
76          Exp.Next()) {
77       if (E.IsSame(TopoDS::Edge(Exp.Current()))){
78         if(Exp.Current().Orientation() == TopAbs_REVERSED) tgE1.Reverse();
79         found = Standard_True;
80       }
81     }
82     if (!found) { return 0; }
83     found = 0;
84     for (Exp.Init(F2,TopAbs_EDGE); 
85          Exp.More() && !found; 
86          Exp.Next()) {
87       if (E.IsSame(TopoDS::Edge(Exp.Current()))){
88         if(Exp.Current().Orientation() == TopAbs_REVERSED) tgE2.Reverse();
89         found = Standard_True;
90       }
91     }
92     if (!found) { return 0; }
93   }
94   BRepAdaptor_Curve2d pc1(E1,F1);
95   BRepAdaptor_Curve2d pc2(E2,F2);
96   gp_Pnt2d p2d1,p2d2;
97   gp_Vec DU1,DV1,DU2,DV2;
98   p2d1 = pc1.Value(par);
99   p2d2 = pc2.Value(par);
100   S1.D1(p2d1.X(),p2d1.Y(),pt1,DU1,DV1);
101   ns1 = DU1.Crossed(DV1);
102   ns1.Normalize();
103   if (F1.Orientation() == TopAbs_REVERSED)
104     ns1.Reverse();
105   S2.D1(p2d2.X(),p2d2.Y(),pt2,DU2,DV2);
106   ns2 = DU2.Crossed(DV2);
107   ns2.Normalize();
108   if (F2.Orientation() == TopAbs_REVERSED)
109     ns2.Reverse();
110
111   dint1 = ns1.Crossed(tgE1);
112   dint2 = ns2.Crossed(tgE2);
113   Standard_Real ang = ns1.CrossMagnitude(ns2);
114   if(ang > 0.0001*M_PI){
115     Standard_Real scal = ns2.Dot(dint1);
116     if ( scal <= 0. ){
117       ns2.Reverse();
118       Or2 = TopAbs_REVERSED; 
119     }
120     scal = ns1.Dot(dint2);
121     if ( scal <= 0. ){
122       ns1.Reverse();
123       Or1 = TopAbs_REVERSED; 
124     }
125   }
126   else { 
127     //the faces are locally tangent - this is fake!
128     if(dint1.Dot(dint2) < 0.){
129       //This is a forgotten regularity
130       gp_Vec DDU, DDV, DDUV;
131       S1.D2(p2d1.X(),p2d1.Y(),pt1,DU1,DV1,DDU,DDV,DDUV);
132       DU1 += ( DU1 * dint1 < 0) ? -DDU : DDU;
133       DV1 += ( DV1 * dint1 < 0) ? -DDV : DDV;
134       ns1 = DU1.Crossed(DV1);
135       ns1.Normalize();
136       if (F1.Orientation() == TopAbs_REVERSED)
137         ns1.Reverse();
138       S2.D2(p2d2.X(),p2d2.Y(),pt2,DU2,DV2,DDU,DDV,DDUV);
139       DU2 += ( DU2 * dint2 < 0) ? -DDU : DDU;
140       DV2 += ( DV2 * dint2 < 0) ? -DDV : DDV;
141       ns2 = DU2.Crossed(DV2);
142       ns2.Normalize();
143       if (F2.Orientation() == TopAbs_REVERSED)
144         ns2.Reverse();
145       
146       dint1 = ns1.Crossed(tgE1);
147       dint2 = ns2.Crossed(tgE2);
148       ang = ns1.CrossMagnitude(ns2);
149       if(ang > 0.0001*M_PI){
150         Standard_Real scal = ns2.Dot(dint1);
151         if ( scal <= 0. ){
152           ns2.Reverse();
153           Or2 = TopAbs_REVERSED; 
154         }
155         scal = ns1.Dot(dint2);
156         if ( scal <= 0. ){
157           ns1.Reverse();
158           Or1 = TopAbs_REVERSED; 
159         }
160       }
161       else {
162 #ifdef OCCT_DEBUG
163         cout<<"ConcaveSide : no concave face"<<endl;
164 #endif
165         //This 10 shows that the face at end is in the extension of one of two base faces
166         return 10;
167       }
168     }
169     else {
170       //here it turns back, the points are taken in faces
171       //neither too close nor too far as much as possible.
172       Standard_Real u,v;
173 #ifdef OCCT_DEBUG
174 //      Standard_Real deport = 1000*BRep_Tool::Tolerance(E);
175 #endif
176       ChFi3d_Coefficient(dint1,DU1,DV1,u,v);
177       p2d1.SetX(p2d1.X() + u); p2d1.SetY(p2d1.Y() + v);
178       ChFi3d_Coefficient(dint1,DU2,DV2,u,v);
179       p2d2.SetX(p2d2.X() + u); p2d2.SetY(p2d2.Y() + v);
180       S1.D1(p2d1.X(),p2d1.Y(),pt1,DU1,DV1);
181       ns1 = DU1.Crossed(DV1);
182       if (F1.Orientation() == TopAbs_REVERSED)
183         ns1.Reverse();
184       S2.D1(p2d2.X(),p2d2.Y(),pt2,DU2,DV2);
185       ns2 = DU2.Crossed(DV2);
186       if (F2.Orientation() == TopAbs_REVERSED)
187         ns2.Reverse();
188       gp_Vec vref(pt1,pt2);
189       if(ns1.Dot(vref) < 0.){
190         Or1 = TopAbs_REVERSED;
191       }
192       if(ns2.Dot(vref) > 0.){
193         Or2 = TopAbs_REVERSED;
194       }
195     }
196   }
197
198
199   if (Or1 == TopAbs_FORWARD) {
200     if (Or2 == TopAbs_FORWARD) ChoixConge = 1;
201     else ChoixConge = 7;
202   }
203   else {
204     if (Or2 == TopAbs_FORWARD) ChoixConge = 3;
205     else ChoixConge = 5;
206   }
207   if ((ns1.Crossed(ns2)).Dot(tgE) >= 0.) ChoixConge++ ;
208   return ChoixConge;
209 }
210
211 //=======================================================================
212 //function : NextSide
213 //purpose  : 
214 //           
215 //=======================================================================
216
217 Standard_Integer  ChFi3d::NextSide(TopAbs_Orientation& Or1, 
218                                    TopAbs_Orientation& Or2,
219                                    const TopAbs_Orientation OrSave1, 
220                                    const TopAbs_Orientation OrSave2,
221                                    const Standard_Integer ChoixSave)
222 {
223   if (Or1 == TopAbs_FORWARD){Or1 = OrSave1;}
224   else {
225     Or1 = TopAbs::Reverse(OrSave1);
226   }
227   if (Or2 == TopAbs_FORWARD){Or2 = OrSave2;}
228   else {
229     Or2 = TopAbs::Reverse(OrSave2);
230   }
231
232   Standard_Integer ChoixConge;
233   if (Or1 == TopAbs_FORWARD) {
234     if (Or2 == TopAbs_FORWARD) ChoixConge = 1;
235     else {
236       if(ChoixSave < 0) ChoixConge = 3;
237       else ChoixConge = 7;
238     }
239   }
240   else {
241     if (Or2 == TopAbs_FORWARD) {
242       if(ChoixSave < 0) ChoixConge = 7;
243       else ChoixConge = 3;
244     }
245     else ChoixConge = 5;
246   }
247   if (Abs(ChoixSave)%2 == 0) ChoixConge++;
248   return ChoixConge;
249 }
250
251
252 //=======================================================================
253 //function : NextSide
254 //purpose  : 
255 //           
256 //=======================================================================
257
258 void ChFi3d::NextSide(TopAbs_Orientation& Or, 
259                      const TopAbs_Orientation OrSave, 
260                      const TopAbs_Orientation OrFace) 
261 {
262   if (Or == OrFace){Or = OrSave;}
263   else {
264     Or = TopAbs::Reverse(OrSave);
265   }
266 }
267
268
269
270 //=======================================================================
271 //function : SameSide
272 //purpose  : 
273 //           
274 //=======================================================================
275
276 Standard_Boolean  ChFi3d::SameSide(const TopAbs_Orientation Or, 
277                                    const TopAbs_Orientation OrSave1, 
278                                    const TopAbs_Orientation OrSave2,
279                                    const TopAbs_Orientation OrFace1, 
280                                    const TopAbs_Orientation OrFace2)
281 {
282   TopAbs_Orientation o1,o2;
283   if (Or == OrFace1){o1 = OrSave1;}
284   else {
285     o1 = TopAbs::Reverse(OrSave1);
286   }
287   if (Or == OrFace2){o2 = OrSave2;}
288   else {
289     o2 = TopAbs::Reverse(OrSave2);
290   }
291   return (o1 == o2);
292 }