Salome HOME
46726dceae50e4fe1aa259f96269528c3c775f30
[modules/geom.git] / src / GEOM / GEOM_Engine.cxx
1 #include "GEOM_Engine.hxx"
2
3 #include "GEOM_Solver.hxx"
4 #include "GEOM_Function.hxx"
5 #include "GEOM_ISubShape.hxx"
6 #include "GEOM_SubShapeDriver.hxx"
7 #include "GEOM_DataMapIteratorOfDataMapOfAsciiStringTransient.hxx"
8
9 #include "utilities.h"
10
11 #include <Interface_DataMapIteratorOfDataMapOfIntegerTransient.hxx>
12
13 #include <TDF_Tool.hxx>
14 #include <TDF_Data.hxx>
15 #include <TDataStd_Integer.hxx>
16 #include <TDataStd_ChildNodeIterator.hxx>
17 #include <TFunction_Driver.hxx>
18 #include <TFunction_DriverTable.hxx>
19
20 #include <TopExp.hxx>
21 #include <TopTools_IndexedMapOfShape.hxx>
22
23 #include <TCollection_AsciiString.hxx>
24 #include <TCollection_ExtendedString.hxx>
25 #include <TColStd_SequenceOfAsciiString.hxx>
26
27 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
28
29 static GEOM_Engine* TheEngine = NULL;
30
31 static TCollection_AsciiString BuildIDFromObject(Handle(GEOM_Object)& theObject)
32 {
33   TCollection_AsciiString anID(theObject->GetDocID()), anEntry;
34   TDF_Tool::Entry(theObject->GetEntry(), anEntry);
35   anID+=(TCollection_AsciiString("_")+anEntry);
36   return anID;
37 }
38
39 static TCollection_AsciiString BuildID(Standard_Integer theDocID, char* theEntry)
40 {
41   TCollection_AsciiString anID(theDocID);
42   anID+=(TCollection_AsciiString("_")+theEntry);
43   return anID;
44 }
45
46 static Standard_Integer ExtractDocID(TCollection_AsciiString& theID)
47 {
48   TCollection_AsciiString aDocID = theID.Token("_");
49   if(aDocID.Length() < 1) return -1;
50   return aDocID.IntegerValue();
51 }
52
53 //=============================================================================
54 /*!
55  *  GetEngine
56  */
57 //=============================================================================
58 GEOM_Engine* GEOM_Engine::GetEngine() { return TheEngine; }
59
60
61 //=============================================================================
62 /*!
63  *  SetEngine
64  */
65 //=============================================================================
66 void GEOM_Engine::SetEngine(GEOM_Engine* theEngine) { TheEngine = theEngine; }
67
68 //=============================================================================
69 /*!
70  *  Constructor
71  */
72 //=============================================================================
73 GEOM_Engine::GEOM_Engine()
74 {
75   TFunction_DriverTable::Get()->AddDriver(GEOM_Object::GetSubShapeID(), new GEOM_SubShapeDriver());
76
77   _OCAFApp = new GEOM_Application();
78   _UndoLimit = 10;
79 }
80
81 //=============================================================================
82 /*!
83  *  GetDocument
84  */
85 //=============================================================================
86 Handle(TDocStd_Document) GEOM_Engine::GetDocument(int theDocID)
87 {
88   Handle(TDocStd_Document) aDoc;
89   if(!_mapIDDocument.IsBound(theDocID)) {
90     _OCAFApp->NewDocument("SALOME_GEOM", aDoc);
91     aDoc->SetUndoLimit(_UndoLimit);
92     _mapIDDocument.Bind(theDocID, aDoc);
93     TDataStd_Integer::Set(aDoc->Main(), theDocID);
94   }
95
96   return Handle(TDocStd_Document)::DownCast(_mapIDDocument(theDocID));
97 }
98
99 //=============================================================================
100 /*!
101  *  GetDocID
102  */
103 //=============================================================================
104 int GEOM_Engine::GetDocID(Handle(TDocStd_Document) theDocument)
105 {
106   if(theDocument.IsNull()) return -1;
107   for(Interface_DataMapIteratorOfDataMapOfIntegerTransient anItr(_mapIDDocument); anItr.More(); anItr.Next())
108     if(anItr.Value() == theDocument) return anItr.Key();
109
110   return -1;
111
112 }
113
114 //=============================================================================
115 /*!
116  *  GetObject
117  */
118 //=============================================================================
119 Handle(GEOM_Object) GEOM_Engine::GetObject(int theDocID, char* theEntry)
120 {
121   TCollection_AsciiString anID = BuildID(theDocID, theEntry);
122   if(_objects.IsBound(anID)) return Handle(GEOM_Object)::DownCast(_objects(anID));
123
124   TDF_Label aLabel;
125   Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
126   TDF_Tool::Label(aDoc->Main().Data(), theEntry, aLabel, Standard_True);
127   Handle(GEOM_Object) anObject = new GEOM_Object(aLabel);
128
129   _objects.Bind(anID, anObject);
130
131   return anObject;
132 }
133
134 //=============================================================================
135 /*!
136  *  AddObject
137  */
138 //=============================================================================
139 Handle(GEOM_Object) GEOM_Engine::AddObject(int theDocID, int theType)
140 {
141     Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
142     Handle(TDataStd_TreeNode) aRoot = TDataStd_TreeNode::Set(aDoc->Main());
143
144     TDF_Label aChild = TDF_TagSource::NewChild(aDoc->Main());
145     Handle(GEOM_Object) anObject = new GEOM_Object(aChild, theType);
146
147     //Put an object in the map of created objects
148     TCollection_AsciiString anID = BuildIDFromObject(anObject);
149     if(_objects.IsBound(anID)) _objects.UnBind(anID);
150     _objects.Bind(anID, anObject);
151
152     return anObject;
153 }
154
155 //=============================================================================
156 /*!
157  *  AddSubShape
158  */
159 //=============================================================================
160 Handle(GEOM_Object) GEOM_Engine::AddSubShape(Handle(GEOM_Object) theMainShape, Handle(TColStd_HArray1OfInteger) theIndices)
161 {
162   if(theMainShape.IsNull() || theIndices.IsNull()) return NULL;
163
164   Handle(TDocStd_Document) aDoc = GetDocument(theMainShape->GetDocID());
165   Handle(TDataStd_TreeNode) aRoot = TDataStd_TreeNode::Set(aDoc->Main());
166
167   TDF_Label aChild = TDF_TagSource::NewChild(aDoc->Main());
168
169   Handle(GEOM_Function) aMainShape = theMainShape->GetLastFunction();
170   Handle(GEOM_Object) anObject = new GEOM_Object(aChild, 28); //28 is SUBSHAPE type
171   Handle(GEOM_Function) aFunction = anObject->AddFunction(GEOM_Object::GetSubShapeID(), 1);
172
173   GEOM_ISubShape aSSI(aFunction);
174   aSSI.SetMainShape(aMainShape);
175   aSSI.SetIndices(theIndices);
176
177   try {
178     GEOM_Solver aSolver (GEOM_Engine::GetEngine());
179     if (!aSolver.ComputeFunction(aFunction)) {
180       MESSAGE("GEOM_Engine::AddSubShape Error: Can't build a sub shape");
181       return NULL;
182     }
183   }
184   catch (Standard_Failure) {
185     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
186     MESSAGE("GEOM_Engine::AddSubShape Error: " << aFail->GetMessageString());
187     return NULL;
188   }
189
190   //Put an object in the map of created objects
191   TCollection_AsciiString anID = BuildIDFromObject(anObject);
192   if(_objects.IsBound(anID)) _objects.UnBind(anID);
193   _objects.Bind(anID, anObject);
194
195   TCollection_AsciiString anEntry, aDescr("");
196   TDF_Tool::Entry(anObject->GetEntry(), anEntry);
197   aDescr += anEntry;
198   aDescr += " = geom.AddSubShape(";
199   TDF_Tool::Entry(theMainShape->GetEntry(), anEntry);
200   aDescr += (anEntry+", ");
201   aDescr += (", [");
202   for(Standard_Integer i=theIndices->Lower(); i<=theIndices->Upper(); i++) {
203     aDescr += (TCollection_AsciiString(theIndices->Value(i))+", ");
204   }
205   aDescr.Trunc(aDescr.Length()-1);
206   aDescr += "])";
207   aFunction->SetDescription(aDescr);
208
209   return anObject;
210 }
211
212 //=============================================================================
213 /*!
214  *  RemoveObject
215  */
216 //=============================================================================
217 bool GEOM_Engine::RemoveObject(Handle(GEOM_Object) theObject)
218 {
219   if(!theObject) return false;
220
221   //Remove an object from the map of available objects
222   TCollection_AsciiString anID = BuildIDFromObject(theObject);
223   if(_objects.IsBound(anID)) _objects.UnBind(anID);
224
225   TDF_Label aLabel = theObject->GetEntry();
226   aLabel.ForgetAllAttributes(Standard_True);
227
228   theObject.Nullify();
229
230   return true;
231 }
232
233 //=============================================================================
234 /*!
235  *  Undo
236  */
237 //=============================================================================
238 void GEOM_Engine::Undo(int theDocID)
239 {
240   GetDocument(theDocID)->Undo();
241 }
242
243 //=============================================================================
244 /*!
245  *  Redo
246  */
247 //=============================================================================
248 void GEOM_Engine::Redo(int theDocID)
249 {
250   GetDocument(theDocID)->Redo();
251 }
252
253 //=============================================================================
254 /*!
255  *  Save
256  */
257 //=============================================================================
258 bool GEOM_Engine::Save(int theDocID, char* theFileName)
259 {
260   if(!_mapIDDocument.IsBound(theDocID)) return false;
261   Handle(TDocStd_Document) aDoc = Handle(TDocStd_Document)::DownCast(_mapIDDocument(theDocID));
262
263   _OCAFApp->SaveAs(aDoc, theFileName);
264
265   return true;
266 }
267
268 //=============================================================================
269 /*!
270  *  Load
271  */
272 //=============================================================================
273 bool GEOM_Engine::Load(int theDocID, char* theFileName)
274 {
275   Handle(TDocStd_Document) aDoc;
276   if(_OCAFApp->Open(theFileName, aDoc) != CDF_RS_OK) return false;
277
278   aDoc->SetUndoLimit(_UndoLimit);
279
280   if(_mapIDDocument.IsBound(theDocID)) _mapIDDocument.UnBind(theDocID);
281   _mapIDDocument.Bind(theDocID, aDoc);
282
283   TDataStd_Integer::Set(aDoc->Main(), theDocID);
284
285   return true;
286 }
287
288 //=============================================================================
289 /*!
290  *  Close
291  */
292 //=============================================================================
293 void GEOM_Engine::Close(int theDocID)
294 {
295   if(_mapIDDocument.IsBound(theDocID)) {
296     Handle(TDocStd_Document) aDoc = Handle(TDocStd_Document)::DownCast(_mapIDDocument(theDocID));
297
298     //Remove all GEOM Objects associated to the given document
299     TColStd_SequenceOfAsciiString aSeq;
300     GEOM_DataMapIteratorOfDataMapOfAsciiStringTransient It(_objects);
301     for(; It.More(); It.Next()) {
302       TCollection_AsciiString anObjID(It.Key());
303       Standard_Integer anID = ExtractDocID(anObjID);
304       if(theDocID == anID) aSeq.Append(It.Key());
305     }
306     for(Standard_Integer i=1; i<=aSeq.Length(); i++) _objects.UnBind(aSeq.Value(i));
307
308    _mapIDDocument.UnBind(theDocID);
309     _OCAFApp->Close(aDoc);
310     aDoc.Nullify();
311   }
312 }