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