1 #include "GEOM_Engine.hxx"
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"
11 #include <Interface_DataMapIteratorOfDataMapOfIntegerTransient.hxx>
13 #include <TDF_Tool.hxx>
14 #include <TDF_Data.hxx>
15 #include <TDF_LabelSequence.hxx>
16 #include <TDataStd_Integer.hxx>
17 #include <TDataStd_ChildNodeIterator.hxx>
18 #include <TFunction_Driver.hxx>
19 #include <TFunction_DriverTable.hxx>
22 #include <TopTools_IndexedMapOfShape.hxx>
24 #include <TCollection_AsciiString.hxx>
25 #include <TCollection_ExtendedString.hxx>
26 #include <TColStd_SequenceOfAsciiString.hxx>
27 #include <TColStd_SequenceOfTransient.hxx>
28 #include <TColStd_HSequenceOfTransient.hxx>
29 #include <TColStd_ListOfTransient.hxx>
30 #include <TColStd_MapOfTransient.hxx>
31 #include <TColStd_HSequenceOfInteger.hxx>
33 #include <Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString.hxx>
38 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
40 static GEOM_Engine* TheEngine = NULL;
42 static TCollection_AsciiString BuildIDFromObject(Handle(GEOM_Object)& theObject)
44 TCollection_AsciiString anID(theObject->GetDocID()), anEntry;
45 TDF_Tool::Entry(theObject->GetEntry(), anEntry);
46 anID+=(TCollection_AsciiString("_")+anEntry);
50 static TCollection_AsciiString BuildID(Standard_Integer theDocID, char* theEntry)
52 TCollection_AsciiString anID(theDocID);
53 anID+=(TCollection_AsciiString("_")+theEntry);
57 static Standard_Integer ExtractDocID(TCollection_AsciiString& theID)
59 TCollection_AsciiString aDocID = theID.Token("_");
60 if(aDocID.Length() < 1) return -1;
61 return aDocID.IntegerValue();
64 void ProcessFunction(Handle(GEOM_Function)& theFunction,
65 TCollection_AsciiString& theScript,
66 TColStd_MapOfTransient& theProcessed);
68 Handle(TColStd_HSequenceOfInteger) FindEntries(TCollection_AsciiString& theString);
70 //=============================================================================
74 //=============================================================================
75 GEOM_Engine* GEOM_Engine::GetEngine() { return TheEngine; }
78 //=============================================================================
82 //=============================================================================
83 void GEOM_Engine::SetEngine(GEOM_Engine* theEngine) { TheEngine = theEngine; }
85 //=============================================================================
89 //=============================================================================
90 GEOM_Engine::GEOM_Engine()
92 TFunction_DriverTable::Get()->AddDriver(GEOM_Object::GetSubShapeID(), new GEOM_SubShapeDriver());
94 _OCAFApp = new GEOM_Application();
98 //=============================================================================
102 //=============================================================================
103 Handle(TDocStd_Document) GEOM_Engine::GetDocument(int theDocID)
105 Handle(TDocStd_Document) aDoc;
106 if(!_mapIDDocument.IsBound(theDocID)) {
107 _OCAFApp->NewDocument("SALOME_GEOM", aDoc);
108 aDoc->SetUndoLimit(_UndoLimit);
109 _mapIDDocument.Bind(theDocID, aDoc);
110 TDataStd_Integer::Set(aDoc->Main(), theDocID);
113 return Handle(TDocStd_Document)::DownCast(_mapIDDocument(theDocID));
116 //=============================================================================
120 //=============================================================================
121 int GEOM_Engine::GetDocID(Handle(TDocStd_Document) theDocument)
123 if(theDocument.IsNull()) return -1;
124 for(Interface_DataMapIteratorOfDataMapOfIntegerTransient anItr(_mapIDDocument); anItr.More(); anItr.Next())
125 if(anItr.Value() == theDocument) return anItr.Key();
131 //=============================================================================
135 //=============================================================================
136 Handle(GEOM_Object) GEOM_Engine::GetObject(int theDocID, char* theEntry)
138 TCollection_AsciiString anID = BuildID(theDocID, theEntry);
139 if(_objects.IsBound(anID)) return Handle(GEOM_Object)::DownCast(_objects(anID));
142 Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
143 TDF_Tool::Label(aDoc->Main().Data(), theEntry, aLabel, Standard_True);
144 Handle(GEOM_Object) anObject = new GEOM_Object(aLabel);
146 _objects.Bind(anID, anObject);
151 //=============================================================================
155 //=============================================================================
156 Handle(GEOM_Object) GEOM_Engine::AddObject(int theDocID, int theType)
158 Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
159 Handle(TDataStd_TreeNode) aRoot = TDataStd_TreeNode::Set(aDoc->Main());
161 TDF_Label aChild = TDF_TagSource::NewChild(aDoc->Main());
162 Handle(GEOM_Object) anObject = new GEOM_Object(aChild, theType);
164 //Put an object in the map of created objects
165 TCollection_AsciiString anID = BuildIDFromObject(anObject);
166 if(_objects.IsBound(anID)) _objects.UnBind(anID);
167 _objects.Bind(anID, anObject);
172 //=============================================================================
176 //=============================================================================
177 Handle(GEOM_Object) GEOM_Engine::AddSubShape(Handle(GEOM_Object) theMainShape,
178 Handle(TColStd_HArray1OfInteger) theIndices,
179 bool isStandaloneOperation)
181 if(theMainShape.IsNull() || theIndices.IsNull()) return NULL;
183 Handle(TDocStd_Document) aDoc = GetDocument(theMainShape->GetDocID());
184 Handle(TDataStd_TreeNode) aRoot = TDataStd_TreeNode::Set(aDoc->Main());
186 TDF_Label aChild = TDF_TagSource::NewChild(aDoc->Main());
188 Handle(GEOM_Function) aMainShape = theMainShape->GetLastFunction();
189 Handle(GEOM_Object) anObject = new GEOM_Object(aChild, 28); //28 is SUBSHAPE type
190 Handle(GEOM_Function) aFunction = anObject->AddFunction(GEOM_Object::GetSubShapeID(), 1);
192 GEOM_ISubShape aSSI(aFunction);
193 aSSI.SetMainShape(aMainShape);
194 aSSI.SetIndices(theIndices);
197 GEOM_Solver aSolver (GEOM_Engine::GetEngine());
198 if (!aSolver.ComputeFunction(aFunction)) {
199 MESSAGE("GEOM_Engine::AddSubShape Error: Can't build a sub shape");
203 catch (Standard_Failure) {
204 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
205 MESSAGE("GEOM_Engine::AddSubShape Error: " << aFail->GetMessageString());
209 //Put an object in the map of created objects
210 TCollection_AsciiString anID = BuildIDFromObject(anObject);
211 if(_objects.IsBound(anID)) _objects.UnBind(anID);
212 _objects.Bind(anID, anObject);
214 TCollection_AsciiString aDescr("");
216 if(isStandaloneOperation) {
217 TCollection_AsciiString anEntry;
218 TDF_Tool::Entry(anObject->GetEntry(), anEntry);
220 aDescr += " = geom.AddSubShape(";
221 TDF_Tool::Entry(theMainShape->GetEntry(), anEntry);
222 aDescr += (anEntry+", ");
224 for(Standard_Integer i=theIndices->Lower(); i<=theIndices->Upper(); i++) {
225 aDescr += (TCollection_AsciiString(theIndices->Value(i))+", ");
227 aDescr.Trunc(aDescr.Length()-1);
231 TCollection_AsciiString aDescr("None");
233 aFunction->SetDescription(aDescr);
238 //=============================================================================
242 //=============================================================================
243 bool GEOM_Engine::RemoveObject(Handle(GEOM_Object) theObject)
245 if(!theObject) return false;
247 //Remove an object from the map of available objects
248 TCollection_AsciiString anID = BuildIDFromObject(theObject);
249 if(_objects.IsBound(anID)) _objects.UnBind(anID);
251 int nb = theObject->GetNbFunctions();
252 Handle(TDataStd_TreeNode) aNode;
253 for(int i = 1; i<=nb; i++) {
254 Handle(GEOM_Function) aFunction = theObject->GetFunction(i);
255 if(aFunction->GetEntry().FindAttribute(GEOM_Function::GetFunctionTreeID(), aNode))
259 TDF_Label aLabel = theObject->GetEntry();
260 aLabel.ForgetAllAttributes(Standard_True);
267 //=============================================================================
271 //=============================================================================
272 void GEOM_Engine::Undo(int theDocID)
274 GetDocument(theDocID)->Undo();
277 //=============================================================================
281 //=============================================================================
282 void GEOM_Engine::Redo(int theDocID)
284 GetDocument(theDocID)->Redo();
287 //=============================================================================
291 //=============================================================================
292 bool GEOM_Engine::Save(int theDocID, char* theFileName)
294 if(!_mapIDDocument.IsBound(theDocID)) return false;
295 Handle(TDocStd_Document) aDoc = Handle(TDocStd_Document)::DownCast(_mapIDDocument(theDocID));
297 _OCAFApp->SaveAs(aDoc, theFileName);
302 //=============================================================================
306 //=============================================================================
307 bool GEOM_Engine::Load(int theDocID, char* theFileName)
309 Handle(TDocStd_Document) aDoc;
310 if(_OCAFApp->Open(theFileName, aDoc) != CDF_RS_OK) {
314 aDoc->SetUndoLimit(_UndoLimit);
316 if(_mapIDDocument.IsBound(theDocID)) _mapIDDocument.UnBind(theDocID);
317 _mapIDDocument.Bind(theDocID, aDoc);
319 TDataStd_Integer::Set(aDoc->Main(), theDocID);
321 _OCAFApp->SaveAs(aDoc, "/dn05/salome/srn/Test.sdg");
326 //=============================================================================
330 //=============================================================================
331 void GEOM_Engine::Close(int theDocID)
333 if(_mapIDDocument.IsBound(theDocID)) {
334 Handle(TDocStd_Document) aDoc = Handle(TDocStd_Document)::DownCast(_mapIDDocument(theDocID));
336 //Remove all GEOM Objects associated to the given document
337 TColStd_SequenceOfAsciiString aSeq;
338 GEOM_DataMapIteratorOfDataMapOfAsciiStringTransient It(_objects);
339 for(; It.More(); It.Next()) {
340 TCollection_AsciiString anObjID(It.Key());
341 Standard_Integer anID = ExtractDocID(anObjID);
342 if(theDocID == anID) aSeq.Append(It.Key());
344 for(Standard_Integer i=1; i<=aSeq.Length(); i++) _objects.UnBind(aSeq.Value(i));
346 _mapIDDocument.UnBind(theDocID);
347 _OCAFApp->Close(aDoc);
352 //=============================================================================
356 //=============================================================================
357 TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID,
358 Resource_DataMapOfAsciiStringAsciiString& theObjectNames,
362 TCollection_AsciiString aScript;
363 Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
365 if(aDoc.IsNull()) return TCollection_AsciiString("def RebuildData(theStudy): pass\n");
367 aScript = "import geompy\n\n";
368 aScript += "def RebuildData(theStudy):";
370 Handle(TDataStd_TreeNode) aNode, aRoot;
371 Handle(GEOM_Function) aFunction;
372 TColStd_MapOfTransient aMap;
374 if(aDoc->Main().FindAttribute(GEOM_Function::GetFunctionTreeID(), aRoot)) {
375 TDataStd_ChildNodeIterator Itr(aRoot);
376 for(; Itr.More(); Itr.Next()) {
378 aFunction = GEOM_Function::GetFunction(aNode->Label());
379 if(aFunction.IsNull()) {
380 cout << "Null function !!!!" << endl;
383 ProcessFunction(aFunction, aScript, aMap);
387 Resource_DataMapOfAsciiStringAsciiString aEntry2StEntry, aStEntry2Entry;
388 Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString anEntryToNameIt;
391 // build maps entry <-> studyEntry
392 for (anEntryToNameIt.Initialize( theObjectNames );
393 anEntryToNameIt.More();
394 anEntryToNameIt.Next())
396 const TCollection_AsciiString& aEntry = anEntryToNameIt.Key();
397 // look for an object by entry
399 TDF_Tool::Label( aDoc->GetData(), aEntry, L );
400 if ( L.IsNull() ) continue;
401 Handle(GEOM_Object) obj = GEOM_Object::GetObject( L );
403 if ( !obj.IsNull() ) {
404 TCollection_AsciiString aStudyEntry (obj->GetAuxData());
405 aEntry2StEntry.Bind( aEntry, aStudyEntry);
406 aStEntry2Entry.Bind( aStudyEntry, aEntry );
411 Handle(TColStd_HSequenceOfInteger) aSeq = FindEntries(aScript);
412 Standard_Integer aLen = aSeq->Length(), objectCounter = 0, aStart = 1, aScriptLength = aScript.Length();
413 Resource_DataMapOfAsciiStringAsciiString aNameToEntry;
415 //Replace entries by the names
416 TCollection_AsciiString anUpdatedScript, anEntry, aName, aBaseName("geomObj_");
417 if(aLen == 0) anUpdatedScript = aScript;
419 for(Standard_Integer i = 1; i <= aLen; i+=2) {
420 anUpdatedScript += aScript.SubString(aStart, aSeq->Value(i)-1);
421 anEntry = aScript.SubString(aSeq->Value(i), aSeq->Value(i+1));
422 if(theObjectNames.IsBound(anEntry)) {
423 aName = theObjectNames.Find(anEntry);
424 if ( aNameToEntry.IsBound( aName ) && anEntry != aNameToEntry( aName ))
425 { // diff objects have same name - make a new name
426 TCollection_AsciiString aName2;
427 Standard_Integer i = 0;
429 aName2 = aName + "_" + ++i;
430 } while ( aNameToEntry.IsBound( aName2 ) && anEntry != aNameToEntry( aName2 ));
432 theObjectNames( anEntry ) = aName;
437 aName = aBaseName + TCollection_AsciiString(++objectCounter);
438 } while(aNameToEntry.IsBound(aName));
439 theObjectNames.Bind(anEntry, aName);
441 aNameToEntry.Bind(aName, anEntry); // to detect same name of diff objects
443 anUpdatedScript += aName;
444 aStart = aSeq->Value(i+1) + 1;
447 //Add final part of the script
448 if(aSeq->Value(aLen) < aScriptLength) anUpdatedScript += aScript.SubString(aSeq->Value(aLen)+1, aScriptLength);
450 // Make script to publish in study
453 map< int, string > anEntryToCommandMap; // sort publishing commands by object entry
454 for (anEntryToNameIt.Initialize( theObjectNames );
455 anEntryToNameIt.More();
456 anEntryToNameIt.Next())
458 const TCollection_AsciiString& aEntry = anEntryToNameIt.Key();
459 const TCollection_AsciiString& aName = anEntryToNameIt.Value();
460 if ( !aEntry2StEntry.IsBound( aEntry ))
461 continue; // was not published
462 TCollection_AsciiString aCommand("\n\tgeompy."), aFatherEntry;
463 // find a father entry
464 const TCollection_AsciiString& aStudyEntry = aEntry2StEntry( aEntry );
465 TCollection_AsciiString aFatherStudyEntry =
466 aStudyEntry.SubString( 1, aStudyEntry.SearchFromEnd(":") - 1 );
467 if ( aStEntry2Entry.IsBound( aFatherStudyEntry ))
468 aFatherEntry = aStEntry2Entry( aFatherStudyEntry );
470 if ( !aFatherEntry.IsEmpty() && theObjectNames.IsBound( aFatherEntry )) {
471 aCommand += "addToStudyInFather( ";
472 aCommand += theObjectNames( aFatherEntry ) + ", ";
475 aCommand += "addToStudy( ";
476 aCommand += aName + ", \"" + aName + "\" )";
477 // bind a command to the last digit of the entry
479 aEntry.SubString( aEntry.SearchFromEnd(":")+1, aEntry.Length() ).IntegerValue();
480 anEntryToCommandMap.insert( make_pair( tag, aCommand.ToCString() ));
483 // add publishing commands to the script
484 map< int, string >::iterator anEntryToCommand = anEntryToCommandMap.begin();
485 for ( ; anEntryToCommand != anEntryToCommandMap.end(); ++anEntryToCommand ) {
486 //cout << anEntryToCommand->first << endl;
487 anUpdatedScript += (char*)anEntryToCommand->second.c_str();
491 anUpdatedScript += "\n\tpass\n";
494 return anUpdatedScript;
498 //===========================================================================
499 // Internal functions
500 //===========================================================================
501 void ProcessFunction(Handle(GEOM_Function)& theFunction,
502 TCollection_AsciiString& theScript,
503 TColStd_MapOfTransient& theProcessed)
505 if(theFunction.IsNull() || theProcessed.Contains(theFunction)) return;
508 TDF_LabelSequence aSeq;
509 theFunction->GetDependency(aSeq);
510 Standard_Integer aLen = aSeq.Length();
511 for(Standard_Integer i = 1; i<= aLen; i++) {
512 Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(aSeq.Value(i));
513 if(aFunction.IsNull()) continue;
514 ProcessFunction(aFunction, theScript, theProcessed);
518 TCollection_AsciiString aDescr = theFunction->GetDescription();
519 if(aDescr.Length() == 0) {
520 //cout << "Warning: the function has no description" << endl;
523 //Check if its internal function which doesn't requires dumping
524 if(aDescr == "None") return;
529 theProcessed.Add(theFunction);
533 //=============================================================================
535 * FindEntries: Returns a sequence of start/end positions of entries in the string
537 //=============================================================================
538 Handle(TColStd_HSequenceOfInteger) FindEntries(TCollection_AsciiString& theString)
540 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
541 Standard_Integer aLen = theString.Length();
542 Standard_Boolean isFound = Standard_False;
544 char* arr = theString.ToCString();
545 Standard_Integer i = 0, j;
550 if(c >= 48 && c <= 57) { //Is digit?
552 isFound = Standard_False;
553 while((j < aLen) && ((c >= 48 && c <= 57) || c == 58) ) { //Check if it is an entry
555 if(c == 58) isFound = Standard_True;
558 if(isFound && arr[j-2] != 58) { // last char should be a diggit
559 aSeq->Append(i+1); // +1 because AsciiString starts from 1