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) |
60 | static const Standard_Real MINIMAL_TOLERANCE = 0.0001; |
61 | |
62 | namespace { |
63 | |
64 | struct 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 | |
83 | TopoDS_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 | |
200 | TopoDS_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 | |
224 | TopoDS_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 | |
360 | TopoDS_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 | } |