1 // Created on: 1997-03-10
2 // Created by: Stagiaire Francois DUMONT
3 // Copyright (c) 1997-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
23 #include <BRepAlgo.ixx>
24 #include <BRepTools_WireExplorer.hxx>
25 #include <BRep_Tool.hxx>
26 #include <BRepLib_MakeEdge.hxx>
27 #include <BRepLib_MakeWire.hxx>
29 #include <GeomConvert.hxx>
30 #include <GeomLProp.hxx>
31 #include <Geom_TrimmedCurve.hxx>
32 #include <Precision.hxx>
33 #include <Standard_ConstructionError.hxx>
34 #include <TColGeom_Array1OfBSplineCurve.hxx>
35 #include <TColGeom_HArray1OfBSplineCurve.hxx>
36 #include <TColStd_Array1OfReal.hxx>
37 #include <TColStd_Array1OfBoolean.hxx>
38 #include <TopoDS_Edge.hxx>
39 #include <TopoDS_Vertex.hxx>
40 #include <TopLoc_Location.hxx>
43 #include <TColGeom_SequenceOfCurve.hxx>
44 #include <TopTools_SequenceOfShape.hxx>
45 #include <TColStd_SequenceOfReal.hxx>
46 #include <GeomAbs_CurveType.hxx>
47 #include <BRepAdaptor_Curve.hxx>
49 #include <BRepLib.hxx>
51 #include <ShapeFix_Shape.hxx>
52 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
55 #//include <DrawTrSurf.hxx>
58 //=======================================================================
59 //function : ConcatenateWire
61 //=======================================================================
63 TopoDS_Wire BRepAlgo::ConcatenateWire(const TopoDS_Wire& W,
64 const GeomAbs_Shape Option,
65 const Standard_Real TolAngular)
69 Standard_Integer nb_curve, //number of curves in the Wire
71 BRepTools_WireExplorer WExp(W) ;
74 Standard_Real First=0.,Last=0., //extremal values for the curve
77 tolleft,tolright; //Vertex tolerances
78 TopoDS_Vertex Vfirst,Vlast; //Vertex of the Wire
79 gp_Pnt Pfirst,Plast; //, Pint; corresponding points
81 BRepLib_MakeWire MakeResult;
82 Standard_Real closed_tolerance =0.0;
83 Standard_Boolean closed_flag = Standard_False ;
87 while ( WExp.More()){ //computation of the curve number
93 TColGeom_Array1OfBSplineCurve tab(0,nb_curve-1); //array of the wire's curve
94 TColStd_Array1OfReal tabtolvertex(0,nb_curve-2); //array of the tolerance's vertex
98 for (index=0 ;index<nb_curve; index++){ //main loop
99 edge = WExp.Current() ;
100 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(edge, L, First, Last);
101 Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(aCurve, First, Last);
102 tab(index) = GeomConvert::CurveToBSplineCurve(aTrCurve); //storage in a array
103 tab(index)->Transform(L.Transformation());
104 GeomConvert::C0BSplineToC1BSplineCurve(tab(index),Precision::Confusion());
106 if (index >= 1){ //continuity test loop
107 if (edge.Orientation()==TopAbs_REVERSED)
108 tab(index)->Reverse();
109 tolleft=BRep_Tool::Tolerance(TopExp::LastVertex(edge));
110 tolright=BRep_Tool::Tolerance(TopExp::FirstVertex(edge));
111 tabtolvertex(index-1)=Max(tolleft,tolright);
114 if(index==0){ //storage of the first edge features
116 if(edge.Orientation()==TopAbs_REVERSED){ //(usefull for the closed wire)
117 Vfirst=TopExp::LastVertex(edge);
118 tab(index)->Reverse();
121 Vfirst=TopExp::FirstVertex(edge);
124 if(index==nb_curve-1){ //storage of the last edge features
125 if(edge.Orientation()==TopAbs_REVERSED)
126 Vlast=TopExp::FirstVertex(edge);
128 Vlast=TopExp::LastVertex(edge);
133 if (BRep_Tool::Tolerance(Vfirst)>BRep_Tool::Tolerance(Vlast)) //computation of the closing tolerance
134 toler=BRep_Tool::Tolerance(Vfirst);
136 toler=BRep_Tool::Tolerance(Vlast);
138 Pfirst=BRep_Tool::Pnt(Vfirst);
139 Plast=BRep_Tool::Pnt(Vlast);
141 if ((Pfirst.Distance(Plast)<=toler)&& //C0 continuity test at the closing point
142 (GeomLProp::Continuity(tab(nb_curve-1),tab(0),Last,First0,
143 Standard_True,Standard_True,
144 toler, TolAngular)>=GeomAbs_G1))
146 closed_tolerance =toler; //if ClosedG1!=0 it will be True and
147 closed_flag = Standard_True ;
148 } //with the toler value
149 Handle(TColGeom_HArray1OfBSplineCurve) concatcurve; //array of the concatenated curves
150 Handle(TColStd_HArray1OfInteger) ArrayOfIndices; //array of the remining Vertex
151 if (Option==GeomAbs_G1)
152 GeomConvert::ConcatG1(tab,
156 closed_tolerance) ; //G1 concatenation
158 GeomConvert::ConcatC1(tab,
163 closed_tolerance); //C1 concatenation
165 for (index=0;index<=(concatcurve->Length()-1);index++){ //building of the resulting Wire
166 BRepLib_MakeEdge EdgeBuilder(concatcurve->Value(index));
167 edge = EdgeBuilder.Edge();
168 MakeResult.Add(edge);
173 TColGeom_Array1OfBSplineCurve tab(0,0); //array of the wire's curve
174 TColStd_Array1OfReal tabtolvertex(0,0); //array of the tolerance's vertex
177 edge = WExp.Current() ;
178 tab(0) = GeomConvert::CurveToBSplineCurve(new //storage in a array
179 Geom_TrimmedCurve(BRep_Tool::Curve(edge,L,First,Last),First,Last));
180 tab(0)->Transform(L.Transformation());
181 GeomConvert::C0BSplineToC1BSplineCurve(tab(0),Precision::Confusion());
182 if (edge.Orientation()==TopAbs_REVERSED)
184 tolleft=BRep_Tool::Tolerance(TopExp::LastVertex(edge));
185 tolright=BRep_Tool::Tolerance(TopExp::FirstVertex(edge));
186 tabtolvertex(0)=Max(tolleft,tolright);
187 if(edge.Orientation()==TopAbs_REVERSED){ //(usefull for the closed wire)
188 Vfirst=TopExp::LastVertex(edge);
189 Vlast=TopExp::FirstVertex(edge);
193 Vfirst=TopExp::FirstVertex(edge);
194 Vlast = TopExp::LastVertex(edge) ;
196 Pfirst=BRep_Tool::Pnt(Vfirst);
197 Plast=BRep_Tool::Pnt(Vlast);
198 if ((Pfirst.Distance(Plast)<=toler)&& //C0 continuity test at the closing point
199 (GeomLProp::Continuity(tab(0),tab(0),Last,First,
200 Standard_True,Standard_True,
201 toler, TolAngular)>=GeomAbs_G1))
203 closed_tolerance =toler; //if ClosedG1!=0 it will be True and
204 closed_flag = Standard_True ;
205 } //with the toler value
206 Handle(TColGeom_HArray1OfBSplineCurve) concatcurve; //array of the concatenated curves
207 Handle(TColStd_HArray1OfInteger) ArrayOfIndices; //array of the remining Vertex
208 if (Option==GeomAbs_G1)
209 GeomConvert::ConcatG1(tab,
213 closed_tolerance) ; //G1 concatenation
215 GeomConvert::ConcatC1(tab,
220 closed_tolerance); //C1 concatenation
222 for (index=0;index<=(concatcurve->Length()-1);index++){ //building of the resulting Wire
223 BRepLib_MakeEdge EdgeBuilder(concatcurve->Value(index));
224 edge = EdgeBuilder.Edge();
225 MakeResult.Add(edge);
228 return MakeResult.Wire() ;
232 //=======================================================================
233 //function : ConcatenateWireC0
235 //=======================================================================
237 TopoDS_Edge BRepAlgo::ConcatenateWireC0(const TopoDS_Wire& aWire)
239 Standard_Real LinTol = Precision::Confusion();
240 Standard_Real AngTol = Precision::Angular();
244 TopoDS_Wire theWire = aWire;
245 BRepLib::BuildCurves3d(theWire);
246 Handle(ShapeFix_Shape) Fixer = new ShapeFix_Shape(theWire);
247 Fixer->SetPrecision(LinTol);
248 Fixer->SetMaxTolerance(LinTol);
250 theWire = TopoDS::Wire(Fixer->Shape());
252 TColGeom_SequenceOfCurve CurveSeq;
253 TopTools_SequenceOfShape LocSeq;
254 TColStd_SequenceOfReal FparSeq;
255 TColStd_SequenceOfReal LparSeq;
256 TColStd_SequenceOfReal TolSeq;
257 GeomAbs_CurveType CurType;
258 TopoDS_Vertex FirstVertex, LastVertex;
259 Standard_Boolean FinalReverse = Standard_False;
261 BRepTools_WireExplorer wexp(theWire) ;
262 for (; wexp.More(); wexp.Next())
264 TopoDS_Edge anEdge = wexp.Current();
265 Standard_Real fpar, lpar;
266 TopLoc_Location aLoc;
267 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aLoc, fpar, lpar);
271 BRepAdaptor_Curve BAcurve(anEdge);
272 GeomAbs_CurveType aType = BAcurve.GetType();
274 Handle(Geom_Curve) aBasisCurve = BAcurve.Curve().Curve();
276 if (aBasisCurve->IsPeriodic())
277 ElCLib::AdjustPeriodic(aBasisCurve->FirstParameter(), aBasisCurve->LastParameter(),
278 Precision::PConfusion(), fpar, lpar);
280 if (CurveSeq.IsEmpty())
282 CurveSeq.Append(aCurve);
283 TopoDS_Shape aLocShape;
284 aLocShape.Location(aLoc);
285 aLocShape.Orientation(wexp.Orientation());
286 LocSeq.Append(aLocShape);
287 FparSeq.Append(fpar);
288 LparSeq.Append(lpar);
290 FirstVertex = wexp.CurrentVertex();
291 if (anEdge.Orientation() == TopAbs_REVERSED)
292 FinalReverse = Standard_True;
296 Standard_Boolean Done = Standard_False;
297 Standard_Real NewFpar, NewLpar;
298 GeomAdaptor_Curve GAprevcurve(CurveSeq.Last());
299 TopoDS_Vertex CurVertex = wexp.CurrentVertex();
300 TopoDS_Vertex CurFirstVer = TopExp::FirstVertex(anEdge);
301 TopAbs_Orientation ConnectByOrigin = (CurVertex.IsSame(CurFirstVer))? TopAbs_FORWARD : TopAbs_REVERSED;
302 if (aCurve == CurveSeq.Last())
306 if (aBasisCurve->IsPeriodic())
308 if (NewLpar < NewFpar)
309 NewLpar += aBasisCurve->Period();
310 if (ConnectByOrigin == TopAbs_FORWARD)
311 ElCLib::AdjustPeriodic(FparSeq.Last(),
312 FparSeq.Last() + aBasisCurve->Period(),
313 Precision::PConfusion(), NewFpar, NewLpar);
315 ElCLib::AdjustPeriodic(FparSeq.Last() - aBasisCurve->Period(),
317 Precision::PConfusion(), NewFpar, NewLpar);
319 Done = Standard_True;
321 else if (aType == CurType &&
322 aType != GeomAbs_BezierCurve &&
323 aType != GeomAbs_BSplineCurve &&
324 aType != GeomAbs_OtherCurve)
329 gp_Lin aLine = BAcurve.Line();
330 gp_Lin PrevLine = GAprevcurve.Line();
331 if (aLine.Contains(PrevLine.Location(), LinTol) &&
332 aLine.Direction().IsParallel(PrevLine.Direction(), AngTol))
334 gp_Pnt P1 = ElCLib::Value(fpar, aLine);
335 gp_Pnt P2 = ElCLib::Value(lpar, aLine);
336 NewFpar = ElCLib::Parameter(PrevLine, P1);
337 NewLpar = ElCLib::Parameter(PrevLine, P2);
338 if (NewLpar < NewFpar)
340 Standard_Real MemNewFpar = NewFpar;
342 NewLpar = MemNewFpar;
343 ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
345 Done = Standard_True;
351 gp_Circ aCircle = BAcurve.Circle();
352 gp_Circ PrevCircle = GAprevcurve.Circle();
353 if (aCircle.Location().Distance(PrevCircle.Location()) <= LinTol &&
354 Abs(aCircle.Radius() - PrevCircle.Radius()) <= LinTol &&
355 aCircle.Axis().IsParallel(PrevCircle.Axis(), AngTol))
357 if (aCircle.Axis().Direction() * PrevCircle.Axis().Direction() < 0.)
359 Standard_Real memfpar = fpar;
362 ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
364 gp_Pnt P1 = ElCLib::Value(fpar, aCircle);
365 gp_Pnt P2 = ElCLib::Value(lpar, aCircle);
366 NewFpar = ElCLib::Parameter(PrevCircle, P1);
367 NewLpar = ElCLib::Parameter(PrevCircle, P2);
368 if (NewLpar < NewFpar)
370 //Standard_Real MemNewFpar = NewFpar, MemNewLpar = NewLpar;
371 if (ConnectByOrigin == TopAbs_FORWARD)
372 ElCLib::AdjustPeriodic(FparSeq.Last(),
373 FparSeq.Last() + 2.*M_PI,
374 Precision::PConfusion(), NewFpar, NewLpar);
376 ElCLib::AdjustPeriodic(FparSeq.Last() - 2.*M_PI,
378 Precision::PConfusion(), NewFpar, NewLpar);
379 Done = Standard_True;
383 case GeomAbs_Ellipse:
385 gp_Elips anEllipse = BAcurve.Ellipse();
386 gp_Elips PrevEllipse = GAprevcurve.Ellipse();
387 if (anEllipse.Focus1().Distance(PrevEllipse.Focus1()) <= LinTol &&
388 anEllipse.Focus2().Distance(PrevEllipse.Focus2()) <= LinTol &&
389 Abs(anEllipse.MajorRadius() - PrevEllipse.MajorRadius()) <= LinTol &&
390 Abs(anEllipse.MinorRadius() - PrevEllipse.MinorRadius()) <= LinTol &&
391 anEllipse.Axis().IsParallel(PrevEllipse.Axis(), AngTol))
393 if (anEllipse.Axis().Direction() * PrevEllipse.Axis().Direction() < 0.)
395 Standard_Real memfpar = fpar;
398 ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
400 gp_Pnt P1 = ElCLib::Value(fpar, anEllipse);
401 gp_Pnt P2 = ElCLib::Value(lpar, anEllipse);
402 NewFpar = ElCLib::Parameter(PrevEllipse, P1);
403 NewLpar = ElCLib::Parameter(PrevEllipse, P2);
404 if (NewLpar < NewFpar)
406 if (ConnectByOrigin == TopAbs_FORWARD)
407 ElCLib::AdjustPeriodic(FparSeq.Last(),
408 FparSeq.Last() + 2.*M_PI,
409 Precision::PConfusion(), NewFpar, NewLpar);
411 ElCLib::AdjustPeriodic(FparSeq.Last() - 2.*M_PI,
413 Precision::PConfusion(), NewFpar, NewLpar);
414 Done = Standard_True;
418 case GeomAbs_Hyperbola:
420 gp_Hypr aHypr = BAcurve.Hyperbola();
421 gp_Hypr PrevHypr = GAprevcurve.Hyperbola();
422 if (aHypr.Focus1().Distance(PrevHypr.Focus1()) <= LinTol &&
423 aHypr.Focus2().Distance(PrevHypr.Focus2()) <= LinTol &&
424 Abs(aHypr.MajorRadius() - PrevHypr.MajorRadius()) <= LinTol &&
425 Abs(aHypr.MinorRadius() - PrevHypr.MinorRadius()) <= LinTol &&
426 aHypr.Axis().IsParallel(PrevHypr.Axis(), AngTol))
428 gp_Pnt P1 = ElCLib::Value(fpar, aHypr);
429 gp_Pnt P2 = ElCLib::Value(lpar, aHypr);
430 NewFpar = ElCLib::Parameter(PrevHypr, P1);
431 NewLpar = ElCLib::Parameter(PrevHypr, P2);
432 if (NewLpar < NewFpar)
434 Standard_Real MemNewFpar = NewFpar;
436 NewLpar = MemNewFpar;
437 ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
439 Done = Standard_True;
443 case GeomAbs_Parabola:
445 gp_Parab aParab = BAcurve.Parabola();
446 gp_Parab PrevParab = GAprevcurve.Parabola();
447 if (aParab.Location().Distance(PrevParab.Location()) <= LinTol &&
448 aParab.Focus().Distance(PrevParab.Focus()) <= LinTol &&
449 Abs(aParab.Focal() - PrevParab.Focal()) <= LinTol &&
450 aParab.Axis().IsParallel(PrevParab.Axis(), AngTol))
452 gp_Pnt P1 = ElCLib::Value(fpar, aParab);
453 gp_Pnt P2 = ElCLib::Value(lpar, aParab);
454 NewFpar = ElCLib::Parameter(PrevParab, P1);
455 NewLpar = ElCLib::Parameter(PrevParab, P2);
456 if (NewLpar < NewFpar)
458 Standard_Real MemNewFpar = NewFpar;
460 NewLpar = MemNewFpar;
461 ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
463 Done = Standard_True;
467 } //end of switch and else
470 if (NewFpar < FparSeq.Last())
471 FparSeq(FparSeq.Length()) = NewFpar;
473 LparSeq(LparSeq.Length()) = NewLpar;
477 CurveSeq.Append(aCurve);
478 TopoDS_Shape aLocShape;
479 aLocShape.Location(aLoc);
480 aLocShape.Orientation(wexp.Orientation());
481 LocSeq.Append(aLocShape);
482 FparSeq.Append(fpar);
483 LparSeq.Append(lpar);
484 TolSeq.Append(BRep_Tool::Tolerance(CurVertex));
487 } //end of else (not first time)
489 LastVertex = wexp.CurrentVertex();
490 TolSeq.Append(BRep_Tool::Tolerance(LastVertex));
492 TopoDS_Vertex FirstVtx_final = (FinalReverse)? LastVertex : FirstVertex;
493 FirstVtx_final.Orientation(TopAbs_FORWARD);
494 TopoDS_Vertex LastVtx_final = (FinalReverse)? FirstVertex : LastVertex;
495 LastVtx_final.Orientation(TopAbs_REVERSED);
497 if (CurveSeq.IsEmpty())
500 Standard_Integer nb_curve = CurveSeq.Length(); //number of curves
501 TColGeom_Array1OfBSplineCurve tab(0,nb_curve-1); //array of the curves
502 TColStd_Array1OfReal tabtolvertex(0,nb_curve-1); //(0,nb_curve-2); //array of the tolerances
508 for (i = 1; i <= nb_curve; i++)
510 if (CurveSeq(i)->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
511 CurveSeq(i) = (*((Handle(Geom_TrimmedCurve)*)&(CurveSeq(i))))->BasisCurve();
513 Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(CurveSeq(i), FparSeq(i), LparSeq(i));
514 tab(i-1) = GeomConvert::CurveToBSplineCurve(aTrCurve);
515 tab(i-1)->Transform(LocSeq(i).Location().Transformation());
516 GeomConvert::C0BSplineToC1BSplineCurve(tab(i-1), Precision::Confusion());
517 if (LocSeq(i).Orientation() == TopAbs_REVERSED)
521 //char* name = new char[100];
522 //sprintf(name, "c%d", i);
523 //DrawTrSurf::Set(name, tab(i-1));
526 tabtolvertex(i-2) = TolSeq(i-1) * 5.;
528 tabtolvertex(nb_curve-1) = TolSeq(TolSeq.Length()) * 5.;
530 Standard_Boolean closed_flag = Standard_False;
531 Standard_Real closed_tolerance = 0.;
532 if (FirstVertex.IsSame(LastVertex) &&
533 GeomLProp::Continuity(tab(0), tab(nb_curve-1),
534 tab(0)->FirstParameter(),
535 tab(nb_curve-1)->LastParameter(),
536 Standard_False, Standard_False, LinTol, AngTol) >= GeomAbs_G1)
538 closed_flag = Standard_True ;
539 closed_tolerance = BRep_Tool::Tolerance(FirstVertex);
542 Handle(TColGeom_HArray1OfBSplineCurve) concatcurve; //array of the concatenated curves
543 Handle(TColStd_HArray1OfInteger) ArrayOfIndices; //array of the remining Vertex
544 GeomConvert::ConcatC1(tab,
549 closed_tolerance); //C1 concatenation
551 if (concatcurve->Length() > 1)
553 Standard_Real MaxTolVer = LinTol;
554 for (i = 1; i <= TolSeq.Length(); i++)
555 if (TolSeq(i) > MaxTolVer)
556 MaxTolVer = TolSeq(i);
559 GeomConvert_CompCurveToBSplineCurve Concat(concatcurve->Value(concatcurve->Lower()));
561 for (i = concatcurve->Lower()+1; i <= concatcurve->Upper(); i++)
562 Concat.Add( concatcurve->Value(i), MaxTolVer, Standard_True );
564 concatcurve->SetValue(concatcurve->Lower(), Concat.BSplineCurve());
567 ResEdge = BRepLib_MakeEdge(concatcurve->Value(concatcurve->Lower()),
568 FirstVtx_final, LastVtx_final,
569 concatcurve->Value(concatcurve->Lower())->FirstParameter(),
570 concatcurve->Value(concatcurve->Lower())->LastParameter());
574 if (CurveSeq(1)->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
575 CurveSeq(1) = (*((Handle(Geom_TrimmedCurve)*)&(CurveSeq(1))))->BasisCurve();
577 CurveSeq(1)->Transform(LocSeq(1).Location().Transformation());
578 ResEdge = BRepLib_MakeEdge(CurveSeq(1),
579 FirstVtx_final, LastVtx_final,
580 FparSeq(1), LparSeq(1));