X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModelHighAPI%2FModelHighAPI_Dumper.cpp;h=7e33d61fea254dd264a0e249f7b433ff07f18ddf;hb=6bd91d6692dfbfa6462e4b6463ff113ad51b3782;hp=2dd5cb2e32adea6ae52a6a181ed658137ff84a6c;hpb=2532fb2df83ee1ddd9ff3e8b381d3788eaa15b69;p=modules%2Fshaper.git diff --git a/src/ModelHighAPI/ModelHighAPI_Dumper.cpp b/src/ModelHighAPI/ModelHighAPI_Dumper.cpp index 2dd5cb2e3..7e33d61fe 100644 --- a/src/ModelHighAPI/ModelHighAPI_Dumper.cpp +++ b/src/ModelHighAPI/ModelHighAPI_Dumper.cpp @@ -14,7 +14,8 @@ // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// See http://www.salome-platform.org/ or +// email : webmaster.salome@opencascade.com // #include "ModelHighAPI_Dumper.h" @@ -24,6 +25,8 @@ #include #include #include +#include +#include #include #include @@ -45,11 +48,15 @@ #include #include #include +#include #include #include -#include #include #include +#include +#include + +#include #include @@ -62,6 +69,7 @@ static int gCompositeStackDepth = 0; ModelHighAPI_Dumper* ModelHighAPI_Dumper::mySelf = 0; ModelHighAPI_Dumper::ModelHighAPI_Dumper() + : myGeometricalSelection(false) { clear(); } @@ -93,6 +101,9 @@ void ModelHighAPI_Dumper::clear(bool bufferOnly) myFeatureCount.clear(); while (!myEntitiesStack.empty()) myEntitiesStack.pop(); + + myPostponed.clear(); + myDumpPostponedInProgress = false; } } @@ -122,16 +133,28 @@ const std::string& ModelHighAPI_Dumper::name(const EntityPtr& theEntity, return aFound->second.myCurrentName; // entity is not found, store it - std::string aName; + std::string aName, aKind; bool isDefaultName = false; + bool isSaveNotDumped = theSaveNotDumped; std::ostringstream aDefaultName; FeaturePtr aFeature = std::dynamic_pointer_cast(theEntity); if (aFeature) { aName = aFeature->name(); - const std::string& aKind = aFeature->getKind(); - DocumentPtr aDoc = aFeature->document(); - int& aNbFeatures = myFeatureCount[aDoc][aKind]; - aNbFeatures += 1; + aKind = aFeature->getKind(); + } else { + FolderPtr aFolder = std::dynamic_pointer_cast(theEntity); + if (aFolder) { + aName = aFolder->data()->name(); + aKind = ModelAPI_Folder::ID(); + isSaveNotDumped = false; + } + } + + ObjectPtr anObject = std::dynamic_pointer_cast(theEntity); + if (anObject) { + DocumentPtr aDoc = anObject->document(); + std::pair& aNbFeatures = myFeatureCount[aDoc][aKind]; + aNbFeatures.first += 1; size_t anIndex = aName.find(aKind); if (anIndex == 0 && aName[aKind.length()] == '_') { // name starts with "FeatureKind_" @@ -140,10 +163,24 @@ const std::string& ModelHighAPI_Dumper::name(const EntityPtr& theEntity, // Check number of already registered objects of such kind. Index of current object // should be the same to identify feature's name as automatically generated. - if (aNbFeatures == anId) { + if (aNbFeatures.first == anId && aNbFeatures.second < anId) { // name is not user-defined isDefaultName = true; + + // check there are postponed features of this kind, + // dump their names, because the sequence of features may be changed + for (std::list::const_iterator aPpIt = myPostponed.begin(); + aPpIt != myPostponed.end(); ++aPpIt) { + FeaturePtr aCurFeature = std::dynamic_pointer_cast(*aPpIt); + if (aCurFeature && aCurFeature->getKind() == aKind) { + myNames[*aPpIt].myIsDefault = false; + isDefaultName = false; + } + } } + + if (anId > aNbFeatures.second) + aNbFeatures.second = anId; } // obtain default name for the feature @@ -153,16 +190,17 @@ const std::string& ModelHighAPI_Dumper::name(const EntityPtr& theEntity, int aFullIndex = 0; NbFeaturesMap::const_iterator aFIt = myFeatureCount.begin(); for (; aFIt != myFeatureCount.end(); ++aFIt) { - std::map::const_iterator aFound = aFIt->second.find(aKind); + std::map >::const_iterator aFound = + aFIt->second.find(aKind); if (aFound != aFIt->second.end()) - aFullIndex += aFound->second; + aFullIndex += aFound->second.first; } aDefaultName << aKind << "_" << aFullIndex; } } myNames[theEntity] = EntityName(aDefaultName.str(), aName, isDefaultName); - if (theSaveNotDumped) + if (isSaveNotDumped) myNotDumpedEntities.insert(theEntity); // store names of results @@ -190,56 +228,19 @@ const std::string& ModelHighAPI_Dumper::parentName(const FeaturePtr& theEntity) void ModelHighAPI_Dumper::saveResultNames(const FeaturePtr& theFeature) { // Default name of the feature - const std::string& aKind = theFeature->getKind(); - DocumentPtr aDoc = theFeature->document(); - int aNbFeatures = myFeatureCount[aDoc][aKind]; - std::ostringstream aNameStream; - aNameStream << aKind << "_" << aNbFeatures; - std::string aFeatureName = aNameStream.str(); + bool isFeatureDefaultName = myNames[theFeature].myIsDefault; // Save only names of results which is not correspond to default feature name const std::list& aResults = theFeature->results(); - std::list::const_iterator aResIt = aResults.begin(); - for (int i = 1; aResIt != aResults.end(); ++aResIt, ++i) { - bool isUserDefined = true; - std::string aResName = (*aResIt)->data()->name(); - size_t anIndex = aResName.find(aFeatureName); - if (anIndex == 0) { - std::string aSuffix = aResName.substr(aFeatureName.length()); - if (aSuffix.empty() && i == 1) // first result may not constain index in the name - isUserDefined = false; - else { - if (aSuffix[0] == '_' && std::stoi(aSuffix.substr(1)) == i) - isUserDefined = false; - } - } - - myNames[*aResIt] = EntityName(aResName, - (isUserDefined ? aResName : std::string()), !isUserDefined); - - // check names of sub-results for CompSolid - ResultCompSolidPtr aCompSolid = std::dynamic_pointer_cast(*aResIt); - if (aCompSolid) { - int aNbSubs = aCompSolid->numberOfSubs(); - for (int j = 0; j < aNbSubs; ++j) { - isUserDefined = true; - ResultPtr aSub = aCompSolid->subResult(j); - std::string aSubName = aSub->data()->name(); - size_t anIndex = aSubName.find(aResName); - if (anIndex == 0) { - std::string aSuffix = aSubName.substr(aResName.length()); - if (aSuffix.empty() && aNbSubs == 1) // first result may not constain index in the name - isUserDefined = false; - else { - if (aSuffix[0] == '_' && std::stoi(aSuffix.substr(1)) == j + 1) - isUserDefined = false; - } - } - - myNames[aSub] = EntityName(aSubName, - (isUserDefined ? aSubName : std::string()), !isUserDefined); - } - } + std::list allRes; + ModelAPI_Tools::allResults(theFeature, allRes); + for(std::list::iterator aRes = allRes.begin(); aRes != allRes.end(); aRes++) { + std::pair aName = ModelAPI_Tools::getDefaultName(*aRes); + std::string aDefaultName = aName.first; + std::string aResName = (*aRes)->data()->name(); + bool isUserDefined = !(isFeatureDefaultName && aDefaultName == aResName); + myNames[*aRes] = + EntityName(aResName, (isUserDefined ? aResName : std::string()), !isUserDefined); } } @@ -258,19 +259,33 @@ bool ModelHighAPI_Dumper::process(const std::shared_ptr& theD bool ModelHighAPI_Dumper::process(const std::shared_ptr& theDoc) { bool isOk = true; - std::list aFeatures = theDoc->allFeatures(); - std::list::const_iterator aFeatIt = aFeatures.begin(); + std::list anObjects = theDoc->allObjects(); + std::list::const_iterator anObjIt = anObjects.begin(); // firstly, dump all parameters - for (; aFeatIt != aFeatures.end(); ++ aFeatIt) - dumpParameter(*aFeatIt); + for (; anObjIt != anObjects.end(); ++ anObjIt) { + FeaturePtr aFeature = std::dynamic_pointer_cast(*anObjIt); + if (aFeature) + dumpParameter(aFeature); + } // dump all other features - for (aFeatIt = aFeatures.begin(); aFeatIt != aFeatures.end(); ++aFeatIt) { - CompositeFeaturePtr aCompFeat = std::dynamic_pointer_cast(*aFeatIt); + for (anObjIt = anObjects.begin(); anObjIt != anObjects.end(); ++anObjIt) { + CompositeFeaturePtr aCompFeat = std::dynamic_pointer_cast(*anObjIt); if (aCompFeat) // iteratively process composite features isOk = process(aCompFeat) && isOk; - else if (!isDumped(*aFeatIt)) // dump common feature - dumpFeature(*aFeatIt); + else if (!isDumped(EntityPtr(*anObjIt))) { + // dump folder + FolderPtr aFolder = std::dynamic_pointer_cast(*anObjIt); + if (aFolder) + dumpFolder(aFolder); + else { + FeaturePtr aFeature = std::dynamic_pointer_cast(*anObjIt); + if (aFeature) // dump common feature + dumpFeature(aFeature); + } + } } + // dump folders if any + dumpPostponed(true); return isOk; } @@ -280,7 +295,7 @@ bool ModelHighAPI_Dumper::process(const std::shared_ptrnumberOfSubs(); for (int anIndex = 0; anIndex < aNbSubs; ++anIndex) { FeaturePtr aFeature = theComposite->subFeature(anIndex); - if (isDumped(aFeature)) + if (isDumped(EntityPtr(aFeature))) continue; isSubDumped = true; @@ -358,6 +373,43 @@ bool ModelHighAPI_Dumper::processSubs( return isOk; } +void ModelHighAPI_Dumper::postpone(const EntityPtr& theEntity) +{ + // keep the name + name(theEntity, false); + myPostponed.push_back(theEntity); +} + +void ModelHighAPI_Dumper::dumpPostponed(bool theDumpFolders) +{ + if (myDumpPostponedInProgress) + return; + + myDumpPostponedInProgress = true; + // make a copy of postponed entities, because the list will be updated + // if some features are not able to be dumped + std::list aPostponedCopy = myPostponed; + myPostponed.clear(); + + // iterate over postponed entities and try to dump them + std::list::const_iterator anIt = aPostponedCopy.begin(); + for (; anIt != aPostponedCopy.end(); ++anIt) { + FolderPtr aFolder = std::dynamic_pointer_cast(*anIt); + if (aFolder) { + if (theDumpFolders) + dumpFolder(aFolder); + else + myPostponed.push_back(*anIt); + } + else { + FeaturePtr aFeature = std::dynamic_pointer_cast(*anIt); + if (aFeature) + dumpFeature(aFeature, true); + } + } + myDumpPostponedInProgress = false; +} + void ModelHighAPI_Dumper::dumpSubFeatureNameAndColor(const std::string theSubFeatureGet, const FeaturePtr& theSubFeature) { @@ -387,7 +439,8 @@ bool ModelHighAPI_Dumper::exportTo(const std::string& theFileName) if (!aFile.is_open()) return false; - // standard header + // standard header (encoding + imported modules) + aFile << "# -*- coding: utf-8 -*-" << std::endl << std::endl; for (ModulesMap::const_iterator aModIt = myModules.begin(); aModIt != myModules.end(); ++aModIt) { aFile << "from " << aModIt->first << " import "; @@ -431,6 +484,7 @@ void ModelHighAPI_Dumper::importModule(const std::string& theModuleName, void ModelHighAPI_Dumper::dumpEntitySetName() { const LastDumpedEntity& aLastDumped = myEntitiesStack.top(); + bool isBufferEmpty = myDumpBuffer.str().empty(); // dump "setName" for the entity if (aLastDumped.myUserName) { @@ -473,17 +527,62 @@ void ModelHighAPI_Dumper::dumpEntitySetName() myDumpBuffer << ".setDeflection(" << aDeflectionAttr->value() << ")" << std::endl; } } + // set result transparency + if (!isDefaultTransparency(*aResIt)) { + AttributeDoublePtr aTransparencyAttr = + (*aResIt)->data()->real(ModelAPI_Result::TRANSPARENCY_ID()); + if(aTransparencyAttr.get() && aTransparencyAttr->isInitialized()) { + *this << *aResIt; + myDumpBuffer << ".setTransparency(" << aTransparencyAttr->value() << ")" << std::endl; + } + } } myNames[aLastDumped.myEntity].myIsDumped = true; myEntitiesStack.pop(); + + // clean buffer if it was clear before + if (isBufferEmpty) { + myFullDump << myDumpBuffer.str(); + myDumpBuffer.str(""); + } } bool ModelHighAPI_Dumper::isDumped(const EntityPtr& theEntity) const { EntityNameMap::const_iterator aFound = myNames.find(theEntity); FeaturePtr aFeature = std::dynamic_pointer_cast(theEntity); - return aFound != myNames.end() || myFeaturesToSkip.find(aFeature) != myFeaturesToSkip.end(); + return (aFound != myNames.end() && aFound->second.myIsDumped) || + myFeaturesToSkip.find(aFeature) != myFeaturesToSkip.end(); +} + +bool ModelHighAPI_Dumper::isDumped(const AttributeRefAttrPtr& theRefAttr) const +{ + FeaturePtr aFeature; + if (theRefAttr->isObject()) + aFeature = ModelAPI_Feature::feature(theRefAttr->object()); + else + aFeature = ModelAPI_Feature::feature(theRefAttr->attr()->owner()); + return aFeature && isDumped(EntityPtr(aFeature)); +} + +bool ModelHighAPI_Dumper::isDumped(const AttributeRefListPtr& theRefList) const +{ + std::list aRefs = theRefList->list(); + std::list::iterator anIt = aRefs.begin(); + for (; anIt != aRefs.end(); ++anIt) { + FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt); + if (aFeature && !isDumped(EntityPtr(aFeature))) + return false; + } + return true; +} + +static bool isSketchSub(const FeaturePtr& theFeature) +{ + static const std::string SKETCH("Sketch"); + CompositeFeaturePtr anOwner = ModelAPI_Tools::compositeOwner(theFeature); + return anOwner && anOwner->getKind() == SKETCH; } bool ModelHighAPI_Dumper::isDefaultColor(const ResultPtr& theResult) const @@ -492,6 +591,15 @@ bool ModelHighAPI_Dumper::isDefaultColor(const ResultPtr& theResult) const if (!aColor || !aColor->isInitialized()) return true; + // check the result belongs to sketch entity, do not dump color in this way + ResultConstructionPtr aResConstr = + std::dynamic_pointer_cast(theResult); + if (aResConstr) { + FeaturePtr aFeature = ModelAPI_Feature::feature(theResult->data()->owner()); + if (isSketchSub(aFeature)) + return true; + } + std::string aSection, aName, aDefault; theResult->colorConfigInfo(aSection, aName, aDefault); @@ -533,6 +641,15 @@ bool ModelHighAPI_Dumper::isDefaultDeflection(const ResultPtr& theResult) const return fabs(aCurrent - aDefault) < 1.e-12; } +bool ModelHighAPI_Dumper::isDefaultTransparency(const ResultPtr& theResult) const +{ + AttributeDoublePtr anAttribute = theResult->data()->real(ModelAPI_Result::TRANSPARENCY_ID()); + if(!anAttribute || !anAttribute->isInitialized()) { + return true; + } + return fabs(anAttribute->value()) < 1.e-12; +} + ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const char theChar) { myDumpBuffer << theChar; @@ -661,6 +778,18 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<( return *this; } +ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const FolderPtr& theFolder) +{ + myDumpBuffer << name(theFolder); + + // add dumped folder to a stack + if (!myNames[theFolder].myIsDumped && + (myEntitiesStack.empty() || myEntitiesStack.top().myEntity != theFolder)) + myEntitiesStack.push(LastDumpedEntity(theFolder, !myNames[theFolder].myIsDefault)); + + return *this; +} + ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const FeaturePtr& theEntity) { myDumpBuffer << name(theEntity); @@ -669,24 +798,12 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const FeaturePtr& theEntity bool isUserDefinedName = !myNames[theEntity].myIsDefault; // store results if they have user-defined names or colors std::list aResultsWithNameOrColor; - const std::list& aResults = theEntity->results(); - std::list::const_iterator aResIt = aResults.begin(); - for (; aResIt != aResults.end(); ++aResIt) { - if (!myNames[*aResIt].myIsDefault || !isDefaultColor(*aResIt) || - !isDefaultDeflection(*aResIt)) - aResultsWithNameOrColor.push_back(*aResIt); - - ResultCompSolidPtr aCompSolid = - std::dynamic_pointer_cast(*aResIt); - if (aCompSolid) { - int aNbSubs = aCompSolid->numberOfSubs(); - for (int i = 0; i < aNbSubs; ++i) { - ResultPtr aCurRes = aCompSolid->subResult(i); - if (!myNames[aCurRes].myIsDefault || !isDefaultColor(aCurRes) || - !isDefaultDeflection(aCurRes)) - aResultsWithNameOrColor.push_back(aCurRes); - } - } + std::list allRes; + ModelAPI_Tools::allResults(theEntity, allRes); + for(std::list::iterator aRes = allRes.begin(); aRes != allRes.end(); aRes++) { + if(!myNames[*aRes].myIsDefault || !isDefaultColor(*aRes) || + !isDefaultDeflection(*aRes) || !isDefaultTransparency(*aRes)) + aResultsWithNameOrColor.push_back(*aRes); } // store just dumped entity to stack if (myEntitiesStack.empty() || myEntitiesStack.top().myEntity != theEntity) @@ -701,37 +818,40 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const FeaturePtr& theEntity ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const ResultPtr& theResult) { + // iterate in the structure of sub-results to the parent + ResultPtr aCurRes = theResult; FeaturePtr aFeature = ModelAPI_Feature::feature(theResult); - int anIndex = 0; - int aSubIndex = -1; - std::list aResults = aFeature->results(); - for(std::list::const_iterator - anIt = aResults.cbegin(); anIt != aResults.cend(); ++anIt, ++anIndex) { - if(theResult->isSame(*anIt)) { - break; - } - - ResultCompSolidPtr aCompSolid = std::dynamic_pointer_cast(*anIt); - if (aCompSolid) { - int aNbSubs = aCompSolid->numberOfSubs(); - for (aSubIndex = 0; aSubIndex < aNbSubs; ++aSubIndex) - if (theResult->isSame(aCompSolid->subResult(aSubIndex))) + std::list anIndices; // indexes of results in the parent result, starting from topmost + while(aCurRes.get()) { + ResultBodyPtr aParent = ModelAPI_Tools::bodyOwner(aCurRes); + if (aParent) { + anIndices.push_front(ModelAPI_Tools::bodyIndex(aCurRes)); + } else { // index of the result in the feature + std::list::const_iterator aRes = aFeature->results().cbegin(); + for(int anIndex = 0; aRes != aFeature->results().cend(); aRes++, anIndex++) { + if (*aRes == aCurRes) { + anIndices.push_front(anIndex); break; - if (aSubIndex < aNbSubs) - break; - aSubIndex = -1; + } + } } + aCurRes = aParent; } myDumpBuffer << name(aFeature); - if(anIndex == 0) { - myDumpBuffer << ".result()"; - } else { - myDumpBuffer << ".results()[" << anIndex << "]"; - } - if (aSubIndex >= 0) { - myDumpBuffer << ".subResult(" << aSubIndex << ")"; + for (std::list::iterator anI = anIndices.begin(); anI != anIndices.end(); anI++) { + if (anI == anIndices.begin()) { + if(*anI == 0) { + myDumpBuffer << ".result()"; + } + else { + myDumpBuffer << ".results()[" << *anI << "]"; + } + } else { + myDumpBuffer << ".subResult(" << *anI << ")"; + } } + return *this; } @@ -847,6 +967,76 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<( return *this; } +static int possibleSelectionsByPoint(const GeomPointPtr& thePoint, + const ResultPtr& theResult, + const GeomShapePtr& theShape, + const FeaturePtr& theStartFeature, + const FeaturePtr& theEndFeature) +{ + DocumentPtr aDoc1 = theStartFeature->document(); + DocumentPtr aDoc2 = theEndFeature->document(); + + std::list aFeatures = aDoc1->allFeatures(); + if (aDoc1 != aDoc2) { + std::list anAdditionalFeatures = aDoc2->allFeatures(); + aFeatures.insert(aFeatures.end(), anAdditionalFeatures.begin(), anAdditionalFeatures.end()); + } + + CompositeFeaturePtr aLastCompositeFeature; + + std::list::const_iterator aFIt = aFeatures.begin(); + while (aFIt != aFeatures.end() && *aFIt != theStartFeature) { + CompositeFeaturePtr aCompFeat = std::dynamic_pointer_cast(*aFIt); + if (aCompFeat) + aLastCompositeFeature = aCompFeat; + ++aFIt; + } + + // collect the list of composite features, containing the last feature; + // these features should be excluded from searching, + // because the feature cannot select sub-shapes from its parent + std::set aEndFeatureParents = ModelAPI_Tools::getParents(theEndFeature); + + int aNbPossibleSelections = 0; + for (; aFIt != aFeatures.end() && *aFIt != theEndFeature; ++aFIt) { + bool isSkipFeature = false; + if (aLastCompositeFeature && aLastCompositeFeature->isSub(*aFIt)) + isSkipFeature = true; + CompositeFeaturePtr aCompFeat = std::dynamic_pointer_cast(*aFIt); + if (aCompFeat) { + ResultPartPtr aPartRes = + std::dynamic_pointer_cast(aCompFeat->firstResult()); + if (!aPartRes) + aLastCompositeFeature = aCompFeat; + if (aEndFeatureParents.find(aCompFeat) != aEndFeatureParents.end()) { + // do not process the parent for the last feature, + // because it cannot select objects from its parent + isSkipFeature = true; + } + } + if (isSkipFeature) + continue; + + std::list anApproproate; + if (ModelGeomAlgo_Shape::findSubshapeByPoint(*aFIt, thePoint, theShape->shapeType(), + anApproproate)) { + std::list::iterator anApIt = anApproproate.begin(); + for (; anApIt != anApproproate.end(); ++anApIt) { + ++aNbPossibleSelections; + + // stop if the target shape and result are found + GeomShapePtr aCurShape = anApIt->mySubshape; + if (!aCurShape) + aCurShape = anApIt->myResult->shape(); + + if (anApIt->myResult->isSame(theResult) && aCurShape->isSame(theShape)) + break; + } + } + } + return aNbPossibleSelections; +} + ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<( const std::shared_ptr& theAttrSelect) { @@ -867,42 +1057,128 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<( return *this; } - myDumpBuffer << "\"" << aShape->shapeTypeStr() << "\", \"" << - theAttrSelect->namingName() << "\")"; + // how to dump selection: construction features are dumped by name always + bool isDumpByGeom = myGeometricalSelection; + FeaturePtr aSelectedFeature; + if (isDumpByGeom) { + ResultPtr aRes = theAttrSelect->context(); + FeaturePtr aFeature = theAttrSelect->contextFeature(); + if (aRes && !aFeature) + aSelectedFeature = ModelAPI_Feature::feature(aRes->data()->owner()); + isDumpByGeom = aSelectedFeature && aSelectedFeature->isInHistory(); + } + + if (theAttrSelect->isGeometricalSelection() && aShape->shapeType() == GeomAPI_Shape::COMPOUND) { + GeomAPI_ShapeIterator anIt(aShape); + aShape = anIt.current(); + } + + myDumpBuffer << "\"" << aShape->shapeTypeStr(); + bool aStandardDump = true; + if (isDumpByGeom) { + // check the selected item is a ResultPart; + // in this case it is necessary to get shape with full transformation + // for correct calculation of the middle point + ResultPartPtr aResPart = + std::dynamic_pointer_cast(theAttrSelect->context()); + if (aResPart && aShape->shapeType() == GeomAPI_Shape::COMPOUND) + aShape = aResPart->shape(); + GeomPointPtr aMiddlePoint = aShape->middlePoint(); + // calculate number of features, which could be selected by the same point + FeaturePtr anOwner = ModelAPI_Feature::feature(theAttrSelect->owner()); + int aNbPossibleSelections = possibleSelectionsByPoint(aMiddlePoint, + theAttrSelect->context(), aShape, aSelectedFeature, anOwner); + + // produce the index if the number of applicable features is greater than 1 + std::string anIndex; + if (aNbPossibleSelections > 1) { + std::ostringstream anOutput; + anOutput << "_" << aNbPossibleSelections; + anIndex = anOutput.str(); + } + + myDumpBuffer << anIndex << "\", "; + *this << aMiddlePoint; + aStandardDump = false; + } if (myWeakNamingSelection && aShape.get() && theAttrSelect->context().get() && + aShape != theAttrSelect->context()->shape()) { // weak naming for local selection only + GeomAlgoAPI_NExplode aNExplode(theAttrSelect->context()->shape(), aShape->shapeType()); + int anIndex = aNExplode.index(aShape); + if (anIndex != 0) { // found a week-naming index, so, export it + myDumpBuffer<<"\", \""<context()->data()->name()<<"\", "<namingName() << "\""; + myDumpBuffer << ")"; return *this; } ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<( const std::shared_ptr& theAttrSelList) { - myDumpBuffer << "["; + static const int aThreshold = 2; + // if number of elements in the list if greater than a threshold, + // dump it in a separate line with specific name + std::string aDumped = myDumpBuffer.str(); - GeomShapePtr aShape; - std::string aShapeTypeStr; + if (aDumped.empty() || theAttrSelList->size() <= aThreshold) { + myDumpBuffer << "["; - bool isAdded = false; + GeomShapePtr aShape; + std::string aShapeTypeStr; - for(int anIndex = 0; anIndex < theAttrSelList->size(); ++anIndex) { - AttributeSelectionPtr anAttribute = theAttrSelList->value(anIndex); - aShape = anAttribute->value(); - if(!aShape.get()) { - aShape = anAttribute->context()->shape(); - } + bool isAdded = false; - if(!aShape.get()) { - continue; + for(int anIndex = 0; anIndex < theAttrSelList->size(); ++anIndex) { + AttributeSelectionPtr anAttribute = theAttrSelList->value(anIndex); + aShape = anAttribute->value(); + if(!aShape.get()) { + ResultPtr aContext = anAttribute->context(); + if (aContext.get()) + aShape = aContext->shape(); + } + + if(!aShape.get()) { + continue; + } + + if(isAdded) { + myDumpBuffer << ", "; + } else { + isAdded = true; + } + *this << anAttribute; } - if(isAdded) { - myDumpBuffer << ", "; - } else { - isAdded = true; + myDumpBuffer << "]"; + } else { + // clear buffer and store list "as is" + myDumpBuffer.str(""); + *this << theAttrSelList; + // save buffer and clear it again + std::string aDumpedList = myDumpBuffer.str(); + myDumpBuffer.str(""); + // obtain name of list (the feature may contain several selection lists) + FeaturePtr anOwner = ModelAPI_Feature::feature(theAttrSelList->owner()); + std::string aListName = name(anOwner) + "_objects"; + std::list aSelLists = + anOwner->data()->attributes(ModelAPI_AttributeSelectionList::typeId()); + if (aSelLists.size() > 1) { + int anIndex = 1; + for (std::list::iterator aSIt = aSelLists.begin(); + aSIt != aSelLists.end(); ++aSIt, ++anIndex) + if ((*aSIt).get() == theAttrSelList.get()) + break; + std::ostringstream aSStream; + aSStream << aListName << "_" << anIndex; + aListName = aSStream.str(); } - myDumpBuffer << "model.selection(\"" << - aShape->shapeTypeStr() << "\", \"" << anAttribute->namingName() << "\")"; + // store all previous data + myDumpBuffer << aListName << " = " << aDumpedList << std::endl + << aDumped << aListName; } - - myDumpBuffer << "]"; return *this; } @@ -945,7 +1221,7 @@ ModelHighAPI_Dumper& operator<<(ModelHighAPI_Dumper& theDumper, isCopy = aCopyAttr.get() && aCopyAttr->value(); } } - } while (isCopy); + } while (isCopy && !theDumper.myEntitiesStack.empty()); } // store all not-dumped entities first @@ -962,6 +1238,20 @@ ModelHighAPI_Dumper& operator<<(ModelHighAPI_Dumper& theDumper, else { FeaturePtr aFeature = std::dynamic_pointer_cast(*anIt); theDumper.dumpFeature(aFeature, true); + // dump the Projection feature which produces this "Copy" entity + AttributeBooleanPtr aCopyAttr = aFeature->boolean("Copy"); + if (aCopyAttr.get() && aCopyAttr->value()) + { + const std::set& aRefs = aFeature->data()->refsToMe(); + std::set::iterator aRefIt = aRefs.begin(); + for (; aRefIt != aRefs.end(); ++aRefIt) + if ((*aRefIt)->id() == "ProjectedFeature") + { // process projection only + FeaturePtr anOwner = ModelAPI_Feature::feature((*aRefIt)->owner()); + if (anOwner && !theDumper.isDumped(EntityPtr(anOwner))) + theDumper.dumpFeature(anOwner, true); + } + } } } @@ -972,5 +1262,8 @@ ModelHighAPI_Dumper& operator<<(ModelHighAPI_Dumper& theDumper, // then store currently dumped string theDumper.myFullDump << aBufCopy; + // now, store all postponed features + theDumper.dumpPostponed(); + return theDumper; }