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