//--------------------------------------------------------------------------------------
#include "ModelHighAPI_Dumper.h"
+#include <Config_PropManager.h>
+
#include <GeomAPI_Pnt.h>
#include <GeomAPI_Dir.h>
+#include <GeomAPI_ShapeExplorer.h>
#include <GeomDataAPI_Dir.h>
#include <GeomDataAPI_Point.h>
#include <ModelAPI_AttributeSelection.h>
#include <ModelAPI_AttributeSelectionList.h>
#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_AttributeStringArray.h>
#include <ModelAPI_CompositeFeature.h>
#include <ModelAPI_Document.h>
#include <ModelAPI_Entity.h>
#include <ModelAPI_Feature.h>
#include <ModelAPI_Result.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_ResultConstruction.h>
#include <ModelAPI_ResultPart.h>
#include <PartSetPlugin_Part.h>
myNotDumpedEntities.clear();
}
+// Convert string to integer. If the string is not a number, return -1
+static int toInt(const std::string& theString)
+{
+ std::string::const_iterator aChar = theString.begin();
+ for (; aChar != theString.end(); ++aChar)
+ if (!std::isdigit(*aChar))
+ break;
+ if (aChar != theString.end())
+ return -1; // not a number
+ return std::stoi(theString);
+}
+
const std::string& ModelHighAPI_Dumper::name(const EntityPtr& theEntity,
bool theSaveNotDumped,
bool theUseEntityName)
{
EntityNameMap::const_iterator aFound = myNames.find(theEntity);
if (aFound != myNames.end())
- return aFound->second.first;
+ return aFound->second.myCurrentName;
// entity is not found, store it
std::string aName;
+ bool isDefaultName = false;
std::ostringstream aDefaultName;
FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theEntity);
if (aFeature) {
size_t anIndex = aName.find(aKind);
if (anIndex == 0 && aName[aKind.length()] == '_') { // name starts with "FeatureKind_"
std::string anIdStr = aName.substr(aKind.length() + 1);
- int anId = std::stoi(anIdStr);
+ int anId = toInt(anIdStr);
// 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) {
// name is not user-defined
- aName.clear();
+ isDefaultName = true;
}
}
}
}
- myNames[theEntity] = std::pair<std::string, std::string>(aDefaultName.str(), aName);
+ myNames[theEntity] = EntityName(aDefaultName.str(), aName, isDefaultName);
if (theSaveNotDumped)
myNotDumpedEntities.insert(theEntity);
if (aFeature)
saveResultNames(aFeature);
- return myNames[theEntity].first;
+ return myNames[theEntity].myCurrentName;
}
const std::string& ModelHighAPI_Dumper::parentName(const FeaturePtr& theEntity)
void ModelHighAPI_Dumper::saveResultNames(const FeaturePtr& theFeature)
{
- const std::string& aFeatureName = myNames[theFeature].first;
+ // 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();
+
+ // Save only names of results which is not correspond to default feature name
const std::list<ResultPtr>& aResults = theFeature->results();
std::list<ResultPtr>::const_iterator aResIt = aResults.begin();
for (int i = 1; aResIt != aResults.end(); ++aResIt, ++i) {
}
}
- myNames[*aResIt] = std::pair<std::string, std::string>(aResName,
- isUserDefined ? aResName : std::string());
+ myNames[*aResIt] = EntityName(aResName,
+ (isUserDefined ? aResName : std::string()), !isUserDefined);
}
}
{
// dump top level document feature
static const std::string aDocName("partSet");
- myNames[theDoc] = std::pair<std::string, std::string>(aDocName, std::string());
+ myNames[theDoc] = EntityName(aDocName, std::string(), true);
*this << aDocName << " = model.moduleDocument()" << std::endl;
// dump subfeatures and store result to file
CompositeFeaturePtr aCompFeat = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aFeatIt);
if (aCompFeat) // iteratively process composite features
isOk = process(aCompFeat) && isOk;
- else if (!isDumped(*aFeatIt)) // dump common feature
+ else if (!isDumped(*aFeatIt)) // dump common feature
dumpFeature(*aFeatIt);
}
return isOk;
}
-bool ModelHighAPI_Dumper::process(const std::shared_ptr<ModelAPI_CompositeFeature>& theComposite, bool isForce)
+bool ModelHighAPI_Dumper::process(const std::shared_ptr<ModelAPI_CompositeFeature>& theComposite,
+ bool isForce)
{
// increase composite features stack
++gCompositeStackDepth;
// dump composite itself
if (!isDumped(theComposite) || isForce)
- dumpFeature(theComposite, isForce);
+ dumpFeature(FeaturePtr(theComposite), isForce);
// sub-part is processed independently, because it provides separate document
if (theComposite->getKind() == PartSetPlugin_Part::ID()) {
+ // dump name of the part if it is different from default
+ if (!myEntitiesStack.empty())
+ dumpEntitySetName();
+
// decrease composite features stack because we run into separate document
--gCompositeStackDepth;
if (!aSubDoc)
return false;
// set name of document
- const std::string& aPartName = myNames[theComposite].first;
+ const std::string& aPartName = myNames[theComposite].myCurrentName;
std::string aDocName = aPartName + "_doc";
- myNames[aSubDoc] = std::pair<std::string, std::string>(aDocName, std::string());
+ myNames[aSubDoc] = EntityName(aDocName, std::string(), true);
// dump document in a separate line
*this << aDocName << " = " << aPartName << ".document()" << std::endl;
return isOk;
}
-bool ModelHighAPI_Dumper::processSubs(const std::shared_ptr<ModelAPI_CompositeFeature>& theComposite,
- bool theDumpModelDo)
+bool ModelHighAPI_Dumper::processSubs(
+ const std::shared_ptr<ModelAPI_CompositeFeature>& theComposite,
+ bool theDumpModelDo)
{
bool isOk = true;
// dump all sub-features;
+ bool isSubDumped = false;
int aNbSubs = theComposite->numberOfSubs();
for (int anIndex = 0; anIndex < aNbSubs; ++anIndex) {
FeaturePtr aFeature = theComposite->subFeature(anIndex);
if (isDumped(aFeature))
continue;
+ isSubDumped = true;
CompositeFeaturePtr aCompFeat = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFeature);
if (aCompFeat) // iteratively process composite features
isOk = process(aCompFeat) && isOk;
bool isDumpSetName = !myEntitiesStack.empty() &&
myEntitiesStack.top().myEntity == EntityPtr(theComposite);
- bool isForceModelDo = isDumpSetName &&
+ bool isForceModelDo = isSubDumped && isDumpSetName &&
(myEntitiesStack.top().myUserName || !myEntitiesStack.top().myResults.empty());
// It is necessary for the sketch to create its result when complete (command "model.do()").
// This option is set by flat theDumpModelDo.
const FeaturePtr& theSubFeature)
{
name(theSubFeature, false);
- myNames[theSubFeature] = std::pair<std::string, std::string>(theSubFeatureGet, theSubFeature->name());
+ myNames[theSubFeature] = EntityName(theSubFeatureGet, theSubFeature->name(), false);
// store results if they have user-defined names or colors
std::list<ResultPtr> aResultsWithNameOrColor;
std::list<ResultPtr>::const_iterator aResIt = aResults.begin();
for (; aResIt != aResults.end(); ++aResIt) {
std::string aResName = (*aResIt)->data()->name();
- myNames[*aResIt] = std::pair<std::string, std::string>(aResName, aResName);
+ myNames[*aResIt] = EntityName(aResName, aResName, false);
aResultsWithNameOrColor.push_back(*aResIt);
}
for (ModulesMap::const_iterator aModIt = myModules.begin();
aModIt != myModules.end(); ++aModIt) {
aFile << "from " << aModIt->first << " import ";
- if (aModIt->second.empty() ||
+ if (aModIt->second.empty() ||
aModIt->second.find(std::string()) != aModIt->second.end())
aFile << "*"; // import whole module
else {
// dump "setName" for the entity
if (aLastDumped.myUserName) {
- std::pair<std::string, std::string> anEntityNames = myNames[aLastDumped.myEntity];
- if (!anEntityNames.second.empty())
- myDumpBuffer << anEntityNames.first << ".setName(\"" << anEntityNames.second << "\")" << std::endl;
- anEntityNames.second.clear(); // don't dump "setName" for the entity twice
+ EntityName& anEntityNames = myNames[aLastDumped.myEntity];
+ if (!anEntityNames.myIsDefault)
+ myDumpBuffer << anEntityNames.myCurrentName << ".setName(\""
+ << anEntityNames.myUserName << "\")" << std::endl;
+ // don't dump "setName" for the entity twice
+ anEntityNames.myUserName.clear();
+ anEntityNames.myIsDefault = true;
}
// dump "setName" for results
std::list<ResultPtr>::const_iterator aResIt = aLastDumped.myResults.begin();
std::list<ResultPtr>::const_iterator aResEnd = aLastDumped.myResults.end();
for (; aResIt != aResEnd; ++aResIt) {
// set result name
- std::pair<std::string, std::string> anEntityNames = myNames[*aResIt];
- if (!anEntityNames.second.empty()) {
+ EntityName& anEntityNames = myNames[*aResIt];
+ if (!anEntityNames.myIsDefault) {
*this << *aResIt;
- myDumpBuffer << ".setName(\"" << anEntityNames.second << "\")" << std::endl;
- anEntityNames.second.clear(); // don't dump "setName" for the entity twice
+ myDumpBuffer << ".setName(\"" << anEntityNames.myUserName << "\")" << std::endl;
+ // don't dump "setName" for the entity twice
+ anEntityNames.myUserName.clear();
+ anEntityNames.myIsDefault = true;
}
// set result color
if (!isDefaultColor(*aResIt)) {
<< ", " << aColor->value(2) << ")" << std::endl;
}
}
+ // set result deflection
+ if (!isDefaultDeflection(*aResIt)) {
+ AttributeDoublePtr aDeflectionAttr =
+ (*aResIt)->data()->real(ModelAPI_Result::DEFLECTION_ID());
+ if(aDeflectionAttr.get() && aDeflectionAttr->isInitialized()) {
+ *this << *aResIt;
+ myDumpBuffer << ".setDeflection(" << aDeflectionAttr->value() << ")" << std::endl;
+ }
+ }
}
myEntitiesStack.pop();
return aDefault == aColorInfo.str();
}
+bool ModelHighAPI_Dumper::isDefaultDeflection(const ResultPtr& theResult) const
+{
+ AttributeDoublePtr aDeflectionAttr = theResult->data()->real(ModelAPI_Result::DEFLECTION_ID());
+ if(!aDeflectionAttr || !aDeflectionAttr->isInitialized()) {
+ return true;
+ }
+
+ double aCurrent = aDeflectionAttr->value();
+ double aDefault = -1;
+
+ bool isConstruction = false;
+ std::string aResultGroup = theResult->groupName();
+ if (aResultGroup == ModelAPI_ResultConstruction::group())
+ isConstruction = true;
+ else if (aResultGroup == ModelAPI_ResultBody::group()) {
+ GeomShapePtr aGeomShape = theResult->shape();
+ if (aGeomShape.get()) {
+ // if the shape could not be exploded on faces, it contains only wires, edges, and vertices
+ // correction of deviation for them should not influence to the application performance
+ GeomAPI_ShapeExplorer anExp(aGeomShape, GeomAPI_Shape::FACE);
+ isConstruction = !anExp.more();
+ }
+ }
+ if (isConstruction)
+ aDefault = Config_PropManager::real("Visualization", "construction_deflection",
+ ModelAPI_ResultConstruction::DEFAULT_DEFLECTION());
+ else
+ aDefault = Config_PropManager::real("Visualization", "body_deflection",
+ ModelAPI_ResultBody::DEFAULT_DEFLECTION());
+
+ return fabs(aCurrent - aDefault) < 1.e-12;
+}
+
ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const char theChar)
{
myDumpBuffer << theChar;
{
myDumpBuffer << name(theEntity);
- bool isUserDefinedName = !myNames[theEntity].second.empty();
+ bool isUserDefinedName = !myNames[theEntity].myIsDefault;
// store results if they have user-defined names or colors
std::list<ResultPtr> aResultsWithNameOrColor;
const std::list<ResultPtr>& aResults = theEntity->results();
std::list<ResultPtr>::const_iterator aResIt = aResults.begin();
for (; aResIt != aResults.end(); ++aResIt)
- if (!myNames[*aResIt].second.empty() || !isDefaultColor(*aResIt))
+ if (!myNames[*aResIt].myIsDefault || !isDefaultColor(*aResIt) || !isDefaultDeflection(*aResIt))
aResultsWithNameOrColor.push_back(*aResIt);
// store just dumped entity to stack
myEntitiesStack.push(LastDumpedEntity(theEntity, isUserDefinedName, aResultsWithNameOrColor));
FeaturePtr aFeature = ModelAPI_Feature::feature(theResult);
int anIndex = 0;
std::list<ResultPtr> aResults = aFeature->results();
- for(std::list<ResultPtr>::const_iterator anIt = aResults.cbegin(); anIt != aResults.cend(); ++anIt, ++anIndex) {
+ for(std::list<ResultPtr>::const_iterator
+ anIt = aResults.cbegin(); anIt != aResults.cend(); ++anIt, ++anIndex) {
if(theResult->isSame(*anIt)) {
break;
}
}
- myDumpBuffer << name(aFeature) << ".result()[" << anIndex << "]";
+
+ myDumpBuffer << name(aFeature);
+ if(anIndex == 0) {
+ myDumpBuffer << ".result()";
+ } else {
+ myDumpBuffer << ".results()[" << anIndex << "]";
+ }
return *this;
}
ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const AttributePtr& theAttr)
{
FeaturePtr anOwner = ModelAPI_Feature::feature(theAttr->owner());
- myDumpBuffer << name(anOwner) << "." << attributeGetter(anOwner, theAttr->id()) << "()";
+
+ std::string aWrapperPrefix, aWrapperSuffix;
+ // Check the attribute belongs to copied (in multi-translation or multi-rotation) feature.
+ // In this case we need to cast explicitly feature to appropriate type.
+ AttributeBooleanPtr isCopy = anOwner->boolean("Copy");
+ if (isCopy.get() && isCopy->value()) {
+ aWrapperPrefix = featureWrapper(anOwner) + "(";
+ aWrapperSuffix = ")";
+ importModule("SketchAPI");
+ }
+
+ myDumpBuffer << aWrapperPrefix << name(anOwner) << aWrapperSuffix
+ << "." << attributeGetter(anOwner, theAttr->id()) << "()";
return *this;
}
return *this;
}
- myDumpBuffer << "\"" << aShape->shapeTypeStr() << "\", \"" << theAttrSelect->namingName() << "\")";
+ myDumpBuffer << "\"" << aShape->shapeTypeStr() << "\", \"" <<
+ theAttrSelect->namingName() << "\")";
return *this;
}
} else {
isAdded = true;
}
- myDumpBuffer << "model.selection(\"" << aShape->shapeTypeStr() << "\", \"" << anAttribute->namingName() << "\")";
+ myDumpBuffer << "model.selection(\"" <<
+ aShape->shapeTypeStr() << "\", \"" << anAttribute->namingName() << "\")";
}
myDumpBuffer << "]";
return *this;
}
+ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
+ const std::shared_ptr<ModelAPI_AttributeStringArray>& theArray)
+{
+ myDumpBuffer<<"[";
+ for(int anIndex = 0; anIndex < theArray->size(); ++anIndex) {
+ if (anIndex != 0)
+ myDumpBuffer<<", ";
+
+ myDumpBuffer<<"\""<<theArray->value(anIndex)<<"\"";
+ }
+
+ myDumpBuffer<<"]";
+ return *this;
+}
+
/// Dump std::endl
-MODELHIGHAPI_EXPORT
ModelHighAPI_Dumper& operator<<(ModelHighAPI_Dumper& theDumper,
std::basic_ostream<char>& (*theEndl)(std::basic_ostream<char>&))
{