5e774a592dec850be8d19a2b86f598ea28ef771f
[occt.git] / src / DNaming / DNaming_TransformationDriver.cxx
1 // Created on: 2009-05-07
2 // Created by: Sergey ZARITCHNY
3 // Copyright (c) 2009-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21 #include <DNaming_TransformationDriver.ixx>
22 #include <Standard_NullObject.hxx>
23 #include <TopAbs.hxx>
24 #include <TopoDS.hxx>
25 #include <TopoDS_Shape.hxx>
26 #include <TopoDS_Edge.hxx>
27 #include <TopoDS_Vertex.hxx>
28 #include <TopoDS_Compound.hxx>
29 #include <TopoDS_Iterator.hxx>
30 #include <TopExp.hxx>
31 #include <TopExp_Explorer.hxx>
32 #include <BRep_Builder.hxx>
33 #include <BRepBuilderAPI_Transform.hxx>
34 #include <BRep_Tool.hxx>
35 #include <BRepBuilderAPI_MakeShape.hxx>
36 #include <TopTools_MapOfShape.hxx>
37 #include <TopTools_DataMapOfShapeShape.hxx>
38 #include <TopTools_MapIteratorOfMapOfShape.hxx>
39 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
40 #include <TopTools_DataMapOfShapeInteger.hxx>
41 #include <TopTools_DataMapIteratorOfDataMapOfShapeInteger.hxx>
42 #include <TNaming_Builder.hxx>
43 #include <TNaming_NamedShape.hxx>
44 #include <TNaming_Tool.hxx>
45 #include <TFunction_Function.hxx>
46 #include <TFunction_Logbook.hxx>
47 #include <DNaming.hxx>
48 #include <TDataStd_Real.hxx>
49 #include <gp_Vec.hxx>
50 #include <gp_Ax1.hxx>
51 #include <gp_Ax2.hxx>
52 #include <gp_Pln.hxx>
53 #include <GeomLib_IsPlanarSurface.hxx>
54 #include <NCollection_Handle.hxx>
55 #include <ModelDefinitions.hxx>
56
57 #ifdef WNT
58 #define EXCEPTION ...
59 #else
60 #define EXCEPTION Standard_Failure
61 #endif 
62
63 #define FACES_TAG  1
64 #define EDGES_TAG  2
65 #define VERTEX_TAG 3
66
67 //#define MDTV_DEB_TRSF
68 #ifdef  MDTV_DEB_TRSF
69 #include <TCollection_AsciiString.hxx>
70 #include <BRepTools.hxx>
71 #include <TDF_Tool.hxx>
72 void PrintE(const TDF_Label&       label)
73 {
74   TCollection_AsciiString entry;
75   TDF_Tool::Entry(label, entry);
76   cout << "LabelEntry = "<< entry << endl;
77 }
78 #endif
79 //=======================================================================
80 //function : TransformationDriver
81 //purpose  : Constructor
82 //=======================================================================
83 DNaming_TransformationDriver::DNaming_TransformationDriver()
84 {}
85
86 //=======================================================================
87 //function : Validate
88 //purpose  : Validates labels of a function in <log>.
89 //=======================================================================
90 void DNaming_TransformationDriver::Validate(TFunction_Logbook& theLog) const
91 {}
92
93 //=======================================================================
94 //function : MustExecute
95 //purpose  : Analyse in <log> if the loaded function must be executed
96 //=======================================================================
97 Standard_Boolean DNaming_TransformationDriver::MustExecute(const TFunction_Logbook& theLog) const
98 {
99   return Standard_True;
100 }
101
102
103 //=======================================================================
104 //function : Execute
105 //purpose  : Execute the function and push in <log> the impacted labels
106 //=======================================================================
107 Standard_Integer DNaming_TransformationDriver::Execute(TFunction_Logbook& theLog) const
108 {
109   Handle(TFunction_Function) aFunction;
110   Label().FindAttribute(TFunction_Function::GetID(),aFunction);
111   if(aFunction.IsNull()) return -1;
112
113   Handle(TFunction_Function) aPrevFun = DNaming::GetPrevFunction(aFunction);
114   if(aPrevFun.IsNull()) return -1;
115   const TDF_Label& aLab = RESPOSITION(aPrevFun);
116   Handle(TNaming_NamedShape) aContextNS;
117   aLab.FindAttribute(TNaming_NamedShape::GetID(), aContextNS);
118   if (aContextNS.IsNull() || aContextNS->IsEmpty()) {
119 #ifdef DEB
120     cout<<"TransformationDriver:: Context is empty"<<endl;
121 #endif
122     aFunction->SetFailure(WRONG_CONTEXT);
123     return -1;
124   }
125 //
126   gp_Trsf aTransformation;
127   const Standard_GUID& aGUID = aFunction->GetDriverGUID();
128   
129   try {
130     if(aGUID == PTXYZ_GUID) {
131       Standard_Real aDX = DNaming::GetReal(aFunction,PTRANSF_DX)->Get();
132       Standard_Real aDY = DNaming::GetReal(aFunction,PTRANSF_DY)->Get();
133       Standard_Real aDZ = DNaming::GetReal(aFunction,PTRANSF_DZ)->Get();  
134       gp_Vec aVector(aDX, aDY, aDZ);
135       aTransformation.SetTranslation(aVector);      
136     }  
137     else if(aGUID == PTALINE_GUID) {
138       Handle(TDataStd_UAttribute) aLineObj  = DNaming::GetObjectArg(aFunction, PTRANSF_LINE);
139       Handle(TNaming_NamedShape) aLineNS = DNaming::GetObjectValue(aLineObj);
140       gp_Ax1 anAxis;
141       if(!DNaming::ComputeAxis(aLineNS, anAxis)) Standard_Failure::Raise();
142       gp_Vec aVector(anAxis.Direction());
143       aVector.Normalize();
144       Standard_Real anOffset = DNaming::GetReal(aFunction,PTRANSF_OFF)->Get();
145       aVector *= anOffset;
146       aTransformation.SetTranslation(aVector);   
147
148     }  else if(aGUID == PRRLINE_GUID) {
149       Handle(TDataStd_UAttribute) aLineObj  = DNaming::GetObjectArg(aFunction, PTRANSF_LINE);
150       Handle(TNaming_NamedShape) aLineNS = DNaming::GetObjectValue(aLineObj);
151       gp_Ax1 anAxis;
152       if(!DNaming::ComputeAxis(aLineNS, anAxis)) Standard_Failure::Raise();
153
154       Standard_Real anAngle = DNaming::GetReal(aFunction,PTRANSF_ANG)->Get();
155       aTransformation.SetRotation(anAxis, anAngle);
156     }  else if(aGUID == PMIRR_GUID) {
157       Handle(TDataStd_UAttribute) aPlaneObj  = DNaming::GetObjectArg(aFunction, PTRANSF_PLANE);
158       Handle(TNaming_NamedShape) aNS = DNaming::GetObjectValue(aPlaneObj);
159       
160       if(aNS.IsNull() ||  aNS->IsEmpty() || aNS->Get().IsNull() || 
161          aNS->Get().ShapeType() != TopAbs_FACE) Standard_Failure::Raise();
162       TopoDS_Face aFace = TopoDS::Face(aNS->Get());
163       Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
164       GeomLib_IsPlanarSurface isPlanarSurface (aSurf);
165       if(!isPlanarSurface.IsPlanar()) Standard_Failure::Raise();
166       gp_Pln aPlane = isPlanarSurface.Plan();
167       gp_Ax2 aMirrorAx2 = aPlane.Position().Ax2();
168       aTransformation.SetMirror(aMirrorAx2);
169     } else {
170       aFunction->SetFailure(UNSUPPORTED_FUNCTION);
171       return -1;
172     }
173   } catch (EXCEPTION) {
174     aFunction->SetFailure(WRONG_ARGUMENT);
175     return -1;
176   }
177 //
178
179 // Naming
180   LoadNamingDS(RESPOSITION(aFunction), aContextNS, aTransformation);
181
182   theLog.SetValid(RESPOSITION(aFunction),Standard_True);  
183   aFunction->SetFailure(DONE);
184   return 0;
185 }
186 //=================================================================================
187 static void BuildMap(const TopTools_MapOfShape& SMap,
188                      BRepBuilderAPI_Transform& Transformer,
189                      TopTools_DataMapOfShapeShape& M)
190 {
191   TopTools_MapIteratorOfMapOfShape anIt(SMap);
192   for(;anIt.More();anIt.Next()) {
193     if(!anIt.Key().IsNull()) {
194       const TopoDS_Shape& aS = anIt.Key(); 
195       M.Bind(aS,Transformer.ModifiedShape(aS));
196     }
197   } 
198 }
199 //=================================================================================
200 static void CollectShapes(const TopoDS_Shape& SSh, TopoDS_Compound& C, 
201                           TopTools_MapOfShape& SMap, const TDF_Label& theLab,
202                           TopTools_DataMapOfShapeInteger& TagMap, const Standard_Boolean isPrimitive)
203 {
204   const TopAbs_ShapeEnum aType = SSh.ShapeType();
205   BRep_Builder aB;
206   switch(aType) {
207   case TopAbs_COMPOUND:
208     {
209       TopoDS_Iterator it(SSh);
210       for(;it.More();it.Next()) 
211         CollectShapes(it.Value(), C, SMap, theLab, TagMap,isPrimitive);
212     }
213     break;
214   case TopAbs_COMPSOLID:
215   case TopAbs_SOLID:
216   case TopAbs_SHELL:
217     {
218       TopExp_Explorer anEx(SSh, TopAbs_FACE);
219       for(;anEx.More();anEx.Next()) {
220         const Handle(TNaming_NamedShape) aNS =  TNaming_Tool::NamedShape(anEx.Current(), theLab);
221         if(aNS.IsNull()) continue;
222         if(SMap.Add(anEx.Current())) {
223           aB.Add(C,anEx.Current());
224           if(isPrimitive)
225             TagMap.Bind(anEx.Current(), aNS->Label().Tag());
226         }
227       }
228       anEx.Init(SSh, TopAbs_EDGE); 
229       for(;anEx.More();anEx.Next()) {
230         const Handle(TNaming_NamedShape) aNS =  TNaming_Tool::NamedShape(anEx.Current(), theLab);
231         if(aNS.IsNull()) continue;
232         if(SMap.Add(anEx.Current())) {
233           aB.Add(C,anEx.Current());
234           if(isPrimitive)
235             TagMap.Bind(anEx.Current(), aNS->Label().Tag());
236         }
237       }
238       anEx.Init(SSh, TopAbs_VERTEX); 
239       for(;anEx.More();anEx.Next()) {
240         const Handle(TNaming_NamedShape) aNS =  TNaming_Tool::NamedShape(anEx.Current(), theLab);
241         if(aNS.IsNull()) continue;
242         if(SMap.Add(anEx.Current())) {
243           aB.Add(C,anEx.Current());
244           if(isPrimitive)
245             TagMap.Bind(anEx.Current(), aNS->Label().Tag());
246         }
247       }
248     }    
249     break;
250   case  TopAbs_FACE:
251     {
252       const Handle(TNaming_NamedShape) aNamedShape =  TNaming_Tool::NamedShape(SSh, theLab);
253       if(!aNamedShape.IsNull())
254         if(SMap.Add(SSh)) 
255           aB.Add(C,SSh); 
256       TopExp_Explorer anEx(SSh, TopAbs_EDGE);
257       for(;anEx.More();anEx.Next()) {
258         const Handle(TNaming_NamedShape) aNS =  TNaming_Tool::NamedShape(anEx.Current(), theLab);
259         if(aNS.IsNull()) continue;
260         if(SMap.Add(anEx.Current())) {
261           aB.Add(C,anEx.Current());
262           if(isPrimitive)
263             TagMap.Bind(anEx.Current(), aNS->Label().Tag());
264         }
265       }
266       anEx.Init(SSh, TopAbs_VERTEX); 
267       for(;anEx.More();anEx.Next()) {
268         const Handle(TNaming_NamedShape) aNS =  TNaming_Tool::NamedShape(anEx.Current(), theLab);
269         if(aNS.IsNull()) continue;
270         if(SMap.Add(anEx.Current())) {
271           aB.Add(C,anEx.Current());
272           if(isPrimitive)
273             TagMap.Bind(anEx.Current(), aNS->Label().Tag());
274         }
275       }
276     }
277     break;
278   case TopAbs_WIRE:
279     {      
280       TopExp_Explorer anEx(SSh, TopAbs_EDGE);
281       for(;anEx.More();anEx.Next()) {
282         const Handle(TNaming_NamedShape) aNS =  TNaming_Tool::NamedShape(anEx.Current(), theLab);
283         if(aNS.IsNull()) continue;
284         if(SMap.Add(anEx.Current())) {
285           aB.Add(C,anEx.Current());
286           if(isPrimitive)
287             TagMap.Bind(anEx.Current(), aNS->Label().Tag());
288         }
289       }  
290       anEx.Init(SSh, TopAbs_VERTEX); 
291       for(;anEx.More();anEx.Next()) {
292         const Handle(TNaming_NamedShape) aNS =  TNaming_Tool::NamedShape(anEx.Current(), theLab);
293         if(aNS.IsNull()) continue;
294         if(SMap.Add(anEx.Current())) {
295           aB.Add(C,anEx.Current()); 
296           if(isPrimitive)
297             TagMap.Bind(anEx.Current(), aNS->Label().Tag());
298         }
299       }     
300     }
301     break;
302     
303   case TopAbs_EDGE:
304     {
305       const Handle(TNaming_NamedShape) aNamedShape =  TNaming_Tool::NamedShape(SSh, theLab);
306       if(!aNamedShape.IsNull())
307         if(SMap.Add(SSh))
308           aB.Add(C,SSh); 
309       TopExp_Explorer anEx(SSh, TopAbs_VERTEX);      
310       anEx.Init(SSh, TopAbs_VERTEX); 
311       for(;anEx.More();anEx.Next()) {
312         const Handle(TNaming_NamedShape) aNS =  TNaming_Tool::NamedShape(anEx.Current(), theLab);
313         if(aNS.IsNull()) continue;
314         if(SMap.Add(anEx.Current())) {
315           aB.Add(C,anEx.Current()); 
316           if(isPrimitive)
317             TagMap.Bind(anEx.Current(), aNS->Label().Tag());
318         }
319       }   
320     }
321     break;
322   case TopAbs_VERTEX:
323     const Handle(TNaming_NamedShape) aNS =  TNaming_Tool::NamedShape(SSh, theLab);
324     if(!aNS.IsNull())
325       if(SMap.Add(SSh)) {
326         aB.Add(C,SSh); 
327 //      if(isPrimitive)
328 //        TagMap.Bind(SSh, aNS->Label().Tag());
329       }
330     break;
331   }   
332 }
333
334 //=======================================================================
335 //function : LoadAndName
336 //purpose  : 
337 //=======================================================================
338 void DNaming_TransformationDriver::LoadNamingDS (const TDF_Label& theResultLabel, 
339                                                  const Handle(TNaming_NamedShape)& theSourceNS,
340                                                  const gp_Trsf& theTrsf) const 
341 {
342   if(theSourceNS.IsNull() || theSourceNS->IsEmpty())
343     return;
344   const TopoDS_Shape& aSrcShape  = theSourceNS->Get();
345   if (aSrcShape.IsNull()) {
346 #ifdef DEB
347     cout<<"DNaming_TransformationDriver::LoadNamingDS: The result of the Transform operation is null"<<endl;
348 #endif
349     return;
350   }
351   Standard_Boolean isPrimitive(Standard_False);
352   if(theSourceNS->Evolution() == TNaming_PRIMITIVE) isPrimitive = Standard_True;
353   const TDF_Label& aSrcLabel     = theSourceNS->Label();
354 #ifdef MDTV_DEB_TRSF
355   cout <<"TransformationDriver: ";
356   PrintE(aSrcLabel);
357 #endif
358
359   TopoDS_Compound aCompShape;
360   BRep_Builder    aB;
361   aB.MakeCompound(aCompShape);
362   TopTools_MapOfShape aSMap;
363   TopTools_DataMapOfShapeInteger aTagMap;
364   //Collect  shapes
365   if(aSMap.Add(aSrcShape))
366     aB.Add(aCompShape, aSrcShape); 
367   CollectShapes(aSrcShape,aCompShape,aSMap, aSrcLabel, aTagMap, isPrimitive);
368
369   //Transform
370   BRepBuilderAPI_Transform aTransformer(aCompShape, theTrsf, Standard_False);
371   TopTools_DataMapOfShapeShape aTMap;
372   BuildMap (aSMap, aTransformer,aTMap);
373
374 //Load
375   TopoDS_Shape aNewSh;
376   if (aTMap.IsBound(aSrcShape)) aNewSh  = aTMap(aSrcShape);
377   if(!aNewSh.IsNull()) {
378     TNaming_Builder aBuilder (theResultLabel);
379     aBuilder.Modify(aSrcShape, aNewSh);
380     aTMap.UnBind(aSrcShape);
381   }
382
383   TopTools_DataMapOfShapeShape SubShapes;
384   TopExp_Explorer Exp(aNewSh, TopAbs_FACE);
385   for (; Exp.More(); Exp.Next()) {
386     SubShapes.Bind(Exp.Current(),Exp.Current());
387   }
388   for (Exp.Init(aNewSh, TopAbs_EDGE); Exp.More(); Exp.Next()) {
389     SubShapes.Bind(Exp.Current(),Exp.Current());
390   }
391   for (Exp.Init(aNewSh, TopAbs_VERTEX); Exp.More(); Exp.Next()) {
392     SubShapes.Bind(Exp.Current(),Exp.Current());
393   }
394
395   Standard_Integer aNextTag(0);
396   TopTools_DataMapIteratorOfDataMapOfShapeInteger it(aTagMap);
397   for(;it.More();it.Next()) {
398     if(it.Value() > aNextTag)
399       aNextTag = it.Value();
400   }
401   NCollection_Handle<TNaming_Builder> aFBuilder, anEBuilder, aVBuilder;
402   TopTools_DataMapIteratorOfDataMapOfShapeShape anIt(aTMap);
403   for(;anIt.More();anIt.Next()) {
404     const TopoDS_Shape& aKey = anIt.Key();
405     TopoDS_Shape newShape = anIt.Value();
406     if (SubShapes.IsBound(newShape)) {
407       newShape.Orientation((SubShapes(newShape)).Orientation());
408     }
409     if(isPrimitive) {
410       if(aTagMap.IsBound(aKey)) {
411         const TDF_Label& aLabel = theResultLabel.FindChild(aTagMap.Find(aKey),  Standard_True);
412         TNaming_Builder aBuilder(aLabel);
413         aBuilder.Modify(aKey, newShape);
414       } else {
415         aNextTag++;
416         const TDF_Label& aLabel = theResultLabel.FindChild(aNextTag,  Standard_True);
417         TNaming_Builder aBuilder(aLabel);
418         aBuilder.Modify(aKey, newShape);
419       }
420     } 
421     else {
422       if(aKey.ShapeType() == TopAbs_FACE) {
423         if (aFBuilder.IsNull()) 
424         {
425           const TDF_Label& aFLabel = theResultLabel.FindChild(FACES_TAG,  Standard_True);
426           aFBuilder = new TNaming_Builder (aFLabel);
427         }
428         aFBuilder->Modify(anIt.Key(), newShape);
429       }
430       else if(aKey.ShapeType() == TopAbs_EDGE) {
431         if (anEBuilder.IsNull()) 
432         {
433           const TDF_Label& aELabel = theResultLabel.FindChild(EDGES_TAG,  Standard_True);
434           anEBuilder = new TNaming_Builder (aELabel);
435         }
436         anEBuilder->Modify(anIt.Key(), newShape);
437       }
438       else if(aKey.ShapeType() == TopAbs_VERTEX) {
439         if (aVBuilder.IsNull())
440         {
441           const TDF_Label& aVLabel = theResultLabel.FindChild(VERTEX_TAG,  Standard_True);
442           aVBuilder = new TNaming_Builder (aVLabel);
443         }
444         aVBuilder->Modify(anIt.Key(), newShape);
445       }
446     }
447   }
448 }