0033661: Data Exchange, Step Import - Tessellated GDTs are not imported
[occt.git] / src / BRepAlgo / BRepAlgo.cxx
CommitLineData
b311480e 1// Created on: 1997-03-10
2// Created by: Stagiaire Francois DUMONT
3// Copyright (c) 1997-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 16
42cf5bc1 17
b71cb85f 18#include <BRep_Builder.hxx>
7fd59977 19#include <BRep_Tool.hxx>
b71cb85f 20#include <BRepBuilderAPI_MakeEdge.hxx>
21#include <BRepBuilderAPI_MakeFace.hxx>
22#include <BRepBuilderAPI_MakeWire.hxx>
42cf5bc1 23#include <BRepAdaptor_Curve.hxx>
b71cb85f 24#include <BRepAdaptor_Curve2d.hxx>
42cf5bc1 25#include <BRepAlgo.hxx>
26#include <BRepLib.hxx>
7fd59977 27#include <BRepLib_MakeEdge.hxx>
28#include <BRepLib_MakeWire.hxx>
42cf5bc1 29#include <BRepTools_WireExplorer.hxx>
30#include <ElCLib.hxx>
31#include <Geom_Curve.hxx>
32#include <Geom_TrimmedCurve.hxx>
b71cb85f 33#include <Geom2d_TrimmedCurve.hxx>
34#include <Geom2dConvert_ApproxArcsSegments.hxx>
42cf5bc1 35#include <GeomAbs_CurveType.hxx>
7fd59977 36#include <GeomConvert.hxx>
42cf5bc1 37#include <GeomConvert_CompCurveToBSplineCurve.hxx>
7fd59977 38#include <GeomLProp.hxx>
b71cb85f 39#include <NCollection_Vector.hxx>
42cf5bc1 40#include <gp_Pnt.hxx>
7fd59977 41#include <Precision.hxx>
42cf5bc1 42#include <ShapeFix_Shape.hxx>
7fd59977 43#include <TColGeom_Array1OfBSplineCurve.hxx>
44#include <TColGeom_HArray1OfBSplineCurve.hxx>
42cf5bc1 45#include <TColGeom_SequenceOfCurve.hxx>
7fd59977 46#include <TColStd_Array1OfBoolean.hxx>
42cf5bc1 47#include <TColStd_Array1OfReal.hxx>
48#include <TColStd_SequenceOfBoolean.hxx>
49#include <TColStd_SequenceOfReal.hxx>
50#include <TopExp.hxx>
b71cb85f 51#include <TopExp_Explorer.hxx>
42cf5bc1 52#include <TopLoc_Location.hxx>
53#include <TopoDS.hxx>
7fd59977 54#include <TopoDS_Edge.hxx>
42cf5bc1 55#include <TopoDS_Shape.hxx>
7fd59977 56#include <TopoDS_Vertex.hxx>
42cf5bc1 57#include <TopoDS_Wire.hxx>
51a849d7 58
b71cb85f 59// The minimal tolerance of approximation (edges can be defined with yet smaller tolerance)
60static const Standard_Real MINIMAL_TOLERANCE = 0.0001;
61
62namespace {
63
64struct OrientedCurve
65{
66 Handle(Geom2d_TrimmedCurve) Curve;
67 Standard_Boolean IsReverse;
68 inline gp_Pnt2d Point (const Standard_Boolean isEnd) const
69 {
70 if (isEnd == IsReverse)
71 return Curve->StartPoint();
72 return Curve->EndPoint();
73 }
74};
75
76}
77
78//=======================================================================
79//function : ConvertWire
80//purpose :
81//=======================================================================
82
83TopoDS_Wire BRepAlgo::ConvertWire(const TopoDS_Wire& theWire,
84 const Standard_Real theAngleTol,
85 const TopoDS_Face& theFace)
86{
87 TopoDS_Wire aResult;
88 Standard_Real aMaxTol(0.);
89 const Handle(Geom_Surface) aSurf = BRep_Tool::Surface(theFace);
90 NCollection_Vector<OrientedCurve> vecCurve;
91
92 BRepTools_WireExplorer anExpE(theWire, theFace);
93 // Explore the edges in the current wire, in their connection order
94 for (; anExpE.More(); anExpE.Next()) {
95 const TopoDS_Edge& anEdge = anExpE.Current();
96 BRepAdaptor_Curve2d aCurve(anEdge, theFace);
97 Standard_Real aTol = BRep_Tool::Tolerance(anEdge);
98 if (aTol < MINIMAL_TOLERANCE)
99 aTol = MINIMAL_TOLERANCE;
100 if (aTol > aMaxTol)
101 aMaxTol = aTol;
102 Geom2dConvert_ApproxArcsSegments anAlgo(aCurve, aTol, theAngleTol);
103 const TColGeom2d_SequenceOfCurve& aResultApprox = anAlgo.GetResult();
104
105 // Form the array of approximated elementary curves
106 if (anEdge.Orientation() == TopAbs_REVERSED) {
107 for (Standard_Integer iCrv = aResultApprox.Length(); iCrv > 0 ; iCrv--) {
108 const Handle(Geom2d_Curve)& aCrv = aResultApprox(iCrv);
109 if (aCrv.IsNull() == Standard_False) {
110 OrientedCurve& anOCurve = vecCurve.Append(OrientedCurve());
111 anOCurve.Curve = Handle(Geom2d_TrimmedCurve)::DownCast(aCrv);
112 anOCurve.IsReverse = Standard_True;
113 }
114 }
115 } else {
116 for (Standard_Integer iCrv = 1; iCrv <= aResultApprox.Length(); iCrv++) {
117 const Handle(Geom2d_Curve)& aCrv = aResultApprox(iCrv);
118 if (aCrv.IsNull() == Standard_False) {
119 OrientedCurve& anOCurve = vecCurve.Append(OrientedCurve());
120 anOCurve.Curve = Handle(Geom2d_TrimmedCurve)::DownCast(aCrv);
121 anOCurve.IsReverse = Standard_False;
122 }
123 }
124 }
125 }
126
127 if (vecCurve.Length() > 0)
128 {
129 // Build the first vertex
130 BRep_Builder aVBuilder;
131 gp_Pnt2d aPnt[2] = {
132 vecCurve(0).Point(Standard_False),
133 vecCurve(vecCurve.Length() - 1).Point(Standard_True)
134 };
135 Standard_Real aDist = aPnt[0].Distance(aPnt[1]);
136 if (aDist > aMaxTol + Precision::Confusion())
137 aDist = Precision::Confusion();
138 else {
139 aDist = 0.5 * aDist + Precision::Confusion();
140 aPnt[0] = 0.5 * (aPnt[0].XY() + aPnt[1].XY());
141 }
142 gp_Pnt aPnt3d;
143 aSurf->D0(aPnt[0].X(), aPnt[0].Y(), aPnt3d);
144 TopoDS_Vertex aFirstVertex;
145 aVBuilder.MakeVertex(aFirstVertex, aPnt3d, aDist);
146
147 // Loop creating edges
148 BRepBuilderAPI_MakeWire aMkWire;
149 TopoDS_Edge anEdgeRes;
150 TopoDS_Vertex aVertex = aFirstVertex;
151 for (Standard_Integer iCrv = 0; iCrv < vecCurve.Length(); iCrv++) {
152 const OrientedCurve& anOCurve = vecCurve(iCrv);
153 TopoDS_Vertex aNextVertex;
154 aPnt[0] = anOCurve.Point(Standard_True);
155 if (iCrv == vecCurve.Length() - 1) {
156 aPnt[1] = vecCurve(0).Point(Standard_False);
157 aDist = aPnt[0].Distance(aPnt[1]);
158 if (aDist > aMaxTol + Precision::Confusion()) {
159 aSurf->D0(aPnt[0].X(), aPnt[0].Y(), aPnt3d);
160 aVBuilder.MakeVertex(aNextVertex, aPnt3d, Precision::Confusion());
161 } else {
162 aNextVertex = aFirstVertex;
163 }
164 } else {
165 aPnt[1] = vecCurve(iCrv + 1).Point(Standard_False);
166 aDist = 0.5 * (aPnt[0].Distance(aPnt[1])) + Precision::Confusion();
167 aPnt[0] = 0.5 * (aPnt[0].XY() + aPnt[1].XY());
168 aSurf->D0(aPnt[0].X(), aPnt[0].Y(), aPnt3d);
169 aVBuilder.MakeVertex(aNextVertex, aPnt3d, aDist);
170 }
171 const Standard_Real aParam[2] = {
172 anOCurve.Curve->FirstParameter(),
173 anOCurve.Curve->LastParameter()
174 };
175 if (anOCurve.IsReverse) {
176 BRepBuilderAPI_MakeEdge aMkEdge(anOCurve.Curve, aSurf, aNextVertex,
177 aVertex, aParam[0], aParam[1]);
178 anEdgeRes = aMkEdge.Edge();
179 anEdgeRes.Orientation(TopAbs_REVERSED);
180 } else {
181 BRepBuilderAPI_MakeEdge aMkEdge(anOCurve.Curve, aSurf, aVertex,
182 aNextVertex, aParam[0], aParam[1]);
183 anEdgeRes = aMkEdge.Edge();
184 }
185 aVertex = aNextVertex;
186 aMkWire.Add(anEdgeRes);
187 }
188
189 if (aMkWire.IsDone())
190 aResult = aMkWire.Wire();
191 }
192 return aResult;
193}
194
195//=======================================================================
196//function : ConvertFace
197//purpose :
198//=======================================================================
199
200TopoDS_Face BRepAlgo::ConvertFace (const TopoDS_Face& theFace,
201 const Standard_Real theAngleTolerance)
202{
203 TopoDS_Face aResult;
204 const Handle(Geom_Surface) aSurf = BRep_Tool::Surface(theFace);
205 BRepBuilderAPI_MakeFace aMkFace(aSurf,Precision::Confusion());
206
207 TopExp_Explorer anExp(theFace, TopAbs_WIRE);
208 for (; anExp.More(); anExp.Next()) {
209 const TopoDS_Wire& aWire = TopoDS::Wire(anExp.Current());
210 const TopoDS_Wire aNewWire = ConvertWire(aWire, theAngleTolerance, theFace);
211 aMkFace.Add(aNewWire);
212 }
213 if (aMkFace.IsDone()) {
214 aResult = aMkFace.Face();
215 }
216 return aResult;
217}
218
7fd59977 219//=======================================================================
220//function : ConcatenateWire
221//purpose :
222//=======================================================================
223
224TopoDS_Wire BRepAlgo::ConcatenateWire(const TopoDS_Wire& W,
0272e740 225 const GeomAbs_Shape Option,
226 const Standard_Real TolAngular)
7fd59977 227{
228
229
230 Standard_Integer nb_curve, //number of curves in the Wire
0272e740 231 index;
7fd59977 232 BRepTools_WireExplorer WExp(W) ;
233 TopoDS_Edge edge;
234 TopLoc_Location L ;
235 Standard_Real First=0.,Last=0., //extremal values for the curve
0272e740 236 First0 = 0.,
237 toler = 0.,
238 tolleft,tolright; //Vertex tolerances
7fd59977 239 TopoDS_Vertex Vfirst,Vlast; //Vertex of the Wire
240 gp_Pnt Pfirst,Plast; //, Pint; corresponding points
241
242 BRepLib_MakeWire MakeResult;
243 Standard_Real closed_tolerance =0.0;
244 Standard_Boolean closed_flag = Standard_False ;
0272e740 245
7fd59977 246 nb_curve = 0;
0272e740 247
7fd59977 248 while ( WExp.More()){ //computation of the curve number
249 nb_curve++ ;
250 WExp.Next();
251 }
0272e740 252
7fd59977 253 if (nb_curve > 1) {
254 TColGeom_Array1OfBSplineCurve tab(0,nb_curve-1); //array of the wire's curve
255 TColStd_Array1OfReal tabtolvertex(0,nb_curve-2); //array of the tolerance's vertex
0272e740 256
7fd59977 257 WExp.Init(W);
0272e740 258
7fd59977 259 for (index=0 ;index<nb_curve; index++){ //main loop
260 edge = WExp.Current() ;
0272e740 261 const Handle(Geom_Curve)& aCurve = BRep_Tool::Curve(edge, L, First, Last);
51a849d7 262 Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(aCurve, First, Last);
263 tab(index) = GeomConvert::CurveToBSplineCurve(aTrCurve); //storage in a array
7fd59977 264 tab(index)->Transform(L.Transformation());
265 GeomConvert::C0BSplineToC1BSplineCurve(tab(index),Precision::Confusion());
0272e740 266
7fd59977 267 if (index >= 1){ //continuity test loop
0272e740 268 if (edge.Orientation()==TopAbs_REVERSED)
269 tab(index)->Reverse();
270 tolleft=BRep_Tool::Tolerance(TopExp::LastVertex(edge));
271 tolright=BRep_Tool::Tolerance(TopExp::FirstVertex(edge));
272 tabtolvertex(index-1)=Max(tolleft,tolright);
7fd59977 273 }
0272e740 274
7fd59977 275 if(index==0){ //storage of the first edge features
0272e740 276 First0=First;
b81b237f 277 if(edge.Orientation()==TopAbs_REVERSED){ //(useful for the closed wire)
0272e740 278 Vfirst=TopExp::LastVertex(edge);
279 tab(index)->Reverse();
280 }
281 else
282 Vfirst=TopExp::FirstVertex(edge);
7fd59977 283 }
0272e740 284
7fd59977 285 if(index==nb_curve-1){ //storage of the last edge features
0272e740 286 if(edge.Orientation()==TopAbs_REVERSED)
287 Vlast=TopExp::FirstVertex(edge);
288 else
289 Vlast=TopExp::LastVertex(edge);
7fd59977 290 }
291 WExp.Next() ;
292 }
0272e740 293
7fd59977 294 if (BRep_Tool::Tolerance(Vfirst)>BRep_Tool::Tolerance(Vlast)) //computation of the closing tolerance
295 toler=BRep_Tool::Tolerance(Vfirst);
296 else
297 toler=BRep_Tool::Tolerance(Vlast);
0272e740 298
7fd59977 299 Pfirst=BRep_Tool::Pnt(Vfirst);
300 Plast=BRep_Tool::Pnt(Vlast);
0272e740 301
7fd59977 302 if ((Pfirst.Distance(Plast)<=toler)&& //C0 continuity test at the closing point
0272e740 303 (GeomLProp::Continuity(tab(nb_curve-1),tab(0),Last,First0,
304 Standard_True,Standard_True,
305 toler, TolAngular)>=GeomAbs_G1))
306 {
307 closed_tolerance =toler; //if ClosedG1!=0 it will be True and
308 closed_flag = Standard_True ;
309 } //with the toler value
7fd59977 310 Handle(TColGeom_HArray1OfBSplineCurve) concatcurve; //array of the concatenated curves
4551e1be 311 Handle(TColStd_HArray1OfInteger) ArrayOfIndices; //array of the remaining Vertex
7fd59977 312 if (Option==GeomAbs_G1)
313 GeomConvert::ConcatG1(tab,
0272e740 314 tabtolvertex,
315 concatcurve,
316 closed_flag,
317 closed_tolerance) ; //G1 concatenation
7fd59977 318 else
319 GeomConvert::ConcatC1(tab,
0272e740 320 tabtolvertex,
321 ArrayOfIndices,
322 concatcurve,
323 closed_flag,
324 closed_tolerance); //C1 concatenation
325
7fd59977 326 for (index=0;index<=(concatcurve->Length()-1);index++){ //building of the resulting Wire
327 BRepLib_MakeEdge EdgeBuilder(concatcurve->Value(index));
328 edge = EdgeBuilder.Edge();
329 MakeResult.Add(edge);
330 }
331
332 }
333 else {
0272e740 334
7fd59977 335 WExp.Init(W);
0272e740 336
7fd59977 337 edge = WExp.Current() ;
0272e740 338 const Handle(Geom_Curve)& aC = BRep_Tool::Curve(edge,L,First,Last);
339 Handle(Geom_BSplineCurve) aBS = GeomConvert::CurveToBSplineCurve(new Geom_TrimmedCurve(aC,First,Last));
340 aBS->Transform(L.Transformation());
341 GeomConvert::C0BSplineToC1BSplineCurve(aBS, Precision::Confusion());
7fd59977 342 if (edge.Orientation()==TopAbs_REVERSED)
0272e740 343 {
344 aBS->Reverse();
7fd59977 345 }
0272e740 346
347 BRepLib_MakeEdge EdgeBuilder(aBS);
348 edge = EdgeBuilder.Edge();
349 MakeResult.Add(edge);
7fd59977 350 }
351 return MakeResult.Wire() ;
0272e740 352
7fd59977 353}
354
51a849d7 355//=======================================================================
356//function : ConcatenateWireC0
357//purpose :
358//=======================================================================
359
360TopoDS_Edge BRepAlgo::ConcatenateWireC0(const TopoDS_Wire& aWire)
361{
362 Standard_Real LinTol = Precision::Confusion();
363 Standard_Real AngTol = Precision::Angular();
364
365 TopoDS_Edge ResEdge;
7fd59977 366
51a849d7 367 TopoDS_Wire theWire = aWire;
368 BRepLib::BuildCurves3d(theWire);
369 Handle(ShapeFix_Shape) Fixer = new ShapeFix_Shape(theWire);
370 Fixer->SetPrecision(LinTol);
371 Fixer->SetMaxTolerance(LinTol);
372 Fixer->Perform();
373 theWire = TopoDS::Wire(Fixer->Shape());
374
375 TColGeom_SequenceOfCurve CurveSeq;
51a849d7 376 TColStd_SequenceOfReal FparSeq;
377 TColStd_SequenceOfReal LparSeq;
378 TColStd_SequenceOfReal TolSeq;
6f005d2a 379 TColStd_SequenceOfBoolean IsFwdSeq;
1d47d8d0 380 GeomAbs_CurveType CurType = GeomAbs_OtherCurve;
51a849d7 381 TopoDS_Vertex FirstVertex, LastVertex;
51a849d7 382
6f005d2a 383 BRepTools_WireExplorer wexp(theWire);
51a849d7 384
6f005d2a 385 for (; wexp.More(); wexp.Next()) {
b2fedee6 386 const TopoDS_Edge& anEdge = wexp.Current();
6f005d2a 387 Standard_Real fpar, lpar;
388 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
51a849d7 389
6f005d2a 390 if (aCurve.IsNull())
391 continue;
51a849d7 392
6f005d2a 393 GeomAdaptor_Curve aGACurve(aCurve);
394 GeomAbs_CurveType aType = aGACurve.GetType();
b2fedee6 395 const Handle(Geom_Curve)& aBasisCurve = aGACurve.Curve();
6f005d2a 396 Standard_Boolean isFwd = (wexp.Orientation() != TopAbs_REVERSED);
51a849d7 397
6f005d2a 398 if (aBasisCurve->IsPeriodic()) {
399 ElCLib::AdjustPeriodic
400 (aBasisCurve->FirstParameter(), aBasisCurve->LastParameter(),
401 Precision::PConfusion(), fpar, lpar);
6f005d2a 402 }
403
404 if (CurveSeq.IsEmpty()) {
405 CurveSeq.Append(aCurve);
406 FparSeq.Append(fpar);
407 LparSeq.Append(lpar);
408 IsFwdSeq.Append(isFwd);
409 CurType = aType;
410 FirstVertex = wexp.CurrentVertex();
411 } else {
412 Standard_Boolean isSameCurve = Standard_False;
498ce76b 413 Standard_Real NewFpar = RealFirst(), NewLpar = RealLast();
6f005d2a 414 GeomAdaptor_Curve GAprevcurve(CurveSeq.Last());
415
416 if (aCurve == CurveSeq.Last()) {
417 NewFpar = fpar;
418 NewLpar = lpar;
419 isSameCurve = Standard_True;
1aec3320 420 } else if (aType == CurType) {
0272e740 421 switch (aType) {
422 case GeomAbs_Line:
423 {
424 gp_Lin aLine = aGACurve.Line();
425 gp_Lin PrevLine = GAprevcurve.Line();
426
427 if (aLine.Contains(PrevLine.Location(), LinTol) &&
428 aLine.Direction().IsParallel(PrevLine.Direction(), AngTol)) {
429 gp_Pnt P1 = ElCLib::Value(fpar, aLine);
430 gp_Pnt P2 = ElCLib::Value(lpar, aLine);
431
432 NewFpar = ElCLib::Parameter(PrevLine, P1);
433 NewLpar = ElCLib::Parameter(PrevLine, P2);
434 isSameCurve = Standard_True;
435 }
436 break;
437 }
438 case GeomAbs_Circle:
439 {
440 gp_Circ aCircle = aGACurve.Circle();
441 gp_Circ PrevCircle = GAprevcurve.Circle();
442
443 if (aCircle.Location().Distance(PrevCircle.Location()) <= LinTol &&
444 Abs(aCircle.Radius() - PrevCircle.Radius()) <= LinTol &&
445 aCircle.Axis().IsParallel(PrevCircle.Axis(), AngTol)) {
446 gp_Pnt P1 = ElCLib::Value(fpar, aCircle);
447 gp_Pnt P2 = ElCLib::Value(lpar, aCircle);
448
449 NewFpar = ElCLib::Parameter(PrevCircle, P1);
450 NewLpar = ElCLib::Parameter(PrevCircle, P2);
451 isSameCurve = Standard_True;
452 }
453 break;
454 }
455 case GeomAbs_Ellipse:
456 {
457 gp_Elips anEllipse = aGACurve.Ellipse();
458 gp_Elips PrevEllipse = GAprevcurve.Ellipse();
459
460 if (anEllipse.Focus1().Distance(PrevEllipse.Focus1()) <= LinTol &&
461 anEllipse.Focus2().Distance(PrevEllipse.Focus2()) <= LinTol &&
462 Abs(anEllipse.MajorRadius() - PrevEllipse.MajorRadius()) <= LinTol &&
463 Abs(anEllipse.MinorRadius() - PrevEllipse.MinorRadius()) <= LinTol &&
464 anEllipse.Axis().IsParallel(PrevEllipse.Axis(), AngTol)) {
465 gp_Pnt P1 = ElCLib::Value(fpar, anEllipse);
466 gp_Pnt P2 = ElCLib::Value(lpar, anEllipse);
467
468 NewFpar = ElCLib::Parameter(PrevEllipse, P1);
469 NewLpar = ElCLib::Parameter(PrevEllipse, P2);
470 isSameCurve = Standard_True;
471 }
472 break;
473 }
474 case GeomAbs_Hyperbola:
475 {
476 gp_Hypr aHypr = aGACurve.Hyperbola();
477 gp_Hypr PrevHypr = GAprevcurve.Hyperbola();
478
479 if (aHypr.Focus1().Distance(PrevHypr.Focus1()) <= LinTol &&
480 aHypr.Focus2().Distance(PrevHypr.Focus2()) <= LinTol &&
481 Abs(aHypr.MajorRadius() - PrevHypr.MajorRadius()) <= LinTol &&
482 Abs(aHypr.MinorRadius() - PrevHypr.MinorRadius()) <= LinTol &&
483 aHypr.Axis().IsParallel(PrevHypr.Axis(), AngTol)) {
484 gp_Pnt P1 = ElCLib::Value(fpar, aHypr);
485 gp_Pnt P2 = ElCLib::Value(lpar, aHypr);
486
487 NewFpar = ElCLib::Parameter(PrevHypr, P1);
488 NewLpar = ElCLib::Parameter(PrevHypr, P2);
489 isSameCurve = Standard_True;
490 }
491 break;
492 }
493 case GeomAbs_Parabola:
494 {
495 gp_Parab aParab = aGACurve.Parabola();
496 gp_Parab PrevParab = GAprevcurve.Parabola();
497
498 if (aParab.Location().Distance(PrevParab.Location()) <= LinTol &&
499 aParab.Focus().Distance(PrevParab.Focus()) <= LinTol &&
500 Abs(aParab.Focal() - PrevParab.Focal()) <= LinTol &&
501 aParab.Axis().IsParallel(PrevParab.Axis(), AngTol)) {
502 gp_Pnt P1 = ElCLib::Value(fpar, aParab);
503 gp_Pnt P2 = ElCLib::Value(lpar, aParab);
504
505 NewFpar = ElCLib::Parameter(PrevParab, P1);
506 NewLpar = ElCLib::Parameter(PrevParab, P2);
507 isSameCurve = Standard_True;
508 }
509 break;
510 }
511 default:
512 break;
513 } //end of switch
6f005d2a 514 } //end of else
515
516 if (isSameCurve) {
517 const Standard_Boolean isSameDir = (isFwd == IsFwdSeq.Last());
518
519 if (aBasisCurve->IsPeriodic()) {
520 // Treat periodic curves.
521 const Standard_Real aPeriod = aBasisCurve->Period();
522
523 if (isSameDir) {
524 // Check if first parameter is greater then the last one.
525 while (NewFpar > NewLpar) {
526 NewFpar -= aPeriod;
527 }
528 } else { // !isSameDir
529 // Check if last parameter is greater then the first one.
530 while (NewLpar > NewFpar) {
531 NewLpar -= aPeriod;
532 }
533
534 // Change parameters
535 const Standard_Real aTmpPar = NewLpar;
536
537 NewLpar = NewFpar;
538 NewFpar = aTmpPar;
539 }
540
541 // Udjust parameters on periodic curves.
542 if (IsFwdSeq.Last()) {
543 // The current curve should be after the previous one.
544 ElCLib::AdjustPeriodic(LparSeq.Last(), LparSeq.Last() + aPeriod,
545 Precision::PConfusion(), NewFpar, NewLpar);
546 } else {
547 // The current curve should be before the previous one.
548 ElCLib::AdjustPeriodic(FparSeq.Last() - aPeriod, FparSeq.Last(),
549 Precision::PConfusion(), NewFpar, NewLpar);
550 }
551 } else if (!isSameDir) {
552 // Not periodic curves. Opposite dirs.
553 const Standard_Real aTmpPar = NewLpar;
554
555 NewLpar = NewFpar;
556 NewFpar = aTmpPar;
557 }
558
559 if (IsFwdSeq.Last()) {
560 // Update last parameter
561 LparSeq(LparSeq.Length()) = NewLpar;
562 } else {
563 // Update first parameter
564 FparSeq(FparSeq.Length()) = NewFpar;
565 }
566 } else {
567 // Add new curve.
568 CurveSeq.Append(aCurve);
569 FparSeq.Append(fpar);
570 LparSeq.Append(lpar);
571 IsFwdSeq.Append(isFwd);
572 TolSeq.Append(BRep_Tool::Tolerance(wexp.CurrentVertex()));
573 CurType = aType;
574 }
51a849d7 575 }
6f005d2a 576 }
577
51a849d7 578 LastVertex = wexp.CurrentVertex();
579 TolSeq.Append(BRep_Tool::Tolerance(LastVertex));
580
6f005d2a 581 Standard_Boolean isReverse = Standard_False;
582
583 if (!IsFwdSeq.IsEmpty()) {
584 isReverse = !IsFwdSeq(1);
585 }
586
1f9cb9f9 587 TopoDS_Vertex FirstVtx_final, LastVtx_final;
588 if (isReverse)
589 {
590 FirstVtx_final = LastVertex;
591 LastVtx_final = FirstVertex;
592 }
593 else
594 {
595 FirstVtx_final = FirstVertex;
596 LastVtx_final = LastVertex;
597 }
51a849d7 598 FirstVtx_final.Orientation(TopAbs_FORWARD);
51a849d7 599 LastVtx_final.Orientation(TopAbs_REVERSED);
0272e740 600
51a849d7 601 if (CurveSeq.IsEmpty())
602 return ResEdge;
7fd59977 603
51a849d7 604 Standard_Integer nb_curve = CurveSeq.Length(); //number of curves
605 TColGeom_Array1OfBSplineCurve tab(0,nb_curve-1); //array of the curves
606 TColStd_Array1OfReal tabtolvertex(0,nb_curve-1); //(0,nb_curve-2); //array of the tolerances
7fd59977 607
51a849d7 608 Standard_Integer i;
609
610 if (nb_curve > 1)
0272e740 611 {
612 for (i = 1; i <= nb_curve; i++)
51a849d7 613 {
0272e740 614 if (CurveSeq(i)->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
615 CurveSeq(i) = (*((Handle(Geom_TrimmedCurve)*)&(CurveSeq(i))))->BasisCurve();
616
617 Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(CurveSeq(i), FparSeq(i), LparSeq(i));
618 tab(i-1) = GeomConvert::CurveToBSplineCurve(aTrCurve);
619 GeomConvert::C0BSplineToC1BSplineCurve(tab(i-1), Precision::Confusion());
620
621 if (!IsFwdSeq(i)) {
622 tab(i-1)->Reverse();
623 }
624
625 //Temporary
626 //char* name = new char[100];
627 //sprintf(name, "c%d", i);
628 //DrawTrSurf::Set(name, tab(i-1));
629
630 if (i > 1)
631 tabtolvertex(i-2) = TolSeq(i-1) * 5.;
51a849d7 632 }
0272e740 633 tabtolvertex(nb_curve-1) = TolSeq(TolSeq.Length()) * 5.;
634
635 Standard_Boolean closed_flag = Standard_False;
636 Standard_Real closed_tolerance = 0.;
637 if (FirstVertex.IsSame(LastVertex) &&
638 GeomLProp::Continuity(tab(0), tab(nb_curve-1),
639 tab(0)->FirstParameter(),
640 tab(nb_curve-1)->LastParameter(),
641 Standard_False, Standard_False, LinTol, AngTol) >= GeomAbs_G1)
642 {
643 closed_flag = Standard_True ;
644 closed_tolerance = BRep_Tool::Tolerance(FirstVertex);
645 }
646
647 Handle(TColGeom_HArray1OfBSplineCurve) concatcurve; //array of the concatenated curves
4551e1be 648 Handle(TColStd_HArray1OfInteger) ArrayOfIndices; //array of the remaining Vertex
0272e740 649 GeomConvert::ConcatC1(tab,
650 tabtolvertex,
651 ArrayOfIndices,
652 concatcurve,
653 closed_flag,
654 closed_tolerance); //C1 concatenation
655
656 if (concatcurve->Length() > 1)
51a849d7 657 {
0272e740 658 Standard_Real MaxTolVer = LinTol;
659 for (i = 1; i <= TolSeq.Length(); i++)
660 if (TolSeq(i) > MaxTolVer)
661 MaxTolVer = TolSeq(i);
662 MaxTolVer *= 5.;
663
664 GeomConvert_CompCurveToBSplineCurve Concat(concatcurve->Value(concatcurve->Lower()));
6f005d2a 665
0272e740 666 for (i = concatcurve->Lower()+1; i <= concatcurve->Upper(); i++)
667 Concat.Add( concatcurve->Value(i), MaxTolVer, Standard_True );
6f005d2a 668
0272e740 669 concatcurve->SetValue(concatcurve->Lower(), Concat.BSplineCurve());
51a849d7 670 }
671
1f9cb9f9 672 if (isReverse) {
673 concatcurve->ChangeValue(concatcurve->Lower())->Reverse();
674 }
0272e740 675 ResEdge = BRepLib_MakeEdge(concatcurve->Value(concatcurve->Lower()),
676 FirstVtx_final, LastVtx_final,
677 concatcurve->Value(concatcurve->Lower())->FirstParameter(),
678 concatcurve->Value(concatcurve->Lower())->LastParameter());
679 }
680 else
681 {
682 if (CurveSeq(1)->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
683 CurveSeq(1) = (*((Handle(Geom_TrimmedCurve)*)&(CurveSeq(1))))->BasisCurve();
684
685 Handle(Geom_Curve) aCopyCurve =
686 Handle(Geom_Curve)::DownCast(CurveSeq(1)->Copy());
687
688 ResEdge = BRepLib_MakeEdge(aCopyCurve,
689 FirstVtx_final, LastVtx_final,
690 FparSeq(1), LparSeq(1));
691 }
692
6f005d2a 693 if (isReverse)
51a849d7 694 ResEdge.Reverse();
0272e740 695
51a849d7 696 return ResEdge;
697}