0031035: Coding - uninitialized class fields reported by Visual Studio Code Analysis
[occt.git] / src / BRepBuilderAPI / BRepBuilderAPI_FastSewing.cxx
1 // Created on: 2015-04-24
2 // Created by: NIKOLAI BUKHALOV
3 // Copyright (c) 2015 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <BRepBuilderAPI_FastSewing.hxx>
17
18 #include <BRepTools_Quilt.hxx>
19 #include <Bnd_Box.hxx>
20
21 #include <Geom2d_Line.hxx>
22 #include <Geom2d_TrimmedCurve.hxx>
23 #include <Geom_Curve.hxx>
24 #include <Geom_RectangularTrimmedSurface.hxx>
25 #include <Geom_Surface.hxx>
26
27 #include <Precision.hxx>
28
29 #include <Standard_NullObject.hxx>
30
31 #include <TopExp_Explorer.hxx>
32 #include <TopoDS.hxx>
33 #include <TopTools_MapOfShape.hxx>
34
35
36 IMPLEMENT_STANDARD_RTTIEXT(BRepBuilderAPI_FastSewing,Standard_Transient)
37
38 //=======================================================================
39 //function : IntersetctionOfSets
40 //purpose  : Returns minimal value of intersection result
41 //=======================================================================
42 static Standard_Integer
43       IntersectionOfSets( const NCollection_List<Standard_Integer>& theSet1,
44                           const NCollection_List<Standard_Integer>& theSet2)
45 {
46   const Standard_Integer anIntMax = IntegerLast();
47   Standard_Integer aRetVal = anIntMax;
48   for(NCollection_List<Standard_Integer>::Iterator
49                             anIt1 = theSet1.begin().Iterator();
50                             anIt1.More(); anIt1.Next())
51   {
52     const Standard_Integer aVal1 = anIt1.Value();
53     for(NCollection_List<Standard_Integer>::Iterator
54                             anIt2 = theSet2.begin().Iterator();
55                             anIt2.More(); anIt2.Next())
56     {
57       const Standard_Integer aVal2 = anIt2.Value();
58       if(aVal1 == aVal2)
59       {
60         //theIntersectionResult.Append(aVal1);
61         if(aVal1 < aRetVal)
62           aRetVal = aVal1;
63       }
64     }
65   }
66
67   if(aRetVal == anIntMax)
68     return -1;
69
70   return aRetVal;
71 }
72
73 //=======================================================================
74 //function : Get2DCurve
75 //purpose  : 
76 //=======================================================================
77 static Handle(Geom2d_Curve)
78             Get2DCurve( const Standard_Integer theIndex,
79                         const Standard_Real theUfirst,
80                         const Standard_Real theUlast,
81                         const Standard_Real theVfirst,
82                         const Standard_Real theVlast,
83                         const Standard_Boolean theIsReverse = Standard_False)
84 {
85   if((theIndex < 0) || (theIndex > 3))
86     throw Standard_OutOfRange("BRepBuilderAPI_FastSewing.cxx, Get2DCurve(): OUT of Range");
87   
88   Handle(Geom2d_Curve) a2dCurv;
89
90   if(!theIsReverse)
91   {
92     switch(theIndex)
93     {
94     case 0:
95       a2dCurv = 
96             new Geom2d_TrimmedCurve(new Geom2d_Line(
97                                           gp_Pnt2d(0.0, theVfirst), gp_Dir2d(1.0,0.0)),
98                                           theUfirst, theUlast);
99       break;
100     case 1:
101       a2dCurv = 
102             new Geom2d_TrimmedCurve(new Geom2d_Line(
103                                           gp_Pnt2d(theUlast, 0.0), gp_Dir2d(0.0,1.0)),
104                                           theVfirst, theVlast);
105       break;
106     case 2:
107       a2dCurv = 
108             new Geom2d_TrimmedCurve(new Geom2d_Line(
109                                           gp_Pnt2d(0.0, theVlast), gp_Dir2d(1.0,0.0)),
110                                           theUfirst, theUlast);
111       break;
112     case 3:
113       a2dCurv =
114             new Geom2d_TrimmedCurve(new Geom2d_Line(
115                                           gp_Pnt2d(theUfirst, 0.0), gp_Dir2d(0.0,1.0)),
116                                           theVfirst, theVlast);
117       break;
118     default:
119       break;
120     }  
121   }
122   else
123   {
124     switch(theIndex)
125     {
126     case 0:
127       a2dCurv = 
128             new Geom2d_TrimmedCurve(new Geom2d_Line(
129                                           gp_Pnt2d(theUfirst+theUlast, theVfirst),
130                                                           gp_Dir2d(-1.0,0.0)),
131                                           theUfirst, theUlast);
132       break;
133     case 1:
134       a2dCurv = 
135             new Geom2d_TrimmedCurve(new Geom2d_Line(
136                                           gp_Pnt2d(theUlast, theVfirst+theVlast),
137                                                           gp_Dir2d(0.0,-1.0)),
138                                           theVfirst, theVlast);
139       break;
140     case 2:
141       a2dCurv = 
142             new Geom2d_TrimmedCurve(new Geom2d_Line(
143                                           gp_Pnt2d(theUfirst+theUlast, theVlast), 
144                                                           gp_Dir2d(-1.0,0.0)),
145                                           theUfirst, theUlast);
146       break;
147     case 3:
148       a2dCurv = 
149             new Geom2d_TrimmedCurve(new Geom2d_Line(
150                                           gp_Pnt2d(theUfirst, theVfirst+theVlast),
151                                                           gp_Dir2d(0.0,-1.0)),
152                                           theVfirst, theVlast);
153       break;
154     default:
155       break;
156     }  
157   }
158
159   return a2dCurv;
160 }
161
162 //=======================================================================
163 //function : Constructor
164 //purpose  : 
165 //=======================================================================
166 BRepBuilderAPI_FastSewing::
167         BRepBuilderAPI_FastSewing( const Standard_Real theTol):
168   myTolerance(theTol),
169   myStatusList(0)
170 {
171 }
172
173 //=======================================================================
174 //function : Add
175 //purpose  : 
176 //=======================================================================
177 Standard_Boolean BRepBuilderAPI_FastSewing::Add(const TopoDS_Shape& theShape)
178 {
179   Standard_Boolean aResult = Standard_False;
180   if(theShape.IsNull())
181   {
182     SetStatus(FS_EmptyInput);
183     return aResult;
184   }
185
186   TopTools_MapOfShape aMS;
187   //aMS.Add(theShape);
188   TopExp_Explorer aFExp(theShape,TopAbs_FACE);
189   for (; aFExp.More(); aFExp.Next())
190   {
191     const TopoDS_Face& aFace = TopoDS::Face(aFExp.Current());
192     if(aMS.Add(aFace))
193     {
194       Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
195       if(aSurf.IsNull())
196       {
197         SetStatus(FS_FaceWithNullSurface);
198         continue;
199       }
200
201       if(aSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
202       {
203         SetStatus(FS_NotNaturalBoundsFace);
204         continue;
205       }
206
207       Standard_Real aUf = 0.0, aUl = 0.0, aVf = 0.0, aVl = 0.0;
208       aSurf->Bounds(aUf, aUl, aVf, aVl);
209
210       if(Precision::IsInfinite(aUf) || Precision::IsInfinite(aUl) ||
211          Precision::IsInfinite(aVf) || Precision::IsInfinite(aVl))
212       {
213         SetStatus(FS_InfiniteSurface);
214         continue;
215       }
216
217       FS_Face aFFace;
218       aFFace.mySrcFace = aFace;
219       aFFace.myID = myFaceVec.Length();//because start index is 0
220       myFaceVec.Append(aFFace);
221       aResult = Standard_True;
222     }
223   }
224
225   return aResult;
226 }
227
228 //=======================================================================
229 //function : Add
230 //purpose  : 
231 //=======================================================================
232 Standard_Boolean BRepBuilderAPI_FastSewing::Add(const Handle(Geom_Surface)& theSurface)
233 {
234   if(theSurface.IsNull())
235   {
236     SetStatus(FS_FaceWithNullSurface);
237     return Standard_False;
238   }
239
240   if(theSurface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
241   {
242     SetStatus(FS_NotNaturalBoundsFace);
243     return Standard_False;
244   }
245
246   Standard_Real aUf = 0.0, aUl = 0.0, aVf = 0.0, aVl = 0.0;
247   theSurface->Bounds(aUf, aUl, aVf, aVl);
248
249   if(Precision::IsInfinite(aUf) || Precision::IsInfinite(aUl) ||
250     Precision::IsInfinite(aVf) || Precision::IsInfinite(aVl))
251   {
252     SetStatus(FS_InfiniteSurface);
253     return Standard_False;
254   }
255
256   FS_Face aFace;
257
258   BRep_Builder aBuilder;
259   aBuilder.MakeFace(aFace.mySrcFace);
260   aBuilder.MakeFace(aFace.mySrcFace, theSurface, myTolerance);
261   aBuilder.NaturalRestriction(aFace.mySrcFace, Standard_True);
262
263   aFace.myID = myFaceVec.Length();//because start index is 0
264   myFaceVec.Append(aFace);
265
266   return Standard_True;
267 }
268
269
270 //=======================================================================
271 //function : Perform
272 //purpose  : 
273 //=======================================================================
274 void BRepBuilderAPI_FastSewing::Perform(void)
275 {
276   if(myFaceVec.IsEmpty())
277   {
278     SetStatus(FS_EmptyInput);
279     return;
280   }
281
282   try
283   {
284     {
285       // create vertices having unique coordinates
286       Standard_Real aRange = Compute3DRange();
287       Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
288       NCollection_CellFilter<NodeInspector> 
289         aCells(Max(myTolerance, aRange/IntegerLast()), anAlloc);
290
291       for(Standard_Integer i = myFaceVec.Lower(); i <= myFaceVec.Upper(); i++)
292       {
293         FindVertexes(i, aCells);
294       }
295     }
296
297     for(Standard_Integer i = myFaceVec.Lower(); i <= myFaceVec.Upper(); i++)
298     {
299       FindEdges(i);
300     }
301
302     //Create topological structures
303
304     for(Standard_Integer i = myVertexVec.Lower(); i <= myVertexVec.Upper(); i++)
305     {
306       myVertexVec.ChangeValue(i).CreateTopologicalVertex(myTolerance);
307     }
308
309     //Edges
310     for(Standard_Integer i = myEdgeVec.Lower(); i <= myEdgeVec.Upper(); i++)
311     {
312       myEdgeVec.ChangeValue(i).CreateTopologicalEdge(myVertexVec, myFaceVec, myTolerance);
313     }
314
315     //Shell
316     BRepTools_Quilt aQuilt;
317
318     //Faces
319     for(Standard_Integer i = myFaceVec.Lower(); i <= myFaceVec.Upper(); i++)
320     {
321       FS_Face& aFace = myFaceVec.ChangeValue(i);
322       aFace.CreateTopologicalWire(myEdgeVec, myTolerance);
323       aFace.CreateTopologicalFace();
324       aQuilt.Add(aFace.myRetFace);
325     }
326
327     myResShape = aQuilt.Shells();
328   }
329   catch(Standard_Failure const&)
330   {
331     SetStatus(FS_Exception);
332 #ifdef OCCT_DEBUG
333     //Standard_Failure::Caught()->Print(std::cout);
334 #endif
335     return;
336   }
337 }
338
339 //=======================================================================
340 //function : UpdateEdgeInfo
341 //purpose  : 
342 //=======================================================================
343 void BRepBuilderAPI_FastSewing::UpdateEdgeInfo( const Standard_Integer theIDPrevVertex,
344                                                 const Standard_Integer theIDCurrVertex,
345                                                 const Standard_Integer theFaceID,
346                                                 const Standard_Integer theIDCurvOnFace)
347 {
348   //Indeed, two vertices combine into one edge only.
349   const Standard_Integer anEdgeID = 
350                       IntersectionOfSets(myVertexVec.Value(theIDPrevVertex).myEdges,
351                                           myVertexVec.Value(theIDCurrVertex).myEdges);
352
353   //For DEBUG mode only
354   Standard_ProgramError_Raise_if(anEdgeID < 0, 
355         "BRepBuilderAPI_FastSewing::UpdateEdgeInfo: Update not existing edge.");
356
357   FS_Edge& anEdge = myEdgeVec.ChangeValue(anEdgeID);
358   anEdge.myFaces.Append(theFaceID);
359   FS_Face& aFace = myFaceVec.ChangeValue(theFaceID);
360   aFace.SetEdge(theIDCurvOnFace, anEdge.myID);
361 }
362
363 //=======================================================================
364 //function : CreateNewEdge
365 //purpose  : Creates FS_Edge
366 //=======================================================================
367 void BRepBuilderAPI_FastSewing::CreateNewEdge(const Standard_Integer theIDPrevVertex,
368                                               const Standard_Integer theIDCurrVertex,
369                                               const Standard_Integer theFaceID,
370                                               const Standard_Integer theIDCurvOnFace)
371 {
372   FS_Edge anEdge(theIDPrevVertex, theIDCurrVertex);
373   anEdge.myID = myEdgeVec.Length(); //because start index is 0
374
375
376   anEdge.myFaces.Append(theFaceID);
377   FS_Face& aFace = myFaceVec.ChangeValue(theFaceID);
378   aFace.SetEdge(theIDCurvOnFace, anEdge.myID);
379
380   myVertexVec.ChangeValue(theIDPrevVertex).myEdges.Append(anEdge.myID);
381
382   if(theIDPrevVertex == theIDCurrVertex)
383   {//the Edge is degenerated
384     SetStatus(FS_Degenerated);
385   }
386   else
387   {
388     myVertexVec.ChangeValue(theIDCurrVertex).myEdges.Append(anEdge.myID);
389   }
390
391   myEdgeVec.Append(anEdge);
392 }
393
394 //=======================================================================
395 //function : FindVertexes
396 //purpose  : 
397 //=======================================================================
398 void BRepBuilderAPI_FastSewing::
399             FindVertexes(const Standard_Integer theSurfID,
400             NCollection_CellFilter<NodeInspector>& theCells)
401 {
402   const Standard_Integer aNbPoints = 4;
403   FS_Face& aFace = myFaceVec.ChangeValue(theSurfID);
404   const Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace.mySrcFace);
405   Standard_Real aUf = 0.0, aUl = 0.0, aVf = 0.0, aVl = 0.0;
406   aSurf->Bounds(aUf, aUl, aVf, aVl);
407
408   const gp_Pnt aPnts[aNbPoints] = { aSurf->Value(aUf, aVf),
409                                     aSurf->Value(aUl, aVf),
410                                     aSurf->Value(aUl, aVl),
411                                     aSurf->Value(aUf, aVl)};
412
413   for(Standard_Integer i = 0; i < aNbPoints; i++)
414   {
415     FS_Vertex aVert;
416
417     NodeInspector anInspector(myVertexVec, aPnts[i], myTolerance);
418     Bnd_Box aBox;
419     aBox.Add(aPnts[i]);
420     aBox.Enlarge(myTolerance);
421
422     theCells.Inspect(aBox.CornerMin().XYZ(), aBox.CornerMax().XYZ(), anInspector);
423     NodeInspector::Target aResID = anInspector.GetResult();
424
425     if(aResID < 0)
426     {//Add new Vertex
427       aVert.myID = myVertexVec.Length(); //because start index is 0
428       aVert.myPnt = aPnts[i];
429       aVert.myFaces.Append(theSurfID);
430       myVertexVec.Append(aVert);
431       aFace.SetVertex(i, aVert.myID);
432
433       theCells.Add(aVert.myID, aBox.CornerMin().XYZ(), aBox.CornerMax().XYZ());
434     }
435     else
436     {//Change existing vertex
437       aFace.SetVertex(i, aResID);
438       myVertexVec.ChangeValue(aResID).myFaces.Append(theSurfID);
439     }
440   }
441 }
442
443 //=======================================================================
444 //function : FindEdges
445 //purpose  : 
446 //=======================================================================
447 void BRepBuilderAPI_FastSewing::FindEdges(const Standard_Integer theSurfID)
448 {
449   const Standard_Integer aNbPoints = 4;
450   FS_Face& aFace = myFaceVec.ChangeValue(theSurfID);
451
452   const Standard_Integer aFirstInd[aNbPoints] = {0, 1, 3, 0};
453   const Standard_Integer aLastInd[aNbPoints] = {1, 2, 2, 3};
454
455   for(Standard_Integer i = 0; i < aNbPoints; i++)
456   {
457     const Standard_Integer  aFirstVertIndex = aFirstInd[i],
458                             aLastVertIndex = aLastInd[i];
459     const Standard_Integer  aFirstVertID = aFace.myVertices[aFirstVertIndex],
460                             aLastVertID  = aFace.myVertices[aLastVertIndex];
461
462     if(aFirstVertID == aLastVertID)
463     {//Edge is degenerated.
464       CreateNewEdge(aFirstVertID, aLastVertID, theSurfID, i);
465       continue;
466     }
467
468     //Must be minimal element from list
469     const Standard_Integer anIntRes = 
470                     IntersectionOfSets(myVertexVec.Value(aFirstVertID).myFaces,
471                     myVertexVec.Value(aLastVertID).myFaces);
472     
473     if((anIntRes < 0) || (anIntRes >= theSurfID))
474     {
475       CreateNewEdge(aFirstVertID, aLastVertID, theSurfID, i);
476     }
477     else
478     {//if(theSurfID > anIntRes) => The edge has been processed earlier
479       UpdateEdgeInfo(aFirstVertID, aLastVertID, theSurfID, i);
480     }
481   }
482 }
483
484 //=======================================================================
485 //function : GetStatuses
486 //purpose  : 
487 //=======================================================================
488 BRepBuilderAPI_FastSewing::FS_VARStatuses 
489       BRepBuilderAPI_FastSewing::GetStatuses(Standard_OStream* const theOS)
490 {
491   if(!theOS)
492     return myStatusList;
493
494   if(!myStatusList)
495   {
496     *theOS << "Fast Sewing OK!\n";
497     return myStatusList;
498   }
499
500   //Number of bits
501   const Standard_Integer aNumMax = 8*sizeof(myStatusList);
502   FS_Statuses anIDS = static_cast<FS_Statuses>(0x0001);
503   for(Standard_Integer i = 1; i <= aNumMax; i++,
504                   anIDS = static_cast<FS_Statuses>(anIDS << 1))
505   {
506     if((anIDS & myStatusList) == 0)
507       continue;
508
509     switch(anIDS)
510     {
511     case FS_Degenerated:
512       *theOS << "Degenerated case. Try to reduce tolerance.\n";
513       break;
514     case FS_FindVertexError:
515       *theOS << "Error while creating list of vertices.\n";
516       break;
517     case FS_FindEdgeError:
518       *theOS << "Error while creating list of edges.\n";
519       break;
520     case FS_Exception:
521       *theOS << "Exception during the operation.\n";
522       break;
523     case FS_FaceWithNullSurface:
524       *theOS << "Source face has null surface.\n";
525       break;
526     case FS_NotNaturalBoundsFace:
527       *theOS << "Source face has trimmed surface.\n";
528       break;
529     case FS_InfiniteSurface:
530       *theOS << "Source face has the surface with infinite boundaries.\n";
531       break;
532     case FS_EmptyInput:
533       *theOS << "Empty source data.\n";
534       break;
535
536
537     default:
538       return myStatusList;
539     }
540   }
541
542   return myStatusList;
543 }
544
545 //=======================================================================
546 //function : Compute3DRange
547 //purpose  : 
548 //=======================================================================
549 Standard_Real BRepBuilderAPI_FastSewing::Compute3DRange()
550 {
551   Bnd_Box aBox;
552
553   for(Standard_Integer i = myFaceVec.Lower(); i <= myFaceVec.Upper(); i++)
554   {
555     FS_Face& aFace = myFaceVec.ChangeValue(i);
556     const Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace.mySrcFace);
557     if(aSurf.IsNull())
558       continue;
559     Standard_Real aUf = 0.0, aUl = 0.0, aVf = 0.0, aVl = 0.0;
560     aSurf->Bounds(aUf, aUl, aVf, aVl);
561     
562     aBox.Add(aSurf->Value(aUf, aVf));
563     aBox.Add(aSurf->Value(aUl, aVf));
564     aBox.Add(aSurf->Value(aUl, aVl));
565     aBox.Add(aSurf->Value(aUf, aVl));
566   }
567
568   Standard_Real aXm = 0.0, aYm = 0.0, aZm = 0.0, aXM = 0.0, aYM = 0.0, aZM = 0.0;
569   aBox.Get(aXm, aYm, aZm, aXM, aYM, aZM);
570   Standard_Real aDelta = aXM - aXm;
571   aDelta = Max(aDelta, aYM - aYm);
572   aDelta = Max(aDelta, aZM - aZm);
573
574   return aDelta;
575 }
576
577 //=======================================================================
578 //function : NodeInspector constructor
579 //purpose  : 
580 //=======================================================================
581 BRepBuilderAPI_FastSewing::NodeInspector::
582                       NodeInspector(const NCollection_Vector<FS_Vertex>& theVec,
583                                     const gp_Pnt& thePnt,
584                                     const Standard_Real theTol)
585 : myVecOfVertexes(theVec),
586   myPoint(thePnt),
587   myResID(-1),
588   myIsFindingEnable(Standard_False)
589 {
590   mySQToler = theTol*theTol;
591 }
592
593 //=======================================================================
594 //function : ::NodeInspector::Inspect
595 //purpose  : 
596 //=======================================================================
597 NCollection_CellFilter_Action BRepBuilderAPI_FastSewing::
598                                   NodeInspector::Inspect(const Target theID)
599 {
600   const gp_Pnt& aPt = myVecOfVertexes.Value(theID).myPnt;
601   const Standard_Real aSQDist = aPt.SquareDistance(myPoint);
602   if(aSQDist < mySQToler)
603   {
604     mySQToler = aSQDist;
605     myResID = theID;
606   }
607
608   return CellFilter_Keep;
609 }
610
611 //=======================================================================
612 //function : ::FS_Edge::CreateTopologicalEdge
613 //purpose  : 
614 //=======================================================================
615 void BRepBuilderAPI_FastSewing::FS_Edge::
616           CreateTopologicalEdge(const NCollection_Vector<FS_Vertex>& theVertexVec,
617                                 const NCollection_Vector<FS_Face>& theFaceVec,
618                                 const Standard_Real theTol)
619 {
620   BRep_Builder aBuilder;
621
622   TopoDS_Vertex aV1 = theVertexVec(myVertices[0]).myTopoVert;
623   TopoDS_Vertex aV2 = theVertexVec(myVertices[1]).myTopoVert;
624
625   aV1.Orientation(TopAbs_FORWARD);
626   aV2.Orientation(TopAbs_REVERSED);
627
628   Handle(Geom_Curve) a3dCurv;
629   TopLoc_Location aLocation;
630
631   const FS_Face& aFace = theFaceVec.Value(myFaces.Value(myFaces.Lower()));
632
633   //3D-curves in 1st and 2nd faces are considered to be in same-range
634   const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aFace.mySrcFace, aLocation);
635
636   Standard_Real aUf = 0.0, aUl = 0.0, aVf = 0.0, aVl = 0.0;
637   aSurf->Bounds(aUf, aUl, aVf, aVl);
638
639   Standard_Integer anEdgeID = -1;
640   for(Standard_Integer anInd = 0; anInd < 4; anInd++)
641   {
642     if(myID == aFace.myEdges[anInd])
643     {
644       anEdgeID = anInd;
645       break;
646     }
647   }
648
649   //For DEBUG mode only
650   Standard_ProgramError_Raise_if(anEdgeID < 0, 
651         "BRepBuilderAPI_FastSewing::FS_Edge::CreateTopologicalEdge: Single edge.");
652
653   if(IsDegenerated())
654   {
655     Handle(Geom2d_Curve) a2dCurv = Get2DCurve(anEdgeID, aUf, aUl, aVf, aVl);
656     const Standard_Real aFPar = a2dCurv->FirstParameter(),
657                         aLPar = a2dCurv->LastParameter();
658
659     aBuilder.MakeEdge(myTopoEdge);
660     aBuilder.UpdateEdge(myTopoEdge, a2dCurv, aSurf, aLocation, theTol);
661     aBuilder.Add(myTopoEdge, aV1);
662     aBuilder.Add(myTopoEdge, aV2);
663     aBuilder.Range(myTopoEdge, aFPar, aLPar);
664     aBuilder.Degenerated(myTopoEdge, Standard_True);
665     return;
666   }
667
668   switch(anEdgeID)
669   {
670   case 0:
671     a3dCurv = aSurf->VIso(aVf);
672     break;
673   case 1:
674     a3dCurv = aSurf->UIso(aUl);
675     break;
676   case 2:
677     a3dCurv = aSurf->VIso(aVl);
678     break;
679   case 3:
680     a3dCurv = aSurf->UIso(aUf);
681     break;
682   default:
683     throw Standard_OutOfRange("FS_Edge::CreateTopologicalEdge()");
684     break;
685   }
686
687   aBuilder.MakeEdge(myTopoEdge, a3dCurv, theTol);
688   aBuilder.Add(myTopoEdge, aV1);
689   aBuilder.Add(myTopoEdge, aV2);
690   aBuilder.Range(myTopoEdge, a3dCurv->FirstParameter(), a3dCurv->LastParameter());
691 }
692
693 //=======================================================================
694 //function : ::FS_Face::CreateTopologicalWire
695 //purpose  : 
696 //=======================================================================
697 void BRepBuilderAPI_FastSewing::FS_Face::
698                 CreateTopologicalWire(const NCollection_Vector<FS_Edge>& theEdgeVec,
699                 const Standard_Real theToler)
700 {
701   TopLoc_Location aLocation;
702   //3D-curves in 1st and 2nd faces are considered to be in same-range
703   const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(mySrcFace, aLocation);
704   Standard_Real aUf = 0.0, aUl = 0.0, aVf = 0.0, aVl = 0.0;
705   aSurf->Bounds(aUf, aUl, aVf, aVl);
706
707   BRep_Builder aB;
708   aB.MakeWire(myWire);
709   for(Standard_Integer anEdge = 0; anEdge < 4; anEdge++)
710   {
711     Standard_ProgramError_Raise_if(myEdges[anEdge] < 0, 
712       "BRepBuilderAPI_FastSewing::FS_Face::CreateTopologicalWire: Wire is not closed.");
713
714     const BRepBuilderAPI_FastSewing::FS_Edge& aFSEdge = theEdgeVec.Value(myEdges[anEdge]);
715     TopAbs_Orientation anOri = anEdge < 2 ? TopAbs_FORWARD : TopAbs_REVERSED;
716     TopoDS_Edge anTopE = aFSEdge.myTopoEdge;
717
718     if(aFSEdge.IsDegenerated())
719     {
720       anTopE.Orientation(anOri);
721       aB.Add(myWire, anTopE);
722       continue;
723     }
724
725     //Check if 3D and 2D-curve have same-orientation.
726     //If it is not, 2d-curve will be reversed.
727     {
728       Standard_Real aFirstPar = 0.0, aLastPar = 0.0;
729
730       const Handle(Geom_Curve) a3dCurv = BRep_Tool::Curve(anTopE, aFirstPar, aLastPar);
731       Handle(Geom2d_Curve) a2dCurv = Get2DCurve(anEdge, aUf, aUl, aVf, aVl);
732       const gp_Pnt aPref(a3dCurv->Value(aFirstPar));
733       const gp_Pnt2d aP2df(a2dCurv->Value(aFirstPar)), aP2dl(a2dCurv->Value(aLastPar));
734       gp_Pnt aP3df(aSurf->Value(aP2df.X(), aP2df.Y()));
735       gp_Pnt aP3dl(aSurf->Value(aP2dl.X(), aP2dl.Y()));
736       aP3df.Transform(aLocation);
737       aP3dl.Transform(aLocation);
738       const Standard_Real aSqD1 = aP3df.SquareDistance(aPref);
739       const Standard_Real aSqD2 = aP3dl.SquareDistance(aPref);
740
741       if(aSqD2 < aSqD1)
742       {
743         a2dCurv = Get2DCurve(anEdge, aUf, aUl, aVf, aVl, Standard_True);
744         anOri = TopAbs::Reverse(anOri);
745       }
746
747       aB.UpdateEdge(anTopE, a2dCurv, aSurf, aLocation, theToler);
748     }
749
750     anTopE.Orientation(anOri);
751
752     aB.Add(myWire, anTopE);
753   }
754
755   myWire.Closed(Standard_True);
756 }
757
758 //=======================================================================
759 //function : ::FS_Face::CreateTopologicalFace
760 //purpose  : 
761 //=======================================================================
762 void BRepBuilderAPI_FastSewing::FS_Face::CreateTopologicalFace()
763 {
764   Standard_ProgramError_Raise_if(myWire.IsNull(), 
765       "BRepBuilderAPI_FastSewing::FS_Face::CreateTopologicalFace: Cannot create wire.");
766
767   BRep_Builder aBuilder;
768   myRetFace = TopoDS::Face(mySrcFace.EmptyCopied());
769   aBuilder.Add(myRetFace, myWire);
770   aBuilder.NaturalRestriction(myRetFace, Standard_True);
771 }