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
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
18 #include <BRep_Tool.hxx>
19 #include <BRepAdaptor_Curve.hxx>
20 #include <BRepAdaptor_Curve2d.hxx>
21 #include <BRepAdaptor_Surface.hxx>
23 #include <ChFi3d_Builder_0.hxx>
25 #include <gp_Pnt2d.hxx>
27 #include <gp_Vec2d.hxx>
28 #include <Precision.hxx>
29 #include <TopExp_Explorer.hxx>
31 #include <TopoDS_Edge.hxx>
32 #include <BRepTools.hxx>
33 #include <IntTools_Tools.hxx>
35 static void Correct2dPoint(const TopoDS_Face& theF, gp_Pnt2d& theP2d);
38 //=======================================================================
39 //function : DefineConnectType
41 //=======================================================================
42 ChFiDS_TypeOfConcavity ChFi3d::DefineConnectType(const TopoDS_Edge& E,
43 const TopoDS_Face& F1,
44 const TopoDS_Face& F2,
45 const Standard_Real SinTol,
46 const Standard_Boolean CorrectPoint)
48 const Handle(Geom_Surface)& S1 = BRep_Tool::Surface(F1);
49 const Handle(Geom_Surface)& S2 = BRep_Tool::Surface(F2);
52 Handle (Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(E,F1,f,l);
53 //For the case of seam edge
57 Handle (Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(EE,F2,f,l);
59 BRepAdaptor_Curve C(E);
60 f = C.FirstParameter();
61 l = C.LastParameter();
63 Standard_Real ParOnC = 0.5*(f+l);
64 gp_Vec T1 = C.DN(ParOnC,1);
65 if (T1.SquareMagnitude() <= gp::Resolution())
67 ParOnC = IntTools_Tools::IntermediatePoint(f,l);
70 if (T1.SquareMagnitude() > gp::Resolution()) {
74 if (BRepTools::OriEdgeInFace(E,F1) == TopAbs_REVERSED) {
77 if (F1.Orientation() == TopAbs_REVERSED) T1.Reverse();
79 gp_Pnt2d P = C1->Value(ParOnC);
84 Correct2dPoint(F1, P);
86 S1->D1(P.X(),P.Y(),P3,D1U,D1V);
88 if (F1.Orientation() == TopAbs_REVERSED) DN1.Reverse();
90 P = C2->Value(ParOnC);
92 Correct2dPoint(F2, P);
93 S2->D1(P.X(),P.Y(),P3,D1U,D1V);
95 if (F2.Orientation() == TopAbs_REVERSED) DN2.Reverse();
100 gp_Vec ProVec = DN1^DN2;
101 Standard_Real NormProVec = ProVec.Magnitude();
103 if (NormProVec < SinTol) {
105 if (DN1.Dot(DN2) > 0) {
107 return ChFiDS_Tangential;
110 //Mixed not finished!
112 std::cout <<" faces locally mixed"<<std::endl;
114 return ChFiDS_Convex;
118 if (NormProVec > gp::Resolution())
119 ProVec /= NormProVec;
120 Standard_Real Prod = T1.Dot(ProVec);
123 return ChFiDS_Convex;
127 return ChFiDS_Concave;
132 //=======================================================================
133 //function : ConcaveSide
134 //purpose : calculate the concave face at the neighborhood of the border of
136 //=======================================================================
137 Standard_Integer ChFi3d::ConcaveSide(const BRepAdaptor_Surface& S1,
138 const BRepAdaptor_Surface& S2,
139 const TopoDS_Edge& E,
140 TopAbs_Orientation& Or1,
141 TopAbs_Orientation& Or2)
144 Standard_Integer ChoixConge;
145 Or1 = Or2 = TopAbs_FORWARD;
146 BRepAdaptor_Curve CE(E);
147 Standard_Real first = CE.FirstParameter();
148 Standard_Real last = CE.LastParameter();
149 Standard_Real par = 0.691254*first + 0.308746*last;
151 gp_Pnt pt, pt1, pt2; gp_Vec tgE, tgE1, tgE2, ns1, ns2, dint1, dint2;
152 TopoDS_Face F1 = S1.Face();
153 TopoDS_Face F2 = S2.Face();
154 //F1.Orientation(TopAbs_FORWARD);
155 //F2.Orientation(TopAbs_FORWARD);
160 if(E.Orientation() == TopAbs_REVERSED) tgE.Reverse();
162 TopoDS_Edge E1 = E, E2 = E;
163 E1.Orientation(TopAbs_FORWARD);
164 E2.Orientation(TopAbs_FORWARD);
166 if(F1.IsSame(F2) && BRep_Tool::IsClosed(E,F1)) {
167 E2.Orientation(TopAbs_REVERSED);
172 Standard_Boolean found = 0;
173 for (Exp.Init(F1,TopAbs_EDGE);
174 Exp.More() && !found;
176 if (E.IsSame(TopoDS::Edge(Exp.Current()))){
177 if(Exp.Current().Orientation() == TopAbs_REVERSED) tgE1.Reverse();
178 found = Standard_True;
181 if (!found) { return 0; }
183 for (Exp.Init(F2,TopAbs_EDGE);
184 Exp.More() && !found;
186 if (E.IsSame(TopoDS::Edge(Exp.Current()))){
187 if(Exp.Current().Orientation() == TopAbs_REVERSED) tgE2.Reverse();
188 found = Standard_True;
191 if (!found) { return 0; }
193 BRepAdaptor_Curve2d pc1(E1,F1);
194 BRepAdaptor_Curve2d pc2(E2,F2);
196 gp_Vec DU1,DV1,DU2,DV2;
197 p2d1 = pc1.Value(par);
198 p2d2 = pc2.Value(par);
199 S1.D1(p2d1.X(),p2d1.Y(),pt1,DU1,DV1);
200 ns1 = DU1.Crossed(DV1);
202 if (F1.Orientation() == TopAbs_REVERSED)
204 S2.D1(p2d2.X(),p2d2.Y(),pt2,DU2,DV2);
205 ns2 = DU2.Crossed(DV2);
207 if (F2.Orientation() == TopAbs_REVERSED)
210 dint1 = ns1.Crossed(tgE1);
211 dint2 = ns2.Crossed(tgE2);
212 Standard_Real ang = ns1.CrossMagnitude(ns2);
213 if(ang > 0.0001*M_PI){
214 Standard_Real scal = ns2.Dot(dint1);
217 Or2 = TopAbs_REVERSED;
219 scal = ns1.Dot(dint2);
222 Or1 = TopAbs_REVERSED;
226 //the faces are locally tangent - this is fake!
227 if(dint1.Dot(dint2) < 0.){
228 //This is a forgotten regularity
229 gp_Vec DDU, DDV, DDUV;
230 S1.D2(p2d1.X(),p2d1.Y(),pt1,DU1,DV1,DDU,DDV,DDUV);
231 DU1 += ( DU1 * dint1 < 0) ? -DDU : DDU;
232 DV1 += ( DV1 * dint1 < 0) ? -DDV : DDV;
233 ns1 = DU1.Crossed(DV1);
235 if (F1.Orientation() == TopAbs_REVERSED)
237 S2.D2(p2d2.X(),p2d2.Y(),pt2,DU2,DV2,DDU,DDV,DDUV);
238 DU2 += ( DU2 * dint2 < 0) ? -DDU : DDU;
239 DV2 += ( DV2 * dint2 < 0) ? -DDV : DDV;
240 ns2 = DU2.Crossed(DV2);
242 if (F2.Orientation() == TopAbs_REVERSED)
245 dint1 = ns1.Crossed(tgE1);
246 dint2 = ns2.Crossed(tgE2);
247 ang = ns1.CrossMagnitude(ns2);
248 if(ang > 0.0001*M_PI){
249 Standard_Real scal = ns2.Dot(dint1);
252 Or2 = TopAbs_REVERSED;
254 scal = ns1.Dot(dint2);
257 Or1 = TopAbs_REVERSED;
262 std::cout<<"ConcaveSide : no concave face"<<std::endl;
264 //This 10 shows that the face at end is in the extension of one of two base faces
269 //here it turns back, the points are taken in faces
270 //neither too close nor too far as much as possible.
273 // Standard_Real deport = 1000*BRep_Tool::Tolerance(E);
275 ChFi3d_Coefficient(dint1,DU1,DV1,u,v);
276 p2d1.SetX(p2d1.X() + u); p2d1.SetY(p2d1.Y() + v);
277 ChFi3d_Coefficient(dint1,DU2,DV2,u,v);
278 p2d2.SetX(p2d2.X() + u); p2d2.SetY(p2d2.Y() + v);
279 S1.D1(p2d1.X(),p2d1.Y(),pt1,DU1,DV1);
280 ns1 = DU1.Crossed(DV1);
281 if (F1.Orientation() == TopAbs_REVERSED)
283 S2.D1(p2d2.X(),p2d2.Y(),pt2,DU2,DV2);
284 ns2 = DU2.Crossed(DV2);
285 if (F2.Orientation() == TopAbs_REVERSED)
287 gp_Vec vref(pt1,pt2);
288 if(ns1.Dot(vref) < 0.){
289 Or1 = TopAbs_REVERSED;
291 if(ns2.Dot(vref) > 0.){
292 Or2 = TopAbs_REVERSED;
298 if (Or1 == TopAbs_FORWARD) {
299 if (Or2 == TopAbs_FORWARD) ChoixConge = 1;
303 if (Or2 == TopAbs_FORWARD) ChoixConge = 3;
306 if ((ns1.Crossed(ns2)).Dot(tgE) >= 0.) ChoixConge++ ;
310 //=======================================================================
311 //function : NextSide
314 //=======================================================================
316 Standard_Integer ChFi3d::NextSide(TopAbs_Orientation& Or1,
317 TopAbs_Orientation& Or2,
318 const TopAbs_Orientation OrSave1,
319 const TopAbs_Orientation OrSave2,
320 const Standard_Integer ChoixSave)
322 if (Or1 == TopAbs_FORWARD){Or1 = OrSave1;}
324 Or1 = TopAbs::Reverse(OrSave1);
326 if (Or2 == TopAbs_FORWARD){Or2 = OrSave2;}
328 Or2 = TopAbs::Reverse(OrSave2);
331 Standard_Integer ChoixConge;
332 if (Or1 == TopAbs_FORWARD) {
333 if (Or2 == TopAbs_FORWARD) ChoixConge = 1;
335 if(ChoixSave < 0) ChoixConge = 3;
340 if (Or2 == TopAbs_FORWARD) {
341 if(ChoixSave < 0) ChoixConge = 7;
346 if (Abs(ChoixSave)%2 == 0) ChoixConge++;
351 //=======================================================================
352 //function : NextSide
355 //=======================================================================
357 void ChFi3d::NextSide(TopAbs_Orientation& Or,
358 const TopAbs_Orientation OrSave,
359 const TopAbs_Orientation OrFace)
361 if (Or == OrFace){Or = OrSave;}
363 Or = TopAbs::Reverse(OrSave);
369 //=======================================================================
370 //function : SameSide
373 //=======================================================================
375 Standard_Boolean ChFi3d::SameSide(const TopAbs_Orientation Or,
376 const TopAbs_Orientation OrSave1,
377 const TopAbs_Orientation OrSave2,
378 const TopAbs_Orientation OrFace1,
379 const TopAbs_Orientation OrFace2)
381 TopAbs_Orientation o1,o2;
382 if (Or == OrFace1){o1 = OrSave1;}
384 o1 = TopAbs::Reverse(OrSave1);
386 if (Or == OrFace2){o2 = OrSave2;}
388 o2 = TopAbs::Reverse(OrSave2);
393 //=======================================================================
394 //function : Correct2dPoint
396 //=======================================================================
397 void Correct2dPoint(const TopoDS_Face& theF, gp_Pnt2d& theP2d)
399 BRepAdaptor_Surface aBAS(theF, Standard_False);
400 if (aBAS.GetType() < GeomAbs_BezierSurface) {
404 const Standard_Real coeff = 0.01;
406 Standard_Real u1, u2, v1, v2;
408 aBAS.Initialize(theF, Standard_True);
409 u1 = aBAS.FirstUParameter();
410 u2 = aBAS.LastUParameter();
411 v1 = aBAS.FirstVParameter();
412 v2 = aBAS.LastVParameter();
413 if (!(Precision::IsInfinite(u1) || Precision::IsInfinite(u2)))
415 eps = Max(coeff*(u2 - u1), Precision::PConfusion());
416 if (Abs(theP2d.X() - u1) < eps)
418 theP2d.SetX(u1 + eps);
420 if (Abs(theP2d.X() - u2) < eps)
422 theP2d.SetX(u2 - eps);
425 if (!(Precision::IsInfinite(v1) || Precision::IsInfinite(v2)))
427 eps = Max(coeff*(v2 - v1), Precision::PConfusion());
428 if (Abs(theP2d.Y() - v1) < eps)
430 theP2d.SetY(v1 + eps);
432 if (Abs(theP2d.Y() - v2) < eps)
434 theP2d.SetY(v2 - eps);