0031682: Visualization - Prs3d_ShadingAspect::SetTransparency() has no effect with...
[occt.git] / src / DNaming / DNaming_RevolutionDriver.cxx
1 // Created on: 2009-06-17
2 // Created by: Sergey ZARITCHNY
3 // Copyright (c) 2009-2014 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
17 #include <BRep_Tool.hxx>
18 #include <BRepBuilderAPI_MakeFace.hxx>
19 #include <BRepBuilderAPI_MakeWire.hxx>
20 #include <BRepCheck_Analyzer.hxx>
21 #include <BRepCheck_Shell.hxx>
22 #include <BRepCheck_Wire.hxx>
23 #include <BRepGProp.hxx>
24 #include <BRepPrimAPI_MakeCylinder.hxx>
25 #include <BRepPrimAPI_MakeRevol.hxx>
26 #include <DNaming.hxx>
27 #include <DNaming_RevolutionDriver.hxx>
28 #include <Geom_Line.hxx>
29 #include <gp_Ax2.hxx>
30 #include <gp_Dir.hxx>
31 #include <gp_Pnt.hxx>
32 #include <gp_Vec.hxx>
33 #include <GProp_GProps.hxx>
34 #include <ModelDefinitions.hxx>
35 #include <Precision.hxx>
36 #include <Standard_GUID.hxx>
37 #include <Standard_Real.hxx>
38 #include <Standard_Type.hxx>
39 #include <TDataStd_Integer.hxx>
40 #include <TDataStd_Real.hxx>
41 #include <TDF_Label.hxx>
42 #include <TDF_TagSource.hxx>
43 #include <TFunction_Function.hxx>
44 #include <TFunction_Logbook.hxx>
45 #include <TNaming.hxx>
46 #include <TNaming_Builder.hxx>
47 #include <TNaming_NamedShape.hxx>
48 #include <TopExp.hxx>
49 #include <TopExp_Explorer.hxx>
50 #include <TopLoc_Location.hxx>
51 #include <TopoDS.hxx>
52 #include <TopoDS_Edge.hxx>
53 #include <TopoDS_Shape.hxx>
54 #include <TopoDS_Solid.hxx>
55 #include <TopoDS_Wire.hxx>
56 #include <TopTools_DataMapOfShapeShape.hxx>
57 #include <TopTools_ListIteratorOfListOfShape.hxx>
58 #include <TopTools_MapIteratorOfMapOfShape.hxx>
59 #include <TopTools_MapOfShape.hxx>
60
61 IMPLEMENT_STANDARD_RTTIEXT(DNaming_RevolutionDriver,TFunction_Driver)
62
63 // OCAF
64 //=======================================================================
65 //function : DNaming_RevolutionDriver
66 //purpose  : Constructor
67 //=======================================================================
68 DNaming_RevolutionDriver::DNaming_RevolutionDriver()
69 {}
70
71 //=======================================================================
72 //function : Validate
73 //purpose  : Validates labels of a function in <theLog>.
74 //=======================================================================
75 void DNaming_RevolutionDriver::Validate(Handle(TFunction_Logbook)&) const
76 {}
77
78 //=======================================================================
79 //function : MustExecute
80 //purpose  : Analyses in <theLog> if the loaded function must be executed
81 //=======================================================================
82 Standard_Boolean DNaming_RevolutionDriver::MustExecute(const Handle(TFunction_Logbook)&) const
83 {
84   return Standard_True;
85 }
86
87 //=======================================================================
88 //function : Execute
89 //purpose  : Executes the function
90 //=======================================================================
91 Standard_Integer DNaming_RevolutionDriver::Execute(Handle(TFunction_Logbook)& theLog) const {
92   Handle(TFunction_Function) aFunction;
93   Label().FindAttribute(TFunction_Function::GetID(), aFunction);
94   if(aFunction.IsNull()) return -1;
95
96   // Save location
97   Handle(TNaming_NamedShape) aPrevRevol = DNaming::GetFunctionResult(aFunction);
98   TopLoc_Location aLocation;
99   if (!aPrevRevol.IsNull() && !aPrevRevol->IsEmpty()) {
100     aLocation = aPrevRevol->Get().Location();
101   }
102
103   //Basis for Revol
104   Handle(TDataStd_UAttribute) aBasObject = DNaming::GetObjectArg(aFunction,REVOL_BASIS);
105   Handle(TNaming_NamedShape) aBasisNS = DNaming::GetObjectValue(aBasObject);
106   if(aBasisNS.IsNull() || aBasisNS->IsEmpty()) {
107     aFunction->SetFailure(WRONG_ARGUMENT);
108     return -1;
109   }
110
111   const TopoDS_Shape& aBasis = aBasisNS->Get();
112   TopoDS_Shape aBASIS;
113   if(aBasis.ShapeType() == TopAbs_WIRE) {
114     Handle(BRepCheck_Wire) aCheck = new BRepCheck_Wire(TopoDS::Wire(aBasis));
115     if(aCheck->Closed(Standard_True) == BRepCheck_NoError) {
116       BRepBuilderAPI_MakeFace aMaker (TopoDS::Wire(aBasis), Standard_True); //Makes planar face
117       if(aMaker.IsDone())
118         aBASIS = aMaker.Face();//aMaker.Face();
119     }
120   } else if(aBasis.ShapeType() == TopAbs_FACE)
121     aBASIS = aBasis;
122   if(aBASIS.IsNull()) {
123     aFunction->SetFailure(WRONG_ARGUMENT);
124     return -1;
125   }
126
127
128   Handle(TNaming_NamedShape) aContextOfBasis;
129   Standard_Boolean anIsAttachment = Standard_False;
130   if(DNaming::IsAttachment(aBasObject)) {
131     aContextOfBasis = DNaming::GetAttachmentsContext(aBasObject); // a Context of Revolution basis
132     if(aContextOfBasis.IsNull() || aContextOfBasis->IsEmpty()) {
133       aFunction->SetFailure(WRONG_ARGUMENT);
134       return -1;
135     }
136     anIsAttachment = Standard_True;
137   }
138
139 // Axis
140   Handle(TDataStd_UAttribute) anAxObject = DNaming::GetObjectArg(aFunction,REVOL_AXIS);
141   Handle(TNaming_NamedShape) anAxNS = DNaming::GetObjectValue(anAxObject);
142   gp_Ax1 anAXIS;
143   TopoDS_Shape aTopoDSAxis;
144   if(anAxNS.IsNull() || anAxNS->IsEmpty()) {
145     aFunction->SetFailure(WRONG_ARGUMENT);
146     return -1;
147   } else {
148     aTopoDSAxis = anAxNS->Get();
149     Standard_Boolean anAxisOK = Standard_False;
150     if (!aTopoDSAxis.IsNull()) {
151       if(aTopoDSAxis.ShapeType() == TopAbs_EDGE || aTopoDSAxis.ShapeType() == TopAbs_WIRE) {
152         if (aTopoDSAxis.ShapeType() == TopAbs_WIRE) {
153           TopExp_Explorer anExplorer(aTopoDSAxis, TopAbs_EDGE);
154           aTopoDSAxis = anExplorer.Current();
155         }
156         const TopoDS_Edge& anEdge = TopoDS::Edge(aTopoDSAxis);
157         Standard_Real aFirst, aLast;
158         Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge,aFirst,aLast) ;
159         if (aCurve->IsKind (STANDARD_TYPE(Geom_Line)) ) {
160           Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast(aCurve) ;
161           if(!aLine.IsNull()) {
162             anAXIS  = aLine->Position() ;
163             anAxisOK = Standard_True;
164           }
165         }
166       }
167     }
168     if(!anAxisOK) {
169 #ifdef OCCT_DEBUG
170       std::cout<<"RevolutionDriver:: Axis is not correct"<<std::endl;
171 #endif
172       aFunction->SetFailure(WRONG_ARGUMENT);
173       return -1;
174     }
175   }
176
177   if(aFunction->GetDriverGUID() == FULREVOL_GUID) {
178     BRepPrimAPI_MakeRevol aMakeRevol(aBASIS, anAXIS, Standard_True);
179     aMakeRevol.Build();
180     if (!aMakeRevol.IsDone()) {
181       aFunction->SetFailure(ALGO_FAILED);
182       return -1;
183     }
184     const TopoDS_Shape aResult = aMakeRevol.Shape();
185     BRepCheck_Analyzer aCheckAnalyzer(aResult);
186     if (!aCheckAnalyzer.IsValid(aResult)) {
187       aFunction->SetFailure(RESULT_NOT_VALID);
188       return -1;
189     }
190     Standard_Boolean aVol = Standard_False;
191     if(aResult.ShapeType() == TopAbs_SOLID) aVol = Standard_True;
192     else if(aResult.ShapeType() == TopAbs_SHELL) {
193       Handle(BRepCheck_Shell) aCheck = new BRepCheck_Shell(TopoDS::Shell(aResult));
194       if(aCheck->Closed() == BRepCheck_NoError)
195         aVol = Standard_True;
196     }
197     if(aVol) {
198       GProp_GProps aGProp;
199       BRepGProp::VolumeProperties(aResult, aGProp);
200       if(aGProp.Mass() <= Precision::Confusion()) {
201         aFunction->SetFailure(RESULT_NOT_VALID);
202         return -1;
203       }
204     }
205       // Naming
206     if(anIsAttachment)
207       LoadNamingDS(RESPOSITION(aFunction), aMakeRevol, aBASIS, aContextOfBasis->Get());
208     else
209       LoadNamingDS(RESPOSITION(aFunction), aMakeRevol, aBASIS, aBASIS);
210
211   } else if(aFunction->GetDriverGUID() == SECREVOL_GUID) {
212     Standard_Real anANGLE = DNaming::GetReal(aFunction,REVOL_ANGLE)->Get();
213     if(anANGLE <= Precision::Confusion()) {
214       aFunction->SetFailure(WRONG_ARGUMENT);
215       return -1;
216     }
217     // Reverse
218     Standard_Integer aRev = DNaming::GetInteger(aFunction,REVOL_REV)->Get();
219     if(aRev) anAXIS.Reverse();
220
221     BRepPrimAPI_MakeRevol aMakeRevol(aBASIS, anAXIS, anANGLE, Standard_True);
222     aMakeRevol.Build();
223     if (!aMakeRevol.IsDone()) {
224       aFunction->SetFailure(ALGO_FAILED);
225       return -1;
226     }
227     const TopoDS_Shape aResult = aMakeRevol.Shape();
228     BRepCheck_Analyzer aCheckAnalyzer(aResult);
229     if (!aCheckAnalyzer.IsValid(aResult)) {
230       aFunction->SetFailure(RESULT_NOT_VALID);
231       return -1;
232     }
233     Standard_Boolean aVol = Standard_False;
234     if(aResult.ShapeType() == TopAbs_SOLID) aVol = Standard_True;
235     else if(aResult.ShapeType() == TopAbs_SHELL) {
236       Handle(BRepCheck_Shell) aCheck = new BRepCheck_Shell(TopoDS::Shell(aResult));
237       if(aCheck->Closed() == BRepCheck_NoError)
238         aVol = Standard_True;
239     }
240     if(aVol) {
241       GProp_GProps aGProp;
242       BRepGProp::VolumeProperties(aResult, aGProp);
243       if(aGProp.Mass() <= Precision::Confusion()) {
244         aFunction->SetFailure(RESULT_NOT_VALID);
245         return -1;
246       }
247     }
248
249     // Naming
250     if(anIsAttachment)
251       LoadNamingDS(RESPOSITION(aFunction), aMakeRevol, aBASIS, aContextOfBasis->Get());
252     else
253       LoadNamingDS(RESPOSITION(aFunction), aMakeRevol, aBASIS, aBASIS);
254
255   } else {
256     aFunction->SetFailure(UNSUPPORTED_FUNCTION);
257     return -1;
258   }
259
260   // restore location
261   if(!aLocation.IsIdentity())
262     TNaming::Displace(RESPOSITION(aFunction), aLocation, Standard_True);
263
264   theLog->SetValid(RESPOSITION(aFunction),Standard_True);
265   aFunction->SetFailure(DONE);
266   return 0;
267 }
268
269 //=======================================================================
270 static void LoadSeamEdge (BRepPrimAPI_MakeRevol&        mkRevol,
271                           const TDF_Label&              ResultLabel,
272                           const TopoDS_Shape&           ShapeIn)
273
274 {
275   TopTools_MapOfShape View;
276   TopExp_Explorer ShapeExplorer (ShapeIn, TopAbs_EDGE);
277   Standard_Boolean isFound(Standard_False);
278   for (; ShapeExplorer.More(); ShapeExplorer.Next ()) {
279     const TopoDS_Shape& Root = ShapeExplorer.Current ();
280     if (!View.Add(Root)) continue;
281     const TopTools_ListOfShape& Shapes = mkRevol.Generated (Root);
282     TopTools_ListIteratorOfListOfShape ShapesIterator (Shapes);
283     for (;ShapesIterator.More (); ShapesIterator.Next ()) {
284       TopoDS_Shape newShape = ShapesIterator.Value ();
285       if(newShape.ShapeType() != TopAbs_FACE)
286         continue;
287       if (!Root.IsSame (newShape)) {
288         TopExp_Explorer exp(newShape, TopAbs_EDGE);
289         for (;exp.More();exp.Next()) {
290           if(BRep_Tool::IsClosed (TopoDS::Edge(exp.Current()), TopoDS::Face(newShape))) {
291             TNaming_Builder Builder(ResultLabel.NewChild());
292             Builder.Generated (exp.Current());
293             isFound = Standard_True;
294             break;
295           }
296         }
297         if(isFound) {isFound = Standard_False;break;}
298       }
299     }
300   }
301 }
302
303 //=======================================================================
304 static Standard_Boolean HasDangle(const TopoDS_Shape& ShapeIn)
305 {
306   if (ShapeIn.ShapeType() == TopAbs_SOLID)
307     return Standard_False;
308   else if (ShapeIn.ShapeType() == TopAbs_SHELL) {
309     Handle(BRepCheck_Shell) aCheck = new BRepCheck_Shell(TopoDS::Shell(ShapeIn));
310     return aCheck->Closed() != BRepCheck_NoError;
311   } else if (ShapeIn.ShapeType() == TopAbs_FACE ||
312              ShapeIn.ShapeType() == TopAbs_WIRE ||
313              ShapeIn.ShapeType() == TopAbs_EDGE ||
314              ShapeIn.ShapeType() == TopAbs_VERTEX)
315     return Standard_True;
316   return Standard_False;
317 }
318 //=======================================================================
319 static void BuildAtomicMap(const TopoDS_Shape& S, TopTools_MapOfShape& M)
320 {
321   if(S.ShapeType() == TopAbs_COMPOUND || S.ShapeType() == TopAbs_COMPSOLID) {
322     TopoDS_Iterator it(S);
323     for(;it.More();it.Next()) {
324       if(it.Value().ShapeType() > TopAbs_COMPSOLID)
325         M.Add(it.Value());
326       else
327         BuildAtomicMap(it.Value(), M);
328     }
329   } else
330     M.Add(S);
331 }
332 //=======================================================================
333 //function : HasDangleShapes
334 //purpose  :
335 //=======================================================================
336
337 Standard_Boolean HasDangleShapes(const TopoDS_Shape& ShapeIn) {
338   if (ShapeIn.ShapeType() == TopAbs_COMPOUND || ShapeIn.ShapeType() == TopAbs_COMPSOLID) {
339     TopTools_MapOfShape M;
340     BuildAtomicMap(ShapeIn, M);
341     TopTools_MapIteratorOfMapOfShape it(M);
342     for (; it.More(); it.Next())
343       if (HasDangle(it.Key())) return Standard_True;
344   } else
345     return HasDangle(ShapeIn);
346   return Standard_False;
347 }
348 //=======================================================================
349 //function : LoadAndName
350 //purpose  :
351 //=======================================================================
352 void DNaming_RevolutionDriver::LoadNamingDS (const TDF_Label& theResultLabel,
353                                         BRepPrimAPI_MakeRevol& MS,
354                                         const TopoDS_Shape& Basis,
355                                         const TopoDS_Shape& Context
356                                         ) const
357 {
358
359   TopTools_DataMapOfShapeShape SubShapes;
360   for (TopExp_Explorer Exp(MS.Shape(),TopAbs_FACE); Exp.More(); Exp.Next()) {
361     SubShapes.Bind(Exp.Current(),Exp.Current());
362   }
363
364   Handle(TDF_TagSource) Tagger = TDF_TagSource::Set(theResultLabel);
365   if (Tagger.IsNull()) return;
366   Tagger->Set(0);
367
368   TNaming_Builder Builder (theResultLabel);
369   if(Basis.IsEqual(Context))
370     Builder.Generated(MS.Shape());
371   else
372     Builder.Generated(Context, MS.Shape());
373
374   //Insert lateral face : Face from Edge
375   TNaming_Builder  LateralFaceBuilder(theResultLabel.NewChild());
376   DNaming::LoadAndOrientGeneratedShapes(MS, Basis, TopAbs_EDGE, LateralFaceBuilder, SubShapes);
377
378  // is full
379   TopoDS_Shape StartShape = MS.FirstShape();
380   TopoDS_Shape EndShape = MS.LastShape();
381   Standard_Boolean isFull(Standard_False);
382   if (!StartShape.IsNull() && !EndShape.IsNull())
383     isFull = StartShape.IsEqual(EndShape);
384
385   Standard_Boolean hasDangle = HasDangleShapes(MS.Shape());
386   Standard_Boolean isBasisClosed(Standard_True);
387   TopoDS_Vertex Vfirst, Vlast;
388   if(Basis.ShapeType() == TopAbs_WIRE) {
389     Handle(BRepCheck_Wire) aCheck = new BRepCheck_Wire(TopoDS::Wire(Basis));
390     if(aCheck->Closed() != BRepCheck_NoError) {
391       isBasisClosed = Standard_False; //open
392       TopExp::Vertices(TopoDS::Wire(Basis), Vfirst, Vlast);
393     }
394   } else if(Basis.ShapeType() == TopAbs_EDGE) {
395     BRepBuilderAPI_MakeWire aMakeWire;
396     aMakeWire.Add(TopoDS::Edge(Basis));
397     if(aMakeWire.IsDone()) {
398       Handle(BRepCheck_Wire) aCheck = new BRepCheck_Wire(aMakeWire.Wire());
399       if(aCheck->Closed() != BRepCheck_NoError) {//check for circle case
400         isBasisClosed = Standard_False; //open
401         TopExp::Vertices(TopoDS::Edge(Basis), Vfirst, Vlast);
402       }
403     }
404   }
405   if(isFull) {
406     //seam edge
407     LoadSeamEdge(MS, theResultLabel, Basis);
408
409     if(hasDangle) {
410       if(!isBasisClosed) {
411       //dangle edges
412         const TopTools_ListOfShape& Shapes = MS.Generated (Vfirst);
413         TopTools_ListIteratorOfListOfShape it (Shapes);
414         for (;it.More (); it.Next ()) {
415           if(!BRep_Tool::Degenerated(TopoDS::Edge(it.Value()))) {
416             TNaming_Builder aBuilder(theResultLabel.NewChild());
417             aBuilder.Generated (Vfirst, it.Value());
418           }
419 #ifdef OCCT_DEBUG
420           else {
421             if(MS.HasDegenerated())
422               std::cout <<"mkRevol has degenerated" <<std::endl;
423             std::cout << "BRep_Tool found degenerated edge (from Vfirst) TS = " << it.Value().TShape().get() <<std::endl;
424           }
425 #endif
426         }
427
428
429         const TopTools_ListOfShape& Shapes2 = MS.Generated (Vlast);
430         it.Initialize(Shapes2);
431         for (;it.More (); it.Next ()) {
432           if(!BRep_Tool::Degenerated(TopoDS::Edge(it.Value()))) {
433             TNaming_Builder aBuilder(theResultLabel.NewChild());
434             aBuilder.Generated (Vlast, it.Value());
435           }
436 #ifdef OCCT_DEBUG
437           else {
438             if(MS.HasDegenerated())
439               std::cout <<"mkRevol has degenerated" <<std::endl;
440             std::cout << "BRep_Tool found degenerated edge (from Vlast) TS = " << it.Value().TShape().get() <<std::endl;
441           }
442 #endif
443         }
444       }
445     }
446   } else {//if(!isFull)
447     //Insert start shape
448     if (!StartShape.IsNull()) {
449       if (StartShape.ShapeType() != TopAbs_COMPOUND) {
450         TNaming_Builder StartBuilder(theResultLabel.NewChild());
451         if (SubShapes.IsBound(StartShape)) {
452           StartShape = SubShapes(StartShape);
453         }
454         StartBuilder.Generated(StartShape);
455         if(StartShape.ShapeType() != TopAbs_FACE) {
456           TopoDS_Iterator it(StartShape);
457           for (; it.More(); it.Next()) {
458             TNaming_Builder aBuilder(theResultLabel.NewChild());
459             aBuilder.Generated(it.Value());
460           }
461         }
462       } else {
463         TopoDS_Iterator itr(StartShape);
464         for (; itr.More(); itr.Next()) {
465           TNaming_Builder StartBuilder(theResultLabel.NewChild());
466           StartBuilder.Generated(itr.Value());
467         }
468       }
469     }
470
471
472   //Insert end shape
473     if (!EndShape.IsNull()) {
474       if (EndShape.ShapeType() != TopAbs_COMPOUND) {
475         TNaming_Builder EndBuilder(theResultLabel.NewChild());
476         if (SubShapes.IsBound(EndShape)) {
477           EndShape = SubShapes(EndShape);
478         }
479         EndBuilder.Generated(EndShape);
480         if(EndShape.ShapeType() != TopAbs_FACE) {
481           TopoDS_Iterator it(EndShape);
482           for (; it.More(); it.Next()) {
483             TNaming_Builder aBuilder(theResultLabel.NewChild());
484             aBuilder.Generated(it.Value());
485           }
486         }
487       } else {
488         TopoDS_Iterator itr(EndShape);
489         for (; itr.More(); itr.Next()) {
490           TNaming_Builder EndBuilder(theResultLabel.NewChild());
491           EndBuilder.Generated(itr.Value());
492         }
493       }
494     }
495     if(hasDangle) {
496       if(!isBasisClosed) {
497       //dangle edges
498         const TopTools_ListOfShape& Shapes = MS.Generated (Vfirst);
499         TopTools_ListIteratorOfListOfShape it (Shapes);
500         for (;it.More (); it.Next ()) {
501           if(!BRep_Tool::Degenerated(TopoDS::Edge(it.Value()))) {
502             TNaming_Builder aBuilder(theResultLabel.NewChild());
503             aBuilder.Generated (Vfirst, it.Value());
504           }
505 #ifdef OCCT_DEBUG
506           else {
507             if(MS.HasDegenerated())
508               std::cout <<"mkRevol has degenerated" <<std::endl;
509             std::cout << "BRep_Tool found degenerated edge (from Vfirst) TS = " << it.Value().TShape().get() <<std::endl;
510           }
511 #endif
512         }
513
514         const TopTools_ListOfShape& Shapes2 = MS.Generated (Vlast);
515         it.Initialize(Shapes2);
516         for (;it.More (); it.Next ()) {
517           if(!BRep_Tool::Degenerated(TopoDS::Edge(it.Value()))) {
518             TNaming_Builder aBuilder(theResultLabel.NewChild());
519             aBuilder.Generated (Vlast, it.Value());
520           }
521 #ifdef OCCT_DEBUG
522           else {
523             if(MS.HasDegenerated())
524               std::cout <<"mkRevol has degenerated" <<std::endl;
525             std::cout << "BRep_Tool found degenerated edge (from Vlast) TS = " << it.Value().TShape().get() <<std::endl;
526           }
527 #endif
528         }
529       }
530     }
531   }
532 }
533