b311480e |
1 | // Created on: 1999-06-17 |
2 | // Created by: data exchange team |
3 | // Copyright (c) 1999-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 | |
18 | #include <BRep_Builder.hxx> |
19 | #include <BRep_Tool.hxx> |
20 | #include <Geom2d_BSplineCurve.hxx> |
7fd59977 |
21 | #include <Geom2d_Conic.hxx> |
42cf5bc1 |
22 | #include <Geom2d_Curve.hxx> |
7fd59977 |
23 | #include <Geom2d_TrimmedCurve.hxx> |
7fd59977 |
24 | #include <Geom2dConvert.hxx> |
42cf5bc1 |
25 | #include <Geom2dConvert_ApproxCurve.hxx> |
26 | #include <Geom_BSplineCurve.hxx> |
27 | #include <Geom_BSplineSurface.hxx> |
28 | #include <Geom_Conic.hxx> |
29 | #include <Geom_Curve.hxx> |
30 | #include <Geom_ElementarySurface.hxx> |
31 | #include <Geom_OffsetCurve.hxx> |
32 | #include <Geom_Plane.hxx> |
7fd59977 |
33 | #include <Geom_RectangularTrimmedSurface.hxx> |
42cf5bc1 |
34 | #include <Geom_Surface.hxx> |
7fd59977 |
35 | #include <Geom_SurfaceOfLinearExtrusion.hxx> |
7fd59977 |
36 | #include <Geom_SurfaceOfRevolution.hxx> |
42cf5bc1 |
37 | #include <Geom_TrimmedCurve.hxx> |
38 | #include <GeomAPI.hxx> |
39 | #include <GeomConvert.hxx> |
40 | #include <GeomConvert_ApproxCurve.hxx> |
41 | #include <GeomConvert_ApproxSurface.hxx> |
7fd59977 |
42 | #include <GeomConvert_CompCurveToBSplineCurve.hxx> |
43 | #include <gp_Pln.hxx> |
44 | #include <gp_Vec.hxx> |
42cf5bc1 |
45 | #include <Precision.hxx> |
7fd59977 |
46 | #include <ShapeAnalysis_Edge.hxx> |
42cf5bc1 |
47 | #include <ShapeConstruct.hxx> |
48 | #include <ShapeConstruct_Curve.hxx> |
49 | #include <Standard_ErrorHandler.hxx> |
50 | #include <Standard_Failure.hxx> |
51 | #include <TColgp_Array1OfPnt.hxx> |
52 | #include <TColgp_Array2OfPnt.hxx> |
53 | #include <TColStd_Array1OfInteger.hxx> |
54 | #include <TColStd_Array1OfReal.hxx> |
55 | #include <TColStd_Array2OfReal.hxx> |
7fd59977 |
56 | #include <TopAbs_Orientation.hxx> |
57 | #include <TopoDS.hxx> |
42cf5bc1 |
58 | #include <TopoDS_Edge.hxx> |
59 | #include <TopoDS_Face.hxx> |
60 | #include <TopTools_HSequenceOfShape.hxx> |
7fd59977 |
61 | |
62 | //======================================================================= |
63 | //function : ConvertCurveToBSpline |
64 | //purpose : |
65 | //======================================================================= |
7fd59977 |
66 | Handle(Geom_BSplineCurve) ShapeConstruct::ConvertCurveToBSpline(const Handle(Geom_Curve)& C3D, |
67 | const Standard_Real First, |
68 | const Standard_Real Last, |
69 | const Standard_Real Tol3d, |
70 | const GeomAbs_Shape Continuity, |
71 | const Standard_Integer MaxSegments, |
72 | const Standard_Integer MaxDegree) |
73 | { |
74 | Standard_Integer MaxDeg = MaxDegree; |
75 | Handle(Geom_BSplineCurve) aBSpline; |
76 | if(C3D->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) |
77 | aBSpline = Handle(Geom_BSplineCurve)::DownCast(C3D); |
78 | else { |
79 | if(C3D->IsKind(STANDARD_TYPE(Geom_Conic))) |
80 | MaxDeg = Min(MaxDeg,6); |
81 | |
316ea293 |
82 | Handle(Geom_Curve) tcurve = new Geom_TrimmedCurve(C3D,First,Last); //protection against parabols ets |
7fd59977 |
83 | try { |
84 | OCC_CATCH_SIGNALS |
85 | GeomConvert_ApproxCurve approx (tcurve, Tol3d, Continuity, MaxSegments, MaxDeg); |
86 | if ( approx.HasResult() ) |
a9dde4a3 |
87 | aBSpline = approx.Curve(); |
7fd59977 |
88 | else |
89 | aBSpline = GeomConvert::CurveToBSplineCurve(C3D,Convert_QuasiAngular); |
90 | } |
9775fa61 |
91 | catch (Standard_Failure const& anException) { |
0797d9d3 |
92 | #ifdef OCCT_DEBUG |
04232180 |
93 | std::cout << "Warning: GeomConvert_ApproxSurface Exception: "; |
94 | anException.Print(std::cout); std::cout << std::endl; |
7fd59977 |
95 | #endif |
9775fa61 |
96 | (void)anException; |
7fd59977 |
97 | aBSpline = GeomConvert::CurveToBSplineCurve(C3D,Convert_QuasiAngular); |
98 | } |
99 | } |
100 | return aBSpline; |
101 | } |
102 | |
103 | //======================================================================= |
104 | //function : ConvertCurveToBSpline |
105 | //purpose : |
106 | //======================================================================= |
107 | |
108 | Handle(Geom2d_BSplineCurve) ShapeConstruct::ConvertCurveToBSpline(const Handle(Geom2d_Curve)& C2D, |
109 | const Standard_Real First, |
110 | const Standard_Real Last, |
111 | const Standard_Real Tol2d, |
112 | const GeomAbs_Shape Continuity, |
113 | const Standard_Integer MaxSegments, |
114 | const Standard_Integer MaxDegree) |
115 | { |
116 | Handle(Geom2d_BSplineCurve) aBSpline2d; |
117 | if(C2D->IsKind(STANDARD_TYPE(Geom2d_Conic))) { |
316ea293 |
118 | Handle(Geom2d_Curve) tcurve = new Geom2d_TrimmedCurve(C2D,First,Last); //protection against parabols ets |
7fd59977 |
119 | Geom2dConvert_ApproxCurve approx (tcurve, Tol2d, Continuity, MaxSegments, MaxDegree); |
120 | if ( approx.HasResult() ) |
a9dde4a3 |
121 | aBSpline2d = approx.Curve(); |
7fd59977 |
122 | else |
123 | aBSpline2d = Geom2dConvert::CurveToBSplineCurve(tcurve,Convert_QuasiAngular); |
124 | } |
125 | else if(!C2D->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) { |
126 | aBSpline2d = Geom2dConvert::CurveToBSplineCurve(C2D,Convert_QuasiAngular); |
127 | } |
128 | else |
129 | aBSpline2d = Handle(Geom2d_BSplineCurve)::DownCast(C2D); |
130 | |
131 | return aBSpline2d; |
132 | } |
133 | |
134 | //======================================================================= |
135 | //function : ConvertSurfaceToBSpline |
136 | //purpose : |
137 | //======================================================================= |
138 | |
139 | // Note: this method has the same purpose as GeomConvert::SurfaceToBSplineSurface(), |
140 | // but treats more correctly offset surfaces and takes parameters such as UV limits |
141 | // and degree as arguments instead of deducing them from the surface. |
142 | // Eventually it may be merged back to GeomConvert. |
143 | |
144 | Handle(Geom_BSplineSurface) ShapeConstruct::ConvertSurfaceToBSpline(const Handle(Geom_Surface)& surf, |
145 | const Standard_Real UF, |
146 | const Standard_Real UL, |
147 | const Standard_Real VF, |
148 | const Standard_Real VL, |
149 | const Standard_Real Tol3d, |
150 | const GeomAbs_Shape Continuity, |
151 | const Standard_Integer MaxSegments, |
152 | const Standard_Integer MaxDegree) |
153 | { |
154 | Handle(Geom_BSplineSurface) res; |
155 | |
156 | Handle(Geom_Surface) S = surf; |
157 | if(surf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) { |
158 | Handle(Geom_RectangularTrimmedSurface) RTS = |
159 | Handle(Geom_RectangularTrimmedSurface)::DownCast(surf); |
160 | S = RTS->BasisSurface(); |
161 | } |
162 | |
163 | // use GeomConvert for direct conversion of analytic surfaces |
164 | if (S->IsKind(STANDARD_TYPE(Geom_ElementarySurface))) |
165 | { |
166 | Handle(Geom_RectangularTrimmedSurface) aRTS = |
167 | new Geom_RectangularTrimmedSurface(S,UF,UL,VF,VL); |
168 | return GeomConvert::SurfaceToBSplineSurface(aRTS); |
169 | } |
170 | |
171 | if(S->IsKind(STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))) { |
172 | Handle(Geom_SurfaceOfLinearExtrusion) extr = Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(S); |
173 | Handle(Geom_Curve) basis = extr->BasisCurve(); |
174 | //gp_Dir direction = extr->Direction(); // direction not used (skl) |
175 | |
176 | GeomAbs_Shape cnt = (Continuity > GeomAbs_C2 ? GeomAbs_C2: Continuity); |
177 | Handle(Geom_BSplineCurve) bspl = ConvertCurveToBSpline(basis, UF, UL, Tol3d, cnt, MaxSegments, MaxDegree); |
178 | |
179 | gp_Trsf shiftF,shiftL; |
180 | shiftF.SetTranslation(extr->Value(UF,0),extr->Value(UF,VF)); |
181 | shiftL.SetTranslation(extr->Value(UF,0),extr->Value(UF,VL)); |
182 | |
183 | Standard_Integer nbPoles = bspl->NbPoles(); |
184 | TColgp_Array1OfPnt poles(1,nbPoles); |
185 | TColStd_Array1OfReal weights(1,nbPoles); |
186 | Standard_Integer nbKnots = bspl->NbKnots(); |
187 | TColStd_Array1OfReal knots(1,nbKnots); |
188 | TColStd_Array1OfInteger mults(1,nbKnots); |
189 | |
190 | bspl->Poles(poles); |
191 | bspl->Knots(knots); |
192 | bspl->Multiplicities(mults); |
193 | bspl->Weights(weights); |
194 | |
195 | TColgp_Array2OfPnt resPoles(1,nbPoles,1,2); |
196 | TColStd_Array2OfReal resWeigth(1,nbPoles,1,2); |
197 | for(Standard_Integer j = 1; j <= nbPoles; j++) { |
198 | resPoles(j,1) = poles(j).Transformed(shiftF); |
199 | resPoles(j,2) = poles(j).Transformed(shiftL); |
200 | resWeigth(j,1)= weights(j); |
201 | resWeigth(j,2)= weights(j); |
202 | } |
203 | |
204 | TColStd_Array1OfReal vknots(1,2); |
205 | TColStd_Array1OfInteger vmults(1,2); |
206 | vknots(1) = VF; |
207 | vknots(2) = VL; |
208 | vmults(1) = vmults(2) = 2; |
209 | |
210 | Handle(Geom_BSplineSurface) bspline = new Geom_BSplineSurface(resPoles, resWeigth, knots, vknots, mults, vmults, |
211 | bspl->Degree(),1,bspl->IsPeriodic(),Standard_False); |
212 | return bspline; |
213 | } |
214 | |
215 | if(S->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution))) { |
216 | Handle(Geom_SurfaceOfRevolution) revol = Handle(Geom_SurfaceOfRevolution)::DownCast(S); |
217 | Handle(Geom_Curve) basis = revol->BasisCurve(); |
218 | if(basis->IsKind(STANDARD_TYPE(Geom_OffsetCurve))) { |
219 | GeomAbs_Shape cnt = basis->Continuity(); |
220 | cnt = (cnt > GeomAbs_C2 ? GeomAbs_C2: cnt); |
221 | Handle(Geom_BSplineCurve) bspl = ConvertCurveToBSpline(basis, VF, VL, Tol3d, cnt, MaxSegments, MaxDegree); |
222 | gp_Ax1 axis = revol->Axis(); |
223 | Handle(Geom_SurfaceOfRevolution) newRevol = new Geom_SurfaceOfRevolution(bspl,axis); |
0797d9d3 |
224 | #ifdef OCCT_DEBUG |
04232180 |
225 | std::cout <<" Revolution on offset converted" << std::endl; |
7fd59977 |
226 | #endif |
227 | S = newRevol; |
228 | } |
229 | } |
230 | |
543a9964 |
231 | Handle(Geom_Surface) aSurface = new Geom_RectangularTrimmedSurface(S,UF,UL,VF,VL); |
7fd59977 |
232 | Handle(Geom_BSplineSurface) errSpl; |
233 | for(Standard_Integer cnt = (Continuity > GeomAbs_C3 ? GeomAbs_C3: Continuity); cnt >= 0 ; ) { |
234 | try { |
235 | OCC_CATCH_SIGNALS |
236 | GeomAbs_Shape aCont = (GeomAbs_Shape) cnt; |
237 | GeomConvert_ApproxSurface anApprox(aSurface,Tol3d/2,aCont,aCont,MaxDegree,MaxDegree,MaxSegments,0); |
238 | Standard_Boolean Done = anApprox.IsDone(); |
239 | if (anApprox.MaxError() <= Tol3d && Done) { |
240 | |
0797d9d3 |
241 | #ifdef OCCT_DEBUG |
7fd59977 |
242 | Standard_Integer nbOfSpan = (anApprox.Surface()->NbUKnots()-1)*(anApprox.Surface()->NbVKnots()-1); |
04232180 |
243 | std::cout << "\terror = " << anApprox.MaxError() << "\tspans = " << nbOfSpan << std::endl; |
316ea293 |
244 | std::cout << " Surface is approximated with continuity " << (GeomAbs_Shape)cnt <<std::endl; |
7fd59977 |
245 | #endif |
246 | S = anApprox.Surface(); |
247 | Handle(Geom_BSplineSurface) Bsc = Handle(Geom_BSplineSurface)::DownCast(S); |
248 | return Bsc; |
249 | } |
250 | else { |
251 | if(anApprox.HasResult()) |
a9dde4a3 |
252 | errSpl = anApprox.Surface(); |
0797d9d3 |
253 | #ifdef OCCT_DEBUG |
04232180 |
254 | std::cout << "\terror = " << anApprox.MaxError() <<std::endl; |
7fd59977 |
255 | #endif |
256 | break; |
257 | } |
258 | } |
259 | |
9775fa61 |
260 | catch (Standard_Failure const& anException) { |
0797d9d3 |
261 | #ifdef OCCT_DEBUG |
04232180 |
262 | std::cout << "Warning: GeomConvert_ApproxSurface Exception: try to decrease continuity "; |
263 | anException.Print(std::cout); std::cout << std::endl; |
7fd59977 |
264 | #endif |
9775fa61 |
265 | (void)anException; |
7fd59977 |
266 | if(cnt > 0) cnt--; |
267 | continue; |
268 | } |
269 | } |
270 | |
271 | return errSpl; |
272 | } |
273 | //======================================================================= |
274 | //function : JoinPCurves |
275 | //purpose : |
276 | //======================================================================= |
277 | |
278 | Standard_Boolean ShapeConstruct::JoinPCurves(const Handle(TopTools_HSequenceOfShape)& edges, |
279 | const TopoDS_Face& theFace, |
280 | TopoDS_Edge& theEdge) |
281 | { |
282 | ShapeAnalysis_Edge sae; |
283 | BRep_Builder B; |
284 | |
285 | try { |
286 | OCC_CATCH_SIGNALS |
287 | // check if current face is plane. |
288 | Handle(Geom_Surface) aGeomSurf = BRep_Tool::Surface(theFace); |
289 | while (aGeomSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) |
290 | { |
291 | |
292 | aGeomSurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(aGeomSurf)->BasisSurface(); |
293 | } |
294 | if (aGeomSurf->IsKind(STANDARD_TYPE(Geom_Plane))) |
295 | return Standard_True; |
296 | |
297 | |
298 | Standard_Boolean IsEdgeSeam = Standard_False; |
299 | Handle(Geom2d_Curve) aCrvRes1, aCrvRes2; |
300 | TopAbs_Orientation resOrient; |
1d47d8d0 |
301 | Standard_Real newf = 0.,newl = 0.; |
7fd59977 |
302 | // iterates on edges |
303 | Standard_Integer i = 1; |
304 | for(; i <= edges->Length(); i++) { |
305 | TopoDS_Edge Edge = TopoDS::Edge(edges->Value(i)); |
306 | if (i == 1) |
307 | IsEdgeSeam = sae.IsSeam(Edge,theFace); |
308 | else if (IsEdgeSeam && (!sae.IsSeam(Edge,theFace))) |
309 | break; // different cases |
310 | else if (!IsEdgeSeam && (sae.IsSeam(Edge,theFace))) |
311 | break; // different cases |
312 | |
313 | resOrient = TopAbs_FORWARD; |
314 | Handle(Geom2d_Curve) c2d,c2d2; |
315 | Standard_Real first, last,first2, last2; |
316 | if(!sae.PCurve ( Edge, theFace, c2d, first, last, Standard_False )) |
317 | break; |
318 | |
319 | if(IsEdgeSeam) { |
320 | TopoDS_Edge tmpE1 =TopoDS::Edge(Edge.Reversed()); |
321 | sae.PCurve ( tmpE1, theFace, c2d2, first2, last2, Standard_False ); |
322 | } |
323 | |
324 | if( i == 1) { |
325 | aCrvRes1 = c2d; |
326 | if(IsEdgeSeam) { |
327 | aCrvRes2 = c2d2; |
328 | } |
329 | newf = first; |
330 | newl = last; |
331 | resOrient = Edge.Orientation(); |
332 | } |
333 | else { |
334 | Handle(Geom2d_Curve) newCrv; |
335 | Standard_Boolean isRev1,isRev2; |
336 | if(!JoinCurves(aCrvRes1,c2d,resOrient,Edge.Orientation(),newf,newl,first, last,newCrv,isRev1,isRev2)) |
337 | break; |
338 | |
339 | if(IsEdgeSeam) { |
340 | Handle(Geom2d_Curve) newCrv2; |
341 | Standard_Real newf2 = newf,newl2 = newl; |
342 | |
343 | if(!JoinCurves(aCrvRes2,c2d2,resOrient,Edge.Orientation(),newf2,newl2,first2, last2,newCrv2,isRev1,isRev2)) |
344 | break; |
345 | aCrvRes2 = newCrv2; |
346 | } |
347 | aCrvRes1 = newCrv; |
348 | Standard_Real fp2d = newCrv->FirstParameter(); |
349 | Standard_Real lp2d = newCrv->LastParameter(); |
350 | newl += (last - first); |
351 | if(fp2d > newf) newf = fp2d; |
352 | if(lp2d < newl) newl = lp2d; |
353 | |
354 | } |
355 | } |
356 | if (IsEdgeSeam) |
357 | B.UpdateEdge(theEdge,aCrvRes1,aCrvRes2,theFace,0); |
358 | else |
359 | B.UpdateEdge(theEdge,aCrvRes1,theFace,0); |
360 | B.Range(theEdge,theFace,newf,newl); |
361 | B.SameRange(theEdge,Standard_False); |
362 | B.SameParameter(theEdge,Standard_False); |
363 | return (i <= edges->Length()); |
364 | } |
9775fa61 |
365 | catch ( Standard_Failure const& anException) { |
0797d9d3 |
366 | #ifdef OCCT_DEBUG |
04232180 |
367 | std::cout<<"Error: ShapeConstruct::JoinPCurves Exception in GeomConvert_CompCurveToBSplineCurve: "; |
368 | anException.Print(std::cout); std::cout<<std::endl; |
7fd59977 |
369 | #endif |
9775fa61 |
370 | (void)anException; |
7fd59977 |
371 | } |
372 | return Standard_False; |
373 | } |
374 | |
375 | //======================================================================= |
376 | //function : JoinCurves |
377 | //purpose : |
378 | //======================================================================= |
379 | |
380 | template<class HCurve> |
381 | static inline HCurve GetCurveCopy(const HCurve& curve, |
382 | Standard_Real& first, Standard_Real& last, |
383 | const TopAbs_Orientation &orient) |
384 | { |
385 | if ( orient == TopAbs_REVERSED ) { |
386 | Standard_Real cf = first; |
387 | first = curve->ReversedParameter ( last ); |
388 | last = curve->ReversedParameter ( cf ); |
389 | return curve->Reversed(); |
390 | } |
391 | return HCurve::DownCast(curve->Copy()); |
392 | } |
393 | |
394 | template<class HCurve> |
395 | static inline void SegmentCurve (HCurve& curve, |
396 | const Standard_Real first, |
397 | const Standard_Real last) |
398 | { |
399 | if(curve->FirstParameter() < first - Precision::PConfusion() || |
400 | curve->LastParameter() > last + Precision::PConfusion()) { |
401 | if(curve->IsPeriodic()) |
402 | curve->Segment(first,last); |
403 | else curve->Segment(Max(curve->FirstParameter(),first), |
404 | Min(curve->LastParameter(),last)); |
405 | } |
406 | } |
407 | |
408 | template<class HPoint> |
409 | static inline void GetReversedParameters(const HPoint& p11, |
410 | const HPoint& p12, |
411 | const HPoint& p21, |
412 | const HPoint& p22, |
413 | Standard_Boolean& isRev1, |
414 | Standard_Boolean& isRev2) |
415 | { |
416 | isRev1 = Standard_False; |
417 | isRev2 = Standard_False; |
418 | //gka protection against crossing seem on second face |
419 | |
420 | Standard_Real d11 = p11.Distance(p21); |
421 | Standard_Real d21 =p12.Distance(p21); |
422 | |
423 | Standard_Real d12 = p11.Distance(p22); |
424 | Standard_Real d22 = p22.Distance(p12); |
425 | Standard_Real Dmin1 = Min(d11,d21); |
426 | Standard_Real Dmin2 = Min(d12,d22); |
427 | if(fabs(Dmin1 - Dmin2) <= Precision::Confusion() || Dmin2 > Dmin1) { |
428 | isRev1 = (d11 < d21 ? Standard_True : Standard_False); |
429 | } |
430 | else if(Dmin2 < Dmin1) { |
431 | isRev1 = (d12 < d22 ? Standard_True : Standard_False); |
432 | isRev2 = Standard_True; |
433 | } |
434 | |
435 | |
436 | } |
437 | //======================================================================= |
438 | //function : JoinCurves |
439 | //purpose : |
440 | //======================================================================= |
441 | |
442 | Standard_Boolean ShapeConstruct::JoinCurves(const Handle(Geom_Curve)& ac3d1, |
443 | const Handle(Geom_Curve)& ac3d2, |
444 | const TopAbs_Orientation Orient1, |
445 | const TopAbs_Orientation Orient2, |
446 | Standard_Real& first1, |
447 | Standard_Real& last1, |
448 | Standard_Real& first2, |
449 | Standard_Real& last2, |
450 | Handle(Geom_Curve)& c3dOut, |
451 | Standard_Boolean& isRev1, |
452 | Standard_Boolean& isRev2) |
453 | |
454 | { |
455 | Handle(Geom_Curve) c3d1,c3d2; |
456 | |
457 | c3d1 = GetCurveCopy ( ac3d1, first1, last1, Orient1 ); |
458 | c3d2 = GetCurveCopy ( ac3d2, first2, last2, Orient2 ); |
459 | ShapeConstruct_Curve scc; |
460 | Standard_Boolean After = Standard_True; |
461 | Handle(Geom_BSplineCurve) bsplc1 = scc.ConvertToBSpline(c3d1,first1, last1,Precision::Confusion()); |
462 | Handle(Geom_BSplineCurve) bsplc2 = scc.ConvertToBSpline(c3d2,first2, last2,Precision::Confusion()); |
463 | // newf = first1; |
464 | // newl = last1 + last2 - first2; |
465 | |
466 | if(bsplc1.IsNull() || bsplc2.IsNull()) return Standard_False; |
467 | |
468 | SegmentCurve(bsplc1,first1, last1); |
469 | SegmentCurve(bsplc2,first2, last2); |
470 | |
471 | //regression on file 866026_M-f276-f311.brep bug OCC482 |
472 | gp_Pnt pp11 = bsplc1->Pole(1); |
473 | gp_Pnt pp12 = bsplc1->Pole(bsplc1->NbPoles()); |
474 | |
475 | gp_Pnt pp21 = bsplc2->Pole(1); |
476 | gp_Pnt pp22 = bsplc2->Pole(bsplc2->NbPoles()); |
477 | |
478 | GetReversedParameters(pp11,pp12,pp21,pp22,isRev1,isRev2); |
479 | |
480 | if(isRev1) { |
481 | bsplc1->Reverse(); |
482 | } |
483 | if(isRev2) |
484 | bsplc2->Reverse(); |
485 | |
486 | gp_Pnt pmid = 0.5 * ( bsplc1->Pole(bsplc1->NbPoles()).XYZ() + bsplc2->Pole(1).XYZ() ); |
487 | bsplc1->SetPole(bsplc1->NbPoles(), pmid); |
488 | bsplc2->SetPole(1, pmid); |
489 | GeomConvert_CompCurveToBSplineCurve connect3d(bsplc1); |
490 | if(!connect3d.Add(bsplc2,Precision::Confusion(), After, Standard_False)) return Standard_False; |
491 | c3dOut = connect3d.BSplineCurve(); |
492 | return Standard_True; |
493 | } |
494 | |
495 | //======================================================================= |
496 | //function : JoinCurves2d |
497 | //purpose : |
498 | //======================================================================= |
499 | |
500 | Standard_Boolean ShapeConstruct::JoinCurves(const Handle(Geom2d_Curve)& aC2d1, |
501 | const Handle(Geom2d_Curve)& aC2d2, |
502 | const TopAbs_Orientation Orient1, |
503 | const TopAbs_Orientation Orient2, |
504 | Standard_Real& first1, |
505 | Standard_Real& last1, |
506 | Standard_Real& first2, |
507 | Standard_Real& last2, |
508 | Handle(Geom2d_Curve)& C2dOut, |
509 | Standard_Boolean& isRev1, |
510 | Standard_Boolean& isRev2, |
511 | const Standard_Boolean isError) |
512 | { |
513 | Handle(Geom2d_Curve) c2d1,c2d2; |
514 | c2d1 = GetCurveCopy ( aC2d1, first1, last1, Orient1 ); |
515 | c2d2 = GetCurveCopy ( aC2d2, first2, last2, Orient2 ); |
516 | ShapeConstruct_Curve scc; |
517 | Standard_Boolean After = Standard_True; |
518 | |
519 | Handle(Geom2d_BSplineCurve) bsplc12d = scc.ConvertToBSpline(c2d1,first1,last1,Precision::Confusion()); |
520 | Handle(Geom2d_BSplineCurve) bsplc22d = scc.ConvertToBSpline(c2d2,first2,last2,Precision::Confusion()); |
521 | |
522 | if(bsplc12d.IsNull() || bsplc22d.IsNull()) return Standard_False; |
523 | |
524 | SegmentCurve(bsplc12d,first1,last1); |
525 | SegmentCurve(bsplc22d,first2,last2); |
526 | //gka protection against crossing seem on second face |
527 | gp_Pnt2d pp112d = bsplc12d->Pole(1).XY(); |
528 | gp_Pnt2d pp122d = bsplc12d->Pole(bsplc12d->NbPoles()).XY(); |
529 | |
530 | gp_Pnt2d pp212d = bsplc22d->Pole(1).XY(); |
531 | gp_Pnt2d pp222d = bsplc22d->Pole(bsplc22d->NbPoles()).XY(); |
532 | |
533 | GetReversedParameters(pp112d,pp122d,pp212d,pp222d,isRev1,isRev2); |
534 | |
535 | //regression on file 866026_M-f276-f311.brep bug OCC482 |
536 | //if(isRev1 || isRev2) |
537 | // return newedge1; |
538 | if(isRev1) { |
539 | bsplc12d->Reverse(); |
540 | } |
541 | if(isRev2) |
542 | bsplc22d->Reverse(); |
543 | |
544 | |
545 | //--------------------------------------------------------- |
546 | //protection against invalid topology Housing(sam1296.brep(face 707) - bugmergeedges4.brep) |
547 | if(isError) { |
548 | gp_Pnt2d pp1 = bsplc12d->Value(bsplc12d->FirstParameter()); |
549 | gp_Pnt2d pp2 = bsplc12d->Value(bsplc12d->LastParameter()); |
550 | gp_Pnt2d pp3 = bsplc12d->Value((bsplc12d->FirstParameter() + bsplc12d->LastParameter())*0.5); |
551 | |
552 | Standard_Real leng = pp1.Distance(pp2); |
553 | Standard_Boolean isCircle = (leng < pp1.Distance(pp3) + Precision::PConfusion()); |
554 | if((pp1.Distance(bsplc22d->Pole(1)) < leng) && !isCircle) return Standard_False; |
555 | } |
556 | //------------------------------------------------------- |
557 | gp_Pnt2d pmid1 = 0.5 * ( bsplc12d->Pole(bsplc12d->NbPoles()).XY() + bsplc22d->Pole(1).XY() ); |
558 | bsplc12d->SetPole(bsplc12d->NbPoles(), pmid1); |
559 | bsplc22d->SetPole(1, pmid1); |
560 | |
561 | // abv 01 Sep 99: Geom2dConvert ALWAYS performs reparametrisation of the |
562 | // second curve before merging; this is quite not suitable |
563 | // Use 3d tool instead |
564 | // Geom2dConvert_CompCurveToBSplineCurve connect2d(bsplc12d); |
565 | gp_Pnt vPnt(0,0,0); |
566 | gp_Vec vDir(0,0,1); |
567 | gp_Pln vPln ( vPnt, vDir ); |
568 | Handle(Geom_BSplineCurve) bspl1 = |
569 | Handle(Geom_BSplineCurve)::DownCast ( GeomAPI::To3d ( bsplc12d, vPln ) ); |
570 | Handle(Geom_BSplineCurve) bspl2 = |
571 | Handle(Geom_BSplineCurve)::DownCast ( GeomAPI::To3d ( bsplc22d, vPln ) ); |
572 | GeomConvert_CompCurveToBSplineCurve connect2d(bspl1); |
573 | if(!connect2d.Add(bspl2,Precision::PConfusion(), After, Standard_False)) return Standard_False; |
574 | C2dOut = GeomAPI::To2d ( connect2d.BSplineCurve(), vPln ); |
575 | |
576 | return Standard_True; |
577 | } |