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 <TColStd_SequenceOfBoolean.hxx>
47 #include <GeomAbs_CurveType.hxx>
48 #include <BRepAdaptor_Curve.hxx>
50 #include <BRepLib.hxx>
52 #include <ShapeFix_Shape.hxx>
53 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
56 #//include <DrawTrSurf.hxx>
59 //=======================================================================
60 //function : ConcatenateWire
62 //=======================================================================
64 TopoDS_Wire BRepAlgo::ConcatenateWire(const TopoDS_Wire& W,
65 const GeomAbs_Shape Option,
66 const Standard_Real TolAngular)
70 Standard_Integer nb_curve, //number of curves in the Wire
72 BRepTools_WireExplorer WExp(W) ;
75 Standard_Real First=0.,Last=0., //extremal values for the curve
78 tolleft,tolright; //Vertex tolerances
79 TopoDS_Vertex Vfirst,Vlast; //Vertex of the Wire
80 gp_Pnt Pfirst,Plast; //, Pint; corresponding points
82 BRepLib_MakeWire MakeResult;
83 Standard_Real closed_tolerance =0.0;
84 Standard_Boolean closed_flag = Standard_False ;
88 while ( WExp.More()){ //computation of the curve number
94 TColGeom_Array1OfBSplineCurve tab(0,nb_curve-1); //array of the wire's curve
95 TColStd_Array1OfReal tabtolvertex(0,nb_curve-2); //array of the tolerance's vertex
99 for (index=0 ;index<nb_curve; index++){ //main loop
100 edge = WExp.Current() ;
101 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(edge, L, First, Last);
102 Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(aCurve, First, Last);
103 tab(index) = GeomConvert::CurveToBSplineCurve(aTrCurve); //storage in a array
104 tab(index)->Transform(L.Transformation());
105 GeomConvert::C0BSplineToC1BSplineCurve(tab(index),Precision::Confusion());
107 if (index >= 1){ //continuity test loop
108 if (edge.Orientation()==TopAbs_REVERSED)
109 tab(index)->Reverse();
110 tolleft=BRep_Tool::Tolerance(TopExp::LastVertex(edge));
111 tolright=BRep_Tool::Tolerance(TopExp::FirstVertex(edge));
112 tabtolvertex(index-1)=Max(tolleft,tolright);
115 if(index==0){ //storage of the first edge features
117 if(edge.Orientation()==TopAbs_REVERSED){ //(usefull for the closed wire)
118 Vfirst=TopExp::LastVertex(edge);
119 tab(index)->Reverse();
122 Vfirst=TopExp::FirstVertex(edge);
125 if(index==nb_curve-1){ //storage of the last edge features
126 if(edge.Orientation()==TopAbs_REVERSED)
127 Vlast=TopExp::FirstVertex(edge);
129 Vlast=TopExp::LastVertex(edge);
134 if (BRep_Tool::Tolerance(Vfirst)>BRep_Tool::Tolerance(Vlast)) //computation of the closing tolerance
135 toler=BRep_Tool::Tolerance(Vfirst);
137 toler=BRep_Tool::Tolerance(Vlast);
139 Pfirst=BRep_Tool::Pnt(Vfirst);
140 Plast=BRep_Tool::Pnt(Vlast);
142 if ((Pfirst.Distance(Plast)<=toler)&& //C0 continuity test at the closing point
143 (GeomLProp::Continuity(tab(nb_curve-1),tab(0),Last,First0,
144 Standard_True,Standard_True,
145 toler, TolAngular)>=GeomAbs_G1))
147 closed_tolerance =toler; //if ClosedG1!=0 it will be True and
148 closed_flag = Standard_True ;
149 } //with the toler value
150 Handle(TColGeom_HArray1OfBSplineCurve) concatcurve; //array of the concatenated curves
151 Handle(TColStd_HArray1OfInteger) ArrayOfIndices; //array of the remining Vertex
152 if (Option==GeomAbs_G1)
153 GeomConvert::ConcatG1(tab,
157 closed_tolerance) ; //G1 concatenation
159 GeomConvert::ConcatC1(tab,
164 closed_tolerance); //C1 concatenation
166 for (index=0;index<=(concatcurve->Length()-1);index++){ //building of the resulting Wire
167 BRepLib_MakeEdge EdgeBuilder(concatcurve->Value(index));
168 edge = EdgeBuilder.Edge();
169 MakeResult.Add(edge);
174 TColGeom_Array1OfBSplineCurve tab(0,0); //array of the wire's curve
175 TColStd_Array1OfReal tabtolvertex(0,0); //array of the tolerance's vertex
178 edge = WExp.Current() ;
179 tab(0) = GeomConvert::CurveToBSplineCurve(new //storage in a array
180 Geom_TrimmedCurve(BRep_Tool::Curve(edge,L,First,Last),First,Last));
181 tab(0)->Transform(L.Transformation());
182 GeomConvert::C0BSplineToC1BSplineCurve(tab(0),Precision::Confusion());
183 if (edge.Orientation()==TopAbs_REVERSED)
185 tolleft=BRep_Tool::Tolerance(TopExp::LastVertex(edge));
186 tolright=BRep_Tool::Tolerance(TopExp::FirstVertex(edge));
187 tabtolvertex(0)=Max(tolleft,tolright);
188 if(edge.Orientation()==TopAbs_REVERSED){ //(usefull for the closed wire)
189 Vfirst=TopExp::LastVertex(edge);
190 Vlast=TopExp::FirstVertex(edge);
194 Vfirst=TopExp::FirstVertex(edge);
195 Vlast = TopExp::LastVertex(edge) ;
197 Pfirst=BRep_Tool::Pnt(Vfirst);
198 Plast=BRep_Tool::Pnt(Vlast);
199 if ((Pfirst.Distance(Plast)<=toler)&& //C0 continuity test at the closing point
200 (GeomLProp::Continuity(tab(0),tab(0),Last,First,
201 Standard_True,Standard_True,
202 toler, TolAngular)>=GeomAbs_G1))
204 closed_tolerance =toler; //if ClosedG1!=0 it will be True and
205 closed_flag = Standard_True ;
206 } //with the toler value
207 Handle(TColGeom_HArray1OfBSplineCurve) concatcurve; //array of the concatenated curves
208 Handle(TColStd_HArray1OfInteger) ArrayOfIndices; //array of the remining Vertex
209 if (Option==GeomAbs_G1)
210 GeomConvert::ConcatG1(tab,
214 closed_tolerance) ; //G1 concatenation
216 GeomConvert::ConcatC1(tab,
221 closed_tolerance); //C1 concatenation
223 for (index=0;index<=(concatcurve->Length()-1);index++){ //building of the resulting Wire
224 BRepLib_MakeEdge EdgeBuilder(concatcurve->Value(index));
225 edge = EdgeBuilder.Edge();
226 MakeResult.Add(edge);
229 return MakeResult.Wire() ;
233 //=======================================================================
234 //function : ConcatenateWireC0
236 //=======================================================================
238 TopoDS_Edge BRepAlgo::ConcatenateWireC0(const TopoDS_Wire& aWire)
240 Standard_Real LinTol = Precision::Confusion();
241 Standard_Real AngTol = Precision::Angular();
245 TopoDS_Wire theWire = aWire;
246 BRepLib::BuildCurves3d(theWire);
247 Handle(ShapeFix_Shape) Fixer = new ShapeFix_Shape(theWire);
248 Fixer->SetPrecision(LinTol);
249 Fixer->SetMaxTolerance(LinTol);
251 theWire = TopoDS::Wire(Fixer->Shape());
253 TColGeom_SequenceOfCurve CurveSeq;
254 TColStd_SequenceOfReal FparSeq;
255 TColStd_SequenceOfReal LparSeq;
256 TColStd_SequenceOfReal TolSeq;
257 TColStd_SequenceOfBoolean IsFwdSeq;
258 GeomAbs_CurveType CurType = GeomAbs_OtherCurve;
259 TopoDS_Vertex FirstVertex, LastVertex;
261 BRepTools_WireExplorer wexp(theWire);
263 for (; wexp.More(); wexp.Next()) {
264 TopoDS_Edge anEdge = wexp.Current();
265 Standard_Real fpar, lpar;
266 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
271 GeomAdaptor_Curve aGACurve(aCurve);
272 GeomAbs_CurveType aType = aGACurve.GetType();
273 Handle(Geom_Curve) aBasisCurve = aGACurve.Curve();
274 Standard_Boolean isFwd = (wexp.Orientation() != TopAbs_REVERSED);
276 if (aBasisCurve->IsPeriodic()) {
277 ElCLib::AdjustPeriodic
278 (aBasisCurve->FirstParameter(), aBasisCurve->LastParameter(),
279 Precision::PConfusion(), fpar, lpar);
285 if (CurveSeq.IsEmpty()) {
286 CurveSeq.Append(aCurve);
287 FparSeq.Append(fpar);
288 LparSeq.Append(lpar);
289 IsFwdSeq.Append(isFwd);
291 FirstVertex = wexp.CurrentVertex();
293 Standard_Boolean isSameCurve = Standard_False;
294 Standard_Real NewFpar, NewLpar;
295 GeomAdaptor_Curve GAprevcurve(CurveSeq.Last());
297 if (aCurve == CurveSeq.Last()) {
300 isSameCurve = Standard_True;
301 } else if (aType == CurType &&
302 aType != GeomAbs_BezierCurve &&
303 aType != GeomAbs_BSplineCurve &&
304 aType != GeomAbs_OtherCurve) {
308 gp_Lin aLine = aGACurve.Line();
309 gp_Lin PrevLine = GAprevcurve.Line();
311 if (aLine.Contains(PrevLine.Location(), LinTol) &&
312 aLine.Direction().IsParallel(PrevLine.Direction(), AngTol)) {
313 gp_Pnt P1 = ElCLib::Value(fpar, aLine);
314 gp_Pnt P2 = ElCLib::Value(lpar, aLine);
316 NewFpar = ElCLib::Parameter(PrevLine, P1);
317 NewLpar = ElCLib::Parameter(PrevLine, P2);
318 isSameCurve = Standard_True;
324 gp_Circ aCircle = aGACurve.Circle();
325 gp_Circ PrevCircle = GAprevcurve.Circle();
327 if (aCircle.Location().Distance(PrevCircle.Location()) <= LinTol &&
328 Abs(aCircle.Radius() - PrevCircle.Radius()) <= LinTol &&
329 aCircle.Axis().IsParallel(PrevCircle.Axis(), AngTol)) {
330 gp_Pnt P1 = ElCLib::Value(fpar, aCircle);
331 gp_Pnt P2 = ElCLib::Value(lpar, aCircle);
333 NewFpar = ElCLib::Parameter(PrevCircle, P1);
334 NewLpar = ElCLib::Parameter(PrevCircle, P2);
335 isSameCurve = Standard_True;
339 case GeomAbs_Ellipse:
341 gp_Elips anEllipse = aGACurve.Ellipse();
342 gp_Elips PrevEllipse = GAprevcurve.Ellipse();
344 if (anEllipse.Focus1().Distance(PrevEllipse.Focus1()) <= LinTol &&
345 anEllipse.Focus2().Distance(PrevEllipse.Focus2()) <= LinTol &&
346 Abs(anEllipse.MajorRadius() - PrevEllipse.MajorRadius()) <= LinTol &&
347 Abs(anEllipse.MinorRadius() - PrevEllipse.MinorRadius()) <= LinTol &&
348 anEllipse.Axis().IsParallel(PrevEllipse.Axis(), AngTol)) {
349 gp_Pnt P1 = ElCLib::Value(fpar, anEllipse);
350 gp_Pnt P2 = ElCLib::Value(lpar, anEllipse);
352 NewFpar = ElCLib::Parameter(PrevEllipse, P1);
353 NewLpar = ElCLib::Parameter(PrevEllipse, P2);
354 isSameCurve = Standard_True;
358 case GeomAbs_Hyperbola:
360 gp_Hypr aHypr = aGACurve.Hyperbola();
361 gp_Hypr PrevHypr = GAprevcurve.Hyperbola();
363 if (aHypr.Focus1().Distance(PrevHypr.Focus1()) <= LinTol &&
364 aHypr.Focus2().Distance(PrevHypr.Focus2()) <= LinTol &&
365 Abs(aHypr.MajorRadius() - PrevHypr.MajorRadius()) <= LinTol &&
366 Abs(aHypr.MinorRadius() - PrevHypr.MinorRadius()) <= LinTol &&
367 aHypr.Axis().IsParallel(PrevHypr.Axis(), AngTol)) {
368 gp_Pnt P1 = ElCLib::Value(fpar, aHypr);
369 gp_Pnt P2 = ElCLib::Value(lpar, aHypr);
371 NewFpar = ElCLib::Parameter(PrevHypr, P1);
372 NewLpar = ElCLib::Parameter(PrevHypr, P2);
373 isSameCurve = Standard_True;
377 case GeomAbs_Parabola:
379 gp_Parab aParab = aGACurve.Parabola();
380 gp_Parab PrevParab = GAprevcurve.Parabola();
382 if (aParab.Location().Distance(PrevParab.Location()) <= LinTol &&
383 aParab.Focus().Distance(PrevParab.Focus()) <= LinTol &&
384 Abs(aParab.Focal() - PrevParab.Focal()) <= LinTol &&
385 aParab.Axis().IsParallel(PrevParab.Axis(), AngTol)) {
386 gp_Pnt P1 = ElCLib::Value(fpar, aParab);
387 gp_Pnt P2 = ElCLib::Value(lpar, aParab);
389 NewFpar = ElCLib::Parameter(PrevParab, P1);
390 NewLpar = ElCLib::Parameter(PrevParab, P2);
391 isSameCurve = Standard_True;
401 const Standard_Boolean isSameDir = (isFwd == IsFwdSeq.Last());
403 if (aBasisCurve->IsPeriodic()) {
404 // Treat periodic curves.
405 const Standard_Real aPeriod = aBasisCurve->Period();
408 // Check if first parameter is greater then the last one.
409 while (NewFpar > NewLpar) {
412 } else { // !isSameDir
413 // Check if last parameter is greater then the first one.
414 while (NewLpar > NewFpar) {
419 const Standard_Real aTmpPar = NewLpar;
425 // Udjust parameters on periodic curves.
426 if (IsFwdSeq.Last()) {
427 // The current curve should be after the previous one.
428 ElCLib::AdjustPeriodic(LparSeq.Last(), LparSeq.Last() + aPeriod,
429 Precision::PConfusion(), NewFpar, NewLpar);
431 // The current curve should be before the previous one.
432 ElCLib::AdjustPeriodic(FparSeq.Last() - aPeriod, FparSeq.Last(),
433 Precision::PConfusion(), NewFpar, NewLpar);
435 } else if (!isSameDir) {
436 // Not periodic curves. Opposite dirs.
437 const Standard_Real aTmpPar = NewLpar;
443 if (IsFwdSeq.Last()) {
444 // Update last parameter
445 LparSeq(LparSeq.Length()) = NewLpar;
447 // Update first parameter
448 FparSeq(FparSeq.Length()) = NewFpar;
452 CurveSeq.Append(aCurve);
453 FparSeq.Append(fpar);
454 LparSeq.Append(lpar);
455 IsFwdSeq.Append(isFwd);
456 TolSeq.Append(BRep_Tool::Tolerance(wexp.CurrentVertex()));
462 LastVertex = wexp.CurrentVertex();
463 TolSeq.Append(BRep_Tool::Tolerance(LastVertex));
465 Standard_Boolean isReverse = Standard_False;
467 if (!IsFwdSeq.IsEmpty()) {
468 isReverse = !IsFwdSeq(1);
471 TopoDS_Vertex FirstVtx_final = (isReverse)? LastVertex : FirstVertex;
472 FirstVtx_final.Orientation(TopAbs_FORWARD);
473 TopoDS_Vertex LastVtx_final = (isReverse)? FirstVertex : LastVertex;
474 LastVtx_final.Orientation(TopAbs_REVERSED);
476 if (CurveSeq.IsEmpty())
479 Standard_Integer nb_curve = CurveSeq.Length(); //number of curves
480 TColGeom_Array1OfBSplineCurve tab(0,nb_curve-1); //array of the curves
481 TColStd_Array1OfReal tabtolvertex(0,nb_curve-1); //(0,nb_curve-2); //array of the tolerances
487 for (i = 1; i <= nb_curve; i++)
489 if (CurveSeq(i)->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
490 CurveSeq(i) = (*((Handle(Geom_TrimmedCurve)*)&(CurveSeq(i))))->BasisCurve();
492 Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(CurveSeq(i), FparSeq(i), LparSeq(i));
493 tab(i-1) = GeomConvert::CurveToBSplineCurve(aTrCurve);
494 GeomConvert::C0BSplineToC1BSplineCurve(tab(i-1), Precision::Confusion());
501 //char* name = new char[100];
502 //sprintf(name, "c%d", i);
503 //DrawTrSurf::Set(name, tab(i-1));
506 tabtolvertex(i-2) = TolSeq(i-1) * 5.;
508 tabtolvertex(nb_curve-1) = TolSeq(TolSeq.Length()) * 5.;
510 Standard_Boolean closed_flag = Standard_False;
511 Standard_Real closed_tolerance = 0.;
512 if (FirstVertex.IsSame(LastVertex) &&
513 GeomLProp::Continuity(tab(0), tab(nb_curve-1),
514 tab(0)->FirstParameter(),
515 tab(nb_curve-1)->LastParameter(),
516 Standard_False, Standard_False, LinTol, AngTol) >= GeomAbs_G1)
518 closed_flag = Standard_True ;
519 closed_tolerance = BRep_Tool::Tolerance(FirstVertex);
522 Handle(TColGeom_HArray1OfBSplineCurve) concatcurve; //array of the concatenated curves
523 Handle(TColStd_HArray1OfInteger) ArrayOfIndices; //array of the remining Vertex
524 GeomConvert::ConcatC1(tab,
529 closed_tolerance); //C1 concatenation
531 if (concatcurve->Length() > 1)
533 Standard_Real MaxTolVer = LinTol;
534 for (i = 1; i <= TolSeq.Length(); i++)
535 if (TolSeq(i) > MaxTolVer)
536 MaxTolVer = TolSeq(i);
539 GeomConvert_CompCurveToBSplineCurve Concat(concatcurve->Value(concatcurve->Lower()));
541 for (i = concatcurve->Lower()+1; i <= concatcurve->Upper(); i++)
542 Concat.Add( concatcurve->Value(i), MaxTolVer, Standard_True );
544 concatcurve->SetValue(concatcurve->Lower(), Concat.BSplineCurve());
547 ResEdge = BRepLib_MakeEdge(concatcurve->Value(concatcurve->Lower()),
548 FirstVtx_final, LastVtx_final,
549 concatcurve->Value(concatcurve->Lower())->FirstParameter(),
550 concatcurve->Value(concatcurve->Lower())->LastParameter());
554 if (CurveSeq(1)->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
555 CurveSeq(1) = (*((Handle(Geom_TrimmedCurve)*)&(CurveSeq(1))))->BasisCurve();
557 Handle(Geom_Curve) aCopyCurve =
558 Handle(Geom_Curve)::DownCast(CurveSeq(1)->Copy());
560 ResEdge = BRepLib_MakeEdge(aCopyCurve,
561 FirstVtx_final, LastVtx_final,
562 FparSeq(1), LparSeq(1));