ffb99f0c341de92c956d04e89e976d94343fa794
[occt.git] / src / LocOpe / LocOpe_FindEdges.cxx
1 // Created on: 1996-02-15
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1996-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 #include <LocOpe_FindEdges.ixx>
18
19 #include <BRep_Tool.hxx>
20 #include <TopExp_Explorer.hxx>
21
22 #include <Geom_Curve.hxx>
23 #include <Geom_TrimmedCurve.hxx>
24 #include <Geom_Line.hxx>
25 #include <Geom_Circle.hxx>
26 #include <Geom_Ellipse.hxx>
27 #include <Geom_BSplineCurve.hxx>
28 #include <Geom_BezierCurve.hxx>
29 #include <TColgp_Array1OfPnt.hxx>
30 #include <TColStd_Array1OfReal.hxx>
31 #include <TColStd_Array1OfInteger.hxx>
32
33
34 #include <ElCLib.hxx>
35 #include <Precision.hxx>
36
37
38
39 //=======================================================================
40 //function : Set
41 //purpose  : 
42 //=======================================================================
43
44 void LocOpe_FindEdges::Set(const TopoDS_Shape& FFrom,
45                            const TopoDS_Shape& FTo)
46 {
47   myFFrom = FFrom;
48   myFTo = FTo;
49   myLFrom.Clear();
50   myLTo.Clear();
51
52
53   TopExp_Explorer expf,expt;
54   Handle(Geom_Curve) Cf,Ct;
55   TopLoc_Location Loc;
56   Standard_Real ff,lf,ft,lt;
57   Handle(Standard_Type) Tf,Tt;
58
59   for (expf.Init(myFFrom,TopAbs_EDGE); expf.More(); expf.Next()) {
60     const TopoDS_Edge& edgf = TopoDS::Edge(expf.Current());
61     Cf = BRep_Tool::Curve(edgf,Loc,ff,lf);
62     if (!Loc.IsIdentity()) {
63       Handle(Geom_Geometry) GGf = Cf->Transformed(Loc.Transformation());
64       Cf = *((Handle(Geom_Curve)*)&GGf);
65     }
66     Tf = Cf->DynamicType();
67     if (Tf == STANDARD_TYPE(Geom_TrimmedCurve)) {
68       Cf = (*((Handle(Geom_TrimmedCurve)*)&Cf))->BasisCurve();
69       Tf = Cf->DynamicType();
70     }
71     if (Tf != STANDARD_TYPE(Geom_Line) && Tf != STANDARD_TYPE(Geom_Circle) &&
72         Tf != STANDARD_TYPE(Geom_Ellipse) && Tf != STANDARD_TYPE(Geom_BSplineCurve)
73         && Tf != STANDARD_TYPE(Geom_BezierCurve)) {
74       continue;
75     }
76     for (expt.Init(myFTo,TopAbs_EDGE); expt.More(); expt.Next()) {
77       const TopoDS_Edge& edgt = TopoDS::Edge(expt.Current());
78       Ct = BRep_Tool::Curve(edgt,Loc,ft,lt);
79       if (!Loc.IsIdentity()) {
80         Handle(Geom_Geometry) GGt = Ct->Transformed(Loc.Transformation());
81         Ct = *((Handle(Geom_Curve)*)&GGt);
82       }
83       Tt = Ct->DynamicType();
84       if (Tt == STANDARD_TYPE(Geom_TrimmedCurve)) {
85         Ct = (*((Handle(Geom_TrimmedCurve)*)&Ct))->BasisCurve();
86         Tt = Ct->DynamicType();
87       }
88       if (Tt != Tf) {
89         continue;
90       }
91       // On a presomption de confusion
92       Standard_Real Tol = Precision::Confusion();
93       if (Tt == STANDARD_TYPE(Geom_Line)) {
94         gp_Lin lif = (*((Handle(Geom_Line)*)&Cf))->Lin();
95         gp_Lin lit = (*((Handle(Geom_Line)*)&Ct))->Lin();
96         gp_Pnt p1 = ElCLib::Value(ff,lif);
97         gp_Pnt p2 = ElCLib::Value(lf,lif);
98         Standard_Real prm1 = ElCLib::Parameter(lit,p1);
99         Standard_Real prm2 = ElCLib::Parameter(lit,p2);
100         if (prm1 >= ft-Tol && prm1 <= lt+Tol &&
101             prm2 >= ft-Tol && prm2 <= lt+Tol) {
102           Tol *= Tol;
103           gp_Pnt pt = ElCLib::Value(prm1,lit);
104           if (pt.SquareDistance(p1) <= Tol) {
105             pt =  ElCLib::Value(prm2,lit);
106             if (pt.SquareDistance(p2) <= Tol) {
107               myLFrom.Append(edgf);
108               myLTo.Append(edgt);
109               break;
110             }
111           }
112         }
113       }
114       else if (Tt == STANDARD_TYPE(Geom_Circle)) {
115         gp_Circ cif = (*((Handle(Geom_Circle)*)&Cf))->Circ();
116         gp_Circ cit = (*((Handle(Geom_Circle)*)&Ct))->Circ();
117         if (Abs(cif.Radius()-cit.Radius()) <= Tol &&
118             cif.Location().SquareDistance(cit.Location()) <= Tol*Tol) {
119           // Point debut, calage dans periode, et detection meme sens
120
121           gp_Pnt p1,p2;
122           gp_Vec tgf,tgt;
123           ElCLib::D1(ff,cif,p1,tgf);
124           p2 = ElCLib::Value(lf,cif);
125
126           Standard_Real prm1 = ElCLib::Parameter(cit,p1);
127           Standard_Real Tol2d = Precision::PConfusion();
128           if (Abs(prm1-ft) <= Tol2d) prm1 = ft;
129           prm1 = ElCLib::InPeriod(prm1,ft,ft+2.*M_PI);
130           ElCLib::D1(prm1,cit,p1,tgt);
131
132           Standard_Real prm2 = ElCLib::Parameter(cit,p2);
133           if (tgt.Dot(tgf) > 0.) { // meme sens
134             while (prm2 <= prm1) {
135               prm2 += 2.*M_PI;
136             }
137           }
138           else {
139             if (Abs(prm1-ft) <= Precision::Angular()) {
140               prm1 += 2.*M_PI;
141             }
142             while (prm2 >= prm1) {
143               prm2 -= 2.*M_PI;
144             }
145           }
146
147           if (prm1 >= ft-Tol && prm1 <= lt+Tol &&
148               prm2 >= ft-Tol && prm2 <= lt+Tol) {
149             myLFrom.Append(edgf);
150             myLTo.Append(edgt);
151             break;
152           }
153           else {
154             // Cas non traite : on est a cheval
155 #ifdef OCCT_DEBUG
156             cout <<" cas a cheval."<< endl;
157 #endif
158
159 //          myLFrom.Append(edgf);
160 //          myLTo.Append(edgt);
161 //          break;
162           }
163         }
164       }
165       else if (Tt == STANDARD_TYPE(Geom_Ellipse)) {
166         gp_Elips cif = (*((Handle(Geom_Ellipse)*)&Cf))->Elips();
167         gp_Elips cit = (*((Handle(Geom_Ellipse)*)&Ct))->Elips();
168         
169
170         if (Abs(cif.MajorRadius()-cit.MajorRadius()) <= Tol &&
171             Abs(cif.MinorRadius()-cit.MinorRadius()) <= Tol &&
172             cif.Location().SquareDistance(cit.Location()) <= Tol*Tol) {
173           // Point debut, calage dans periode, et detection meme sens
174
175           gp_Pnt p1,p2;
176           gp_Vec tgf,tgt;
177           ElCLib::D1(ff,cif,p1,tgf);
178           p2 = ElCLib::Value(lf,cif);
179
180           Standard_Real prm1 = ElCLib::Parameter(cit,p1);
181           prm1 = ElCLib::InPeriod(prm1,ft,ft+2.*M_PI);
182           ElCLib::D1(prm1,cit,p1,tgt);
183
184           Standard_Real prm2 = ElCLib::Parameter(cit,p2);
185           if (tgt.Dot(tgf) > 0.) { // meme sens
186             while (prm2 <= prm1) {
187               prm2 += 2.*M_PI;
188             }
189           }
190           else {
191             if (Abs(prm1-ft) <= Precision::Angular()) {
192               prm1 += 2.*M_PI;
193             }
194             while (prm2 >= prm1) {
195               prm2 -= 2.*M_PI;
196             }
197           }
198
199           if (prm1 >= ft-Tol && prm1 <= lt+Tol &&
200               prm2 >= ft-Tol && prm2 <= lt+Tol) {
201             myLFrom.Append(edgf);
202             myLTo.Append(edgt);
203             break;
204           }
205           else {
206             // Cas non traite : on est a cheval
207 #ifdef OCCT_DEBUG
208             cout <<" cas a cheval."<< endl;
209 #endif
210 //          myLFrom.Append(edgf);
211 //          myLTo.Append(edgt);
212           }
213         }
214       }
215       else if (Tt == STANDARD_TYPE(Geom_BSplineCurve)) {
216         Handle(Geom_BSplineCurve) Bf = *((Handle(Geom_BSplineCurve)*)&Cf);
217         Handle(Geom_BSplineCurve) Bt = *((Handle(Geom_BSplineCurve)*)&Ct);
218
219         Standard_Boolean IsSame = Standard_True;
220
221         Standard_Integer nbpoles = Bf->NbPoles();
222         if (nbpoles != Bt->NbPoles()) {
223           IsSame = Standard_False;
224         }
225
226         if (IsSame) {
227           Standard_Integer nbknots = Bf->NbKnots();
228           if (nbknots != Bt->NbKnots()) {
229             IsSame = Standard_False;
230           }
231
232           if (IsSame) {
233             TColgp_Array1OfPnt Pf(1, nbpoles), Pt(1, nbpoles);
234             Bf->Poles(Pf);
235             Bt->Poles(Pt);
236             
237             Standard_Real tol3d = BRep_Tool::Tolerance(edgt);
238             for (Standard_Integer p = 1; p <= nbpoles; p++) {
239               if ( (Pf(p)).Distance(Pt(p)) > tol3d) {
240                 IsSame = Standard_False;
241                 break;
242               }
243             }
244             
245             if (IsSame) {
246               TColStd_Array1OfReal Kf(1, nbknots), Kt(1, nbknots);
247               Bf->Knots(Kf);
248               Bt->Knots(Kt);
249
250               TColStd_Array1OfInteger Mf(1, nbknots), Mt(1, nbknots);
251               Bf->Multiplicities(Mf);
252               Bt->Multiplicities(Mt);
253             
254               for (Standard_Integer k = 1; k <= nbknots; k++) {
255                 if ((Kf(k)-Kt(k)) > Tol) {
256                   IsSame = Standard_False;
257                   break;
258                 }
259                 if (Abs(Mf(k)-Mt(k)) > Tol) {
260                   IsSame = Standard_False;
261                   break;
262                 }
263               }
264               
265               if (!Bf->IsRational()) {
266                 if (Bt->IsRational()) {
267                   IsSame = Standard_False;
268                 }
269               }
270               else {
271                 if (!Bt->IsRational()) {
272                   IsSame = Standard_False;
273                 }
274               }
275
276               if (IsSame && Bf->IsRational()) {
277                 TColStd_Array1OfReal Wf(1, nbpoles), Wt(1, nbpoles);
278                 Bf->Weights(Wf);
279                 Bt->Weights(Wt);
280                 
281                 for (Standard_Integer w = 1; w <= nbpoles; w++) {
282                   if (Abs(Wf(w)-Wt(w)) > Tol) {
283                     IsSame = Standard_False;
284                     break;
285                   }
286                 }
287               }
288
289               if (IsSame) {
290 #ifdef OCCT_DEBUG
291                 cout <<"memes bsplines."<< endl;
292 #endif
293                 myLFrom.Append(edgf);
294                 myLTo.Append(edgt);
295                 break;
296               }
297             }
298           }
299         }
300       }
301       else if (Tt == STANDARD_TYPE(Geom_BezierCurve)) {
302         Handle(Geom_BezierCurve) Bf = *((Handle(Geom_BezierCurve)*)&Cf);
303         Handle(Geom_BezierCurve) Bt = *((Handle(Geom_BezierCurve)*)&Ct);
304
305         Standard_Boolean IsSame = Standard_True;
306
307         Standard_Integer nbpoles = Bf->NbPoles();
308         if (nbpoles != Bt->NbPoles()) {
309           IsSame = Standard_False;
310         }
311
312         if (IsSame) {
313           TColgp_Array1OfPnt Pf(1, nbpoles), Pt(1, nbpoles);
314           Bf->Poles(Pf);
315           Bt->Poles(Pt);
316           
317           for (Standard_Integer p = 1; p <= nbpoles; p++) {
318             if ( (Pf(p)).Distance(Pt(p)) > Tol) {
319               IsSame = Standard_False;
320               break;
321             }
322           }
323             
324           if (IsSame) {
325             if (!Bf->IsRational()) {
326               if (Bt->IsRational()) {
327                 IsSame = Standard_False;
328               }
329             }
330             else {
331               if (!Bt->IsRational()) {
332                 IsSame = Standard_False;
333               }
334             }
335
336             if (IsSame && Bf->IsRational()) {
337               TColStd_Array1OfReal Wf(1, nbpoles), Wt(1, nbpoles);
338               Bf->Weights(Wf);
339               Bt->Weights(Wt);
340               
341               for (Standard_Integer w = 1; w <= nbpoles; w++) {
342                 if (Abs(Wf(w)-Wt(w)) > Tol) {
343                   IsSame = Standard_False;
344                   break;
345                 }
346               }
347             }
348             
349             if (IsSame) {
350 #ifdef OCCT_DEBUG
351               cout <<"memes beziers."<< endl;
352 #endif
353               myLFrom.Append(edgf);
354               myLTo.Append(edgt);
355               break;
356             }
357           }
358         }
359       }
360     }
361   }
362 }