From: sbh Date: Thu, 26 Mar 2015 09:55:05 +0000 (+0300) Subject: Merge branch 'master' into Dev_1.1.0 X-Git-Tag: V_1.1.0~78^2~1 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=a24b7e6f4d112d5e7889fd76f030298fc428cd01;p=modules%2Fshaper.git Merge branch 'master' into Dev_1.1.0 Conflicts: CMakeLists.txt src/Config/Config_FeatureReader.cpp src/Config/Config_FeatureReader.h src/ConstructionPlugin/ConstructionPlugin_Axis.cpp src/ConstructionPlugin/ConstructionPlugin_Plane.cpp src/ConstructionPlugin/ConstructionPlugin_Point.cpp src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp src/FeaturesPlugin/FeaturesPlugin_Placement.cpp src/FeaturesPlugin/Test/TestMultiBoolean.py src/Model/Model_AttributeSelection.cpp src/Model/Model_Update.cpp src/ModelAPI/ModelAPI_RefAttrValidator.h src/ModelAPI/ModelAPI_ShapeValidator.cpp src/ModuleBase/ModuleBase_WidgetShapeSelector.cpp src/PartSet/CMakeLists.txt src/PartSet/PartSet_Validators.cpp src/PartSet/PartSet_Validators.h src/PartSet/PartSet_WidgetShapeSelector.cpp src/SketchPlugin/CMakeLists.txt src/SketchPlugin/SketchPlugin_Arc.cpp src/SketchPlugin/SketchPlugin_Circle.cpp src/SketchPlugin/SketchPlugin_ConstraintParallel.cpp src/SketchPlugin/SketchPlugin_Line.cpp src/SketchPlugin/SketchPlugin_Plugin.cpp src/SketchPlugin/SketchPlugin_Point.cpp src/SketchPlugin/SketchPlugin_Sketch.cpp src/SketchPlugin/SketchPlugin_Validators.cpp src/SketchPlugin/SketchPlugin_Validators.h src/SketchPlugin/plugin-Sketch.xml --- a24b7e6f4d112d5e7889fd76f030298fc428cd01 diff --cc CMakeLists.txt index bb42d8b4a,ce89f8361..0cf7163c2 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@@ -54,7 -54,7 +54,8 @@@ ADD_SUBDIRECTORY (src/GeomDataAPI ADD_SUBDIRECTORY (src/PartSetPlugin) ADD_SUBDIRECTORY (src/ConstructionPlugin) ADD_SUBDIRECTORY (src/FeaturesPlugin) +ADD_SUBDIRECTORY (src/SketcherPrs) + ADD_SUBDIRECTORY (src/PythonFeaturesPlugin) ADD_SUBDIRECTORY (src/SketchPlugin) ADD_SUBDIRECTORY (src/SketchSolver) ADD_SUBDIRECTORY (src/ModuleBase) diff --cc src/Config/Config_FeatureReader.cpp index dea07dfc7,48f091aa3..2b024061a --- a/src/Config/Config_FeatureReader.cpp +++ b/src/Config/Config_FeatureReader.cpp @@@ -61,35 -61,18 +61,35 @@@ void Config_FeatureReader::processNode( } else if (isNode(theNode, NODE_WORKBENCH, NODE_GROUP, NULL)) { storeAttribute(theNode, _ID); storeAttribute(theNode, WORKBENCH_DOC); - } else if (myIsProcessWidgets && isWidgetNode(theNode)) { - std::shared_ptr aMessage(new Config_AttributeMessage(aMenuItemEvent, this)); - aMessage->setFeatureId(restoreAttribute(NODE_FEATURE, _ID)); - std::string anAttributeID = getProperty(theNode, _ID); - if (!anAttributeID.empty()) { - aMessage->setAttributeId(anAttributeID); - aMessage->setObligatory(getBooleanAttribute(theNode, ATTR_OBLIGATORY, true)); - aMessage->setConcealment(getBooleanAttribute(theNode, ATTR_CONCEALMENT, false)); - Events_Loop::loop()->send(aMessage); + } else if (myIsProcessWidgets) { + // widgets, like shape_selector or containers, like toolbox + if (isAttributeNode(theNode)) { + std::shared_ptr aMessage(new Config_AttributeMessage(aMenuItemEvent, this)); + aMessage->setFeatureId(restoreAttribute(NODE_FEATURE, _ID)); + std::string anAttributeID = getProperty(theNode, _ID); + if (!anAttributeID.empty()) { + aMessage->setAttributeId(anAttributeID); + aMessage->setObligatory(getBooleanAttribute(theNode, ATTR_OBLIGATORY, true)); + aMessage->setConcealment(getBooleanAttribute(theNode, ATTR_CONCEALMENT, false)); + // nested "paged" widgets are not allowed, this issue may be resolved here: + if (hasParent(theNode, WDG_SWITCH_CASE, WDG_TOOLBOX_BOX, NULL)) { + const char* kWdgCase = hasParent(theNode, WDG_SWITCH_CASE, NULL) + ? WDG_SWITCH_CASE + : WDG_TOOLBOX_BOX; + const char* kWdgSwitch = hasParent(theNode, WDG_SWITCH_CASE, NULL) + ? WDG_SWITCH + : WDG_TOOLBOX; + aMessage->setCaseId(restoreAttribute(kWdgCase, _ID)); + aMessage->setSwitchId(restoreAttribute(kWdgSwitch, _ID)); + } + Events_Loop::loop()->send(aMessage); + } + // container pages, like "case" or "box" + } else if (isNode(theNode, WDG_SWITCH, WDG_SWITCH_CASE, WDG_TOOLBOX, WDG_TOOLBOX_BOX, NULL)) { + storeAttribute(theNode, _ID); // save case:caseId (or box:boxId) } } - //Process SOURCE, VALIDATOR nodes. + //Process SOURCE nodes. Config_XMLReader::processNode(theNode); } diff --cc src/Config/Config_XMLReader.cpp index 768232b74,ab15f3621..c0a0a2ee0 --- a/src/Config/Config_XMLReader.cpp +++ b/src/Config/Config_XMLReader.cpp @@@ -150,45 -138,26 +144,43 @@@ std::string Config_XMLReader::getNodeNa return result; } - void Config_XMLReader::processValidator(xmlNodePtr theNode) + void Config_XMLReader::storeAttribute(xmlNodePtr theNode, const char* theAttribute) { - Events_ID aValidatoEvent = Events_Loop::eventByName(EVENT_VALIDATOR_LOADED); - Events_Loop* aEvLoop = Events_Loop::loop(); - std::shared_ptr - aMessage(new Config_ValidatorMessage(aValidatoEvent, this)); - std::string aValidatorId; - std::list aParameters; - getParametersInfo(theNode, aValidatorId, aParameters); - aMessage->setValidatorId(aValidatorId); - aMessage->setValidatorParameters(aParameters); - xmlNodePtr aFeatureOrWdgNode = theNode->parent; - if (isNode(aFeatureOrWdgNode, NODE_FEATURE, NULL)) { - aMessage->setFeatureId(getProperty(aFeatureOrWdgNode, _ID)); - } else { - aMessage->setAttributeId(getProperty(aFeatureOrWdgNode, _ID)); - aMessage->setFeatureId(myCurrentFeature); + std::string aKey = getNodeName(theNode) + ":" + std::string(theAttribute); + std::string aValue = getProperty(theNode, theAttribute); + if(!aValue.empty()) { + myCachedAttributes[aKey] = aValue; } - aEvLoop->send(aMessage); } - void Config_XMLReader::processSelectionFilter(xmlNodePtr theNode) + std::string Config_XMLReader::restoreAttribute(xmlNodePtr theNode, const char* theAttribute) { - Events_ID aFilterEvent = Events_Loop::eventByName(EVENT_SELFILTER_LOADED); - Events_Loop* aEvLoop = Events_Loop::loop(); - std::shared_ptr aMessage = - std::make_shared(aFilterEvent, this); - std::string aSelectionFilterId; - std::list aParameters; - getParametersInfo(theNode, aSelectionFilterId, aParameters); - aMessage->setSelectionFilterId(aSelectionFilterId); - aMessage->setFilterParameters(aParameters); - - xmlNodePtr aFeatureOrWdgNode = theNode->parent; - if (isNode(aFeatureOrWdgNode, NODE_FEATURE, NULL)) { - aMessage->setFeatureId(getProperty(aFeatureOrWdgNode, _ID)); - } else { - aMessage->setAttributeId(getProperty(aFeatureOrWdgNode, _ID)); - aMessage->setFeatureId(myCurrentFeature); + return restoreAttribute(getNodeName(theNode).c_str(), theAttribute); + } + + std::string Config_XMLReader::restoreAttribute(const char* theNodeName, const char* theAttribute) + { + std::string aKey = std::string(theNodeName) + ":" + std::string(theAttribute); + std::string result = ""; + if(myCachedAttributes.find(aKey) != myCachedAttributes.end()) { + result = myCachedAttributes[aKey]; } - aEvLoop->send(aMessage); + return result; + } ++ ++bool Config_XMLReader::cleanupAttribute(xmlNodePtr theNode, const char* theNodeAttribute) ++{ ++ return cleanupAttribute(getNodeName(theNode).c_str(), theNodeAttribute); ++} ++ ++bool Config_XMLReader::cleanupAttribute(const char* theNodeName, const char* theNodeAttribute) ++{ ++ std::string aKey = std::string(theNodeName) + ":" + std::string(theNodeAttribute); ++ bool result = false; ++ std::map::iterator anEntry = myCachedAttributes.find(aKey); ++ if( anEntry != myCachedAttributes.end()) { ++ myCachedAttributes.erase(anEntry); ++ result = true; ++ } ++ return result; +} diff --cc src/Config/Config_XMLReader.h index 603ce7d1f,8b6f963d1..d19bd8467 --- a/src/Config/Config_XMLReader.h +++ b/src/Config/Config_XMLReader.h @@@ -84,21 -79,20 +85,22 @@@ class Config_XMLReade xmlNodePtr node(void* theNode); /// Gets xml node name std::string getNodeName(xmlNodePtr theNode); - /*! - * \brief Retrieves all the necessary info from the validator node. - * Sends ValidatorLoaded event - */ - void processValidator(xmlNodePtr theNode); - /*! - * \brief Retrieves all the necessary info from the SelectionFilter node. - * Sends SelectionFilterLoaded event - */ - void processSelectionFilter(xmlNodePtr theNode); + /// Stores an attribute in internal map for later use. + /// Key is "Node_Name:Node_Attribute" and value is getProperty(theNodeAttribute) + void storeAttribute(xmlNodePtr theNode, const char* theNodeAttribute); + /// Restores an attribute from internal map. + std::string restoreAttribute(xmlNodePtr theNode, const char* theNodeAttribute); + /// Restores an attribute from internal map. + std::string restoreAttribute(const char* theNodeName, const char* theNodeAttribute); ++ bool cleanupAttribute(xmlNodePtr theNode, const char* theNodeAttribute); ++ bool cleanupAttribute(const char* theNodeName, const char* theNodeAttribute); protected: - std::string myCurrentFeature; ///< Name of currently processed feature std::string myDocumentPath; ///< Path to the xml document xmlDocPtr myXmlDoc; ///< Root of the xml document + /// A map to store all parent's attributes. + /// The key has from "Node_Name:Node_Attribute" + std::map myCachedAttributes; }; #endif /* CONFIG_XMLREADER_H_ */ diff --cc src/Config/plugins.xml index 623b80973,bf95bc97c..65cdd3bee --- a/src/Config/plugins.xml +++ b/src/Config/plugins.xml @@@ -8,8 -6,8 +8,9 @@@ + + diff --cc src/ConstructionPlugin/ConstructionPlugin_Axis.cpp index 5017f496a,78de925dc..e3d7eb34c --- a/src/ConstructionPlugin/ConstructionPlugin_Axis.cpp +++ b/src/ConstructionPlugin/ConstructionPlugin_Axis.cpp @@@ -28,20 -23,14 +28,20 @@@ ConstructionPlugin_Axis::ConstructionPl void ConstructionPlugin_Axis::initAttributes() { - data()->addAttribute(POINT_ATTR_FIRST, ModelAPI_AttributeSelection::typeId()); - data()->addAttribute(POINT_ATTR_SECOND, ModelAPI_AttributeSelection::typeId()); + data()->addAttribute(ConstructionPlugin_Axis::METHOD(), - ModelAPI_AttributeString::type()); ++ ModelAPI_AttributeString::typeId()); + data()->addAttribute(ConstructionPlugin_Axis::POINT_FIRST(), - ModelAPI_AttributeSelection::type()); ++ ModelAPI_AttributeSelection::typeId()); + data()->addAttribute(ConstructionPlugin_Axis::POINT_SECOND(), - ModelAPI_AttributeSelection::type()); ++ ModelAPI_AttributeSelection::typeId()); + data()->addAttribute(ConstructionPlugin_Axis::CYLINDRICAL_FACE(), - ModelAPI_AttributeSelection::type()); ++ ModelAPI_AttributeSelection::typeId()); } -void ConstructionPlugin_Axis::execute() +void ConstructionPlugin_Axis::createAxisByTwoPoints() { - AttributeSelectionPtr aRef1 = data()->selection(POINT_ATTR_FIRST); - AttributeSelectionPtr aRef2 = data()->selection(POINT_ATTR_SECOND); + AttributeSelectionPtr aRef1 = data()->selection(ConstructionPlugin_Axis::POINT_FIRST()); + AttributeSelectionPtr aRef2 = data()->selection(ConstructionPlugin_Axis::POINT_SECOND()); if ((aRef1.get() != NULL) && (aRef2.get() != NULL)) { GeomShapePtr aShape1 = aRef1->value(); GeomShapePtr aShape2 = aRef2->value(); diff --cc src/ConstructionPlugin/ConstructionPlugin_Plane.cpp index 7448f5a7e,07d3d24bc..c206ff4d5 --- a/src/ConstructionPlugin/ConstructionPlugin_Plane.cpp +++ b/src/ConstructionPlugin/ConstructionPlugin_Plane.cpp @@@ -23,15 -22,8 +23,15 @@@ ConstructionPlugin_Plane::ConstructionP void ConstructionPlugin_Plane::initAttributes() { - data()->addAttribute(ConstructionPlugin_Plane::METHOD(), ModelAPI_AttributeString::type()); - data()->addAttribute(FACE_ATTR, ModelAPI_AttributeSelection::typeId()); - data()->addAttribute(DISTANCE_ATTR, ModelAPI_AttributeDouble::typeId()); ++ data()->addAttribute(ConstructionPlugin_Plane::METHOD(), ModelAPI_AttributeString::typeId()); + // Face & Distance - data()->addAttribute(ConstructionPlugin_Plane::FACE(), ModelAPI_AttributeSelection::type()); - data()->addAttribute(ConstructionPlugin_Plane::DISTANCE(), ModelAPI_AttributeDouble::type()); ++ data()->addAttribute(ConstructionPlugin_Plane::FACE(), ModelAPI_AttributeSelection::typeId()); ++ data()->addAttribute(ConstructionPlugin_Plane::DISTANCE(), ModelAPI_AttributeDouble::typeId()); + // General equation - data()->addAttribute(ConstructionPlugin_Plane::A(), ModelAPI_AttributeDouble::type()); - data()->addAttribute(ConstructionPlugin_Plane::B(), ModelAPI_AttributeDouble::type()); - data()->addAttribute(ConstructionPlugin_Plane::C(), ModelAPI_AttributeDouble::type()); - data()->addAttribute(ConstructionPlugin_Plane::D(), ModelAPI_AttributeDouble::type()); ++ data()->addAttribute(ConstructionPlugin_Plane::A(), ModelAPI_AttributeDouble::typeId()); ++ data()->addAttribute(ConstructionPlugin_Plane::B(), ModelAPI_AttributeDouble::typeId()); ++ data()->addAttribute(ConstructionPlugin_Plane::C(), ModelAPI_AttributeDouble::typeId()); ++ data()->addAttribute(ConstructionPlugin_Plane::D(), ModelAPI_AttributeDouble::typeId()); } void ConstructionPlugin_Plane::execute() diff --cc src/ConstructionPlugin/ConstructionPlugin_Point.cpp index 671a38cd7,7a9d66b2d..b31b3b552 --- a/src/ConstructionPlugin/ConstructionPlugin_Point.cpp +++ b/src/ConstructionPlugin/ConstructionPlugin_Point.cpp @@@ -21,17 -19,11 +21,17 @@@ ConstructionPlugin_Point::ConstructionP { } +const std::string& ConstructionPlugin_Point::getKind() +{ + static std::string MY_KIND = ConstructionPlugin_Point::ID(); + return MY_KIND; +} + void ConstructionPlugin_Point::initAttributes() { - data()->addAttribute(ConstructionPlugin_Point::X(), ModelAPI_AttributeDouble::type()); - data()->addAttribute(ConstructionPlugin_Point::Y(), ModelAPI_AttributeDouble::type()); - data()->addAttribute(ConstructionPlugin_Point::Z(), ModelAPI_AttributeDouble::type()); - data()->addAttribute(POINT_ATTR_X, ModelAPI_AttributeDouble::typeId()); - data()->addAttribute(POINT_ATTR_Y, ModelAPI_AttributeDouble::typeId()); - data()->addAttribute(POINT_ATTR_Z, ModelAPI_AttributeDouble::typeId()); ++ data()->addAttribute(ConstructionPlugin_Point::X(), ModelAPI_AttributeDouble::typeId()); ++ data()->addAttribute(ConstructionPlugin_Point::Y(), ModelAPI_AttributeDouble::typeId()); ++ data()->addAttribute(ConstructionPlugin_Point::Z(), ModelAPI_AttributeDouble::typeId()); } void ConstructionPlugin_Point::execute() diff --cc src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp index 873753a8c,042ee8e21..3d8c5bbc8 --- a/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp @@@ -28,13 -27,9 +28,13 @@@ FeaturesPlugin_Extrusion::FeaturesPlugi void FeaturesPlugin_Extrusion::initAttributes() { - data()->addAttribute(FeaturesPlugin_Extrusion::FACE_ID(), ModelAPI_AttributeSelection::typeId()); + AttributeSelectionListPtr aSelection = + std::dynamic_pointer_cast(data()->addAttribute( - FeaturesPlugin_Extrusion::LIST_ID(), ModelAPI_AttributeSelectionList::type())); ++ FeaturesPlugin_Extrusion::LIST_ID(), ModelAPI_AttributeSelectionList::typeId())); + // extrusion works with faces always + aSelection->setSelectionType("FACE"); - data()->addAttribute(FeaturesPlugin_Extrusion::SIZE_ID(), ModelAPI_AttributeDouble::type()); - data()->addAttribute(FeaturesPlugin_Extrusion::REVERSE_ID(), ModelAPI_AttributeBoolean::type()); + data()->addAttribute(FeaturesPlugin_Extrusion::SIZE_ID(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(FeaturesPlugin_Extrusion::REVERSE_ID(), ModelAPI_AttributeBoolean::typeId()); } void FeaturesPlugin_Extrusion::execute() @@@ -150,12 -131,3 +150,12 @@@ void FeaturesPlugin_Extrusion::LoadNami } } + +//============================================================================ +void FeaturesPlugin_Extrusion::clearResult() +{ + std::shared_ptr aResultBody = document()->createBody(data()); + std::shared_ptr anEmptyShape(new GeomAPI_Shape); + aResultBody->store(anEmptyShape); + setResult(aResultBody); - } ++} diff --cc src/FeaturesPlugin/FeaturesPlugin_Placement.cpp index f97b3248d,ae772bd44..3ba02779f --- a/src/FeaturesPlugin/FeaturesPlugin_Placement.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Placement.cpp @@@ -26,10 -24,8 +26,10 @@@ FeaturesPlugin_Placement::FeaturesPlugi void FeaturesPlugin_Placement::initAttributes() { - data()->addAttribute(FeaturesPlugin_Placement::BASE_OBJECT_ID(), ModelAPI_AttributeSelection::type()); - data()->addAttribute(FeaturesPlugin_Placement::ATTRACT_OBJECT_ID(), ModelAPI_AttributeSelection::type()); - data()->addAttribute(FeaturesPlugin_Placement::REVERSE_ID(), ModelAPI_AttributeBoolean::type()); - data()->addAttribute(FeaturesPlugin_Placement::CENTERING_ID(), ModelAPI_AttributeBoolean::type()); - data()->addAttribute(FeaturesPlugin_Placement::BASE_FACE_ID(), ModelAPI_AttributeSelection::typeId()); - data()->addAttribute(FeaturesPlugin_Placement::ATTRACT_FACE_ID(), ModelAPI_AttributeSelection::typeId()); ++ data()->addAttribute(FeaturesPlugin_Placement::BASE_OBJECT_ID(), ModelAPI_AttributeSelection::typeId()); ++ data()->addAttribute(FeaturesPlugin_Placement::ATTRACT_OBJECT_ID(), ModelAPI_AttributeSelection::typeId()); ++ data()->addAttribute(FeaturesPlugin_Placement::REVERSE_ID(), ModelAPI_AttributeBoolean::typeId()); ++ data()->addAttribute(FeaturesPlugin_Placement::CENTERING_ID(), ModelAPI_AttributeBoolean::typeId()); } void FeaturesPlugin_Placement::execute() diff --cc src/FeaturesPlugin/Test/TestMultiBoolean.py index 594c3af72,0b7a63903..953ffc4ee --- a/src/FeaturesPlugin/Test/TestMultiBoolean.py +++ b/src/FeaturesPlugin/Test/TestMultiBoolean.py @@@ -4,13 -4,13 +4,13 @@@ class FeaturesPlugin_Extrusion : public ModelAPI_Feature static const std::string MY_EXTRUSION_ID("Extrusion"); - static const std::string MY_FACE_ID("extrusion_face"); - static const std::string MY_SIZE_ID("extrusion_size"); - static const std::string MY_REVERSE_ID("extrusion_reverse"); + static const std::string MY_FACE_ID("base"); + static const std::string MY_SIZE_ID("size"); + static const std::string MY_REVERSE_ID("reverse"); -- data()->addAttribute(FeaturesPlugin_Extrusion::FACE_ID(), ModelAPI_AttributeSelection::type()); -- data()->addAttribute(FeaturesPlugin_Extrusion::SIZE_ID(), ModelAPI_AttributeDouble::type()); -- data()->addAttribute(FeaturesPlugin_Extrusion::REVERSE_ID(), ModelAPI_AttributeBoolean::type()); ++ data()->addAttribute(FeaturesPlugin_Extrusion::FACE_ID(), ModelAPI_AttributeSelection::typeId()); ++ data()->addAttribute(FeaturesPlugin_Extrusion::SIZE_ID(), ModelAPI_AttributeDouble::typeId()); ++ data()->addAttribute(FeaturesPlugin_Extrusion::REVERSE_ID(), ModelAPI_AttributeBoolean::typeId()); """ # Number rows and columns of cylinders that cuts the big box. Number of Boolena operations is N*N @@@ -19,12 -19,12 +19,13 @@@ N = #========================================================================= # Initialization of the test #========================================================================= --from ModelAPI import * --from GeomDataAPI import * --from GeomAlgoAPI import * from GeomAPI import * ++from GeomAlgoAPI import * ++from GeomDataAPI import * ++from ModelAPI import * + - __updated__ = "2015-02-25" + -__updated__ = "2015-02-25" ++__updated__ = "2015-03-26" aSession = ModelAPI_Session.get() aDocument = aSession.moduleDocument() @@@ -47,23 -47,23 +48,23 @@@ radius = 95. / N / 2 aSession.startOperation() aSketchFeatures = [] for i in xrange(0, N): -- for j in xrange(0, N): -- # Create circle -- aSketchFeature = modelAPI_CompositeFeature(aPart.addFeature("Sketch")) -- origin = geomDataAPI_Point(aSketchFeature.attribute("Origin")) -- origin.setValue(0, 0, 0) -- dirx = geomDataAPI_Dir(aSketchFeature.attribute("DirX")) -- dirx.setValue(1, 0, 0) -- diry = geomDataAPI_Dir(aSketchFeature.attribute("DirY")) -- diry.setValue(0, 1, 0) -- norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm")) -- norm.setValue(0, 0, 1) -- aSketchCircle = aSketchFeature.addFeature("SketchCircle") -- anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter")) -- aCircleRadius = aSketchCircle.real("CircleRadius") -- anCircleCentr.setValue(0.5 + step * (0.5 + i), 0.5 + step * (0.5 + j)) -- aCircleRadius.setValue(radius) -- aSketchFeatures.append(aSketchFeature) ++ for j in xrange(0, N): ++ # Create circle ++ aSketchFeature = modelAPI_CompositeFeature(aPart.addFeature("Sketch")) ++ origin = geomDataAPI_Point(aSketchFeature.attribute("Origin")) ++ origin.setValue(0, 0, 0) ++ dirx = geomDataAPI_Dir(aSketchFeature.attribute("DirX")) ++ dirx.setValue(1, 0, 0) ++ diry = geomDataAPI_Dir(aSketchFeature.attribute("DirY")) ++ diry.setValue(0, 1, 0) ++ norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm")) ++ norm.setValue(0, 0, 1) ++ aSketchCircle = aSketchFeature.addFeature("SketchCircle") ++ anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter")) ++ aCircleRadius = aSketchCircle.real("CircleRadius") ++ anCircleCentr.setValue(0.5 + step * (0.5 + i), 0.5 + step * (0.5 + j)) ++ aCircleRadius.setValue(radius) ++ aSketchFeatures.append(aSketchFeature) aSession.finishOperation() @@@ -77,24 -77,23 +78,29 @@@ aSession.startOperation( anExtrusions = [] for i in xrange(0, N * N): -- aSketchResult = aSketchFeatures[i].firstResult() -- aSketchEdges = modelAPI_ResultConstruction(aSketchResult).shape() -- origin = geomDataAPI_Point(aSketchFeatures[i].attribute("Origin")).pnt() -- dirX = geomDataAPI_Dir(aSketchFeatures[i].attribute("DirX")).dir() -- dirY = geomDataAPI_Dir(aSketchFeatures[i].attribute("DirY")).dir() -- norm = geomDataAPI_Dir(aSketchFeatures[i].attribute("Norm")).dir() -- aSketchFaces = ShapeList() -- GeomAlgoAPI_SketchBuilder.createFaces( -- origin, dirX, dirY, norm, aSketchEdges, aSketchFaces) -- -- anExtrusionFt = aPart.addFeature("Extrusion") -- assert (anExtrusionFt.getKind() == "Extrusion") - - anExtrusionFt.selectionList("base").append( - anExtrusionFt.selection("extrusion_face").setValue( -- aSketchResult, aSketchFaces[0]) - anExtrusionFt.real("size").setValue(10) - anExtrusionFt.boolean("reverse").setValue(False) - anExtrusionFt.real("extrusion_size").setValue(10) - anExtrusionFt.boolean("extrusion_reverse").setValue(False) -- anExtrusions.append(anExtrusionFt) ++ aSketchResult = aSketchFeatures[i].firstResult() ++ aSketchEdges = modelAPI_ResultConstruction(aSketchResult).shape() ++ origin = geomDataAPI_Point(aSketchFeatures[i].attribute("Origin")).pnt() ++ dirX = geomDataAPI_Dir(aSketchFeatures[i].attribute("DirX")).dir() ++ dirY = geomDataAPI_Dir(aSketchFeatures[i].attribute("DirY")).dir() ++ norm = geomDataAPI_Dir(aSketchFeatures[i].attribute("Norm")).dir() ++ aSketchFaces = ShapeList() ++ GeomAlgoAPI_SketchBuilder.createFaces( ++ origin, dirX, dirY, norm, aSketchEdges, aSketchFaces) ++ ++ anExtrusionFt = aPart.addFeature("Extrusion") ++ assert (anExtrusionFt.getKind() == "Extrusion") ++ ++ anExtrusionFt.selectionList("base").append( ++ aSketchResult, aSketchFaces[0]) ++ anExtrusionFt.real("size").setValue(10) ++ anExtrusionFt.boolean("reverse").setValue(False) ++ # v1.0.2 from master ++ # anExtrusionFt.selection("extrusion_face").setValue( ++ # aSketchResult, aSketchFaces[0]) ++ # anExtrusionFt.real("extrusion_size").setValue(10) ++ # anExtrusionFt.boolean("extrusion_reverse").setValue(False) ++ anExtrusions.append(anExtrusionFt) aSession.finishOperation() @@@ -149,27 -148,28 +155,33 @@@ GeomAlgoAPI_SketchBuilder.createFaces origin, dirX, dirY, norm, aSketchEdges, aSketchFaces) # Create extrusion on them aBox = aPart.addFeature("Extrusion") -aBox.selection("extrusion_face").setValue( +aBox.selectionList("base").append( aSketchResult, aSketchFaces[0]) -aBox.real("extrusion_size").setValue(10) -aBox.boolean("extrusion_reverse").setValue(False) +aBox.real("size").setValue(10) +aBox.boolean("reverse").setValue(False) ++# v 1.0.2 from master ++# aBox.selection("extrusion_face").setValue( ++# aSketchResult, aSketchFaces[0]) ++# aBox.real("extrusion_size").setValue(10) ++# aBox.boolean("extrusion_reverse").setValue(False) + aSession.finishOperation() #========================================================================= --# Create a boolean cut of cylinders from the box: ++# Create a boolean cut of cylinders from the box: # result of Boolean is the first argument of the next Boolean #========================================================================= aCurrentResult = aBox.firstResult() aSession.startOperation() for i in xrange(0, N * N): -- aBooleanFt = aPart.addFeature("Boolean") -- aBooleanFt.reference("main_object").setValue(modelAPI_ResultBody(aCurrentResult)) -- aBooleanFt.reference("tool_object").setValue(modelAPI_ResultBody(anExtrusions[i].firstResult())) -- kBooleanTypeCut = 0 -- aBooleanFt.integer("bool_type").setValue(kBooleanTypeCut) -- aBooleanFt.execute() -- aCurrentResult = aBooleanFt.firstResult() ++ aBooleanFt = aPart.addFeature("Boolean") ++ aBooleanFt.reference("main_object").setValue(modelAPI_ResultBody(aCurrentResult)) ++ aBooleanFt.reference("tool_object").setValue(modelAPI_ResultBody(anExtrusions[i].firstResult())) ++ kBooleanTypeCut = 0 ++ aBooleanFt.integer("bool_type").setValue(kBooleanTypeCut) ++ aBooleanFt.execute() ++ aCurrentResult = aBooleanFt.firstResult() aSession.finishOperation() #========================================================================= diff --cc src/GeomDataAPI/GeomDataAPI_Dir.h index 85d4b3a8c,85a3cc031..4e61cd8f0 --- a/src/GeomDataAPI/GeomDataAPI_Dir.h +++ b/src/GeomDataAPI/GeomDataAPI_Dir.h @@@ -34,11 -33,9 +34,11 @@@ class GeomDataAPI_Dir : public ModelAPI virtual double z() const = 0; /// Returns the direction of this attribute virtual std::shared_ptr dir() = 0; + /// Returns the coordinates of this attribute + virtual std::shared_ptr xyz() = 0; /// Returns the type of this class of attributes - static inline std::string type() + static std::string typeId() { return std::string("Dir"); } diff --cc src/GeomValidators/GeomValidators_EdgeOrVertex.cpp index 642d1cde9,000000000..cfd78c994 mode 100644,000000..100644 --- a/src/GeomValidators/GeomValidators_EdgeOrVertex.cpp +++ b/src/GeomValidators/GeomValidators_EdgeOrVertex.cpp @@@ -1,62 -1,0 +1,62 @@@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + + +#include "GeomValidators_EdgeOrVertex.h" +#include "GeomValidators_Tools.h" +#include "GeomValidators_Edge.h" + +#include "ModelAPI_AttributeRefAttr.h" +#include "ModelAPI_Result.h" + +#include + +#include +#include + +#include + +#include + +#include +#include + + +bool GeomValidators_EdgeOrVertex::isValid(const AttributePtr& theAttribute, + const std::list& theArguments) const +{ + bool aValid = false; + + // 1. check whether the attribute is a linear edge + // there is a check whether the feature contains a point and a linear edge or two point values + SessionPtr aMgr = ModelAPI_Session::get(); + ModelAPI_ValidatorsFactory* aFactory = aMgr->validators(); + + const GeomValidators_Edge* aLinearEdgeValidator = + dynamic_cast(aFactory->validator("GeomValidators_Edge")); + + std::list anArguments; + anArguments.push_back("line"); + aValid = aLinearEdgeValidator->isValid(theAttribute, anArguments); + if (!aValid) { + //2. check whether the attribute is a vertex + ObjectPtr anObject = GeomValidators_Tools::getObject(theAttribute); + if (anObject.get() != NULL) { + FeaturePtr aFeature = ModelAPI_Feature::feature(anObject); + ResultPtr aResult = std::dynamic_pointer_cast(anObject); + if (aResult.get() != NULL) { + GeomShapePtr aShape = aResult->shape(); + if (aShape.get() != NULL) { + aValid = aShape->isVertex(); + } + } + } + else { + AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast(theAttribute); + if (anAttr.get() != NULL) { + AttributePtr aRefAttr = anAttr->attr(); - aValid = aRefAttr.get() != NULL && aRefAttr->attributeType() == GeomDataAPI_Point2D::type(); ++ aValid = aRefAttr.get() != NULL && aRefAttr->attributeType() == GeomDataAPI_Point2D::typeId(); + } + } + } + return aValid; +} diff --cc src/GeomValidators/GeomValidators_Tools.cpp index f98088ed3,000000000..898296961 mode 100644,000000..100644 --- a/src/GeomValidators/GeomValidators_Tools.cpp +++ b/src/GeomValidators/GeomValidators_Tools.cpp @@@ -1,36 -1,0 +1,36 @@@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: GeomValidators_Tools.cpp +// Created: 06 Aug 2014 +// Author: Vitaly Smetannikov + +#include "GeomValidators_Tools.h" + +#include "ModelAPI_AttributeRefAttr.h" +#include "ModelAPI_AttributeSelection.h" +#include "ModelAPI_AttributeReference.h" + +namespace GeomValidators_Tools { + + ObjectPtr getObject(const AttributePtr& theAttribute) + { + ObjectPtr anObject; + std::string anAttrType = theAttribute->attributeType(); - if (anAttrType == ModelAPI_AttributeRefAttr::type()) { ++ if (anAttrType == ModelAPI_AttributeRefAttr::typeId()) { + AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast(theAttribute); + if (anAttr != NULL && anAttr->isObject()) + anObject = anAttr->object(); + } - if (anAttrType == ModelAPI_AttributeSelection::type()) { ++ if (anAttrType == ModelAPI_AttributeSelection::typeId()) { + AttributeSelectionPtr anAttr = std::dynamic_pointer_cast(theAttribute); + if (anAttr != NULL && anAttr->isInitialized()) + anObject = anAttr->context(); + } - if (anAttrType == ModelAPI_AttributeReference::type()) { ++ if (anAttrType == ModelAPI_AttributeReference::typeId()) { + AttributeReferencePtr anAttr = std::dynamic_pointer_cast(theAttribute); + if (anAttr.get() != NULL && anAttr->isInitialized()) + anObject = anAttr->value(); + } + return anObject; + } +} diff --cc src/Model/Model_AttributeSelection.cpp index 9133794ae,d19f2d6d1..003fb28e9 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@@ -655,149 -644,130 +673,149 @@@ std::string Model_AttributeSelection::n aName = GetShapeName(aDoc, aSubShape, selectionLabel()); if(aName.empty() ) { // not in the document! TopAbs_ShapeEnum aType = aSubShape.ShapeType(); - switch (aType) { - case TopAbs_FACE: + switch (aType) { + case TopAbs_FACE: // the Face should be in DF. If it is not the case, it is an error ==> to be debugged - break; - case TopAbs_EDGE: - { - // name structure: F1 | F2 [| F3 | F4], where F1 & F2 the faces which gives the Edge in trivial case - // if it is not atrivial case we use localization by neighbours. F3 & F4 - neighbour faces - TopTools_IndexedDataMapOfShapeListOfShape aMap; - TopExp::MapShapesAndAncestors(aContext, TopAbs_EDGE, TopAbs_FACE, aMap); - TopTools_IndexedMapOfShape aSMap; // map for ancestors of the sub-shape - bool isTrivialCase(true); - /* for (int i = 1; i <= aMap.Extent(); i++) { - const TopoDS_Shape& aKey = aMap.FindKey(i); - //if (aKey.IsNotEqual(aSubShape)) continue; // find exactly the selected key - if (aKey.IsSame(aSubShape)) continue; - const TopTools_ListOfShape& anAncestors = aMap.FindFromIndex(i); - // check that it is not a trivial case (F1 & F2: aNumber = 1) - isTrivialCase = isTrivial(anAncestors, aSMap); - break; - }*/ - if(aMap.Contains(aSubShape)) { - const TopTools_ListOfShape& anAncestors = aMap.FindFromKey(aSubShape); - // check that it is not a trivial case (F1 & F2: aNumber = 1) - isTrivialCase = isTrivial(anAncestors, aSMap); - } else - break; - TopTools_ListOfShape aListOfNbs; - if(!isTrivialCase) { // find Neighbors - TNaming_Localizer aLocalizer; - TopTools_MapOfShape aMap3; - aLocalizer.FindNeighbourg(aContext, aSubShape, aMap3); - //int n = aMap3.Extent(); - TopTools_MapIteratorOfMapOfShape it(aMap3); - for(;it.More();it.Next()) { - const TopoDS_Shape& aNbShape = it.Key(); // neighbor edge - //TopAbs_ShapeEnum aType = aNbShape.ShapeType(); - const TopTools_ListOfShape& aList = aMap.FindFromKey(aNbShape); - TopTools_ListIteratorOfListOfShape it2(aList); - for(;it2.More();it2.Next()) { - if(aSMap.Contains(it2.Value())) continue; // skip this Face - aListOfNbs.Append(it2.Value()); - } - } - } // else a trivial case - - // build name of the sub-shape Edge - for(int i=1; i <= aSMap.Extent(); i++) { - const TopoDS_Shape& aFace = aSMap.FindKey(i); - std::string aFaceName = GetShapeName(aDoc, aFace, selectionLabel()); - if(i == 1) - aName = aFaceName; - else - aName += "|" + aFaceName; - } - TopTools_ListIteratorOfListOfShape itl(aListOfNbs); - for (;itl.More();itl.Next()) { - std::string aFaceName = GetShapeName(aDoc, itl.Value(), selectionLabel()); - aName += "|" + aFaceName; - } - } - break; + break; + case TopAbs_EDGE: + { + // name structure: F1 | F2 [| F3 | F4], where F1 & F2 the faces which gives the Edge in trivial case + // if it is not atrivial case we use localization by neighbours. F3 & F4 - neighbour faces + if (BRep_Tool::Degenerated(TopoDS::Edge(aSubShape))) { + aName = "Degenerated_Edge"; + break; + } + TopTools_IndexedDataMapOfShapeListOfShape aMap; + TopExp::MapShapesAndAncestors(aContext, TopAbs_EDGE, TopAbs_FACE, aMap); + TopTools_IndexedMapOfShape aSMap; // map for ancestors of the sub-shape + bool isTrivialCase(true); +/* for (int i = 1; i <= aMap.Extent(); i++) { + const TopoDS_Shape& aKey = aMap.FindKey(i); + //if (aKey.IsNotEqual(aSubShape)) continue; // find exactly the selected key + if (aKey.IsSame(aSubShape)) continue; + const TopTools_ListOfShape& anAncestors = aMap.FindFromIndex(i); + // check that it is not a trivial case (F1 & F2: aNumber = 1) + isTrivialCase = isTrivial(anAncestors, aSMap); + break; + }*/ + if(aMap.Contains(aSubShape)) { + const TopTools_ListOfShape& anAncestors = aMap.FindFromKey(aSubShape); + // check that it is not a trivial case (F1 & F2: aNumber = 1) + isTrivialCase = isTrivial(anAncestors, aSMap); + } else + break; + TopTools_ListOfShape aListOfNbs; + if(!isTrivialCase) { // find Neighbors + TNaming_Localizer aLocalizer; + TopTools_MapOfShape aMap3; + aLocalizer.FindNeighbourg(aContext, aSubShape, aMap3); + //int n = aMap3.Extent(); + TopTools_MapIteratorOfMapOfShape it(aMap3); + for(;it.More();it.Next()) { + const TopoDS_Shape& aNbShape = it.Key(); // neighbor edge + //TopAbs_ShapeEnum aType = aNbShape.ShapeType(); + const TopTools_ListOfShape& aList = aMap.FindFromKey(aNbShape); + TopTools_ListIteratorOfListOfShape it2(aList); + for(;it2.More();it2.Next()) { + if(aSMap.Contains(it2.Value())) continue; // skip this Face + aListOfNbs.Append(it2.Value()); + } + } + } // else a trivial case + + // build name of the sub-shape Edge + for(int i=1; i <= aSMap.Extent(); i++) { + const TopoDS_Shape& aFace = aSMap.FindKey(i); + std::string aFaceName = GetShapeName(aDoc, aFace, selectionLabel()); + if(i == 1) + aName = aFaceName; + else + aName += "|" + aFaceName; + } + TopTools_ListIteratorOfListOfShape itl(aListOfNbs); + for (;itl.More();itl.Next()) { + std::string aFaceName = GetShapeName(aDoc, itl.Value(), selectionLabel()); + aName += "|" + aFaceName; + } + } + break; - case TopAbs_VERTEX: - // name structure (Monifold Topology): - // 1) F1 | F2 | F3 - intersection of 3 faces defines a vertex - trivial case. - // 2) F1 | F2 | F3 [|F4 [|Fn]] - redundant definition, but it should be kept as is to obtain safe recomputation - // 2) F1 | F2 - intersection of 2 faces definses a vertex - applicable for case - // when 1 faces is cylindrical, conical, spherical or revolution and etc. - // 3) E1 | E2 | E3 - intersection of 3 edges defines a vertex - when we have case of a shell - // or compound of 2 open faces. - // 4) E1 | E2 - intesection of 2 edges defines a vertex - when we have a case of - // two independent edges (wire or compound) - // implemented 2 first cases - { - TopTools_IndexedDataMapOfShapeListOfShape aMap; - TopExp::MapShapesAndAncestors(aContext, TopAbs_VERTEX, TopAbs_FACE, aMap); - const TopTools_ListOfShape& aList2 = aMap.FindFromKey(aSubShape); - TopTools_ListOfShape aList; - TopTools_MapOfShape aFMap; + case TopAbs_VERTEX: + // name structure (Monifold Topology): + // 1) F1 | F2 | F3 - intersection of 3 faces defines a vertex - trivial case. + // 2) F1 | F2 | F3 [|F4 [|Fn]] - redundant definition, but it should be kept as is to obtain safe recomputation + // 2) F1 | F2 - intersection of 2 faces definses a vertex - applicable for case + // when 1 faces is cylindrical, conical, spherical or revolution and etc. + // 3) E1 | E2 | E3 - intersection of 3 edges defines a vertex - when we have case of a shell + // or compound of 2 open faces. + // 4) E1 | E2 - intesection of 2 edges defines a vertex - when we have a case of + // two independent edges (wire or compound) + // implemented 2 first cases + { + TopTools_IndexedDataMapOfShapeListOfShape aMap; + TopExp::MapShapesAndAncestors(aContext, TopAbs_VERTEX, TopAbs_FACE, aMap); + const TopTools_ListOfShape& aList2 = aMap.FindFromKey(aSubShape); + TopTools_ListOfShape aList; + TopTools_MapOfShape aFMap; #ifdef FIX_BUG1 - //int n = aList2.Extent(); //bug! duplication - // fix is below - TopTools_ListIteratorOfListOfShape itl2(aList2); - for (int i = 1;itl2.More();itl2.Next(),i++) { - if(aFMap.Add(itl2.Value())) - aList.Append(itl2.Value()); - } - //n = aList.Extent(); + //int n = aList2.Extent(); //bug! duplication + // fix is below + TopTools_ListIteratorOfListOfShape itl2(aList2); + for (int i = 1;itl2.More();itl2.Next(),i++) { + if(aFMap.Add(itl2.Value())) + aList.Append(itl2.Value()); + } + //n = aList.Extent(); #endif - int n = aList.Extent(); - if(n < 3) { // open topology case or Compound case => via edges - TopTools_IndexedDataMapOfShapeListOfShape aMap; - TopExp::MapShapesAndAncestors(aContext, TopAbs_VERTEX, TopAbs_EDGE, aMap); - const TopTools_ListOfShape& aList22 = aMap.FindFromKey(aSubShape); - if(aList22.Extent() >= 2) { // regular solution + int n = aList.Extent(); - if(n < 3) { // open topology case => via edges ++ if(n < 3) { // open topology case or Compound case => via edges + TopTools_IndexedDataMapOfShapeListOfShape aMap; + TopExp::MapShapesAndAncestors(aContext, TopAbs_VERTEX, TopAbs_EDGE, aMap); - const TopTools_ListOfShape& aList2 = aMap.FindFromKey(aSubShape); - if(aList2.Extent() >= 2) { // regular solution - TopTools_ListIteratorOfListOfShape itl(aList2); ++ const TopTools_ListOfShape& aList22 = aMap.FindFromKey(aSubShape); ++ if(aList22.Extent() >= 2) { // regular solution +#ifdef FIX_BUG1 - - // bug! duplication; fix is below - aFMap.Clear(); - TopTools_ListOfShape aListE; - TopTools_ListIteratorOfListOfShape itl2(aList22); - for (int i = 1;itl2.More();itl2.Next(),i++) { - if(aFMap.Add(itl2.Value())) - aListE.Append(itl2.Value()); - } - n = aListE.Extent(); ++ ++ // bug! duplication; fix is below ++ aFMap.Clear(); ++ TopTools_ListOfShape aListE; ++ TopTools_ListIteratorOfListOfShape itl2(aList22); ++ for (int i = 1;itl2.More();itl2.Next(),i++) { ++ if(aFMap.Add(itl2.Value())) ++ aListE.Append(itl2.Value()); ++ } ++ n = aListE.Extent(); +#endif - TopTools_ListIteratorOfListOfShape itl(aListE); - for (int i = 1;itl.More();itl.Next(),i++) { - const TopoDS_Shape& anEdge = itl.Value(); - std::string anEdgeName = GetShapeName(aDoc, anEdge, selectionLabel()); - if(i == 1) - aName = anEdgeName; - else - aName += "|" + anEdgeName; - } - }//reg - else { // dangle vertex: if(aList22.Extent() == 1) - //it should be already in DF - } - } - else { - TopTools_ListIteratorOfListOfShape itl(aList); - for (int i = 1;itl.More();itl.Next(),i++) { - const TopoDS_Shape& aFace = itl.Value(); - std::string aFaceName = GetShapeName(aDoc, aFace, selectionLabel()); - if(i == 1) - aName = aFaceName; - else - aName += "|" + aFaceName; - } - } - } - break; - } ++ TopTools_ListIteratorOfListOfShape itl(aListE); + for (int i = 1;itl.More();itl.Next(),i++) { + const TopoDS_Shape& anEdge = itl.Value(); + std::string anEdgeName = GetShapeName(aDoc, anEdge, selectionLabel()); + if(i == 1) + aName = anEdgeName; + else + aName += "|" + anEdgeName; + } ++ }//reg ++ else { // dangle vertex: if(aList22.Extent() == 1) ++ //it should be already in DF + } + } + else { + TopTools_ListIteratorOfListOfShape itl(aList); + for (int i = 1;itl.More();itl.Next(),i++) { + const TopoDS_Shape& aFace = itl.Value(); + std::string aFaceName = GetShapeName(aDoc, aFace, selectionLabel()); + if(i == 1) + aName = aFaceName; + else + aName += "|" + aFaceName; + } + } + } + break; + } // register name // aDoc->addNamingName(selectionLabel(), aName); - // the selected sub-shape will not be shared and as result it will not require registration + // the selected sub-shape will not be shared and as result it will not require registration } return aName; } diff --cc src/Model/Model_Data.cpp index 82cc25918,f280f8fc6..d537db894 --- a/src/Model/Model_Data.cpp +++ b/src/Model/Model_Data.cpp @@@ -70,40 -66,37 +70,40 @@@ void Model_Data::setName(const std::str } } -void Model_Data::addAttribute(const std::string& theID, const std::string theAttrType) +AttributePtr Model_Data::addAttribute(const std::string& theID, const std::string theAttrType) { + AttributePtr aResult; TDF_Label anAttrLab = myLab.FindChild(myAttrs.size() + 1); ModelAPI_Attribute* anAttr = 0; - if (theAttrType == ModelAPI_AttributeDocRef::type()) { + if (theAttrType == ModelAPI_AttributeDocRef::typeId()) { anAttr = new Model_AttributeDocRef(anAttrLab); - } else if (theAttrType == Model_AttributeInteger::type()) { + } else if (theAttrType == Model_AttributeInteger::typeId()) { anAttr = new Model_AttributeInteger(anAttrLab); - } else if (theAttrType == ModelAPI_AttributeDouble::type()) { + } else if (theAttrType == ModelAPI_AttributeDouble::typeId()) { anAttr = new Model_AttributeDouble(anAttrLab); - } else if (theAttrType == Model_AttributeBoolean::type()) { + } else if (theAttrType == Model_AttributeBoolean::typeId()) { anAttr = new Model_AttributeBoolean(anAttrLab); - } else if (theAttrType == Model_AttributeString::type()) { + } else if (theAttrType == Model_AttributeString::typeId()) { anAttr = new Model_AttributeString(anAttrLab); - } else if (theAttrType == ModelAPI_AttributeReference::type()) { + } else if (theAttrType == ModelAPI_AttributeReference::typeId()) { anAttr = new Model_AttributeReference(anAttrLab); - } else if (theAttrType == ModelAPI_AttributeSelection::type()) { + } else if (theAttrType == ModelAPI_AttributeSelection::typeId()) { anAttr = new Model_AttributeSelection(anAttrLab); - } else if (theAttrType == ModelAPI_AttributeSelectionList::type()) { + } else if (theAttrType == ModelAPI_AttributeSelectionList::typeId()) { anAttr = new Model_AttributeSelectionList(anAttrLab); - } else if (theAttrType == ModelAPI_AttributeRefAttr::type()) { + } else if (theAttrType == ModelAPI_AttributeRefAttr::typeId()) { anAttr = new Model_AttributeRefAttr(anAttrLab); - } else if (theAttrType == ModelAPI_AttributeRefList::type()) { + } else if (theAttrType == ModelAPI_AttributeRefList::typeId()) { anAttr = new Model_AttributeRefList(anAttrLab); - } else if (theAttrType == ModelAPI_AttributeIntArray::type()) { ++ } else if (theAttrType == ModelAPI_AttributeIntArray::typeId()) { + anAttr = new Model_AttributeIntArray(anAttrLab); } // create also GeomData attributes here because only here the OCAF strucure is known - else if (theAttrType == GeomData_Point::type()) { + else if (theAttrType == GeomData_Point::typeId()) { anAttr = new GeomData_Point(anAttrLab); - } else if (theAttrType == GeomData_Dir::type()) { + } else if (theAttrType == GeomData_Dir::typeId()) { anAttr = new GeomData_Dir(anAttrLab); - } else if (theAttrType == GeomData_Point2D::type()) { + } else if (theAttrType == GeomData_Point2D::typeId()) { anAttr = new GeomData_Point2D(anAttrLab); } if (anAttr) { diff --cc src/Model/Model_ResultBody.cpp index 2bdea7f5f,7d3fa0b82..7708c92cf --- a/src/Model/Model_ResultBody.cpp +++ b/src/Model/Model_ResultBody.cpp @@@ -42,21 -40,6 +42,21 @@@ Model_ResultBody::Model_ResultBody( setIsConcealed(false); } +void Model_ResultBody::initAttributes() +{ + // append the color attribute. It is empty, the attribute will be filled by a request + DataPtr aData = data(); - aData->addAttribute(COLOR_ID(), ModelAPI_AttributeIntArray::type()); ++ aData->addAttribute(COLOR_ID(), ModelAPI_AttributeIntArray::typeId()); +} + +void Model_ResultBody::colorConfigInfo(std::string& theSection, std::string& theName, + std::string& theDefault) +{ + theSection = "Visualization"; + theName = "result_body_color"; + theDefault = DEFAULT_COLOR(); +} + void Model_ResultBody::store(const std::shared_ptr& theShape) { std::shared_ptr aData = std::dynamic_pointer_cast(data()); diff --cc src/Model/Model_ResultConstruction.cpp index 2998e9f2d,aaade70ff..1e2021c42 --- a/src/Model/Model_ResultConstruction.cpp +++ b/src/Model/Model_ResultConstruction.cpp @@@ -6,35 -6,9 +6,35 @@@ #include +#include +#include +#include +#include + +void Model_ResultConstruction::initAttributes() +{ + // append the color attribute. It is empty, the attribute will be filled by a request + DataPtr aData = data(); - aData->addAttribute(COLOR_ID(), ModelAPI_AttributeIntArray::type()); ++ aData->addAttribute(COLOR_ID(), ModelAPI_AttributeIntArray::typeId()); +} + +void Model_ResultConstruction::colorConfigInfo(std::string& theSection, std::string& theName, + std::string& theDefault) +{ + theSection = "Visualization"; + theName = "result_construction_color"; + theDefault = DEFAULT_COLOR(); +} + void Model_ResultConstruction::setShape(std::shared_ptr theShape) { - myShape = theShape; + if (myShape != theShape && (!theShape.get() || !theShape->isEqual(myShape))) { + myShape = theShape; + if (theShape.get()) { + myFacesUpToDate = false; + myFaces.clear(); + } + } } std::shared_ptr Model_ResultConstruction::shape() diff --cc src/Model/Model_ResultGroup.cpp index dd4ee732b,ebcdb9b43..39809bade --- a/src/Model/Model_ResultGroup.cpp +++ b/src/Model/Model_ResultGroup.cpp @@@ -18,21 -14,6 +18,21 @@@ Model_ResultGroup::Model_ResultGroup(st myOwnerData = theOwnerData; } +void Model_ResultGroup::initAttributes() +{ + // append the color attribute. It is empty, the attribute will be filled by a request + DataPtr aData = data(); - aData->addAttribute(COLOR_ID(), ModelAPI_AttributeIntArray::type()); ++ aData->addAttribute(COLOR_ID(), ModelAPI_AttributeIntArray::typeId()); +} + +void Model_ResultGroup::colorConfigInfo(std::string& theSection, std::string& theName, + std::string& theDefault) +{ + theSection = "Visualization"; + theName = "result_group_color"; + theDefault = DEFAULT_COLOR(); +} + std::shared_ptr Model_ResultGroup::shape() { std::shared_ptr aResult; diff --cc src/ModelAPI/ModelAPI_AttributeIntArray.cpp index 0e0304c46,000000000..52d870d57 mode 100644,000000..100644 --- a/src/ModelAPI/ModelAPI_AttributeIntArray.cpp +++ b/src/ModelAPI/ModelAPI_AttributeIntArray.cpp @@@ -1,22 -1,0 +1,22 @@@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: ModelAPI_AttributeIntArray.cpp +// Created: 6 Mar 2015 +// Author: Natalia ERMOLAEVA + +#include + + +std::string ModelAPI_AttributeIntArray::attributeType() +{ - return type(); ++ return typeId(); +} + +/// To virtually destroy the fields of successors +ModelAPI_AttributeIntArray::~ModelAPI_AttributeIntArray() +{ +} + +ModelAPI_AttributeIntArray::ModelAPI_AttributeIntArray() +{ +} diff --cc src/ModelAPI/ModelAPI_AttributeIntArray.h index 177db0422,000000000..8b319a16d mode 100644,000000..100644 --- a/src/ModelAPI/ModelAPI_AttributeIntArray.h +++ b/src/ModelAPI/ModelAPI_AttributeIntArray.h @@@ -1,59 -1,0 +1,59 @@@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: ModelAPI_AttributeIntArray.h +// Created: 6 Mar 2015 +// Author: Natalia ERMOLAEVA + +#ifndef ModelAPI_AttributeIntArray_H_ +#define ModelAPI_AttributeIntArray_H_ + +#include +#include + +#include + + +/**\class ModelAPI_AttributeIntArray + * \ingroup DataModel + * \brief API for the attribute that contains several integers in the array inside. + * Used for RGB color storage for an example. By default size is one, zero-based. + */ + +class ModelAPI_AttributeIntArray : public ModelAPI_Attribute +{ + public: + + /// Returns the size of the array (zero means that it is empty) + MODELAPI_EXPORT virtual int size() = 0; + + /// Sets the new size of the array. The previous data is erased. + MODELAPI_EXPORT virtual void setSize(const int theSize) = 0; + + /// Defines the value of the array by index [0; size-1] + MODELAPI_EXPORT virtual void setValue(const int theIndex, + const int theValue) = 0; + + /// Returns the value by the index + MODELAPI_EXPORT virtual int value(const int theIndex) = 0; + + /// Returns the type of this class of attributes - MODELAPI_EXPORT static std::string type() ++ MODELAPI_EXPORT static std::string typeId() + { + return "IntArray"; + } + + /// Returns the type of this class of attributes, not static method + MODELAPI_EXPORT virtual std::string attributeType(); + + /// To virtually destroy the fields of successors + MODELAPI_EXPORT virtual ~ModelAPI_AttributeIntArray(); + + protected: + /// Objects are created for features automatically + MODELAPI_EXPORT ModelAPI_AttributeIntArray(); +}; + +//! Pointer on double attribute +typedef std::shared_ptr AttributeIntArrayPtr; + +#endif diff --cc src/ModelAPI/ModelAPI_ShapeValidator.cpp index 0ef625cd7,8de8d2767..fb03f459f --- a/src/ModelAPI/ModelAPI_ShapeValidator.cpp +++ b/src/ModelAPI/ModelAPI_ShapeValidator.cpp @@@ -20,8 -16,8 +20,8 @@@ bool ModelAPI_ShapeValidator::isValid(c std::string aCurrentAttributeId = theAttribute->id(); // get all feature attributes std::list anAttrs = - aFeature->data()->attributes(ModelAPI_AttributeSelection::type()); - theFeature->data()->attributes(ModelAPI_AttributeSelection::typeId()); - if (anAttrs.size() > 0 && theShape.get() != NULL) { ++ aFeature->data()->attributes(ModelAPI_AttributeSelection::typeId()); + if (anAttrs.size() > 0 && aShape.get() != NULL) { std::list::iterator anAttr = anAttrs.begin(); for(; anAttr != anAttrs.end(); anAttr++) { AttributePtr anAttribute = *anAttr; diff --cc src/ModuleBase/ModuleBase_Operation.cpp index 4b8c7d34b,63a3e1e6a..ff2780957 --- a/src/ModuleBase/ModuleBase_Operation.cpp +++ b/src/ModuleBase/ModuleBase_Operation.cpp @@@ -127,16 -137,28 +127,25 @@@ bool ModuleBase_Operation::hasObject(Ob return false; } - -std::shared_ptr ModuleBase_Operation::document() const -{ - return ModelAPI_Session::get()->moduleDocument(); -} - - void ModuleBase_Operation::start() { - ModelAPI_Session::get()->startOperation(); + QString anId = getDescription()->operationId(); + if (myIsEditing) { + anId = anId.append(EditSuffix()); + } + ModelAPI_Session::get()->startOperation(anId.toStdString()); - if (!myIsEditing) - createFeature(); + if (!myIsEditing) { + FeaturePtr aFeature = createFeature(); + // if the feature is not created, there is no sense to start the operation + if (aFeature.get() == NULL) { + // it is necessary to abor the operation in the session and emit the aborted signal + // in order to update commands status in the workshop, to be exact the feature action + // to be unchecked + abort(); + return; + } + } startOperation(); emit started(); diff --cc src/ModuleBase/ModuleBase_WidgetShapeSelector.cpp index ef46fa062,74bd7f61a..c0e4faacf --- a/src/ModuleBase/ModuleBase_WidgetShapeSelector.cpp +++ b/src/ModuleBase/ModuleBase_WidgetShapeSelector.cpp @@@ -387,72 -467,53 +387,81 @@@ void ModuleBase_WidgetShapeSelector::st } //******************************************************************** -bool ModuleBase_WidgetShapeSelector::isValid(ObjectPtr theObj, std::shared_ptr theShape) +void ModuleBase_WidgetShapeSelector::restoreAttributeValue(bool theValid) { - SessionPtr aMgr = ModelAPI_Session::get(); - ModelAPI_ValidatorsFactory* aFactory = aMgr->validators(); - std::list aValidators; - std::list > anArguments; - aFactory->validators(parentID(), attributeID(), aValidators, anArguments); - - // Check the type of selected object - std::list::iterator aValidator = aValidators.begin(); - bool isValid = true; - for (; aValidator != aValidators.end(); aValidator++) { - const ModelAPI_ResultValidator* aResValidator = - dynamic_cast(*aValidator); - if (aResValidator) { - isValid = false; - if (aResValidator->isValid(theObj)) { - isValid = true; - break; - } - } + DataPtr aData = myFeature->data(); + AttributePtr anAttribute = myFeature->attribute(attributeID()); + + setObject(myObject, myShape); + AttributeRefAttrPtr aRefAttr = aData->refattr(attributeID()); + if (aRefAttr) { + if (!myIsObject) + aRefAttr->setAttr(myRefAttribute); } - if (!isValid) +} + +//******************************************************************** +bool ModuleBase_WidgetShapeSelector::setSelection(const Handle_SelectMgr_EntityOwner& theOwner) +{ + bool isDone = false; + + ModuleBase_ViewerPrs aPrs; + myWorkshop->selection()->fillPresentation(aPrs, theOwner); + ObjectPtr aObject = aPrs.object(); + ObjectPtr aCurrentObject = GeomValidators_Tools::getObject(myFeature->attribute(attributeID())); + if ((!aCurrentObject) && (!aObject)) + return false; + + // Check that the selected object is result (others can not be accepted) + ResultPtr aRes = std::dynamic_pointer_cast(aObject); + if (!aRes) return false; - // Check the acceptability of the object as attribute - aValidator = aValidators.begin(); - std::list >::iterator aArgs = anArguments.begin(); - for (; aValidator != aValidators.end(); aValidator++, aArgs++) { - const ModelAPI_RefAttrValidator* aAttrValidator = - dynamic_cast(*aValidator); - if (aAttrValidator) { - if (!aAttrValidator->isValid(myFeature, *aArgs, theObj, theShape)) { + if (myFeature) { + // We can not select a result of our feature + const std::list>& aResList = myFeature->results(); + std::list >::const_iterator aIt; + for (aIt = aResList.cbegin(); aIt != aResList.cend(); ++aIt) { + if ((*aIt) == aRes) ++// TODO(nds): v1.0.2 (master) ++// // Check the acceptability of the object as attribute ++// aValidator = aValidators.begin(); ++// std::list >::iterator aArgs = anArguments.begin(); ++// for (; aValidator != aValidators.end(); aValidator++, aArgs++) { ++// const ModelAPI_RefAttrValidator* aAttrValidator = ++// dynamic_cast(*aValidator); ++// if (aAttrValidator) { ++// if (!aAttrValidator->isValid(myFeature, *aArgs, theObj, theShape)) { return false; - } - } - else { - const ModelAPI_ShapeValidator* aShapeValidator = - dynamic_cast(*aValidator); - if (aShapeValidator) { - DataPtr aData = myFeature->data(); - AttributeSelectionPtr aSelectAttr = aData->selection(attributeID()); - if (!aShapeValidator->isValid(myFeature, aSelectAttr, theShape)) { - return false; - } - } } } + // Check that object belongs to active document or PartSet + DocumentPtr aDoc = aRes->document(); + SessionPtr aMgr = ModelAPI_Session::get(); + if (!(aDoc == aMgr->activeDocument()) && !(aDoc == aMgr->moduleDocument())) + return false; + + // Check that the result has a shape + GeomShapePtr aShape = ModelAPI_Tools::shape(aRes); + if (!aShape) + return false; + + // Get sub-shapes from local selection + if (!aPrs.shape().IsNull()) { + aShape = std::shared_ptr(new GeomAPI_Shape()); + aShape->setImpl(new TopoDS_Shape(aPrs.shape())); + } + // Check that the selection corresponds to selection type + if (!acceptSubShape(aShape)) + return false; + + setObject(aObject, aShape); return true; -} +} + +//******************************************************************** +void ModuleBase_WidgetShapeSelector::deactivate() +{ + activateSelection(false); + disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged())); +} diff --cc src/ParametersPlugin/ParametersPlugin_Parameter.cpp index 498b83d9a,000000000..c3d72d272 mode 100644,000000..100644 --- a/src/ParametersPlugin/ParametersPlugin_Parameter.cpp +++ b/src/ParametersPlugin/ParametersPlugin_Parameter.cpp @@@ -1,22 -1,0 +1,22 @@@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: ParametersPlugin_Parameter.cpp +// Created: 23 MArch 2015 +// Author: sbh + +#include "ParametersPlugin_Parameter.h" +#include + +ParametersPlugin_Parameter::ParametersPlugin_Parameter() +{ +} + +void ParametersPlugin_Parameter::initAttributes() +{ - data()->addAttribute(ParametersPlugin_Parameter::VARIABLE_ID(), ModelAPI_AttributeString::type()); - data()->addAttribute(ParametersPlugin_Parameter::EXPRESSION_ID(), ModelAPI_AttributeString::type()); ++ data()->addAttribute(ParametersPlugin_Parameter::VARIABLE_ID(), ModelAPI_AttributeString::typeId()); ++ data()->addAttribute(ParametersPlugin_Parameter::EXPRESSION_ID(), ModelAPI_AttributeString::typeId()); +} + +void ParametersPlugin_Parameter::execute() +{ +} diff --cc src/PartSet/CMakeLists.txt index bdbc48c52,f919c05fd..486a87511 --- a/src/PartSet/CMakeLists.txt +++ b/src/PartSet/CMakeLists.txt @@@ -46,7 -42,7 +46,8 @@@ SET(PROJECT_LIBRARIE ModuleBase Config GeomAPI + GeomValidators + GeomDataAPI ${QT_LIBRARIES} ${CAS_KERNEL} ${CAS_SHAPE} diff --cc src/PartSet/PartSet_Tools.cpp index f7c4ab57f,9157938f1..a92364d05 --- a/src/PartSet/PartSet_Tools.cpp +++ b/src/PartSet/PartSet_Tools.cpp @@@ -363,10 -361,8 +363,10 @@@ void PartSet_Tools::setConstraints(Comp new GeomAPI_Pnt2d(theClickedX, theClickedY)); for (; anIt != aLast; anIt++) { FeaturePtr aFeature = std::dynamic_pointer_cast(*anIt); + if (theFeature == aFeature) + continue; // find the given point in the feature attributes - anAttiributes = aFeature->data()->attributes(GeomDataAPI_Point2D::type()); + anAttiributes = aFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); std::list >::const_iterator anIt = anAttiributes.begin(), aLast = anAttiributes.end(); std::shared_ptr aFPoint; diff --cc src/PartSet/PartSet_Validators.cpp index 85b0dd3ec,f92793f71..0e2ca6f20 --- a/src/PartSet/PartSet_Validators.cpp +++ b/src/PartSet/PartSet_Validators.cpp @@@ -113,54 -110,86 +113,132 @@@ bool PartSet_RigidValidator::isValid(co return (aCount > 0) && (aCount < 2); } -bool PartSet_DifferentObjectsValidator::isValid(const FeaturePtr& theFeature, - const std::list& theArguments, - const ObjectPtr& theObject, - const GeomShapePtr& theShape) const +bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute, + const std::list& theArguments) const { - // Check RefAttr attributes - std::list > anAttrs = - theFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId()); - if (anAttrs.size() > 0) { - std::list >::iterator anAttr = anAttrs.begin(); - for(; anAttr != anAttrs.end(); anAttr++) { - if (*anAttr) { - std::shared_ptr aRef = - std::dynamic_pointer_cast(*anAttr); - // check the object is already presented - if (aRef->isObject() && aRef->object() == theObject) - return false; - } + FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); + + // 1. check whether the object of the attribute is not among the feature attributes + // find the attribute's object + ObjectPtr anObject = GeomValidators_Tools::getObject(theAttribute); + + // check whether the object is not among other feature attributes + if (anObject.get() != NULL) { + // Check RefAttr attributes + std::list > anAttrs = aFeature->data()->attributes(""); + //if (anAttrs.size() > 0) { + std::list >::iterator anIt = anAttrs.begin(); + for(; anIt != anAttrs.end(); anIt++) { + AttributePtr anAttr = *anIt; + // the function parameter attribute should be skipped + if (anAttr.get() == NULL || anAttr->id() == theAttribute->id()) + continue; + ObjectPtr aCurObject = GeomValidators_Tools::getObject(anAttr); + if (aCurObject && aCurObject == anObject) + return false; } } - // Check selection attributes - anAttrs = theFeature->data()->attributes(ModelAPI_AttributeSelection::typeId()); - if (anAttrs.size() > 0) { - std::list >::iterator anAttr = anAttrs.begin(); - for(; anAttr != anAttrs.end(); anAttr++) { - if (*anAttr) { - std::shared_ptr aRef = - std::dynamic_pointer_cast(*anAttr); - // check the object is already presented - if (aRef->isInitialized() && aRef->context() == theObject) { - if (theShape.get() != NULL) { - if (aRef->value()->isEqual(theShape)) - return false; - } else + else { + // 2. collect object referenced by theAttribute and ... + if (featureHasReferences(theAttribute)) { + // 3. check whether the attribute value is not among other feature attributes + std::list > anAttrs = - aFeature->data()->attributes(ModelAPI_AttributeRefAttr::type()); ++ aFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId()); + std::list >::iterator anAttr = anAttrs.begin(); + for(; anAttr != anAttrs.end(); anAttr++) { + if (*anAttr) { + std::shared_ptr aRef = + std::dynamic_pointer_cast(*anAttr); + // check the object is already presented + if (!aRef->isObject() && aRef->attr() == theAttribute) return false; } ++// TODO(nds) v1.0.2 master ++//bool PartSet_DifferentObjectsValidator::isValid(const FeaturePtr& theFeature, ++// const std::list& theArguments, ++// const ObjectPtr& theObject, ++// const GeomShapePtr& theShape) const ++//{ ++// // Check RefAttr attributes ++// std::list > anAttrs = ++// theFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId()); ++// if (anAttrs.size() > 0) { ++// std::list >::iterator anAttr = anAttrs.begin(); ++// for(; anAttr != anAttrs.end(); anAttr++) { ++// if (*anAttr) { ++// std::shared_ptr aRef = ++// std::dynamic_pointer_cast(*anAttr); ++// // check the object is already presented ++// if (aRef->isObject() && aRef->object() == theObject) ++// return false; ++// } ++// } ++// } ++// // Check selection attributes ++// anAttrs = theFeature->data()->attributes(ModelAPI_AttributeSelection::typeId()); ++// if (anAttrs.size() > 0) { ++// std::list >::iterator anAttr = anAttrs.begin(); ++// for(; anAttr != anAttrs.end(); anAttr++) { ++// if (*anAttr) { ++// std::shared_ptr aRef = ++// std::dynamic_pointer_cast(*anAttr); ++// // check the object is already presented ++// if (aRef->isInitialized() && aRef->context() == theObject) { ++// if (theShape.get() != NULL) { ++// if (aRef->value()->isEqual(theShape)) ++// return false; ++// } else ++// return false; ++// } ++// } ++// } ++// } ++// // Check selection attributes ++// anAttrs = theFeature->data()->attributes(ModelAPI_AttributeReference::typeId()); ++// if (anAttrs.size() > 0) { ++// std::list >::iterator anAttr = anAttrs.begin(); ++// for(; anAttr != anAttrs.end(); anAttr++) { ++// if (*anAttr) { ++// std::shared_ptr aRef = ++// std::dynamic_pointer_cast(*anAttr); ++// // check the object is already presented ++// if (aRef->isInitialized() && aRef->value() == theObject) ++// return false; ++// ======= end of todo } - } - } - // Check selection attributes - anAttrs = theFeature->data()->attributes(ModelAPI_AttributeReference::typeId()); - if (anAttrs.size() > 0) { - std::list >::iterator anAttr = anAttrs.begin(); - for(; anAttr != anAttrs.end(); anAttr++) { - if (*anAttr) { - std::shared_ptr aRef = - std::dynamic_pointer_cast(*anAttr); - // check the object is already presented - if (aRef->isInitialized() && aRef->value() == theObject) - return false; - } + return true; } } return true; } -bool PartSet_DifferentObjectsValidator::isValid(const FeaturePtr& theFeature, - const std::list& theArguments, - const AttributePtr& theAttribute) const -{ - if (PartSet_DifferentObjectsValidator::isValid(theAttribute, theArguments)) { - std::list > anAttrs = - theFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId()); - std::list >::iterator anAttr = anAttrs.begin(); - for(; anAttr != anAttrs.end(); anAttr++) { - if (*anAttr) { - std::shared_ptr aRef = - std::dynamic_pointer_cast(*anAttr); - // check the object is already presented - if (!aRef->isObject() && aRef->attr() == theAttribute) - return false; - } - } - return true; - } - return false; -} - -bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute, - const std::list& theArguments) const +bool PartSet_DifferentObjectsValidator::featureHasReferences(const AttributePtr& theAttribute) const ++// TODO(nds) v1.0.2 master ++//bool PartSet_DifferentObjectsValidator::isValid(const FeaturePtr& theFeature, ++// const std::list& theArguments, ++// const AttributePtr& theAttribute) const ++//{ ++// if (PartSet_DifferentObjectsValidator::isValid(theAttribute, theArguments)) { ++// std::list > anAttrs = ++// theFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId()); ++// std::list >::iterator anAttr = anAttrs.begin(); ++// for(; anAttr != anAttrs.end(); anAttr++) { ++// if (*anAttr) { ++// std::shared_ptr aRef = ++// std::dynamic_pointer_cast(*anAttr); ++// // check the object is already presented ++// if (!aRef->isObject() && aRef->attr() == theAttribute) ++// return false; ++// } ++// } ++// return true; ++// } ++// return false; ++//} ++// ++//bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute, ++// const std::list& theArguments) const ++// ======= end of todo { std::list > > allRefs; if (theAttribute->owner().get() && theAttribute->owner()->data().get()) @@@ -190,44 -219,8 +268,44 @@@ return true; } -bool PartSet_SketchValidator::isValid(const ObjectPtr theObject) const +bool PartSet_SketchEntityValidator::isValid(const AttributePtr& theAttribute, + const std::list& theArguments) const { - FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); - return aFeature->getKind() == SketchPlugin_Sketch::ID(); + bool isSketchEntities = true; + std::set anEntityKinds; + std::list::const_iterator anIt = theArguments.begin(), aLast = theArguments.end(); + for (; anIt != aLast; anIt++) { + anEntityKinds.insert(*anIt); + } + + std::string anAttributeType = theAttribute->attributeType(); - if (anAttributeType == ModelAPI_AttributeSelectionList::type()) { ++ if (anAttributeType == ModelAPI_AttributeSelectionList::typeId()) { + AttributeSelectionListPtr aSelectionListAttr = + std::dynamic_pointer_cast(theAttribute); + // it filters only selection list attributes + std::string aType = aSelectionListAttr->selectionType().c_str(); + // all context objects should be sketch entities + int aSize = aSelectionListAttr->size(); + for (int i = 0; i < aSelectionListAttr->size() && isSketchEntities; i++) { + AttributeSelectionPtr aSelectAttr = aSelectionListAttr->value(i); + ObjectPtr anObject = aSelectAttr->context(); + FeaturePtr aFeature = ModelAPI_Feature::feature(anObject); + isSketchEntities = anEntityKinds.find(aFeature->getKind()) != anEntityKinds.end(); + } + } - if (anAttributeType == ModelAPI_AttributeRefAttr::type()) { ++ if (anAttributeType == ModelAPI_AttributeRefAttr::typeId()) { + std::shared_ptr aRef = + std::dynamic_pointer_cast(theAttribute); + isSketchEntities = false; + if (aRef->isObject()) { + ObjectPtr anObject = aRef->object(); + if (anObject.get() != NULL) { + FeaturePtr aFeature = ModelAPI_Feature::feature(anObject); + if (aFeature.get() != NULL) + isSketchEntities = anEntityKinds.find(aFeature->getKind()) != anEntityKinds.end(); + } + } + } + + return isSketchEntities; } diff --cc src/PartSet/PartSet_Validators.h index 389cc4fa2,6c3fc1897..02e73de5f --- a/src/PartSet/PartSet_Validators.h +++ b/src/PartSet/PartSet_Validators.h @@@ -69,9 -70,24 +69,25 @@@ class PartSet_RigidValidator : public M * \ingroup Validators * A validator which checks that objects selected for feature attributes are different (not the same) */ -class PartSet_DifferentObjectsValidator : public ModelAPI_RefAttrValidator +class PartSet_DifferentObjectsValidator : public ModelAPI_AttributeValidator { public: - /// Returns True if the feature is valid - /// \param theFeature a feature to check - /// \param theArguments a list of arguments (names of attributes to check) - /// \param theObject a selected object - /// \param theShape a selected sub-shape - virtual bool isValid(const FeaturePtr& theFeature, const std::list& theArguments, - const ObjectPtr& theObject, const GeomShapePtr& theShape) const; - - //! Returns true if the attribute is good for the feature attribute - //! \param theFeature a feature to check - //! \param theArguments a list of arguments (names of attributes to check) - //! \param theAttribute an attribute - virtual bool isValid(const FeaturePtr& theFeature, const std::list& theArguments, - const AttributePtr& theAttribute) const; - ++// TODO(nds) v1.0.2 master ++// /// Returns True if the feature is valid ++// /// \param theFeature a feature to check ++// /// \param theArguments a list of arguments (names of attributes to check) ++// /// \param theObject a selected object ++// /// \param theShape a selected sub-shape ++// virtual bool isValid(const FeaturePtr& theFeature, const std::list& theArguments, ++// const ObjectPtr& theObject, const GeomShapePtr& theShape) const; ++// ++// //! Returns true if the attribute is good for the feature attribute ++// //! \param theFeature a feature to check ++// //! \param theArguments a list of arguments (names of attributes to check) ++// //! \param theAttribute an attribute ++// virtual bool isValid(const FeaturePtr& theFeature, const std::list& theArguments, ++// const AttributePtr& theAttribute) const; ++ // ======= end of todo //! Returns true if the attribute is good for the feature attribute //! \param theAttribute an attribute //! \param theArguments a list of arguments (names of attributes to check) @@@ -92,16 -97,15 +108,16 @@@ protected /** * \ingroup Validators -* A Validator which validates tha selected object is a Sketch +* A validator which checks that objects selected for feature attributes are different (not the same) */ -class PartSet_SketchValidator : public ModelAPI_ResultValidator +class PartSet_SketchEntityValidator : public ModelAPI_AttributeValidator { public: - /// Returns True if the given object is a sketch - /// \param theObject an object - virtual bool isValid(const ObjectPtr theObject) const; + //! Returns true if the attribute is good for the feature attribute + //! \param theAttribute an attribute + //! \param theArguments a list of arguments (names of attributes to check) + virtual bool isValid(const AttributePtr& theAttribute, + const std::list& theArguments) const; }; - #endif - + #endif diff --cc src/PartSet/PartSet_WidgetShapeSelector.cpp index 578e1cdf9,d0b1f8bc1..98c25d47b --- a/src/PartSet/PartSet_WidgetShapeSelector.cpp +++ b/src/PartSet/PartSet_WidgetShapeSelector.cpp @@@ -77,52 -63,84 +77,86 @@@ bool PartSet_WidgetShapeSelector::setOb } //******************************************************************** -bool PartSet_WidgetShapeSelector::isValid(ObjectPtr theObj, std::shared_ptr theShape) +void PartSet_WidgetShapeSelector::storeAttributeValue() { - // the method is redefined to analize the selected shape in validators - SessionPtr aMgr = ModelAPI_Session::get(); - ModelAPI_ValidatorsFactory* aFactory = aMgr->validators(); - std::list aValidators; - std::list > anArguments; - aFactory->validators(parentID(), attributeID(), aValidators, anArguments); + /// this is a temporary code, will be removed when master is merged to this branch + /*XGUI_ModuleConnector* aConnector = dynamic_cast(myWorkshop); + XGUI_Workshop* aWorkshop = aConnector->workshop(); + aWorkshop->displayer()->enableUpdateViewer(false); + */ + ModuleBase_WidgetShapeSelector::storeAttributeValue(); +} - // Check the type of selected object - std::list::iterator aValidator = aValidators.begin(); - bool isValid = true; - for (; aValidator != aValidators.end(); aValidator++) { - const ModelAPI_ResultValidator* aResValidator = - dynamic_cast(*aValidator); - if (aResValidator) { - isValid = false; - if (aResValidator->isValid(theObj)) { - isValid = true; - break; - } - } - } - if (!isValid) - return false; +//******************************************************************** +void PartSet_WidgetShapeSelector::restoreAttributeValue(const bool theValid) +{ + ModuleBase_WidgetShapeSelector::restoreAttributeValue(theValid); + /// this is a temporary code, will be removed when master is merged to this branch + /// after merge, the external edge should be removed always, without flag checking + if (!theValid) + removeExternal(); + /* + XGUI_ModuleConnector* aConnector = dynamic_cast(myWorkshop); + XGUI_Workshop* aWorkshop = aConnector->workshop(); + aWorkshop->displayer()->enableUpdateViewer(false);//->erase(myExternalObject); + aWorkshop->displayer()->enableUpdateViewer(true);*/ +} - // Check the acceptability of the object and shape as validator attribute - AttributePtr aPntAttr; - DataPtr aData = myFeature->data(); - if (theShape.get() != NULL) { - AttributePtr aAttr = aData->attribute(attributeID()); - AttributeRefAttrPtr aRefAttr = - std::dynamic_pointer_cast(aAttr); - if (aRefAttr) { - TopoDS_Shape aShape = theShape->impl(); - aPntAttr = PartSet_Tools::findAttributeBy2dPoint(theObj, aShape, mySketch); - } - } - // Check the acceptability of the object as attribute - aValidator = aValidators.begin(); - std::list >::iterator aArgs = anArguments.begin(); - for (; aValidator != aValidators.end(); aValidator++, aArgs++) { - const ModelAPI_RefAttrValidator* aAttrValidator = - dynamic_cast(*aValidator); - if (aAttrValidator) { - if (aPntAttr.get() != NULL) - { - if (!aAttrValidator->isValid(myFeature, *aArgs, aPntAttr)) { - return false; - } - } - else - { - if (!aAttrValidator->isValid(myFeature, *aArgs, theObj, theShape)) { - return false; - } - } - } +//******************************************************************** +void PartSet_WidgetShapeSelector::createExternal(ObjectPtr theSelectedObject, + GeomShapePtr theShape) +{ + ObjectPtr aObj = PartSet_Tools::createFixedObjectByExternal(theShape->impl(), + theSelectedObject, mySketch); + if (aObj != myExternalObject) { + removeExternal(); + myExternalObject = aObj; ++// TODO(nds) v1.0.2 master ++// // Check the acceptability of the object and shape as validator attribute ++// AttributePtr aPntAttr; ++// DataPtr aData = myFeature->data(); ++// if (theShape.get() != NULL) { ++// AttributePtr aAttr = aData->attribute(attributeID()); ++// AttributeRefAttrPtr aRefAttr = ++// std::dynamic_pointer_cast(aAttr); ++// if (aRefAttr) { ++// TopoDS_Shape aShape = theShape->impl(); ++// aPntAttr = PartSet_Tools::findAttributeBy2dPoint(theObj, aShape, mySketch); ++// } ++// } ++// // Check the acceptability of the object as attribute ++// aValidator = aValidators.begin(); ++// std::list >::iterator aArgs = anArguments.begin(); ++// for (; aValidator != aValidators.end(); aValidator++, aArgs++) { ++// const ModelAPI_RefAttrValidator* aAttrValidator = ++// dynamic_cast(*aValidator); ++// if (aAttrValidator) { ++// if (aPntAttr.get() != NULL) ++// { ++// if (!aAttrValidator->isValid(myFeature, *aArgs, aPntAttr)) { ++// return false; ++// } ++// } ++// else ++// { ++// if (!aAttrValidator->isValid(myFeature, *aArgs, theObj, theShape)) { ++// return false; ++// } ++// } ++// } ++// ======= end of todo } - return true; } -//********************************************* -bool PartSet_WidgetConstraintShapeSelector::storeValue() const +//******************************************************************** +void PartSet_WidgetShapeSelector::removeExternal() { - FeaturePtr aFeature = ModelAPI_Feature::feature(mySelectedObject); - if (aFeature) { - std::shared_ptr aSPFeature = - std::dynamic_pointer_cast(aFeature); - if ((!aSPFeature) && (!myShape->isNull())) { - ObjectPtr aObj = PartSet_Tools::createFixedObjectByEdge(myShape->impl(), - mySelectedObject, mySketch); - if (aObj) { - PartSet_WidgetConstraintShapeSelector* that = (PartSet_WidgetConstraintShapeSelector*) this; - that->mySelectedObject = aObj; - } else - return false; + if (myExternalObject.get()) { + DocumentPtr aDoc = myExternalObject->document(); + FeaturePtr aFeature = ModelAPI_Feature::feature(myExternalObject); + if (aFeature.get() != NULL) { + aDoc->removeFeature(aFeature); } + myExternalObject = NULL; } - return ModuleBase_WidgetShapeSelector::storeValue(); } diff --cc src/SketchPlugin/CMakeLists.txt index 22ce7d27e,9d14f6b4c..d6a7d77ac --- a/src/SketchPlugin/CMakeLists.txt +++ b/src/SketchPlugin/CMakeLists.txt @@@ -63,9 -49,8 +63,10 @@@ SET(PROJECT_LIBRARIE Config GeomAPI GeomAlgoAPI + GeomValidators ModelAPI + SketcherPrs + GeomDataAPI ${CAS_KERNEL} ${CAS_SHAPE} ) diff --cc src/SketchPlugin/SketchPlugin_Arc.cpp index 27e3512ba,629505797..026266a30 --- a/src/SketchPlugin/SketchPlugin_Arc.cpp +++ b/src/SketchPlugin/SketchPlugin_Arc.cpp @@@ -31,12 -31,10 +31,12 @@@ SketchPlugin_Arc::SketchPlugin_Arc( void SketchPlugin_Arc::initAttributes() { + SketchPlugin_SketchEntity::initAttributes(); + - data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::type()); - data()->addAttribute(START_ID(), GeomDataAPI_Point2D::type()); - data()->addAttribute(END_ID(), GeomDataAPI_Point2D::type()); - data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::type()); + data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(START_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(END_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID()); } diff --cc src/SketchPlugin/SketchPlugin_Circle.cpp index 934f40a04,c92948bd2..623b6c625 --- a/src/SketchPlugin/SketchPlugin_Circle.cpp +++ b/src/SketchPlugin/SketchPlugin_Circle.cpp @@@ -28,11 -28,9 +28,11 @@@ SketchPlugin_Circle::SketchPlugin_Circl void SketchPlugin_Circle::initAttributes() { + SketchPlugin_SketchEntity::initAttributes(); + - data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::type()); - data()->addAttribute(RADIUS_ID(), ModelAPI_AttributeDouble::type()); - data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::type()); + data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(RADIUS_ID(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID()); } diff --cc src/SketchPlugin/SketchPlugin_ConstraintCoincidence.cpp index 358158325,02cf66ca0..a78e1b4ef --- a/src/SketchPlugin/SketchPlugin_ConstraintCoincidence.cpp +++ b/src/SketchPlugin/SketchPlugin_ConstraintCoincidence.cpp @@@ -28,15 -24,3 +28,15 @@@ void SketchPlugin_ConstraintCoincidence { } +AISObjectPtr SketchPlugin_ConstraintCoincidence::getAISObject(AISObjectPtr thePrevious) +{ + if (!sketch()) + return thePrevious; + + AISObjectPtr anAIS = thePrevious; + if (!anAIS) { + anAIS = SketcherPrs_Factory::coincidentConstraint(this, sketch()->coordinatePlane()); + anAIS->setColor(0, 0, 255); + } + return anAIS; - } ++} diff --cc src/SketchPlugin/SketchPlugin_ConstraintEqual.cpp index efd034fea,000000000..1b80c0c6b mode 100644,000000..100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintEqual.cpp +++ b/src/SketchPlugin/SketchPlugin_ConstraintEqual.cpp @@@ -1,46 -1,0 +1,46 @@@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: SketchPlugin_ConstraintEqual.cpp +// Created: 16 Mar 2015 +// Author: Artem ZHIDKOV + +#include "SketchPlugin_ConstraintEqual.h" + +#include +#include +#include + +#include +#include + +#include + +#include + +SketchPlugin_ConstraintEqual::SketchPlugin_ConstraintEqual() +{ +} + +void SketchPlugin_ConstraintEqual::initAttributes() +{ - data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::type()); - data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::type()); ++ data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId()); ++ data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId()); +} + +void SketchPlugin_ConstraintEqual::execute() +{ +} + +AISObjectPtr SketchPlugin_ConstraintEqual::getAISObject(AISObjectPtr thePrevious) +{ + if (!sketch()) + return thePrevious; + + AISObjectPtr anAIS = thePrevious; + if (!anAIS) { + anAIS = SketcherPrs_Factory::equalConstraint(this, sketch()->coordinatePlane()); + } + return anAIS; +} + + diff --cc src/SketchPlugin/SketchPlugin_ConstraintFillet.cpp index 4b7b4cff7,000000000..22bc2541a mode 100644,000000..100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintFillet.cpp +++ b/src/SketchPlugin/SketchPlugin_ConstraintFillet.cpp @@@ -1,91 -1,0 +1,91 @@@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: SketchPlugin_ConstraintFillet.cpp +// Created: 19 Mar 2015 +// Author: Artem ZHIDKOV + +#include "SketchPlugin_ConstraintFillet.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +SketchPlugin_ConstraintFillet::SketchPlugin_ConstraintFillet() +{ +} + +void SketchPlugin_ConstraintFillet::initAttributes() +{ - data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeDouble::type()); - data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::type()); - data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::type()); - data()->addAttribute(SketchPlugin_Constraint::ENTITY_C(), ModelAPI_AttributeRefList::type()); ++ data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeDouble::typeId()); ++ data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId()); ++ data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId()); ++ data()->addAttribute(SketchPlugin_Constraint::ENTITY_C(), ModelAPI_AttributeRefList::typeId()); + // initialize attribute not applicable for user + data()->attribute(SketchPlugin_Constraint::ENTITY_C())->setInitialized(); +} + +void SketchPlugin_ConstraintFillet::execute() +{ + std::shared_ptr aData = data(); + // Check the base objects are initialized + AttributeRefAttrPtr aBaseA = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Constraint::ENTITY_A())); + AttributeRefAttrPtr aBaseB = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Constraint::ENTITY_B())); + if (!aBaseA->isInitialized() || !aBaseB->isInitialized() || + !aBaseA->isObject() || !aBaseB->isObject()) + return; + // Check the fillet shapes is not initialized yet + AttributeRefListPtr aRefListOfFillet = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Constraint::ENTITY_C())); + if (aRefListOfFillet->size() > 0) + return; + // Obtain features for the base objects + FeaturePtr aFeatureA, aFeatureB; + ResultConstructionPtr aRC = + std::dynamic_pointer_cast(aBaseA->object()); + if (aRC) aFeatureA = aRC->document()->feature(aRC); + aRC = std::dynamic_pointer_cast(aBaseB->object()); + if (aRC) aFeatureB = aRC->document()->feature(aRC); + if (!aFeatureA || !aFeatureB) + return; + + // Create list of objects composing a fillet + // copy aFeatureA + FeaturePtr aNewFeature = sketch()->addFeature(aFeatureA->getKind()); + aFeatureA->data()->copyTo(aNewFeature->data()); + aRefListOfFillet->append(aNewFeature); + // copy aFeatureB + aNewFeature = sketch()->addFeature(aFeatureB->getKind()); + aFeatureB->data()->copyTo(aNewFeature->data()); + aRefListOfFillet->append(aNewFeature); + // create filleting arc + aNewFeature = sketch()->addFeature(SketchPlugin_Arc::ID()); + aNewFeature->attribute(SketchPlugin_Arc::CENTER_ID())->setInitialized(); + aNewFeature->attribute(SketchPlugin_Arc::START_ID())->setInitialized(); + aNewFeature->attribute(SketchPlugin_Arc::END_ID())->setInitialized(); + aRefListOfFillet->append(aNewFeature); + aRefListOfFillet->setInitialized(); +} + +AISObjectPtr SketchPlugin_ConstraintFillet::getAISObject(AISObjectPtr thePrevious) +{ + if (!sketch()) + return thePrevious; + + AISObjectPtr anAIS = thePrevious; + /// TODO: Equal constraint presentation should be put here + return anAIS; +} + + diff --cc src/SketchPlugin/SketchPlugin_ConstraintHorizontal.cpp index 175715d28,000000000..9fe7e5188 mode 100644,000000..100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintHorizontal.cpp +++ b/src/SketchPlugin/SketchPlugin_ConstraintHorizontal.cpp @@@ -1,45 -1,0 +1,45 @@@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: SketchPlugin_ConstraintHorizontal.cpp +// Created: 16 Mar 2015 +// Author: Artem ZHIDKOV + +#include "SketchPlugin_ConstraintHorizontal.h" + +#include +#include +#include + +#include +#include + +#include + +#include + +SketchPlugin_ConstraintHorizontal::SketchPlugin_ConstraintHorizontal() +{ +} + +void SketchPlugin_ConstraintHorizontal::initAttributes() +{ - data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::type()); ++ data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId()); +} + +void SketchPlugin_ConstraintHorizontal::execute() +{ +} + +AISObjectPtr SketchPlugin_ConstraintHorizontal::getAISObject(AISObjectPtr thePrevious) +{ + if (!sketch()) + return thePrevious; + + AISObjectPtr anAIS = thePrevious; + if (!anAIS) { + anAIS = SketcherPrs_Factory::horisontalConstraint(this, sketch()->coordinatePlane()); + } + return anAIS; +} + + diff --cc src/SketchPlugin/SketchPlugin_ConstraintMirror.cpp index 8479e107d,000000000..f0da5515f mode 100644,000000..100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintMirror.cpp +++ b/src/SketchPlugin/SketchPlugin_ConstraintMirror.cpp @@@ -1,113 -1,0 +1,113 @@@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: SketchPlugin_ConstraintMirror.cpp +// Created: 17 Mar 2015 +// Author: Artem ZHIDKOV + +#include "SketchPlugin_ConstraintMirror.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +SketchPlugin_ConstraintMirror::SketchPlugin_ConstraintMirror() +{ +} + +void SketchPlugin_ConstraintMirror::initAttributes() +{ - data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::type()); - data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefList::type()); - data()->addAttribute(SketchPlugin_Constraint::ENTITY_C(), ModelAPI_AttributeRefList::type()); ++ data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId()); ++ data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefList::typeId()); ++ data()->addAttribute(SketchPlugin_Constraint::ENTITY_C(), ModelAPI_AttributeRefList::typeId()); +} + +void SketchPlugin_ConstraintMirror::execute() +{ + // Objects to be mirrored will be created here + std::shared_ptr aData = data(); + AttributeRefListPtr aRefListOfShapes = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Constraint::ENTITY_B())); + if (!aRefListOfShapes->isInitialized()) + return ; + + AttributeRefListPtr aRefListOfMirrored = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Constraint::ENTITY_C())); + // Check consistency of initial list and mirrored list + std::list anInitialList = aRefListOfShapes->list(); + std::list aMirroredList = aRefListOfMirrored->list(); + std::list::iterator anInitIter = anInitialList.begin(); + std::list::iterator aMirrorIter = aMirroredList.begin(); + int indFirstWrong = 0; // index of element starts difference in the lists + std::set anInvalidInd; // list of indices of removed features + std::shared_ptr aFeatureIn, aFeatureOut; + for ( ; anInitIter != anInitialList.end(); anInitIter++, indFirstWrong++) { + // Add features and store indices of objects to remove + aFeatureIn = std::dynamic_pointer_cast(*anInitIter); + aFeatureOut = aMirrorIter != aMirroredList.end() ? + std::dynamic_pointer_cast(*aMirrorIter) : + std::shared_ptr(); + if (!aFeatureIn) { + if (aFeatureOut) + break; // the lists are inconsistent + continue; + } + if (!aFeatureOut) { + if (aMirrorIter != aMirroredList.end()) + break; // the lists are inconsistent + // There is no mirrored object yet, create it + FeaturePtr aNewFeature = sketch()->addFeature(aFeatureIn->getKind()); + aFeatureIn->data()->copyTo(aNewFeature->data()); + aRefListOfMirrored->append(aNewFeature); + continue; + } + if (aFeatureIn->getKind() != aFeatureOut->getKind()) + break; // the lists are inconsistent + if (!aFeatureIn->data()->isValid()) { + // initial feature was removed, delete it from lists + anInvalidInd.insert(indFirstWrong); + } + aMirrorIter++; + } + // Remove from the list objects already deleted before + std::set::reverse_iterator anIt = anInvalidInd.rbegin(); + for ( ; anIt != anInvalidInd.rend(); anIt++) { + if (*anIt < indFirstWrong) indFirstWrong--; + aRefListOfShapes->remove(aRefListOfShapes->object(*anIt)); + aRefListOfMirrored->remove(aRefListOfMirrored->object(*anIt)); + } + // If the lists inconsistent, remove all objects from mirrored list starting from indFirstWrong + if (anInitIter != anInitialList.end()) { + while (aRefListOfMirrored->size() > indFirstWrong) + aRefListOfMirrored->remove(aRefListOfMirrored->object(indFirstWrong)); + // Create mirrored features instead of removed + anInitialList = aRefListOfShapes->list(); + anInitIter = anInitialList.begin(); + for (int i = 0; i < indFirstWrong; i++) anInitIter++; + for ( ; anInitIter != anInitialList.end(); anInitIter++) { + aFeatureIn = std::dynamic_pointer_cast(*anInitIter); + FeaturePtr aNewFeature = aFeatureIn->document()->addFeature(aFeatureIn->getKind()); + aRefListOfMirrored->append(aNewFeature); + } + } +} + +AISObjectPtr SketchPlugin_ConstraintMirror::getAISObject(AISObjectPtr thePrevious) +{ + if (!sketch()) + return thePrevious; + + AISObjectPtr anAIS = thePrevious; + /// TODO: Equal constraint presentation should be put here + return anAIS; +} + + diff --cc src/SketchPlugin/SketchPlugin_ConstraintParallel.cpp index 29a7f0a25,f22260247..42ce74b78 --- a/src/SketchPlugin/SketchPlugin_ConstraintParallel.cpp +++ b/src/SketchPlugin/SketchPlugin_ConstraintParallel.cpp @@@ -29,9 -25,9 +29,9 @@@ SketchPlugin_ConstraintParallel::Sketch void SketchPlugin_ConstraintParallel::initAttributes() { - data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::type()); - data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::type()); - //data()->addAttribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT(), GeomDataAPI_Point2D::type()); + data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId()); + data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId()); - data()->addAttribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT(), GeomDataAPI_Point2D::typeId()); ++ //data()->addAttribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT(), GeomDataAPI_Point2D::typeId()); } void SketchPlugin_ConstraintParallel::execute() diff --cc src/SketchPlugin/SketchPlugin_ConstraintTangent.cpp index c979d8939,000000000..9d7256c18 mode 100644,000000..100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintTangent.cpp +++ b/src/SketchPlugin/SketchPlugin_ConstraintTangent.cpp @@@ -1,46 -1,0 +1,46 @@@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: SketchPlugin_ConstraintTangent.cpp +// Created: 16 Mar 2015 +// Author: Artem ZHIDKOV + +#include "SketchPlugin_ConstraintTangent.h" + +#include +#include +#include + +#include +#include + +#include + +#include + +SketchPlugin_ConstraintTangent::SketchPlugin_ConstraintTangent() +{ +} + +void SketchPlugin_ConstraintTangent::initAttributes() +{ - data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::type()); - data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::type()); ++ data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId()); ++ data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId()); +} + +void SketchPlugin_ConstraintTangent::execute() +{ +} + +AISObjectPtr SketchPlugin_ConstraintTangent::getAISObject(AISObjectPtr thePrevious) +{ + if (!sketch()) + return thePrevious; + + AISObjectPtr anAIS = thePrevious; + if (!anAIS) { + anAIS = SketcherPrs_Factory::tangentConstraint(this, sketch()->coordinatePlane()); + } + return anAIS; +} + + diff --cc src/SketchPlugin/SketchPlugin_ConstraintVertical.cpp index bb824715a,000000000..d5865e6ab mode 100644,000000..100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintVertical.cpp +++ b/src/SketchPlugin/SketchPlugin_ConstraintVertical.cpp @@@ -1,45 -1,0 +1,45 @@@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: SketchPlugin_ConstraintVertical.cpp +// Created: 16 Mar 2015 +// Author: Artem ZHIDKOV + +#include "SketchPlugin_ConstraintVertical.h" + +#include +#include +#include + +#include +#include + +#include + +#include + +SketchPlugin_ConstraintVertical::SketchPlugin_ConstraintVertical() +{ +} + +void SketchPlugin_ConstraintVertical::initAttributes() +{ - data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::type()); ++ data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId()); +} + +void SketchPlugin_ConstraintVertical::execute() +{ +} + +AISObjectPtr SketchPlugin_ConstraintVertical::getAISObject(AISObjectPtr thePrevious) +{ + if (!sketch()) + return thePrevious; + + AISObjectPtr anAIS = thePrevious; + if (!anAIS) { + anAIS = SketcherPrs_Factory::verticalConstraint(this, sketch()->coordinatePlane()); + } + return anAIS; +} + + diff --cc src/SketchPlugin/SketchPlugin_Line.cpp index ea5d0a42b,2525b642e..ed07e4079 --- a/src/SketchPlugin/SketchPlugin_Line.cpp +++ b/src/SketchPlugin/SketchPlugin_Line.cpp @@@ -28,11 -27,9 +28,11 @@@ SketchPlugin_Line::SketchPlugin_Line( void SketchPlugin_Line::initAttributes() { + SketchPlugin_SketchEntity::initAttributes(); + - data()->addAttribute(START_ID(), GeomDataAPI_Point2D::type()); - data()->addAttribute(END_ID(), GeomDataAPI_Point2D::type()); - data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::type()); + data()->addAttribute(START_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(END_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID()); } diff --cc src/SketchPlugin/SketchPlugin_Plugin.cpp index 04347759e,21f74bc63..35ff48c6a --- a/src/SketchPlugin/SketchPlugin_Plugin.cpp +++ b/src/SketchPlugin/SketchPlugin_Plugin.cpp @@@ -53,9 -45,9 +53,7 @@@ SketchPlugin_Plugin::SketchPlugin_Plugi new SketchPlugin_DistanceAttrValidator); //aFactory->registerValidator("SketchPlugin_DifferentObjects", // new SketchPlugin_DifferentObjectsValidator); - - aFactory->registerValidator("SketchPlugin_ShapeValidator", - new SketchPlugin_ShapeValidator); - aFactory->registerValidator("SketchPlugin_ResultPoint", new SketchPlugin_ResultPointValidator); - aFactory->registerValidator("SketchPlugin_ResultLine", new SketchPlugin_ResultLineValidator); - aFactory->registerValidator("SketchPlugin_ResultArc", new SketchPlugin_ResultArcValidator); ++ aFactory->registerValidator("SketchPlugin_ShapeValidator", new SketchPlugin_ShapeValidator); // register this plugin ModelAPI_Session::get()->registerPlugin(this); diff --cc src/SketchPlugin/SketchPlugin_Point.cpp index 036fde19d,cb2cad6de..6fe1e2cfa --- a/src/SketchPlugin/SketchPlugin_Point.cpp +++ b/src/SketchPlugin/SketchPlugin_Point.cpp @@@ -27,10 -26,8 +27,10 @@@ SketchPlugin_Point::SketchPlugin_Point( void SketchPlugin_Point::initAttributes() { + SketchPlugin_SketchEntity::initAttributes(); + - data()->addAttribute(SketchPlugin_Point::COORD_ID(), GeomDataAPI_Point2D::type()); - data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::type()); + data()->addAttribute(SketchPlugin_Point::COORD_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID()); } diff --cc src/SketchPlugin/SketchPlugin_Sketch.cpp index b57c1e3ba,b85b3d209..377fc0bed --- a/src/SketchPlugin/SketchPlugin_Sketch.cpp +++ b/src/SketchPlugin/SketchPlugin_Sketch.cpp @@@ -44,14 -43,15 +44,14 @@@ SketchPlugin_Sketch::SketchPlugin_Sketc void SketchPlugin_Sketch::initAttributes() { - data()->addAttribute(SketchPlugin_Sketch::ORIGIN_ID(), GeomDataAPI_Point::type()); - data()->addAttribute(SketchPlugin_Sketch::DIRX_ID(), GeomDataAPI_Dir::type()); - data()->addAttribute(SketchPlugin_Sketch::NORM_ID(), GeomDataAPI_Dir::type()); - data()->addAttribute(SketchPlugin_Sketch::FEATURES_ID(), ModelAPI_AttributeRefList::type()); + data()->addAttribute(SketchPlugin_Sketch::ORIGIN_ID(), GeomDataAPI_Point::typeId()); + data()->addAttribute(SketchPlugin_Sketch::DIRX_ID(), GeomDataAPI_Dir::typeId()); - data()->addAttribute(SketchPlugin_Sketch::DIRY_ID(), GeomDataAPI_Dir::typeId()); + data()->addAttribute(SketchPlugin_Sketch::NORM_ID(), GeomDataAPI_Dir::typeId()); + data()->addAttribute(SketchPlugin_Sketch::FEATURES_ID(), ModelAPI_AttributeRefList::typeId()); // the selected face, base for the sketcher plane, not obligatory - data()->addAttribute(SketchPlugin_SketchEntity::EXTERNAL_ID(), ModelAPI_AttributeSelection::type()); - data()->addAttribute(SketchPlugin_Feature::EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId()); ++ data()->addAttribute(SketchPlugin_SketchEntity::EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId()); ModelAPI_Session::get()->validators()->registerNotObligatory( - getKind(), SketchPlugin_Feature::EXTERNAL_ID()); + getKind(), SketchPlugin_SketchEntity::EXTERNAL_ID()); } void SketchPlugin_Sketch::execute() diff --cc src/SketchPlugin/SketchPlugin_SketchEntity.cpp index 39cc06a67,000000000..9e95496ef mode 100644,000000..100644 --- a/src/SketchPlugin/SketchPlugin_SketchEntity.cpp +++ b/src/SketchPlugin/SketchPlugin_SketchEntity.cpp @@@ -1,18 -1,0 +1,18 @@@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +#include "SketchPlugin_SketchEntity.h" + +#include +#include +#include + +SketchPlugin_SketchEntity::SketchPlugin_SketchEntity() +: SketchPlugin_Feature() +{ +} + +void SketchPlugin_SketchEntity::initAttributes() +{ - data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::type()); ++ data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), AUXILIARY_ID()); +} diff --cc src/SketchPlugin/SketchPlugin_Validators.cpp index 32a0b30b5,43186329b..ca7df854d --- a/src/SketchPlugin/SketchPlugin_Validators.cpp +++ b/src/SketchPlugin/SketchPlugin_Validators.cpp @@@ -11,52 -11,111 +11,138 @@@ #include #include #include + +#include + #include -bool SketchPlugin_DistanceAttrValidator::isValid(const FeaturePtr& theFeature, - const std::list& theArguments, - const ObjectPtr& theObject, - const GeomShapePtr& theShape) const +bool SketchPlugin_DistanceAttrValidator::isValid( + const AttributePtr& theAttribute, const std::list& theArguments ) const ++//bool SketchPlugin_DistanceAttrValidator::isValid(const FeaturePtr& theFeature, ++// const std::list& theArguments, ++// const ObjectPtr& theObject, ++// const GeomShapePtr& theShape) const ++// ======= end of todo master { + // there is a check whether the feature contains a point and a linear edge or two point values std::string aParamA = theArguments.front(); SessionPtr aMgr = ModelAPI_Session::get(); ModelAPI_ValidatorsFactory* aFactory = aMgr->validators(); - const ModelAPI_ResultValidator* anArcValidator = - dynamic_cast(aFactory->validator("SketchPlugin_ResultArc")); - bool anArcValid = anArcValidator->isValid(theObject); - if (anArcValid) + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(theAttribute); + if (!aRefAttr) return false; - - // If the object is not a line then it is accepted - const ModelAPI_ResultValidator* aLineValidator = - dynamic_cast(aFactory->validator("SketchPlugin_ResultLine")); - bool aLineValid = aLineValidator->isValid(theObject); - if (!aLineValid) + bool isObject = aRefAttr->isObject(); + if (!isObject) { + // an attribute is a point. A point value is valid always for the distance return true; + } else { + // 1. check whether the references object is a linear + ObjectPtr anObject = aRefAttr->object(); - // If it is a line then we have to check that first attribute id not a line - std::shared_ptr aPoint = getFeaturePoint(theFeature->data(), aParamA); - if (aPoint) - return true; - return false; -} + const ModelAPI_AttributeValidator* anEdgeValidator = + dynamic_cast(aFactory->validator("GeomValidators_Edge")); + std::list anArguments; + anArguments.push_back("circle"); + bool anEdgeValid = anEdgeValidator->isValid(aRefAttr, anArguments); + // the circle line is not a valid case + if (anEdgeValid) + return false; + + anArguments.clear(); + anArguments.push_back("line"); + anEdgeValid = anEdgeValidator->isValid(aRefAttr, anArguments); + // if the attribute value is not a line, that means it is a vertex. A vertex is always valid + if (!anEdgeValid) + return true; -bool SketchPlugin_DistanceAttrValidator::isValid( - const AttributePtr& theAttribute, const std::list& theArguments ) const -{ - // any point attribute is acceptable for the distance operation - return true; + FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); + // If it is a line then we have to check that first attribute id not a line + std::shared_ptr aPoint = getFeaturePoint(aFeature->data(), aParamA); + if (aPoint) + return true; + } + return false; } ++// TODO(nds) v1.0.2, master ++// return false; ++//} + -bool SketchPlugin_DistanceAttrValidator::isValid(const FeaturePtr& theFeature, - const std::list& theArguments, - const AttributePtr& theAttribute) const -{ - return isValid(theAttribute, theArguments); -} ++//bool SketchPlugin_DistanceAttrValidator::isValid( ++// const AttributePtr& theAttribute, const std::list& theArguments ) const ++//{ ++// // any point attribute is acceptable for the distance operation ++// return true; ++//} ++// ++//bool SketchPlugin_DistanceAttrValidator::isValid(const FeaturePtr& theFeature, ++// const std::list& theArguments, ++// const AttributePtr& theAttribute) const ++//{ ++// return isValid(theAttribute, theArguments); ++//} + ++// commented in v1.0.2, master: + //bool SketchPlugin_DifferentObjectsValidator::isValid(const FeaturePtr& theFeature, + // const std::list& theArguments, + // const ObjectPtr& theObject) const + //{ + // std::list > anAttrs = + // theFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId()); + // std::list >::iterator anAttr = anAttrs.begin(); + // for(; anAttr != anAttrs.end(); anAttr++) { + // if (*anAttr) { + // std::shared_ptr aRef = + // std::dynamic_pointer_cast(*anAttr); + // // check the object is already presented + // if (aRef->isObject() && aRef->object() == theObject) + // return false; + // } + // } + // return true; + //} + + //bool SketchPlugin_DifferentObjectsValidator::isValid( + // const AttributePtr& theAttribute, const std::list& theArguments ) const + //{ + // std::shared_ptr anOrigAttr = + // std::dynamic_pointer_cast(theAttribute); + // if (anOrigAttr && anOrigAttr->isObject()) { + // const ObjectPtr& anObj = theAttribute->owner(); + // const FeaturePtr aFeature = std::dynamic_pointer_cast(anObj); + // + // std::list > anAttrs = + // aFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId()); + // std::list >::iterator anAttr = anAttrs.begin(); + // for(; anAttr != anAttrs.end(); anAttr++) { + // if (*anAttr && *anAttr != theAttribute) { + // std::shared_ptr aRef = + // std::dynamic_pointer_cast(*anAttr); + // // check the object is already presented + // if (aRef->isObject() && aRef->object() == anOrigAttr->object()) + // return false; + // } + // } + // } + // return true; + //} + + //bool SketchPlugin_DifferentObjectsValidator::isValid(const FeaturePtr& theFeature, + // const std::list& theArguments, const AttributePtr& theAttribute) const + //{ + // std::list > anAttrs = + // theFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId()); + // std::list >::iterator anAttr = anAttrs.begin(); + // for(; anAttr != anAttrs.end(); anAttr++) { + // if (*anAttr) { + // std::shared_ptr aRef = + // std::dynamic_pointer_cast(*anAttr); + // // check the object is already presented + // if (!aRef->isObject() && aRef->attr() == theAttribute) + // return false; + // } + // } + // return true; + //} ++// =========== end of todo diff --cc src/SketchPlugin/SketchPlugin_Validators.h index f686d3e6e,88c8d3a48..6259c2bd6 --- a/src/SketchPlugin/SketchPlugin_Validators.h +++ b/src/SketchPlugin/SketchPlugin_Validators.h @@@ -22,8 -22,39 +22,44 @@@ class SketchPlugin_DistanceAttrValidato //! returns true if attribute is valid //! \param theAttribute the checked attribute //! \param theArguments arguments of the attribute - virtual bool isValid(const AttributePtr& theAttribute, + virtual bool isValid(const AttributePtr& theAttribute, const std::list& theArguments) const; - - //! Returns true if object is good for the feature attribute - virtual bool isValid(const FeaturePtr& theFeature, const std::list& theArguments, - const ObjectPtr& theObject, const GeomShapePtr& theShape) const; - - //! Returns true if the attribute is good for the feature attribute - virtual bool isValid(const FeaturePtr& theFeature, const std::list& theArguments, - const AttributePtr& theAttribute) const; }; ++// virtual bool isValid(const AttributePtr& theAttribute, ++// const std::list& theArguments) const; ++// ++// //! Returns true if object is good for the feature attribute ++// virtual bool isValid(const FeaturePtr& theFeature, const std::list& theArguments, ++// const ObjectPtr& theObject, const GeomShapePtr& theShape) const; ++// ++// //! Returns true if the attribute is good for the feature attribute ++// virtual bool isValid(const FeaturePtr& theFeature, const std::list& theArguments, ++// const AttributePtr& theAttribute) const; ++//}; + ++// commented in v1.0.2, master: + /**\class SketchPlugin_DifferentObjectsValidator + * \ingroup Validators + * + * Check that there is no same object was already selected in the feature. + * For an example: to avoid perpendicularity on line and the same line. + */ + // Use PartSet_DifferentObjectsValidator instead + //class SketchPlugin_DifferentObjectsValidator : public ModelAPI_RefAttrValidator + //{ + // public: + // //! returns true if attribute is valid + // //! \param theAttribute the checked attribute + // //! \param theArguments arguments of the attribute + // virtual bool isValid( + // const AttributePtr& theAttribute, const std::list& theArguments) const; + // //! Returns true if object is good for the feature attribute + // virtual bool isValid(const FeaturePtr& theFeature, const std::list& theArguments, + // const ObjectPtr& theObject) const; + // //! Returns true if the attribute is good for the feature attribute + // virtual bool isValid(const FeaturePtr& theFeature, const std::list& theArguments, + // const AttributePtr& theAttribute) const; + //}; ++// ======= end of todo #endif diff --cc src/SketchPlugin/Test/TestConstraintEqual.py index 09f8f076d,000000000..5e99e0512 mode 100644,000000..100644 --- a/src/SketchPlugin/Test/TestConstraintEqual.py +++ b/src/SketchPlugin/Test/TestConstraintEqual.py @@@ -1,120 -1,0 +1,120 @@@ +""" + TestConstraintEqual.py + Unit test of SketchPlugin_ConstraintEqual class + + SketchPlugin_ConstraintEqual + static const std::string MY_CONSTRAINT_EQAUL_ID("SketchConstraintEqual"); - data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::type()); - data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::type()); ++ data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId()); ++ data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId()); + +""" +from GeomDataAPI import * +from ModelAPI import * +import math +#========================================================================= +# Initialization of the test +#========================================================================= + +__updated__ = "2015-03-16" + +aSession = ModelAPI_Session.get() +aDocument = aSession.moduleDocument() +#========================================================================= +# Creation of a sketch +#========================================================================= +aSession.startOperation() +aSketchCommonFeature = aDocument.addFeature("Sketch") +aSketchFeature = modelAPI_CompositeFeature(aSketchCommonFeature) +origin = geomDataAPI_Point(aSketchFeature.attribute("Origin")) +origin.setValue(0, 0, 0) +dirx = geomDataAPI_Dir(aSketchFeature.attribute("DirX")) +dirx.setValue(1, 0, 0) +diry = geomDataAPI_Dir(aSketchFeature.attribute("DirY")) +diry.setValue(0, 1, 0) +norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm")) +norm.setValue(0, 0, 1) +aSession.finishOperation() +#========================================================================= +# Creation of an arc and a circle +#========================================================================= +aSession.startOperation() +aSketchArc = aSketchFeature.addFeature("SketchArc") +anArcCentr = geomDataAPI_Point2D(aSketchArc.attribute("ArcCenter")) +anArcCentr.setValue(10., 10.) +anArcStartPoint = geomDataAPI_Point2D(aSketchArc.attribute("ArcStartPoint")) +anArcStartPoint.setValue(0., 50.) +anArcEndPoint = geomDataAPI_Point2D(aSketchArc.attribute("ArcEndPoint")) +anArcEndPoint.setValue(50., 0.) +aSession.finishOperation() +# Circle +aSession.startOperation() +aSketchCircle = aSketchFeature.addFeature("SketchCircle") +anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter")) +aCircleRadius = aSketchCircle.real("CircleRadius") +anCircleCentr.setValue(-25., -25) +aCircleRadius.setValue(25.) +aSession.finishOperation() +#========================================================================= +# A constraint to make equal radii of arc and circle +#========================================================================= +aSession.startOperation() +aConstraintEqRad = aSketchFeature.addFeature("SketchConstraintEqual") +aRefObjectA = aConstraintEqRad.refattr("ConstraintEntityA") +aRefObjectB = aConstraintEqRad.refattr("ConstraintEntityB") +aResultA = modelAPI_ResultConstruction(aSketchArc.lastResult()) +aResultB = modelAPI_ResultConstruction(aSketchCircle.lastResult()) +assert (aResultA is not None) +assert (aResultB is not None) +aRefObjectA.setObject(aResultA) +aRefObjectB.setObject(aResultB) +aConstraintEqRad.execute() +aSession.finishOperation() +aCircRadius = aCircleRadius.value(); +anArcVecX = anArcStartPoint.x() - anArcCentr.x(); +anArcVecY = anArcStartPoint.y() - anArcCentr.y(); +anArcRadius = math.sqrt(anArcVecX**2 + anArcVecY**2) +assert (math.fabs(aCircRadius - anArcRadius) <= 1.e-10) +#========================================================================= +# Creation of two different lines +#========================================================================= +# First Line +aSession.startOperation() +aSketchLine1 = aSketchFeature.addFeature("SketchLine") +aLine1StartPoint = geomDataAPI_Point2D(aSketchLine1.attribute("StartPoint")) +aLine1EndPoint = geomDataAPI_Point2D(aSketchLine1.attribute("EndPoint")) +aLine1StartPoint.setValue(0., 15.) +aLine1EndPoint.setValue(20., 25.) +aSession.finishOperation() +# Second Line +aSession.startOperation() +aSketchLine2 = aSketchFeature.addFeature("SketchLine") +aLine2StartPoint = geomDataAPI_Point2D(aSketchLine2.attribute("StartPoint")) +aLine2EndPoint = geomDataAPI_Point2D(aSketchLine2.attribute("EndPoint")) +aLine2StartPoint.setValue(0., 0.) +aLine2EndPoint.setValue(-1., 10.) +aSession.finishOperation() +#========================================================================= +# A constraint to make equal lengths of lines +#========================================================================= +aSession.startOperation() +aConstraintEqLen = aSketchFeature.addFeature("SketchConstraintEqual") +aRefObjectA = aConstraintEqLen.refattr("ConstraintEntityA") +aRefObjectB = aConstraintEqLen.refattr("ConstraintEntityB") +aResultA = modelAPI_ResultConstruction(aSketchLine1.firstResult()) +aResultB = modelAPI_ResultConstruction(aSketchLine2.firstResult()) +assert (aResultA is not None) +assert (aResultB is not None) +aRefObjectA.setObject(aResultA) +aRefObjectB.setObject(aResultB) +aConstraintEqLen.execute() +aSession.finishOperation() +aVecX = aLine1StartPoint.x() - aLine1EndPoint.x(); +aVecY = aLine1StartPoint.y() - aLine1EndPoint.y(); +aLine1Len = math.sqrt(anArcVecX * anArcVecX + anArcVecY * anArcVecY) +aVecX = aLine2StartPoint.x() - aLine2EndPoint.x(); +aVecY = aLine2StartPoint.y() - aLine2EndPoint.y(); +aLine2Len = math.sqrt(anArcVecX**2 + anArcVecY**2) +assert (aLine1Len == aLine2Len) +#========================================================================= +# End of test +#========================================================================= diff --cc src/SketchPlugin/Test/TestConstraintHorizontal.py index 337315858,000000000..050c60f24 mode 100644,000000..100644 --- a/src/SketchPlugin/Test/TestConstraintHorizontal.py +++ b/src/SketchPlugin/Test/TestConstraintHorizontal.py @@@ -1,78 -1,0 +1,78 @@@ +""" + TestConstraintHorizontal.py + Unit test of SketchPlugin_ConstraintHorizontal class + + SketchPlugin_ConstraintHorizontal + static const std::string MY_CONSTRAINT_HORIZONTAL_ID("SketchConstraintHorizontal"); - data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::type()); ++ data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId()); + +""" +from GeomDataAPI import * +from ModelAPI import * +#========================================================================= +# Initialization of the test +#========================================================================= + +__updated__ = "2015-03-16" + +aSession = ModelAPI_Session.get() +aDocument = aSession.moduleDocument() +#========================================================================= +# Creation of a sketch +#========================================================================= +aSession.startOperation() +aSketchCommonFeature = aDocument.addFeature("Sketch") +aSketchFeature = modelAPI_CompositeFeature(aSketchCommonFeature) +origin = geomDataAPI_Point(aSketchFeature.attribute("Origin")) +origin.setValue(0, 0, 0) +dirx = geomDataAPI_Dir(aSketchFeature.attribute("DirX")) +dirx.setValue(1, 0, 0) +diry = geomDataAPI_Dir(aSketchFeature.attribute("DirY")) +diry.setValue(0, 1, 0) +norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm")) +norm.setValue(0, 0, 1) +aSession.finishOperation() +#========================================================================= +# Create non-horizontal line +#========================================================================= +aSession.startOperation() +aSketchLine = aSketchFeature.addFeature("SketchLine") +aLineStartPoint = geomDataAPI_Point2D(aSketchLine.attribute("StartPoint")) +aLineEndPoint = geomDataAPI_Point2D(aSketchLine.attribute("EndPoint")) +aLineStartPoint.setValue(0., 15.) +aLineEndPoint.setValue(20., 25.) +aSession.finishOperation() +#========================================================================= +# Assign horizontal constraint for a line +#========================================================================= +aSession.startOperation() +aHorizontalConstraint = aSketchFeature.addFeature("SketchConstraintHorizontal") +refattrA = aHorizontalConstraint.refattr("ConstraintEntityA") +aResult = modelAPI_ResultConstruction(aSketchLine.firstResult()) +assert (aResult is not None) +refattrA.setObject(aResult) +aHorizontalConstraint.execute() +aSession.finishOperation() +assert(aLineStartPoint.y() == aLineEndPoint.y()) +#========================================================================= +# Move one of boundary points of a line +#========================================================================= +deltaX = deltaY = 10. +aSession.startOperation() +aLineStartPoint.setValue(aLineStartPoint.x() + deltaX, + aLineStartPoint.y() + deltaY) +aSession.finishOperation() +assert(aLineStartPoint.y() == aLineEndPoint.y()) +#========================================================================= +# Move other boundary point of a line +#========================================================================= +deltaX = -3. +deltaY = -10. +aSession.startOperation() +aLineEndPoint.setValue(aLineEndPoint.x() + deltaX, + aLineEndPoint.y() + deltaY) +aSession.finishOperation() +assert(aLineStartPoint.y() == aLineEndPoint.y()) +#========================================================================= +# End of test +#========================================================================= diff --cc src/SketchPlugin/Test/TestConstraintMirror.py index 3c3c2d052,000000000..4f85ec44e mode 100644,000000..100644 --- a/src/SketchPlugin/Test/TestConstraintMirror.py +++ b/src/SketchPlugin/Test/TestConstraintMirror.py @@@ -1,158 -1,0 +1,158 @@@ +""" + TestConstraintMirror.py + Unit test of SketchPlugin_ConstraintMirror class + + SketchPlugin_ConstraintMirror + static const std::string MY_CONSTRAINT_MIRROR_ID("SketchConstraintMirror"); - data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::type()); - data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefListAttr::type()); - data()->addAttribute(SketchPlugin_Constraint::ENTITY_C(), ModelAPI_AttributeRefListAttr::type()); ++ data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId()); ++ data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefListAttr::typeId()); ++ data()->addAttribute(SketchPlugin_Constraint::ENTITY_C(), ModelAPI_AttributeRefListAttr::typeId()); + +""" +from GeomDataAPI import * +from ModelAPI import * +import math +#========================================================================= +# Initialization of the test +#========================================================================= + +__updated__ = "2015-03-17" + +aSession = ModelAPI_Session.get() +aDocument = aSession.moduleDocument() +#========================================================================= +# Creation of a sketch +#========================================================================= +aSession.startOperation() +aSketchCommonFeature = aDocument.addFeature("Sketch") +aSketchFeature = modelAPI_CompositeFeature(aSketchCommonFeature) +origin = geomDataAPI_Point(aSketchFeature.attribute("Origin")) +origin.setValue(0, 0, 0) +dirx = geomDataAPI_Dir(aSketchFeature.attribute("DirX")) +dirx.setValue(1, 0, 0) +diry = geomDataAPI_Dir(aSketchFeature.attribute("DirY")) +diry.setValue(0, 1, 0) +norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm")) +norm.setValue(0, 0, 1) +aSession.finishOperation() +#========================================================================= +# Creation of an arc and two lines +#========================================================================= +# Arc +aSession.startOperation() +aSketchArc1 = aSketchFeature.addFeature("SketchArc") +anArcCentr = geomDataAPI_Point2D(aSketchArc1.attribute("ArcCenter")) +anArcCentr.setValue(10., 10.) +anArcStartPoint = geomDataAPI_Point2D(aSketchArc1.attribute("ArcStartPoint")) +anArcStartPoint.setValue(0., 50.) +anArcEndPoint = geomDataAPI_Point2D(aSketchArc1.attribute("ArcEndPoint")) +anArcEndPoint.setValue(50., 0.) +aSession.finishOperation() +# Line 1 +aSession.startOperation() +aSketchLine1 = aSketchFeature.addFeature("SketchLine") +aLine1StartPoint = geomDataAPI_Point2D(aSketchLine1.attribute("StartPoint")) +aLine1EndPoint = geomDataAPI_Point2D(aSketchLine1.attribute("EndPoint")) +aLine1StartPoint.setValue(0., 50.) +aLine1EndPoint.setValue(0., 100.) +aSession.finishOperation() +# Line 2 +aSession.startOperation() +aSketchLine2 = aSketchFeature.addFeature("SketchLine") +aLine2StartPoint = geomDataAPI_Point2D(aSketchLine2.attribute("StartPoint")) +aLine2EndPoint = geomDataAPI_Point2D(aSketchLine2.attribute("EndPoint")) +aLine2StartPoint.setValue(50., 0.) +aLine2EndPoint.setValue(100., 0.) +aSession.finishOperation() +#========================================================================= +# Link arc points and lines points by the coincidence constraint +#========================================================================= +aSession.startOperation() +aConstraint = aSketchFeature.addFeature("SketchConstraintCoincidence") +reflistA = aConstraint.refattr("ConstraintEntityA") +reflistB = aConstraint.refattr("ConstraintEntityB") +reflistA.setAttr(anArcStartPoint) +reflistB.setAttr(aLine1StartPoint) +aConstraint.execute() +aSession.finishOperation() +aSession.startOperation() +aConstraint = aSketchFeature.addFeature("SketchConstraintCoincidence") +reflistA = aConstraint.refattr("ConstraintEntityA") +reflistB = aConstraint.refattr("ConstraintEntityB") +reflistA.setAttr(anArcEndPoint) +reflistB.setAttr(aLine2StartPoint) +aConstraint.execute() +aSession.finishOperation() +#========================================================================= +# Add tangency constraint and check correctness +#========================================================================= +aSession.startOperation() +aTangency = aSketchFeature.addFeature("SketchConstraintTangent") +aRefObjectA = aTangency.refattr("ConstraintEntityA") +aRefObjectB = aTangency.refattr("ConstraintEntityB") +anObjectA = modelAPI_ResultConstruction(aSketchArc1.lastResult()) +anObjectB = modelAPI_ResultConstruction(aSketchLine1.firstResult()) +assert (anObjectA is not None) +assert (anObjectB is not None) +aRefObjectA.setObject(anObjectA) +aRefObjectB.setObject(anObjectB) +aTangency.execute() +aSession.finishOperation() +#========================================================================= +# Create mirror line +#========================================================================= +aSession.startOperation() +aMirrorLine = aSketchFeature.addFeature("SketchLine") +aLineStartPoint = geomDataAPI_Point2D(aMirrorLine.attribute("StartPoint")) +aLineEndPoint = geomDataAPI_Point2D(aMirrorLine.attribute("EndPoint")) +aLineStartPoint.setValue(100., 0.) +aLineEndPoint.setValue(100., 100.) +aSession.finishOperation() +#========================================================================= +# Make mirror for objects created above +#========================================================================= +aSession.startOperation() +aMirror = aSketchFeature.addFeature("SketchConstraintMirror") +aRefObjectA = aMirror.refattr("ConstraintEntityA") +aRefObjectA.setObject(modelAPI_ResultConstruction(aMirrorLine.firstResult())) +aRefListB = aMirror.reflist("ConstraintEntityB") +aRefListB.append(aSketchArc1) +aRefListB.append(aSketchLine1) +aRefListB.append(aSketchLine2) +aMirror.execute() +aSession.finishOperation() +#========================================================================= +# Verify the simmetricity of all mirrored objects +#========================================================================= +aRefListC = aMirror.reflist("ConstraintEntityC") +aListSize = aRefListB.size() +aLineDirX = aLineEndPoint.x() - aLineStartPoint.x() +aLineDirY = aLineEndPoint.y() - aLineStartPoint.y() + +for ind in range(0, aListSize): + aFeatureB = modelAPI_Feature(aRefListB.object(ind)) + aFeatureC = modelAPI_Feature(aRefListC.object(ind)) + assert(aFeatureB is not None) + assert(aFeatureC is not None) + assert(aFeatureB.getKind() == aFeatureC.getKind()) + anAttributes = {} + print aFeatureB.getKind() + if (aFeatureB.getKind() == "SketchLine"): + anAttributes = {'StartPoint':'StartPoint', 'EndPoint':'EndPoint'} + elif (aFeatureB.getKind() == "SketchArc"): + anAttributes = {'ArcCenter':'ArcCenter', 'ArcStartPoint':'ArcEndPoint', 'ArcEndPoint':'ArcStartPoint'} + + for key in anAttributes: + aPointB = geomDataAPI_Point2D(aFeatureB.attribute(key)) + aPointC = geomDataAPI_Point2D(aFeatureC.attribute(anAttributes[key])) + aDirX = aPointC.x() - aPointB.x() + aDirY = aPointC.y() - aPointB.y() + aDot = aLineDirX * aDirX + aLineDirY * aDirY + assert(math.fabs(aDot) < 1.e-10) + aDirX = aLineEndPoint.x() - 0.5 * (aPointB.x() + aPointC.x()) + aDirY = aLineEndPoint.y() - 0.5 * (aPointB.y() + aPointC.y()) + aCross = aLineDirX * aDirY - aLineDirY * aDirX + assert(math.fabs(aCross) < 1.e-10) +#========================================================================= +# End of test +#========================================================================= diff --cc src/SketchPlugin/Test/TestConstraintTangent.py index df753488a,000000000..a64b8a3a8 mode 100644,000000..100644 --- a/src/SketchPlugin/Test/TestConstraintTangent.py +++ b/src/SketchPlugin/Test/TestConstraintTangent.py @@@ -1,226 -1,0 +1,226 @@@ +""" + TestConstraintTangent.py + Unit test of SketchPlugin_ConstraintTangent class + + SketchPlugin_ConstraintTangent + static const std::string MY_CONSTRAINT_TANGENT_ID("SketchConstraintTangent"); - data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::type()); - data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::type()); ++ data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId()); ++ data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId()); + +""" +from GeomDataAPI import * +from GeomAPI import * +from ModelAPI import * +import math +#========================================================================= +# Initialization of the test +#========================================================================= + +__updated__ = "2015-03-17" + +aSession = ModelAPI_Session.get() +aDocument = aSession.moduleDocument() +#========================================================================= +# Creation of a sketch +#========================================================================= +aSession.startOperation() +aSketchCommonFeature = aDocument.addFeature("Sketch") +aSketchFeature = modelAPI_CompositeFeature(aSketchCommonFeature) +origin = geomDataAPI_Point(aSketchFeature.attribute("Origin")) +origin.setValue(0, 0, 0) +dirx = geomDataAPI_Dir(aSketchFeature.attribute("DirX")) +dirx.setValue(1, 0, 0) +diry = geomDataAPI_Dir(aSketchFeature.attribute("DirY")) +diry.setValue(0, 1, 0) +norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm")) +norm.setValue(0, 0, 1) +aSession.finishOperation() +#========================================================================= +# TEST 1. Arc-line tangency +#========================================================================= +# Creation of an arc and two lines +#========================================================================= +# Arc +aSession.startOperation() +aSketchArc1 = aSketchFeature.addFeature("SketchArc") +anArcCentr = geomDataAPI_Point2D(aSketchArc1.attribute("ArcCenter")) +anArcCentr.setValue(10., 10.) +anArcStartPoint = geomDataAPI_Point2D(aSketchArc1.attribute("ArcStartPoint")) +anArcStartPoint.setValue(0., 50.) +anArcEndPoint = geomDataAPI_Point2D(aSketchArc1.attribute("ArcEndPoint")) +anArcEndPoint.setValue(50., 0.) +aSession.finishOperation() +# Line 1 +aSession.startOperation() +aSketchLine1 = aSketchFeature.addFeature("SketchLine") +aLine1StartPoint = geomDataAPI_Point2D(aSketchLine1.attribute("StartPoint")) +aLine1EndPoint = geomDataAPI_Point2D(aSketchLine1.attribute("EndPoint")) +aLine1StartPoint.setValue(0., 50.) +aLine1EndPoint.setValue(0., 100.) +aSession.finishOperation() +# Line 2 +aSession.startOperation() +aSketchLine2 = aSketchFeature.addFeature("SketchLine") +aLine2StartPoint = geomDataAPI_Point2D(aSketchLine2.attribute("StartPoint")) +aLine2EndPoint = geomDataAPI_Point2D(aSketchLine2.attribute("EndPoint")) +aLine2StartPoint.setValue(50., 0.) +aLine2EndPoint.setValue(100., 0.) +aSession.finishOperation() +#========================================================================= +# Link arc points and lines points by the coincidence constraint +#========================================================================= +aSession.startOperation() +aConstraint = aSketchFeature.addFeature("SketchConstraintCoincidence") +reflistA = aConstraint.refattr("ConstraintEntityA") +reflistB = aConstraint.refattr("ConstraintEntityB") +reflistA.setAttr(anArcStartPoint) +reflistB.setAttr(aLine1StartPoint) +aConstraint.execute() +aSession.finishOperation() +aSession.startOperation() +aConstraint = aSketchFeature.addFeature("SketchConstraintCoincidence") +reflistA = aConstraint.refattr("ConstraintEntityA") +reflistB = aConstraint.refattr("ConstraintEntityB") +reflistA.setAttr(anArcEndPoint) +reflistB.setAttr(aLine2StartPoint) +aConstraint.execute() +aSession.finishOperation() +#========================================================================= +# Add tangency constraint and check correctness +#========================================================================= +aSession.startOperation() +aTangency = aSketchFeature.addFeature("SketchConstraintTangent") +aRefObjectA = aTangency.refattr("ConstraintEntityA") +aRefObjectB = aTangency.refattr("ConstraintEntityB") +anObjectA = modelAPI_ResultConstruction(aSketchArc1.lastResult()) +anObjectB = modelAPI_ResultConstruction(aSketchLine1.firstResult()) +assert (anObjectA is not None) +assert (anObjectB is not None) +aRefObjectA.setObject(anObjectA) +aRefObjectB.setObject(anObjectB) +aTangency.execute() +aSession.finishOperation() +anArcVecX = anArcStartPoint.x() - anArcCentr.x() +anArcVecY = anArcStartPoint.y() - anArcCentr.y() +aLineVecX = aLine1EndPoint.x() - aLine1StartPoint.x() +aLineVecY = aLine1EndPoint.y() - aLine1StartPoint.y() +aDot = anArcVecX * aLineVecX + anArcVecY * aLineVecY +assert(math.fabs(aDot) <= 1.e-12) +#========================================================================= +# Add tangency constraint for arc and second line and check correctness +#========================================================================= +aSession.startOperation() +aTangency = aSketchFeature.addFeature("SketchConstraintTangent") +aRefObjectA = aTangency.refattr("ConstraintEntityA") +aRefObjectB = aTangency.refattr("ConstraintEntityB") +anObjectA = modelAPI_ResultConstruction(aSketchArc1.lastResult()) +anObjectB = modelAPI_ResultConstruction(aSketchLine2.firstResult()) +assert (anObjectA is not None) +assert (anObjectB is not None) +aRefObjectA.setObject(anObjectA) +aRefObjectB.setObject(anObjectB) +aTangency.execute() +aSession.finishOperation() +anArcVecX = anArcEndPoint.x() - anArcCentr.x() +anArcVecY = anArcEndPoint.y() - anArcCentr.y() +aLineVecX = aLine2EndPoint.x() - aLine2StartPoint.x() +aLineVecY = aLine2EndPoint.y() - aLine2StartPoint.y() +aDot = anArcVecX * aLineVecX + anArcVecY * aLineVecY +assert(math.fabs(aDot) <= 1.e-12) + +#========================================================================= +# TEST 2. Arc-arc tangency +#========================================================================= +# Creation of arcs +#========================================================================= +# Arc 1 +aSession.startOperation() +aSketchArc1 = aSketchFeature.addFeature("SketchArc") +anArc1Centr = geomDataAPI_Point2D(aSketchArc1.attribute("ArcCenter")) +anArc1Centr.setValue(10., 10.) +anArc1StartPoint = geomDataAPI_Point2D(aSketchArc1.attribute("ArcStartPoint")) +anArc1StartPoint.setValue(50., 0.) +anArc1EndPoint = geomDataAPI_Point2D(aSketchArc1.attribute("ArcEndPoint")) +anArc1EndPoint.setValue(0., 50.) +aSession.finishOperation() +# Arc 2 +aSession.startOperation() +aSketchArc2 = aSketchFeature.addFeature("SketchArc") +anArc2Centr = geomDataAPI_Point2D(aSketchArc2.attribute("ArcCenter")) +anArc2Centr.setValue(-10., 10.) +anArc2StartPoint = geomDataAPI_Point2D(aSketchArc2.attribute("ArcStartPoint")) +anArc2StartPoint.setValue(0., 50.) +anArc2EndPoint = geomDataAPI_Point2D(aSketchArc2.attribute("ArcEndPoint")) +anArc2EndPoint.setValue(-50., 0.) +aSession.finishOperation() +#========================================================================= +# Link points of arcs by the coincidence constraint +#========================================================================= +aSession.startOperation() +aConstraint = aSketchFeature.addFeature("SketchConstraintCoincidence") +reflistA = aConstraint.refattr("ConstraintEntityA") +reflistB = aConstraint.refattr("ConstraintEntityB") +reflistA.setAttr(anArc1EndPoint) +reflistB.setAttr(anArc2StartPoint) +aConstraint.execute() +aSession.finishOperation() +#========================================================================= +# Add tangency constraint and check correctness +#========================================================================= +aSession.startOperation() +aTangency = aSketchFeature.addFeature("SketchConstraintTangent") +aRefObjectA = aTangency.refattr("ConstraintEntityA") +aRefObjectB = aTangency.refattr("ConstraintEntityB") +anObjectA = modelAPI_ResultConstruction(aSketchArc1.lastResult()) +anObjectB = modelAPI_ResultConstruction(aSketchArc2.lastResult()) +assert (anObjectA is not None) +assert (anObjectB is not None) +aRefObjectA.setObject(anObjectA) +aRefObjectB.setObject(anObjectB) +aTangency.execute() +aSession.finishOperation() +anArc1VecX = anArc1EndPoint.x() - anArc1Centr.x() +anArc1VecY = anArc1EndPoint.y() - anArc1Centr.y() +anArc2VecX = anArc2StartPoint.x() - anArc2Centr.x() +anArc2VecY = anArc2StartPoint.y() - anArc2Centr.y() +aCross = anArc1VecX * anArc2VecY - anArc1VecY * anArc2VecX +assert(math.fabs(aCross) <= 1.e-12) + +#========================================================================= +# TEST 3. Tangency between non-connected objects should be wrong +#========================================================================= +# Store data +aLine2StartPointPrev = (aLine2StartPoint.x(), aLine2StartPoint.y()) +aLine2EndPointPrev = (aLine2EndPoint.x(), aLine2EndPoint.y()) +anArc2CenterPrev = (anArc2Centr.x(), anArc2Centr.y()) +anArc2StartPointPrev = (anArc2StartPoint.x(), anArc2StartPoint.y()) +anArc2EndPointPrev = (anArc2EndPoint.x(), anArc2EndPoint.y()) +#========================================================================= +# Add tangency between arc2 and line2 +#========================================================================= +aSession.startOperation() +aTangency = aSketchFeature.addFeature("SketchConstraintTangent") +aRefObjectA = aTangency.refattr("ConstraintEntityA") +aRefObjectB = aTangency.refattr("ConstraintEntityB") +anObjectA = modelAPI_ResultConstruction(aSketchArc2.lastResult()) +anObjectB = modelAPI_ResultConstruction(aSketchLine2.firstResult()) +assert (anObjectA is not None) +assert (anObjectB is not None) +aRefObjectA.setObject(anObjectA) +aRefObjectB.setObject(anObjectB) +aTangency.execute() +aSession.finishOperation() +# Check that nothing is changed +aLine2StartPointNew = (aLine2StartPoint.x(), aLine2StartPoint.y()) +aLine2EndPointNew = (aLine2EndPoint.x(), aLine2EndPoint.y()) +anArc2CenterNew = (anArc2Centr.x(), anArc2Centr.y()) +anArc2StartPointNew = (anArc2StartPoint.x(), anArc2StartPoint.y()) +anArc2EndPointNew = (anArc2EndPoint.x(), anArc2EndPoint.y()) +assert(aLine2StartPointNew == aLine2StartPointPrev) +assert(aLine2EndPointNew == aLine2EndPointPrev) +assert(anArc2CenterNew == anArc2CenterPrev) +assert(anArc2StartPointNew == anArc2StartPointPrev) +assert(anArc2EndPointNew == anArc2EndPointPrev) +#========================================================================= +# End of test +#========================================================================= diff --cc src/SketchPlugin/Test/TestConstraintVertical.py index 87ba28f97,000000000..9272b21ec mode 100644,000000..100644 --- a/src/SketchPlugin/Test/TestConstraintVertical.py +++ b/src/SketchPlugin/Test/TestConstraintVertical.py @@@ -1,78 -1,0 +1,78 @@@ +""" + TestConstraintVertical.py + Unit test of SketchPlugin_ConstraintVertical class + + SketchPlugin_ConstraintVertical + static const std::string MY_CONSTRAINT_VERTICAL_ID("SketchConstraintVertical"); - data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::type()); ++ data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId()); + +""" +from GeomDataAPI import * +from ModelAPI import * +#========================================================================= +# Initialization of the test +#========================================================================= + +__updated__ = "2015-03-16" + +aSession = ModelAPI_Session.get() +aDocument = aSession.moduleDocument() +#========================================================================= +# Creation of a sketch +#========================================================================= +aSession.startOperation() +aSketchCommonFeature = aDocument.addFeature("Sketch") +aSketchFeature = modelAPI_CompositeFeature(aSketchCommonFeature) +origin = geomDataAPI_Point(aSketchFeature.attribute("Origin")) +origin.setValue(0, 0, 0) +dirx = geomDataAPI_Dir(aSketchFeature.attribute("DirX")) +dirx.setValue(1, 0, 0) +diry = geomDataAPI_Dir(aSketchFeature.attribute("DirY")) +diry.setValue(0, 1, 0) +norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm")) +norm.setValue(0, 0, 1) +aSession.finishOperation() +#========================================================================= +# Create non-vertical line +#========================================================================= +aSession.startOperation() +aSketchLine = aSketchFeature.addFeature("SketchLine") +aLineStartPoint = geomDataAPI_Point2D(aSketchLine.attribute("StartPoint")) +aLineEndPoint = geomDataAPI_Point2D(aSketchLine.attribute("EndPoint")) +aLineStartPoint.setValue(0., 15.) +aLineEndPoint.setValue(20., 25.) +aSession.finishOperation() +#========================================================================= +# Assign vertical constraint for a line +#========================================================================= +aSession.startOperation() +aVerticalConstraint = aSketchFeature.addFeature("SketchConstraintVertical") +refattrA = aVerticalConstraint.refattr("ConstraintEntityA") +aResult = modelAPI_ResultConstruction(aSketchLine.firstResult()) +assert (aResult is not None) +refattrA.setObject(aResult) +aVerticalConstraint.execute() +aSession.finishOperation() +assert(aLineStartPoint.x() == aLineEndPoint.x()) +#========================================================================= +# Move one of boundary points of a line +#========================================================================= +deltaX = deltaY = 10. +aSession.startOperation() +aLineStartPoint.setValue(aLineStartPoint.x() + deltaX, + aLineStartPoint.y() + deltaY) +aSession.finishOperation() +assert(aLineStartPoint.x() == aLineEndPoint.x()) +#========================================================================= +# Move other boundary point of a line +#========================================================================= +deltaX = -3. +deltaY = -10. +aSession.startOperation() +aLineEndPoint.setValue(aLineEndPoint.x() + deltaX, + aLineEndPoint.y() + deltaY) +aSession.finishOperation() +assert(aLineStartPoint.x() == aLineEndPoint.x()) +#========================================================================= +# End of test +#========================================================================= diff --cc src/SketchPlugin/plugin-Sketch.xml index f1bc36d9b,81c396a77..af51a5dd6 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@@ -64,16 -56,15 +64,26 @@@ id="ConstraintEntityB" label="Last object" tooltip="Select point, line end point, line, center of circle or arc." - shape_types="edge vertex"> ++ shape_types="edge vertex"> + + + + + ++ - + + + @@@ -103,104 -96,47 +113,136 @@@ - + + + + + + + + + + + + ++ - - + - ++ + + + + + + + + + + ++ - + - - - - - + shape_types="edge vertex"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --cc src/SketchSolver/SketchSolver_ConstraintGroup.cpp index b650cbdab,3cb517247..05171749b --- a/src/SketchSolver/SketchSolver_ConstraintGroup.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintGroup.cpp @@@ -603,492 -540,6 +603,492 @@@ bool SketchSolver_ConstraintGroup::chan return true; } +// ============================================================================ +// Function: changeMirrorConstraint +// Class: SketchSolver_ConstraintGroup +// Purpose: create/update the "Mirror" constraint in the group +// ============================================================================ +bool SketchSolver_ConstraintGroup::changeMirrorConstraint( + std::shared_ptr theConstraint) +{ + DataPtr aConstrData = theConstraint->data(); + + // Search this constraint in the current group to update it + ConstraintMap::const_iterator aConstrMapIter = myConstraintMap.find(theConstraint); + std::vector::iterator aConstrIter; + if (aConstrMapIter != myConstraintMap.end()) { + int aConstrPos = Search(aConstrMapIter->second.front(), myConstraints); + aConstrIter = myConstraints.begin() + aConstrPos; + } + + // Get constraint type and verify the constraint parameters are correct + SketchSolver_Constraint aConstraint(theConstraint); + int aConstrType = aConstraint.getType(); + if (aConstrType == SLVS_C_UNKNOWN + || (aConstrMapIter != myConstraintMap.end() && aConstrIter->type != aConstrType)) + return false; + const std::vector& aConstraintAttributes = aConstraint.getAttributes(); + + Slvs_hEntity aMirrorLineEnt = SLVS_E_UNKNOWN; + AttributeRefAttrPtr aConstrAttr = std::dynamic_pointer_cast( + aConstrData->attribute(aConstraintAttributes[0])); + if (!aConstrAttr) + return false; + + // Convert the object of the attribute to the feature + FeaturePtr aMirrorLineFeat; + if (aConstrAttr->isObject() && aConstrAttr->object()) { + ResultConstructionPtr aRC = std::dynamic_pointer_cast( + aConstrAttr->object()); + if (!aRC) + return false; + std::shared_ptr aDoc = aRC->document(); + aMirrorLineFeat = aDoc->feature(aRC); + } + aMirrorLineEnt = aConstrAttr->isObject() ? + changeEntityFeature(aMirrorLineFeat) : changeEntity(aConstrAttr->attr()); + + if (aConstrMapIter == myConstraintMap.end()) { // Add new constraint + // Append symmetric constraint for each point of mirroring features + AttributeRefListPtr aBaseRefList = std::dynamic_pointer_cast( + aConstrData->attribute(aConstraintAttributes[1])); + AttributeRefListPtr aMirroredRefList = std::dynamic_pointer_cast( + aConstrData->attribute(aConstraintAttributes[2])); + if (!aBaseRefList || !aMirroredRefList) + return false; + + std::list aBaseList = aBaseRefList->list(); + std::list aMirroredList = aMirroredRefList->list(); + if (aBaseList.size() != aMirroredList.size()) + return false; + + myConstraintMap[theConstraint] = std::vector(); + + FeaturePtr aBaseFeature, aMirrorFeature; + ResultConstructionPtr aRC; + std::list::iterator aBaseIter = aBaseList.begin(); + std::list::iterator aMirIter = aMirroredList.begin(); + for ( ; aBaseIter != aBaseList.end(); aBaseIter++, aMirIter++) { + aRC = std::dynamic_pointer_cast(*aBaseIter); + aBaseFeature = aRC ? aRC->document()->feature(aRC) : + std::dynamic_pointer_cast(*aBaseIter); + aRC = std::dynamic_pointer_cast(*aMirIter); + aMirrorFeature = aRC ? aRC->document()->feature(aRC) : + std::dynamic_pointer_cast(*aMirIter); + + if (!aBaseFeature || !aMirrorFeature || + aBaseFeature->getKind() != aMirrorFeature->getKind()) + return false; + Slvs_hEntity aBaseEnt = changeEntityFeature(aBaseFeature); + Slvs_hEntity aMirrorEnt = changeEntityFeature(aMirrorFeature); + // Make aMirrorEnt parameters to be symmetric with aBaseEnt + makeMirrorEntity(aBaseEnt, aMirrorEnt, aMirrorLineEnt); + + if (aBaseFeature->getKind() == SketchPlugin_Point::ID()) { + Slvs_Constraint aConstraint = Slvs_MakeConstraint(++myConstrMaxID, myID, aConstrType, + myWorkplane.h, 0.0, aBaseEnt, aMirrorEnt, aMirrorLineEnt, SLVS_E_UNKNOWN); + myConstraints.push_back(aConstraint); + myConstraintMap[theConstraint].push_back(aConstraint.h); + } else { + int aBasePos = Search(aBaseEnt, myEntities); + int aMirrorPos = Search(aMirrorEnt, myEntities); + if (aBaseFeature->getKind() == SketchPlugin_Line::ID()) { + for (int ind = 0; ind < 2; ind++) { + Slvs_Constraint aConstraint = Slvs_MakeConstraint( + ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0, + myEntities[aBasePos].point[ind], myEntities[aMirrorPos].point[ind], + aMirrorLineEnt, SLVS_E_UNKNOWN); + myConstraints.push_back(aConstraint); + myConstraintMap[theConstraint].push_back(aConstraint.h); + } + } else if (aBaseFeature->getKind() == SketchPlugin_Circle::ID()) { + Slvs_Constraint aConstraint = Slvs_MakeConstraint( + ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0, + myEntities[aBasePos].point[0], myEntities[aMirrorPos].point[0], + aMirrorLineEnt, SLVS_E_UNKNOWN); + myConstraints.push_back(aConstraint); + myConstraintMap[theConstraint].push_back(aConstraint.h); + // Additional constraint for equal radii + Slvs_Constraint anEqRadConstr = Slvs_MakeConstraint( + ++myConstrMaxID, myID, SLVS_C_EQUAL_RADIUS, myWorkplane.h, 0.0, + SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aBaseEnt, aMirrorEnt); + myConstraints.push_back(anEqRadConstr); + myConstraintMap[theConstraint].push_back(anEqRadConstr.h); + } else if (aBaseFeature->getKind() == SketchPlugin_Arc::ID()) { + // Workaround to avoid problems in SolveSpace. + // The symmetry of two arcs will be done using symmetry of three points on these arcs: + // start point, end point, and any other point on the arc + Slvs_hEntity aBaseArcPoints[3] = { + myEntities[aBasePos].point[1], + myEntities[aBasePos].point[2], + SLVS_E_UNKNOWN}; + Slvs_hEntity aMirrorArcPoints[3] = { // indices of points of arc, center corresponds center, first point corresponds last point + myEntities[aMirrorPos].point[2], + myEntities[aMirrorPos].point[1], + SLVS_E_UNKNOWN}; + Slvs_hEntity aBothArcs[2] = {aBaseEnt, aMirrorEnt}; + Slvs_hEntity aBothMiddlePoints[2]; + for (int i = 0; i < 2; i++) { + double x, y; + calculateMiddlePoint(aBothArcs[i], x, y); + std::vector::iterator aParamIter = myParams.end(); + Slvs_hParam u = changeParameter(x, aParamIter); + Slvs_hParam v = changeParameter(y, aParamIter); + Slvs_Entity aPoint = Slvs_MakePoint2d(++myEntityMaxID, myID, myWorkplane.h, u, v); + myEntities.push_back(aPoint); + aBothMiddlePoints[i] = aPoint.h; + // additional constraint point-on-curve + Slvs_Constraint aPonCircConstr = Slvs_MakeConstraint( + ++myConstrMaxID, myID, SLVS_C_PT_ON_CIRCLE, myWorkplane.h, 0.0, + aPoint.h, SLVS_E_UNKNOWN, aBothArcs[i], SLVS_E_UNKNOWN); + myConstraints.push_back(aPonCircConstr); + myConstraintMap[theConstraint].push_back(aPonCircConstr.h); + } + + aBaseArcPoints[2] = aBothMiddlePoints[0]; + aMirrorArcPoints[2] = aBothMiddlePoints[1]; + for (int ind = 0; ind < 3; ind++) { + Slvs_Constraint aConstraint = Slvs_MakeConstraint( + ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0, + aBaseArcPoints[ind], aMirrorArcPoints[ind], aMirrorLineEnt, SLVS_E_UNKNOWN); + myConstraints.push_back(aConstraint); + myConstraintMap[theConstraint].push_back(aConstraint.h); + } + } + } + } + + // Set the mirror line unchanged during constraint recalculation + int aMirrorLinePos = Search(aMirrorLineEnt, myEntities); + Slvs_Constraint aRigidStart = Slvs_MakeConstraint( + ++myConstrMaxID, myID, SLVS_C_WHERE_DRAGGED, myWorkplane.h, 0, + myEntities[aMirrorLinePos].point[0], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); + myConstraints.push_back(aRigidStart); + myConstraintMap[theConstraint].push_back(aRigidStart.h); + Slvs_Constraint aRigidEnd = Slvs_MakeConstraint( + ++myConstrMaxID, myID, SLVS_C_WHERE_DRAGGED, myWorkplane.h, 0, + myEntities[aMirrorLinePos].point[1], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); + myConstraints.push_back(aRigidEnd); + myConstraintMap[theConstraint].push_back(aRigidEnd.h); + + // Add temporary constraints for initial objects to be unchanged + for (aBaseIter = aBaseList.begin(); aBaseIter != aBaseList.end(); aBaseIter++) { + aRC = std::dynamic_pointer_cast(*aBaseIter); + aBaseFeature = aRC ? aRC->document()->feature(aRC) : + std::dynamic_pointer_cast(*aBaseIter); + if (!aBaseFeature) continue; - std::list aPoints = aBaseFeature->data()->attributes(GeomDataAPI_Point2D::type()); ++ std::list aPoints = aBaseFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); + std::list::iterator anIt = aPoints.begin(); + for ( ; anIt != aPoints.end(); anIt++) { + // Arcs are fixed by center and start points only (to avoid solving errors in SolveSpace) + if (aBaseFeature->getKind() == SketchPlugin_Arc::ID() && + (*anIt)->id() == SketchPlugin_Arc::END_ID()) + continue; + addTemporaryConstraintWhereDragged(*anIt); + } + } + } + return true; +} + +// ============================================================================ +// Function: changeFilletConstraint +// Class: SketchSolver_ConstraintGroup +// Purpose: create/update the "Fillet" constraint in the group +// ============================================================================ +bool SketchSolver_ConstraintGroup::changeFilletConstraint( + std::shared_ptr theConstraint) +{ + DataPtr aConstrData = theConstraint->data(); + + // Search this constraint in the current group to update it + ConstraintMap::const_iterator aConstrMapIter = myConstraintMap.find(theConstraint); + std::vector::iterator aConstrIter; + if (aConstrMapIter != myConstraintMap.end()) { + int aConstrPos = Search(aConstrMapIter->second.front(), myConstraints); + aConstrIter = myConstraints.begin() + aConstrPos; + } + + // Get constraint type and verify the constraint parameters are correct + SketchSolver_Constraint aConstraint(theConstraint); + int aConstrType = aConstraint.getType(); + if (aConstrType == SLVS_C_UNKNOWN) + return false; + const std::vector& aConstraintAttributes = aConstraint.getAttributes(); + + // Obtain hEntity for basic objects of fillet + Slvs_hEntity aBaseObject[2]; + FeaturePtr aBaseFeature[2]; + for (unsigned int indAttr = 0; indAttr < 2; indAttr++) { + AttributeRefAttrPtr aConstrAttr = std::dynamic_pointer_cast( + aConstrData->attribute(aConstraintAttributes[indAttr])); + if (!aConstrAttr) + return false; + if (aConstrAttr->isObject() && aConstrAttr->object()) { + ResultConstructionPtr aRC = std::dynamic_pointer_cast( + aConstrAttr->object()); + if (!aRC) + return false; + std::shared_ptr aDoc = aRC->document(); + aBaseFeature[indAttr] = aDoc->feature(aRC); + } + aBaseObject[indAttr] = aConstrAttr->isObject() ? + changeEntityFeature(aBaseFeature[indAttr]) : changeEntity(aConstrAttr->attr()); + } + // Check the base entities have a coincident point + int aBaseObjInd[2] = { + Search(aBaseObject[0], myEntities), + Search(aBaseObject[1], myEntities) + }; + int aShift[2] = { // shift for calculating correct start and end points for different types of objects + myEntities[aBaseObjInd[0]].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0, + myEntities[aBaseObjInd[1]].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0, + }; + Slvs_hEntity aFirstObjPoints[2] = { // indices of start and end point of first object + myEntities[aBaseObjInd[0]].point[aShift[0]], + myEntities[aBaseObjInd[0]].point[1+aShift[0]] + }; + Slvs_hEntity aSecondObjPoints[2] = { // indices of start and end point of second object + myEntities[aBaseObjInd[1]].point[aShift[1]], + myEntities[aBaseObjInd[1]].point[1+aShift[1]] + }; + bool isCoincidentFound = false; + int aBaseCoincInd[2] = {0, 0}; // indices in aFirstObjPoint and aSecondObjPoint identifying coincident points + std::vector >::iterator aCPIter = myCoincidentPoints.begin(); + for ( ; aCPIter != myCoincidentPoints.end() && !isCoincidentFound; aCPIter++) + for (int ind1 = 0; ind1 < 2 && !isCoincidentFound; ind1++) + for (int ind2 = 0; ind2 < 2 && !isCoincidentFound; ind2++) + if (aCPIter->find(aFirstObjPoints[ind1]) != aCPIter->end() && + aCPIter->find(aSecondObjPoints[ind2]) != aCPIter->end()) { + aBaseCoincInd[0] = ind1; + aBaseCoincInd[1] = ind2; + isCoincidentFound = true; + } + if (!isCoincidentFound) { + // There is no coincident points between objects. Generate error message + Events_Error::send(SketchSolver_Error::NO_COINCIDENT_POINTS(), this); + return false; + } + + // Create fillet entities + // - first object is placed on the first base + // - second object is on the second base + // - third object is a filleting arc + static const int aNbFilletEnt = 3; + Slvs_hEntity aFilletEnt[aNbFilletEnt]; + int aFilletObjInd[aNbFilletEnt]; + AttributeRefListPtr aFilletRefList = std::dynamic_pointer_cast( + aConstrData->attribute(aConstraintAttributes[2])); + if (!aFilletRefList) + return false; + std::list aFilletList = aFilletRefList->list(); + if (aFilletList.size() < aNbFilletEnt) + return false; + FeaturePtr aFilletFeature; + ResultConstructionPtr aRC; + std::list::iterator aFilIter = aFilletList.begin(); + for (int indEnt = 0; aFilIter != aFilletList.end(); aFilIter++, indEnt++) { + aRC = std::dynamic_pointer_cast(*aFilIter); + aFilletFeature = aRC ? aRC->document()->feature(aRC) : + std::dynamic_pointer_cast(*aFilIter); + if (!aFilletFeature) + return false; + aFilletEnt[indEnt] = changeEntityFeature(aFilletFeature); + aFilletObjInd[indEnt] = Search(aFilletEnt[indEnt], myEntities); + } + // At first time, for correct result, move floating points of fillet on the middle points of base objects + if (myConstraintMap.find(theConstraint) == myConstraintMap.end()) { + double anArcPoints[6]; + for (int indEnt = 0; indEnt < aNbFilletEnt - 1; indEnt++) { + int anIndShift = myEntities[aFilletObjInd[indEnt]].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0; + int aPointsPos[2] = { + Search(myEntities[aFilletObjInd[indEnt]].point[anIndShift], myEntities), + Search(myEntities[aFilletObjInd[indEnt]].point[1+anIndShift], myEntities) + }; + int aParamPos[2] = { + Search(myEntities[aPointsPos[0]].param[0], myParams), + Search(myEntities[aPointsPos[1]].param[0], myParams) + }; + int anIndex = aParamPos[aBaseCoincInd[indEnt]]; + if (anIndShift == 0) { + myParams[anIndex].val = + 0.5 * (myParams[aParamPos[0]].val + myParams[aParamPos[1]].val); + myParams[1 + anIndex].val = + 0.5 * (myParams[1 + aParamPos[0]].val + myParams[1 + aParamPos[1]].val); + } else { // place the changed point on the arc + double x = 0, y = 0; + calculateMiddlePoint(aFilletEnt[indEnt], x, y); + myParams[anIndex].val = x; + myParams[1 + anIndex].val = y; + } + anArcPoints[indEnt*2+2] = myParams[anIndex].val; + anArcPoints[indEnt*2+3] = myParams[1 + anIndex].val; + } + anArcPoints[0] = 0.5 * (anArcPoints[2] + anArcPoints[4]); + anArcPoints[1] = 0.5 * (anArcPoints[3] + anArcPoints[5]); + for (int indArcPt = 0; indArcPt < 3; indArcPt++) { + int aPtPos = Search(myEntities[aFilletObjInd[2]].point[indArcPt], myEntities); + int aParamPos = Search(myEntities[aPtPos].param[0], myParams); + myParams[aParamPos].val = anArcPoints[indArcPt * 2]; + myParams[aParamPos + 1].val = anArcPoints[indArcPt * 2 + 1]; + } + } + + // Check the fillet arc which point to be connected to + bool isArcInversed = false; // indicates that start and end points of arc should be connected to second and first object respectively + Slvs_hEntity hEnt = myEntities[aFilletObjInd[2]].point[1]; + int aPos = Search(hEnt, myEntities); + Slvs_hParam anArcStartPoint = myEntities[aPos].param[0]; + aPos = Search(anArcStartPoint, myParams); + double anArcPtCoord[2] = {myParams[aPos].val, myParams[aPos+1].val}; + double aSqDistances[2]; + int aPtInd; + for (int indEnt = 0; indEnt < aNbFilletEnt - 1; indEnt++) { + aPtInd = aBaseCoincInd[indEnt]+aShift[indEnt]; + hEnt = myEntities[aFilletObjInd[indEnt]].point[aPtInd]; + aPos = Search(hEnt, myEntities); + Slvs_hParam anObjectPoint = myEntities[aPos].param[0]; + aPos = Search(anObjectPoint, myParams); + double aPtCoord[2] = {myParams[aPos].val, myParams[aPos+1].val}; + aSqDistances[indEnt] = + (anArcPtCoord[0] - aPtCoord[0]) * (anArcPtCoord[0] - aPtCoord[0]) + + (anArcPtCoord[1] - aPtCoord[1]) * (anArcPtCoord[1] - aPtCoord[1]); + } + if (aSqDistances[1] < aSqDistances[0]) + isArcInversed = true; + + // Create list of constraints to generate fillet + std::vector aConstrList; + bool isExists = myConstraintMap.find(theConstraint) != myConstraintMap.end(); // constraint already exists + std::vector::iterator aCMapIter = + isExists ? myConstraintMap[theConstraint].begin() : aConstrList.begin(); + int aCurConstrPos = isExists ? Search(*aCMapIter, myConstraints) : 0; + for (int indEnt = 0; indEnt < aNbFilletEnt - 1; indEnt++) { + // one point of fillet object should be coincident with the point on base, non-coincident with another base object + aPtInd = 1-aBaseCoincInd[indEnt]+aShift[indEnt]; // (1-aBaseCoincInd[indEnt]) = index of non-coincident point, aShift is used to process all types of shapes + Slvs_hEntity aPtBase = myEntities[aBaseObjInd[indEnt]].point[aPtInd]; + Slvs_hEntity aPtFillet = myEntities[aFilletObjInd[indEnt]].point[aPtInd]; + if (isExists) { + myConstraints[aCurConstrPos].ptA = aPtBase; + myConstraints[aCurConstrPos].ptB = aPtFillet; + aCMapIter++; + aCurConstrPos = Search(*aCMapIter, myConstraints); + } else { + Slvs_Constraint aCoincConstr = Slvs_MakeConstraint( + ++myConstrMaxID, myID, SLVS_C_POINTS_COINCIDENT, myWorkplane.h, + 0, aPtBase, aPtFillet, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); + myConstraints.push_back(aCoincConstr); + aConstrList.push_back(aCoincConstr.h); + } + + // another point of fillet object should be placed on the base object + Slvs_Constraint aPonCurveConstr; + int aTangentType; + if (myEntities[aFilletObjInd[indEnt]].type == SLVS_E_ARC_OF_CIRCLE) { + // centers of arcs should be coincident + aPtBase = myEntities[aBaseObjInd[indEnt]].point[0]; + aPtFillet = myEntities[aFilletObjInd[indEnt]].point[0]; + if (isExists) { + myConstraints[aCurConstrPos].ptA = aPtBase; + myConstraints[aCurConstrPos].ptB = aPtFillet; + aCMapIter++; + aCurConstrPos = Search(*aCMapIter, myConstraints); + } else { + aPonCurveConstr = Slvs_MakeConstraint( + ++myConstrMaxID, myID, SLVS_C_POINTS_COINCIDENT, myWorkplane.h, + 0, aPtBase, aPtFillet, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); + } + aPtFillet = myEntities[aFilletObjInd[indEnt]].point[1+aBaseCoincInd[indEnt]]; // !!! will be used below + aTangentType = SLVS_C_CURVE_CURVE_TANGENT; + } else { + aPtInd = aBaseCoincInd[indEnt]; + aPtFillet = myEntities[aFilletObjInd[indEnt]].point[aPtInd]; + if (isExists) { + myConstraints[aCurConstrPos].ptA = aPtFillet; + aCMapIter++; + aCurConstrPos = Search(*aCMapIter, myConstraints); + } else { + aPonCurveConstr = Slvs_MakeConstraint( + ++myConstrMaxID, myID, SLVS_C_PT_ON_LINE, myWorkplane.h, + 0, aPtFillet, SLVS_E_UNKNOWN, aBaseObject[indEnt], SLVS_E_UNKNOWN); + } + aTangentType = SLVS_C_ARC_LINE_TANGENT; + } + if (!isExists) { + myConstraints.push_back(aPonCurveConstr); + aConstrList.push_back(aPonCurveConstr.h); + } + + // Bound point of fillet arc should be tangently coincident with a bound point of fillet object + aPtInd = 1 + (isArcInversed ? 1-indEnt : indEnt); + Slvs_hEntity aPtArc = myEntities[aFilletObjInd[2]].point[aPtInd]; + if (isExists) { + myConstraints[aCurConstrPos].ptA = aPtArc; + myConstraints[aCurConstrPos].ptB = aPtFillet; + aCMapIter++; + aCurConstrPos = Search(*aCMapIter, myConstraints); + myConstraints[aCurConstrPos].entityA = aFilletEnt[2]; + myConstraints[aCurConstrPos].entityB = aFilletEnt[indEnt]; + myConstraints[aCurConstrPos].other = (isArcInversed ? 1-indEnt : indEnt); + aCMapIter++; + aCurConstrPos = Search(*aCMapIter, myConstraints); + } else { + Slvs_Constraint aCoincConstr = Slvs_MakeConstraint( + ++myConstrMaxID, myID, SLVS_C_POINTS_COINCIDENT, myWorkplane.h, + 0, aPtArc, aPtFillet, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); + myConstraints.push_back(aCoincConstr); + aConstrList.push_back(aCoincConstr.h); + Slvs_Constraint aTangency = Slvs_MakeConstraint( + ++myConstrMaxID, myID, aTangentType, myWorkplane.h, + 0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aFilletEnt[2], aFilletEnt[indEnt]); + aTangency.other = (isArcInversed ? 1-indEnt : indEnt); + aTangency.other2 = aTangentType == SLVS_C_CURVE_CURVE_TANGENT ? aBaseCoincInd[indEnt] : 0; + myConstraints.push_back(aTangency); + aConstrList.push_back(aTangency.h); + } + } + + // Additional constraint for fillet diameter + double aRadius = 0.0; // scalar value of the constraint + AttributeDoublePtr aDistAttr = std::dynamic_pointer_cast( + aConstrData->attribute(SketchPlugin_Constraint::VALUE())); + aRadius = aDistAttr->value(); + if (isExists) { + myConstraints[aCurConstrPos].entityA = aFilletEnt[2]; + myConstraints[aCurConstrPos].valA = aRadius * 2.0; + aCMapIter++; + } else { + Slvs_Constraint aDiamConstr = Slvs_MakeConstraint( + ++myConstrMaxID, myID, SLVS_C_DIAMETER, myWorkplane.h, aRadius * 2.0, + SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aFilletEnt[2], SLVS_E_UNKNOWN); + myConstraints.push_back(aDiamConstr); + aConstrList.push_back(aDiamConstr.h); + + myConstraintMap[theConstraint] = aConstrList; + } + + // Additional temporary constraints for base objects to be fixed + for (unsigned int indAttr = 0; indAttr < 2; indAttr++) { + if (!aBaseFeature[indAttr]) { + AttributeRefAttrPtr aConstrAttr = std::dynamic_pointer_cast( + aConstrData->attribute(aConstraintAttributes[indAttr])); + addTemporaryConstraintWhereDragged(aConstrAttr->attr()); + continue; + } + std::list anAttributes = - aBaseFeature[indAttr]->data()->attributes(GeomDataAPI_Point2D::type()); ++ aBaseFeature[indAttr]->data()->attributes(GeomDataAPI_Point2D::typeId()); + std::list::iterator anIt = anAttributes.begin(); + for ( ; anIt != anAttributes.end(); anIt++) { + // Arc should be fixed by center and start points only (to avoid "conflicting constraints" message) + if (aBaseFeature[indAttr]->getKind() == SketchPlugin_Arc::ID() && + (*anIt)->id() == SketchPlugin_Arc::END_ID()) + continue; + addTemporaryConstraintWhereDragged(*anIt); + } + } + return true; +} + // ============================================================================ // Function: changeEntity // Class: SketchSolver_ConstraintGroup