0022492: Scaled sphere (Solid with BSplineSurface) is wrongly exported in STEP.
[occt.git] / src / BRepAlgoAPI / BRepAlgoAPI_Section.cxx
1 // File:        BRepAlgoAPI_Section.cxx
2 // Created:     Fri Feb 18 11:14:56 1994
3 // Author:      Remi LEQUETTE
4 //              
5 // modified by Michael KLOKOV  Wed Mar  6 15:01:25 2002
6
7 #include <BRepAlgoAPI_Section.ixx>
8
9
10 #include <BRepBuilderAPI_MakeFace.hxx>
11 #include <BRepBuilderAPI_MakeShell.hxx>
12 #include <Geom_Plane.hxx>
13 #include <Geom2d_TrimmedCurve.hxx>
14 #include <BOP_Section.hxx>
15 #include <BOPTools_SSIntersectionAttribute.hxx>
16
17 #include <BOPTools_SplitShapesPool.hxx>
18 #include <BOPTools_InterferencePool.hxx>
19
20 #include <BOPTools_PaveBlock.hxx>
21 #include <BOPTools_PaveFiller.hxx>
22 #include <BooleanOperations_ShapesDataStructure.hxx>
23 #include <BOPTools_ListOfPaveBlock.hxx>
24 #include <BOPTools_ListIteratorOfListOfPaveBlock.hxx>
25 #include <BOPTools_SSInterference.hxx>
26 #include <BOPTools_Curve.hxx>
27 #include <TopExp.hxx>
28 #include <TopTools_IndexedMapOfShape.hxx>
29 #include <TopTools_MapOfShape.hxx>
30 #include <TopoDS.hxx>
31 #include <TopoDS_Face.hxx>
32 #include <BRep_Tool.hxx>
33
34 #include <BOP_SectionHistoryCollector.hxx>
35
36 static TopoDS_Shape MakeShape(const Handle(Geom_Surface)& S)
37 {
38   GeomAbs_Shape c = S->Continuity();
39   if (c >= GeomAbs_C2) return BRepBuilderAPI_MakeFace(S, Precision::Confusion());
40   else return BRepBuilderAPI_MakeShell(S);
41 }
42
43 static Standard_Boolean HasAncestorFaces(const BOPTools_DSFiller& theDSFiller, 
44                                          const TopoDS_Shape&      E,
45                                          TopoDS_Shape&            F1,
46                                          TopoDS_Shape&            F2);
47
48 //=======================================================================
49 //function : Constructor
50 //purpose  : 
51 //=======================================================================
52 BRepAlgoAPI_Section::BRepAlgoAPI_Section(const TopoDS_Shape& Sh1,
53                                          const TopoDS_Shape& Sh2,
54                                          const Standard_Boolean PerformNow)
55 : BRepAlgoAPI_BooleanOperation(Sh1, Sh2, BOP_SECTION)
56 {
57   InitParameters();
58   myparameterschanged = Standard_True;
59
60   if(myS1.IsNull() || myS2.IsNull()) {
61     //     StdFail_NotDone::Raise("BRepAlgoAPI_Section : Shape NULL");
62     myshapeisnull = Standard_True;
63   }
64   if (PerformNow)
65     Build();
66 }
67
68 BRepAlgoAPI_Section::BRepAlgoAPI_Section(const TopoDS_Shape&      aS1, 
69                                          const TopoDS_Shape&      aS2,
70                                          const BOPTools_DSFiller& aDSF,
71                                          const Standard_Boolean   PerformNow)
72 : BRepAlgoAPI_BooleanOperation(aS1, aS2, aDSF, BOP_SECTION)
73 {
74   InitParameters();
75   myparameterschanged = Standard_True;
76
77   if(myS1.IsNull() || myS2.IsNull()) {
78     //     StdFail_NotDone::Raise("BRepAlgoAPI_Section : Shape NULL");
79     myshapeisnull = Standard_True;
80   }
81
82   if(PerformNow) {
83     Build();
84   }
85 }
86
87
88 //=======================================================================
89 //function : Constructor
90 //purpose  : 
91 //=======================================================================
92 BRepAlgoAPI_Section::BRepAlgoAPI_Section(const TopoDS_Shape&    Sh,
93                                          const gp_Pln&          Pl,
94                                          const Standard_Boolean PerformNow)
95 : BRepAlgoAPI_BooleanOperation(Sh, MakeShape(new Geom_Plane(Pl)), BOP_SECTION)
96 {
97   InitParameters();
98   myparameterschanged = Standard_True;
99
100   if(Sh.IsNull() || myS2.IsNull()) {
101     //     StdFail_NotDone::Raise("BRepAlgoAPI_Section : Shape NULL");
102     myshapeisnull = Standard_True;
103   }
104   if (PerformNow)
105     Build();
106 }
107
108 //=======================================================================
109 //function : Constructor
110 //purpose  : 
111 //=======================================================================
112 BRepAlgoAPI_Section::BRepAlgoAPI_Section(const TopoDS_Shape&         Sh,
113                                                const Handle(Geom_Surface)& Sf,
114                                                const Standard_Boolean      PerformNow)
115 : BRepAlgoAPI_BooleanOperation(Sh, MakeShape(Sf), BOP_SECTION)
116 {
117   InitParameters();
118   myparameterschanged = Standard_True;
119
120   if(Sh.IsNull() || myS2.IsNull()) {
121 //     StdFail_NotDone::Raise("BRepAlgoAPI_Section : Shape NULL");
122     myshapeisnull = Standard_True;
123   }
124   if (PerformNow)
125     Build();
126 }
127
128 //=======================================================================
129 //function : Constructor
130 //purpose  : 
131 //=======================================================================
132 BRepAlgoAPI_Section::BRepAlgoAPI_Section(const Handle(Geom_Surface)& Sf,
133                                                const TopoDS_Shape&         Sh,
134                                                const Standard_Boolean      PerformNow)
135 : BRepAlgoAPI_BooleanOperation(MakeShape(Sf), Sh, BOP_SECTION)
136 {
137   InitParameters();
138   myparameterschanged = Standard_True;
139
140   if(myS1.IsNull() || Sh.IsNull()) {
141 //     StdFail_NotDone::Raise("BRepAlgoAPI_Section : Shape NULL");
142     myshapeisnull = Standard_True;
143   }
144   if (PerformNow)
145     Build();
146 }
147
148 //=======================================================================
149 //function : Constructor
150 //purpose  : 
151 //=======================================================================
152 BRepAlgoAPI_Section::BRepAlgoAPI_Section(const Handle(Geom_Surface)& Sf1,
153                                                const Handle(Geom_Surface)& Sf2,
154                                                const Standard_Boolean      PerformNow)
155 : BRepAlgoAPI_BooleanOperation(MakeShape(Sf1), MakeShape(Sf2), BOP_SECTION)
156 {
157   InitParameters();
158   myparameterschanged = Standard_True;
159
160   if(myS1.IsNull() || myS2.IsNull()) {
161 //     StdFail_NotDone::Raise("BRepAlgoAPI_Section : Shape NULL");
162     myshapeisnull = Standard_True;
163   }
164
165   if (PerformNow)
166     Build();
167 }
168
169 //=======================================================================
170 //function : Init1
171 //purpose  : 
172 //=======================================================================
173 void BRepAlgoAPI_Section::Init1(const TopoDS_Shape& S1) 
174 {
175   if(!S1.IsNull()) {
176     if (!S1.IsEqual(myS1)) {
177       myS1 = S1;
178
179       if(!myS2.IsNull()) {
180         myshapeisnull = Standard_False;
181       }
182       myparameterschanged = Standard_True;
183     }
184   }
185   else {
186     if(!myS1.IsNull()) {
187       myS1 = S1;
188       myshapeisnull = Standard_True;
189       myparameterschanged = Standard_True;
190     }
191   }
192
193   if(myparameterschanged)
194     NotDone();
195 }
196
197 //=======================================================================
198 //function : Init1
199 //purpose  : 
200 //=======================================================================
201 void BRepAlgoAPI_Section::Init1(const gp_Pln& Pl) 
202 {
203   Init1(MakeShape(new Geom_Plane(Pl)));
204 }
205
206 //=======================================================================
207 //function : Init1
208 //purpose  : 
209 //=======================================================================
210 void BRepAlgoAPI_Section::Init1(const Handle(Geom_Surface)& Sf) 
211 {
212   Init1(MakeShape(Sf));
213 }
214
215 //=======================================================================
216 //function : Init2
217 //purpose  : 
218 //=======================================================================
219 void BRepAlgoAPI_Section::Init2(const TopoDS_Shape& S2) 
220 {
221   if(!S2.IsNull()) {
222     if (!S2.IsEqual(myS2)) {
223       myS2 = S2;
224
225       if(!myS1.IsNull()) {
226         myshapeisnull = Standard_False;
227       }
228       myparameterschanged = Standard_True;
229     }
230   }
231   else {
232     if(!myS2.IsNull()) {
233       myS2 = S2;
234       myshapeisnull = Standard_True;
235       myparameterschanged = Standard_True;
236     }
237   }
238
239   if(myparameterschanged) {
240     NotDone();
241   }
242 }
243
244 //=======================================================================
245 //function : Init2
246 //purpose  : 
247 //=======================================================================
248 void BRepAlgoAPI_Section::Init2(const gp_Pln& Pl) 
249 {
250   Init2(MakeShape(new Geom_Plane(Pl)));
251 }
252
253 //=======================================================================
254 //function : Init2
255 //purpose  : 
256 //=======================================================================
257 void BRepAlgoAPI_Section::Init2(const Handle(Geom_Surface)& Sf) 
258 {
259   Init2(MakeShape(Sf));
260 }
261
262 //=======================================================================
263 //function : Approximation
264 //purpose  : 
265 //=======================================================================
266 void BRepAlgoAPI_Section::Approximation(const Standard_Boolean B) 
267 {
268   if(myApprox != B) {
269     myApprox = B;
270     myparameterschanged = Standard_True;
271   }
272 }
273
274 //=======================================================================
275 //function : ComputePCurveOn1
276 //purpose  : 
277 //=======================================================================
278 void BRepAlgoAPI_Section::ComputePCurveOn1(const Standard_Boolean B) 
279 {
280   if(myComputePCurve1 != B) {
281     myComputePCurve1 = B;
282     myparameterschanged = Standard_True;
283   }
284 }
285
286 //=======================================================================
287 //function : ComputePCurveOn2
288 //purpose  : 
289 //=======================================================================
290 void BRepAlgoAPI_Section::ComputePCurveOn2(const Standard_Boolean B) 
291 {
292   if(myComputePCurve2 != B) {
293     myComputePCurve2 = B;
294     myparameterschanged = Standard_True;
295   }
296 }
297
298 //=======================================================================
299 //function : Build
300 //purpose  : 
301 //=======================================================================
302 void BRepAlgoAPI_Section::Build() 
303 {
304   if(myshapeisnull) {
305     myErrorStatus = 2;
306     NotDone();
307     return;
308   }
309
310   if(myparameterschanged) {
311
312     myBuilderCanWork = Standard_False;
313
314     Standard_Boolean bIsNewFiller = PrepareFiller();
315     //
316     if (myErrorStatus!=1) {
317       NotDone();
318       // there were errors during the preparation 
319       return;
320     }
321     //
322     if (bIsNewFiller) {
323       //Prepare the DS
324       BOPTools_SSIntersectionAttribute aSectionAttribute(myApprox, myComputePCurve1, myComputePCurve2);
325       myDSFiller->Perform(aSectionAttribute);
326     }
327     BOP_Section* aSectionAlgo = new BOP_Section();
328     aSectionAlgo->SetShapes(myS1, myS2);
329
330     myHistory = new BOP_SectionHistoryCollector(myS1, myS2);
331     aSectionAlgo->SetHistoryCollector(myHistory);
332
333     aSectionAlgo->DoWithFiller(*myDSFiller);
334
335     myBuilder = aSectionAlgo;
336
337     if(aSectionAlgo->IsDone()) {
338       myErrorStatus=0;
339       myBuilderCanWork=Standard_True;
340       myShape = aSectionAlgo->Result();
341       Done();
342     }
343     else {
344       myErrorStatus = 100 + aSectionAlgo->ErrorStatus();
345       NotDone();
346     }    
347     myparameterschanged = Standard_False;
348   }
349 }
350
351 //=======================================================================
352 //function : HasAncestorFaceOn1
353 //purpose  : 
354 //=======================================================================
355 Standard_Boolean BRepAlgoAPI_Section::HasAncestorFaceOn1(const TopoDS_Shape& E, TopoDS_Shape& F) const
356 {
357   Standard_Boolean aResult = Standard_False;
358   if(E.IsNull()) {
359     return aResult;
360   }
361
362   if(E.ShapeType() != TopAbs_EDGE) {
363     return aResult;
364   }
365   TopoDS_Shape F1, F2;
366   aResult = HasAncestorFaces(*myDSFiller, E, F1, F2);
367
368   if(F1.IsNull()) {
369     return Standard_False;
370   }
371   F = F1;
372   return aResult;
373 }
374
375 //=======================================================================
376 //function : HasAncestorFaceOn2
377 //purpose  : 
378 //=======================================================================
379 Standard_Boolean BRepAlgoAPI_Section::HasAncestorFaceOn2(const TopoDS_Shape& E,TopoDS_Shape& F) const
380 {
381   Standard_Boolean aResult = Standard_False;
382   if(E.IsNull()) {
383     return aResult;
384   }
385
386   if(E.ShapeType() != TopAbs_EDGE) {
387     return aResult;
388   }
389   TopoDS_Shape F1, F2;
390   aResult = HasAncestorFaces(*myDSFiller, E, F1, F2);
391
392   if(F2.IsNull()) {
393     return Standard_False;
394   }
395   F = F2;
396   return aResult;
397 }
398
399 //=======================================================================
400 //function : PCurveOn1
401 //purpose  : 
402 //=======================================================================
403 Handle(Geom2d_Curve) BRepAlgoAPI_Section::PCurveOn1(const TopoDS_Shape& E) const
404 {
405   Handle(Geom2d_Curve) aResult;
406   
407   if(myComputePCurve1) {
408     TopoDS_Shape aShape;
409
410     if(HasAncestorFaceOn1(E, aShape)) {
411       const TopoDS_Edge& anEdge = TopoDS::Edge(E);
412       const TopoDS_Face& aFace  = TopoDS::Face(aShape);
413       Standard_Real f, l;
414       aResult = BRep_Tool::CurveOnSurface(anEdge, aFace, f, l);
415
416       if(!aResult->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) {
417         aResult = new Geom2d_TrimmedCurve(aResult, f, l);
418       }
419     }
420   }
421   return aResult;
422 }
423
424 //=======================================================================
425 //function : PCurveOn2
426 //purpose  : 
427 //=======================================================================
428 Handle(Geom2d_Curve) BRepAlgoAPI_Section::PCurveOn2(const TopoDS_Shape& E) const
429 {
430   Handle(Geom2d_Curve) aResult;
431   
432   if(myComputePCurve2) {
433     TopoDS_Shape aShape;
434
435     if(HasAncestorFaceOn2(E, aShape)) {
436       const TopoDS_Edge& anEdge = TopoDS::Edge(E);
437       const TopoDS_Face& aFace  = TopoDS::Face(aShape);
438       Standard_Real f, l;
439       aResult = BRep_Tool::CurveOnSurface(anEdge, aFace, f, l);
440       
441       if(!aResult->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) {
442         aResult = new Geom2d_TrimmedCurve(aResult, f, l);
443       }
444     }
445   }
446   return aResult;
447 }
448
449 //=======================================================================
450 //function : InitParameters
451 //purpose  : 
452 //=======================================================================
453 void BRepAlgoAPI_Section::InitParameters() 
454 {
455   myparameterschanged = Standard_False;
456   myshapeisnull = Standard_False;
457   myApprox = Standard_False;
458   myComputePCurve1 = Standard_False;
459   myComputePCurve2 = Standard_False;
460 }
461
462 // ------------------------------------------------------------------------
463 // static function : HasAncestorFaces
464 // purpose  : 
465 // ------------------------------------------------------------------------
466 static Standard_Boolean HasAncestorFaces(const BOPTools_DSFiller& theDSFiller, 
467                                          const TopoDS_Shape&      E,
468                                          TopoDS_Shape&            F1,
469                                          TopoDS_Shape&            F2) {
470
471   BOPTools_PaveFiller* aPaveFiller = (BOPTools_PaveFiller*) &theDSFiller.PaveFiller();
472   const BOPTools_CArray1OfSSInterference& aFFs = aPaveFiller->InterfPool()->SSInterferences();
473   const BooleanOperations_ShapesDataStructure& aDS = theDSFiller.DS();
474   Standard_Integer aNb = aFFs.Extent();
475   Standard_Integer i = 0;
476
477   for (i = 1; i <= aNb; i++) {
478     BOPTools_SSInterference* aFFi = (BOPTools_SSInterference*) &aFFs(i);
479     const BOPTools_SequenceOfCurves& aSeqOfCurve = aFFi->Curves();
480     
481     for(Standard_Integer j = 1; j <= aSeqOfCurve.Length(); j++) {
482       const BOPTools_Curve& aCurve = aSeqOfCurve.Value(j);
483       BOPTools_ListIteratorOfListOfPaveBlock anIt(aCurve.NewPaveBlocks());
484
485       for(; anIt.More(); anIt.Next()) {
486         const BOPTools_PaveBlock& aPB = anIt.Value();
487         Standard_Integer anIndex = aPB.Edge();
488
489         if(anIndex <= 0)
490           continue;
491
492         if(E.IsSame(aDS.Shape(anIndex))) {
493           for(Standard_Integer fIt = 0; fIt < 2; fIt++) {
494             anIndex = (fIt == 0) ? aFFi->Index1() : aFFi->Index2();
495             
496             if(anIndex > 0) {
497               if (fIt == 0)
498                 F1 = aDS.Shape(anIndex);
499               else
500                 F2 = aDS.Shape(anIndex);
501             }
502           }
503           return Standard_True;
504         }
505       }
506     }
507
508     BOPTools_ListIteratorOfListOfPaveBlock anIt(aFFi->PaveBlocks());
509     
510     for(; anIt.More(); anIt.Next()) {
511       const BOPTools_PaveBlock& aPB = anIt.Value();
512       Standard_Integer anIndex = aPB.Edge();
513
514       if(anIndex <= 0)
515         continue;
516       
517       if(E.IsSame(aDS.Shape(anIndex))) {
518         for(Standard_Integer fIt = 0; fIt < 2; fIt++) {
519           anIndex = (fIt == 0) ? aFFi->Index1() : aFFi->Index2();
520           
521           if(anIndex > 0) {
522             if (fIt == 0)
523               F1 = aDS.Shape(anIndex);
524             else
525               F2 = aDS.Shape(anIndex);
526           }
527         }
528         return Standard_True;
529       }
530     }
531   }
532   return Standard_False;
533 }