From 9775db177bfd744b9a8e85e5fbab0f2327e11183 Mon Sep 17 00:00:00 2001 From: nds Date: Tue, 14 Mar 2017 13:37:49 +0300 Subject: [PATCH] #2027 Sketcher Trim feature; Reference attribute in Point2D control instead of immediate coincidence constraint creation. --- src/PartSet/PartSet_Tools.cpp | 40 ++-- src/PartSet/PartSet_Tools.h | 13 +- src/PartSet/PartSet_WidgetPoint2d.cpp | 90 +++++++-- src/PartSet/PartSet_WidgetPoint2d.h | 10 +- src/SketchPlugin/CMakeLists.txt | 4 +- src/SketchPlugin/SketchPlugin_Arc.cpp | 3 + src/SketchPlugin/SketchPlugin_Arc.h | 7 + .../SketchPlugin_ConstraintSplit.cpp | 91 ++++----- .../SketchPlugin_ConstraintSplit.h | 8 +- src/SketchPlugin/SketchPlugin_Trim.cpp | 161 +++++++++------ src/SketchPlugin/SketchPlugin_Trim.h | 37 ++-- src/SketchPlugin/Test/TestSplit.py | 14 +- src/SketchPlugin/Test/TestTrimArc.py | 180 +++++++++++++++++ src/SketchPlugin/Test/TestTrimCircle.py | 64 +++++- src/SketchPlugin/Test/TestTrimLine.py | 191 ++++++++++++++++++ src/SketchPlugin/plugin-Sketch.xml | 2 +- 16 files changed, 715 insertions(+), 200 deletions(-) create mode 100644 src/SketchPlugin/Test/TestTrimArc.py create mode 100644 src/SketchPlugin/Test/TestTrimLine.py diff --git a/src/PartSet/PartSet_Tools.cpp b/src/PartSet/PartSet_Tools.cpp index 9affd9803..77f1344a1 100755 --- a/src/PartSet/PartSet_Tools.cpp +++ b/src/PartSet/PartSet_Tools.cpp @@ -353,30 +353,11 @@ std::shared_ptr PartSet_Tools::findFirstEqualPoint( return aFPoint; } -void PartSet_Tools::setConstraints(CompositeFeaturePtr theSketch, FeaturePtr theFeature, - const std::string& theAttribute, double theClickedX, - double theClickedY) +std::shared_ptr PartSet_Tools::findFirstEqualPointInSketch( + const CompositeFeaturePtr& theSketch, + const std::shared_ptr& theFeaturePoint, + const std::shared_ptr& thePoint) { - if (!theFeature.get()) - return; - - std::shared_ptr aClickedPoint = std::shared_ptr( - new GeomAPI_Pnt2d(theClickedX, theClickedY)); - - // find a feature point by the selection mode - std::shared_ptr aFeaturePoint; - if (theFeature->isMacro()) { - // the macro feature will be removed after the operation is stopped, so we need to build - // coicidence to possible sub-features - aFeaturePoint = PartSet_Tools::findFirstEqualPointInArgumentFeatures(theFeature, aClickedPoint); - } - else { - aFeaturePoint = std::dynamic_pointer_cast< - GeomDataAPI_Point2D>(theFeature->data()->attribute(theAttribute)); - } - if (!aFeaturePoint) - return; - // get all sketch features. If the point with the given coordinates belong to any sketch feature, // the constraint is created between the feature point and the found sketch point std::shared_ptr aData = theSketch->data(); @@ -386,15 +367,18 @@ void PartSet_Tools::setConstraints(CompositeFeaturePtr theSketch, FeaturePtr the std::list aFeatures = aRefList->list(); std::list::const_iterator anIt = aFeatures.begin(), aLast = aFeatures.end(); std::list > anAttiributes; + + FeaturePtr aFeatureOfPoint = ModelAPI_Feature::feature(theFeaturePoint->owner()); + std::shared_ptr aFPoint; for (; anIt != aLast; anIt++) { FeaturePtr aFeature = std::dynamic_pointer_cast(*anIt); - if (!aFeature.get() || (theFeature == aFeature) || (aFeaturePoint->owner() == aFeature)) + if (!aFeature.get() || aFeatureOfPoint == aFeature) continue; - std::shared_ptr aFPoint = PartSet_Tools::findFirstEqualPoint(aFeature, - aClickedPoint); - if (aFPoint) - PartSet_Tools::createConstraint(theSketch, aFPoint, aFeaturePoint); + aFPoint = PartSet_Tools::findFirstEqualPoint(aFeature, thePoint); + if (aFPoint.get()) + break; } + return aFPoint; } std::shared_ptr PartSet_Tools::sketchPlane(CompositeFeaturePtr theSketch) diff --git a/src/PartSet/PartSet_Tools.h b/src/PartSet/PartSet_Tools.h index b4b26139c..ef4659704 100755 --- a/src/PartSet/PartSet_Tools.h +++ b/src/PartSet/PartSet_Tools.h @@ -135,15 +135,10 @@ public: static std::shared_ptr findFirstEqualPoint(const FeaturePtr& theFeature, const std::shared_ptr& thePoint); - /// Creates constrains of the current - /// \param theSketch a sketch feature - /// \param theFeature a source feature - /// \param theAttribute a name of the requried attribute attribute - /// \param theClickedX the horizontal coordnate of the point - /// \param theClickedY the vertical coordnate of the point - static void setConstraints(CompositeFeaturePtr theSketch, FeaturePtr theFeature, - const std::string& theAttribute, double theClickedX, - double theClickedY); + static std::shared_ptr findFirstEqualPointInSketch( + const CompositeFeaturePtr& theSketch, + const std::shared_ptr& theFeaturePoint, + const std::shared_ptr& thePoint); /// Create a sketch plane instance /// \param theSketch a sketch feature diff --git a/src/PartSet/PartSet_WidgetPoint2d.cpp b/src/PartSet/PartSet_WidgetPoint2d.cpp index 2a7ef76fa..2fef715df 100644 --- a/src/PartSet/PartSet_WidgetPoint2d.cpp +++ b/src/PartSet/PartSet_WidgetPoint2d.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -70,6 +71,7 @@ PartSet_WidgetPoint2D::PartSet_WidgetPoint2D(QWidget* theParent, myValueIsCashed(false), myIsFeatureVisibleInCash(true), myXValueInCash(0), myYValueInCash(0) { + myRefAttribute = theData->getProperty("reference_attribute"); if (MyFeaturesForCoincedence.isEmpty()) { MyFeaturesForCoincedence << SketchPlugin_Line::ID().c_str() << SketchPlugin_Arc::ID().c_str() @@ -223,7 +225,8 @@ bool PartSet_WidgetPoint2D::setSelection(QList& theValu const TopoDS_Shape& aTDShape = aShape->impl(); if (getPoint2d(aView, aTDShape, aX, aY)) { isDone = setPoint(aX, aY); - PartSet_Tools::setConstraints(mySketch, feature(), attributeID(), aX, aY); + setConstraintTo(aX, aY); + //PartSet_Tools::setConstraints(mySketch, feature(), attributeID(), aX, aY); } } return isDone; @@ -390,9 +393,49 @@ bool PartSet_WidgetPoint2D::getPoint2d(const Handle(V3d_View)& theView, return false; } +bool PartSet_WidgetPoint2D::setConstraintTo(double theClickedX, double theClickedY) +{ + FeaturePtr aFeature = feature(); + std::string anAttribute = attributeID(); + + if (!aFeature.get()) + return false; + + std::shared_ptr aClickedPoint = std::shared_ptr( + new GeomAPI_Pnt2d(theClickedX, theClickedY)); + + // find a feature point by the selection mode + std::shared_ptr aFeaturePoint; + if (aFeature->isMacro()) { + // the macro feature will be removed after the operation is stopped, so we need to build + // coicidence to possible sub-features + aFeaturePoint = PartSet_Tools::findFirstEqualPointInArgumentFeatures(aFeature, aClickedPoint); + } + else { + aFeaturePoint = std::dynamic_pointer_cast< + GeomDataAPI_Point2D>(aFeature->data()->attribute(anAttribute)); + } + if (!aFeaturePoint.get()) + return false; + + std::shared_ptr aFPoint = PartSet_Tools::findFirstEqualPointInSketch( + mySketch, aFeaturePoint, aClickedPoint); + if (!aFPoint.get()) + return false; + + AttributeRefAttrPtr aRefAttr = attributeRefAttr(); + if (aRefAttr.get()) + aRefAttr->setAttr(aFPoint); + else + PartSet_Tools::createConstraint(mySketch, aFPoint, aFeaturePoint); + + return true; +} + bool PartSet_WidgetPoint2D::setConstraintWith(const ObjectPtr& theObject) { std::shared_ptr aFeaturePoint; + if (feature()->isMacro()) { AttributePtr aThisAttr = feature()->data()->attribute(attributeID()); std::shared_ptr anAttrPoint = @@ -411,22 +454,26 @@ bool PartSet_WidgetPoint2D::setConstraintWith(const ObjectPtr& theObject) if (!aFeaturePoint.get()) return false; - // Create point-edge coincedence - FeaturePtr aFeature = mySketch->addFeature(SketchPlugin_ConstraintCoincidence::ID()); - std::shared_ptr aData = aFeature->data(); - - std::shared_ptr aRef1 = std::dynamic_pointer_cast< - ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_A())); + AttributeRefAttrPtr aRefAttr = attributeRefAttr(); + if (aRefAttr.get()) + aRefAttr->setObject(theObject); + else { + // Create point-edge coincedence + FeaturePtr aFeature = mySketch->addFeature(SketchPlugin_ConstraintCoincidence::ID()); + std::shared_ptr aData = aFeature->data(); - aRef1->setAttr(aFeaturePoint); + std::shared_ptr aRef1 = std::dynamic_pointer_cast< + ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_A())); - std::shared_ptr aRef2 = std::dynamic_pointer_cast< - ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_B())); - aRef2->setObject(theObject); + aRef1->setAttr(aFeaturePoint); - // we need to flush created signal in order to coincidence is processed by solver - Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED)); + std::shared_ptr aRef2 = std::dynamic_pointer_cast< + ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_B())); + aRef2->setObject(theObject); + // we need to flush created signal in order to coincidence is processed by solver + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED)); + } return true; } @@ -525,7 +572,9 @@ void PartSet_WidgetPoint2D::mouseReleased(ModuleBase_IViewWindow* theWindow, QMo if (getPoint2d(aView, aShape, aX, aY)) { setPoint(aX, aY); feature()->execute(); - PartSet_Tools::setConstraints(mySketch, feature(), attributeID(), aX, aY); + + setConstraintTo(aX, aY); + //PartSet_Tools::setConstraints(mySketch, feature(), attributeID(), aX, aY); } else if (aShape.ShapeType() == TopAbs_EDGE) { // point is taken from mouse event and set in attribute. It should be done before setting @@ -748,3 +797,16 @@ bool PartSet_WidgetPoint2D::shapeContainsPoint(const GeomShapePtr& theShape, } return aContainPoint; } + +AttributeRefAttrPtr PartSet_WidgetPoint2D::attributeRefAttr() const +{ + AttributeRefAttrPtr anAttribute; + if (myRefAttribute.empty()) + return anAttribute; + + AttributePtr anAttributeRef = feature()->attribute(myRefAttribute); + if (!anAttributeRef.get()) + return anAttribute; + + return std::dynamic_pointer_cast(anAttributeRef); +} diff --git a/src/PartSet/PartSet_WidgetPoint2d.h b/src/PartSet/PartSet_WidgetPoint2d.h index 3de0dc147..2e17c1dd1 100755 --- a/src/PartSet/PartSet_WidgetPoint2d.h +++ b/src/PartSet/PartSet_WidgetPoint2d.h @@ -19,6 +19,7 @@ #include class ModelAPI_Feature; +class ModelAPI_AttributeRefAttr; class ModuleBase_IWorkshop; class ModuleBase_ParamSpinBox; class ModuleBase_IViewWindow; @@ -173,6 +174,11 @@ protected: bool getPoint2d(const Handle(V3d_View)& theView, const TopoDS_Shape& theShape, double& theX, double& theY) const; + /// Creates constrains of the clicked point + /// \param theClickedX the horizontal coordnate of the point + /// \param theClickedY the vertical coordnate of the point + bool setConstraintTo(double theClickedX, double theClickedY); + /// Create a coincidence constraint between the attribute and the parameter object /// \theObject a result object /// \return true if succed @@ -198,11 +204,12 @@ protected: const std::shared_ptr& thePoint, const CompositeFeaturePtr& theSketch); + std::shared_ptr attributeRefAttr() const; + protected: ModuleBase_IWorkshop* myWorkshop; ///< workshop private: - QGroupBox* myGroupBox; ///< the parent group box for all intenal widgets //ModuleBase_ParamSpinBox* myXSpin; ///< the spin box for the X coordinate //ModuleBase_ParamSpinBox* myYSpin; ///< the spin box for the Y coordinate @@ -215,6 +222,7 @@ private: /// it is important during restart operation CompositeFeaturePtr mySketch; + std::string myRefAttribute; /// if not empty, coincidences are not set but attribute is filled bool myValueIsCashed; /// boolean state if the value is cashed during value state change bool myIsFeatureVisibleInCash; /// boolean value if the feature was visible when cash if filled double myXValueInCash; /// the cashed X value during value state change diff --git a/src/SketchPlugin/CMakeLists.txt b/src/SketchPlugin/CMakeLists.txt index 5bb60a4cf..6553c6b18 100644 --- a/src/SketchPlugin/CMakeLists.txt +++ b/src/SketchPlugin/CMakeLists.txt @@ -153,4 +153,6 @@ ADD_UNIT_TESTS(TestSketchPointLine.py Test1924.py Test1966.py Test1967.py - TestTrimCircle.py ) + TestTrimArc.py + TestTrimCircle.py + TestTrimLine.py ) diff --git a/src/SketchPlugin/SketchPlugin_Arc.cpp b/src/SketchPlugin/SketchPlugin_Arc.cpp index c800c58f6..451b29875 100644 --- a/src/SketchPlugin/SketchPlugin_Arc.cpp +++ b/src/SketchPlugin/SketchPlugin_Arc.cpp @@ -101,6 +101,9 @@ void SketchPlugin_Arc::initDerivedClassAttributes() if (!isInversed->isInitialized()) isInversed->setValue(false); anArcType->setValue(ARC_TYPE_CENTER_START_END()); + + data()->addAttribute(CENTER_REF_ID(), ModelAPI_AttributeRefAttr::typeId()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_REF_ID()); } void SketchPlugin_Arc::execute() diff --git a/src/SketchPlugin/SketchPlugin_Arc.h b/src/SketchPlugin/SketchPlugin_Arc.h index 50ccbf323..1a5a5fc5e 100644 --- a/src/SketchPlugin/SketchPlugin_Arc.h +++ b/src/SketchPlugin/SketchPlugin_Arc.h @@ -73,6 +73,13 @@ class SketchPlugin_Arc : public SketchPlugin_SketchEntity, public GeomAPI_IPrese static const std::string MY_CENTER_ID = "ArcCenter"; return MY_CENTER_ID; } + + inline static const std::string& CENTER_REF_ID() + { + static const std::string MY_CENTER_REF_ID = "ArcCenterRef"; + return MY_CENTER_REF_ID; + } + /// Start 2D point of the arc inline static const std::string& START_ID() { diff --git a/src/SketchPlugin/SketchPlugin_ConstraintSplit.cpp b/src/SketchPlugin/SketchPlugin_ConstraintSplit.cpp index 38a0c067a..db8606551 100755 --- a/src/SketchPlugin/SketchPlugin_ConstraintSplit.cpp +++ b/src/SketchPlugin/SketchPlugin_ConstraintSplit.cpp @@ -98,9 +98,10 @@ void SketchPlugin_ConstraintSplit::execute() ResultPtr aBaseFeatureResult = getFeatureResult(aBaseFeature); std::set aFeaturesToDelete, aFeaturesToUpdate; - std::map aTangentFeatures; + //std::map aTangentFeatures; std::map aCoincidenceToFeature; - getConstraints(aFeaturesToDelete, aFeaturesToUpdate, aTangentFeatures, aCoincidenceToFeature); + getConstraints(aFeaturesToDelete, aFeaturesToUpdate, /*aTangentFeatures, */ + aCoincidenceToFeature); std::map > aBaseRefAttributes; std::list aRefsToFeature; @@ -141,7 +142,7 @@ void SketchPlugin_ConstraintSplit::execute() } } - if (!aTangentFeatures.empty()) { + /*if (!aTangentFeatures.empty()) { std::cout << std::endl; std::cout << "Tangencies to base feature[" << aTangentFeatures.size() << "]: " << std::endl; std::map::const_iterator anIt = aTangentFeatures.begin(), @@ -156,7 +157,7 @@ void SketchPlugin_ConstraintSplit::execute() std::cout << " -Point attribute:" << ModelGeomAlgo_Point2D::getPointAttributeInfo(aPointAttr) << std::endl; } - } + }*/ std::map >::const_iterator aRefIt = aBaseRefAttributes.begin(), aRefLast = aBaseRefAttributes.end(); @@ -286,7 +287,7 @@ void SketchPlugin_ConstraintSplit::execute() updateCoincidenceConstraintsToFeature(aCoincidenceToFeature, aFurtherCoincidences, aFeatureResults, aSplitFeature); // tangency - updateTangentConstraintsToFeature(aTangentFeatures, aFurtherCoincidences); + //updateTangentConstraintsToFeature(aTangentFeatures, aFurtherCoincidences); updateRefAttConstraints(aBaseRefAttributes, aModifiedAttributes); @@ -439,7 +440,7 @@ void SketchPlugin_ConstraintSplit::getFeaturePoints(const FeaturePtr& theFeature void SketchPlugin_ConstraintSplit::getConstraints(std::set& theFeaturesToDelete, std::set& theFeaturesToUpdate, - std::map& theTangentFeatures, + //std::map& theTangentFeatures, std::map& theCoincidenceToFeature) { std::shared_ptr aData = data(); @@ -466,7 +467,7 @@ void SketchPlugin_ConstraintSplit::getConstraints(std::set& theFeatu theFeaturesToDelete.insert(aRefFeature); else if (aRefFeatureKind == SketchPlugin_ConstraintLength::ID()) theFeaturesToUpdate.insert(aRefFeature); - else if (aRefFeatureKind == SketchPlugin_ConstraintTangent::ID()) { + /*else if (aRefFeatureKind == SketchPlugin_ConstraintTangent::ID()) { if (aBaseFeature->getKind() == SketchPlugin_Circle::ID()) /// TEMPORARY limitaion /// until tangency between arc and line is implemented theFeaturesToDelete.insert(aRefFeature); @@ -505,7 +506,7 @@ void SketchPlugin_ConstraintSplit::getConstraints(std::set& theFeatu theFeaturesToDelete.insert(aRefFeature); } } - else if (aRefFeatureKind == SketchPlugin_ConstraintCoincidence::ID()) { + */else if (aRefFeatureKind == SketchPlugin_ConstraintCoincidence::ID()) { std::string anAttributeToBeModified; AttributePoint2DPtr aCoincidentPoint; AttributeRefAttrPtr anAttrA = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_A()); @@ -681,43 +682,43 @@ void SketchPlugin_ConstraintSplit::updateCoincidenceConstraintsToFeature( } } -void SketchPlugin_ConstraintSplit::updateTangentConstraintsToFeature( - const std::map, IdToPointPair>& theTangentFeatures, - const std::set >& theFurtherCoincidences) -{ - if (theTangentFeatures.empty()) - return; - - std::map::const_iterator aTIt = theTangentFeatures.begin(), - aTLast = theTangentFeatures.end(); -#ifdef DEBUG_SPLIT - std::cout << std::endl; - std::cout << "Tangencies to feature(modified):"<< std::endl; -#endif - for (; aTIt != aTLast; aTIt++) { - FeaturePtr aTangentFeature = aTIt->first; - std::string anAttributeId = aTIt->second.first; - AttributePoint2DPtr aTangentPoint = aTIt->second.second; - std::set::const_iterator aFCIt = theFurtherCoincidences.begin(), - aFCLast = theFurtherCoincidences.end(); - std::shared_ptr aCoincPnt = aTangentPoint->pnt(); - AttributePoint2DPtr aFeaturePointAttribute; - /// here we rely on created coincidence between further coincidence point and tangent result - for (; aFCIt != aFCLast && !aFeaturePointAttribute.get(); aFCIt++) { - AttributePoint2DPtr aFCAttribute = *aFCIt; - if (aCoincPnt->isEqual(aFCAttribute->pnt())) - aFeaturePointAttribute = aFCAttribute; - } - if (aFeaturePointAttribute.get()) { - FeaturePtr aFeature = - std::dynamic_pointer_cast(aFeaturePointAttribute->owner()); - aTangentFeature->refattr(anAttributeId)->setObject(getFeatureResult(aFeature)); - } -#ifdef DEBUG_SPLIT - std::cout << " -" << getFeatureInfo(aTangentFeature) << std::endl; -#endif - } -} +//void SketchPlugin_ConstraintSplit::updateTangentConstraintsToFeature( +// const std::map, IdToPointPair>& theTangentFeatures, +// const std::set >& theFurtherCoincidences) +//{ +// if (theTangentFeatures.empty()) +// return; +// +// std::map::const_iterator aTIt = theTangentFeatures.begin(), +// aTLast = theTangentFeatures.end(); +//#ifdef DEBUG_SPLIT +// std::cout << std::endl; +// std::cout << "Tangencies to feature(modified):"<< std::endl; +//#endif +// for (; aTIt != aTLast; aTIt++) { +// FeaturePtr aTangentFeature = aTIt->first; +// std::string anAttributeId = aTIt->second.first; +// AttributePoint2DPtr aTangentPoint = aTIt->second.second; +// std::set::const_iterator aFCIt = theFurtherCoincidences.begin(), +// aFCLast = theFurtherCoincidences.end(); +// std::shared_ptr aCoincPnt = aTangentPoint->pnt(); +// AttributePoint2DPtr aFeaturePointAttribute; +// /// here we rely on created coincidence between further coincidence point and tangent result +// for (; aFCIt != aFCLast && !aFeaturePointAttribute.get(); aFCIt++) { +// AttributePoint2DPtr aFCAttribute = *aFCIt; +// if (aCoincPnt->isEqual(aFCAttribute->pnt())) +// aFeaturePointAttribute = aFCAttribute; +// } +// if (aFeaturePointAttribute.get()) { +// FeaturePtr aFeature = +// std::dynamic_pointer_cast(aFeaturePointAttribute->owner()); +// aTangentFeature->refattr(anAttributeId)->setObject(getFeatureResult(aFeature)); +// } +//#ifdef DEBUG_SPLIT +// std::cout << " -" << getFeatureInfo(aTangentFeature) << std::endl; +//#endif +// } +//} void SketchPlugin_ConstraintSplit::updateRefFeatureConstraints( const ResultPtr& theFeatureBaseResult, diff --git a/src/SketchPlugin/SketchPlugin_ConstraintSplit.h b/src/SketchPlugin/SketchPlugin_ConstraintSplit.h index bf5fcc2dd..39bf2c03e 100755 --- a/src/SketchPlugin/SketchPlugin_ConstraintSplit.h +++ b/src/SketchPlugin/SketchPlugin_ConstraintSplit.h @@ -112,7 +112,7 @@ private: /// \param theCoincidenceToPoint [out] coincidence to point be connected to new feature void getConstraints(std::set>& theFeaturesToDelete, std::set>& theFeaturesToUpdate, - std::map, IdToPointPair>& theTangentFeatures, + //std::map, IdToPointPair>& theTangentFeatures, std::map, IdToPointPair>& theCoincidenceToFeature/*, std::map, IdToPointPair>& theCoincidenceToPoint*/); @@ -142,9 +142,9 @@ private: /// Move tangency constraint to the nearest split feature that has a coincidence to the tangent /// \param theTangentFeatures tangencies to feature to be connected to nearest feature /// \param theFurtherCoincidences a list of points where coincidences is built - void updateTangentConstraintsToFeature( - const std::map, IdToPointPair>& theTangentFeatures, - const std::set >& theFurtherCoincidences); + //void updateTangentConstraintsToFeature( + // const std::map, IdToPointPair>& theTangentFeatures, + // const std::set >& theFurtherCoincidences); /// Move constraints from base feature to given feature diff --git a/src/SketchPlugin/SketchPlugin_Trim.cpp b/src/SketchPlugin/SketchPlugin_Trim.cpp index d8663ee54..daab0d607 100644 --- a/src/SketchPlugin/SketchPlugin_Trim.cpp +++ b/src/SketchPlugin/SketchPlugin_Trim.cpp @@ -176,21 +176,27 @@ void SketchPlugin_Trim::execute() std::shared_ptr aLastShapePoint2d = convertPoint(aLastShapePoint); - std::set aFeaturesToDelete, aFeaturesToUpdate; - getConstraints(aFeaturesToDelete, aFeaturesToUpdate); + std::set aFeaturesToDelete; + getConstraints(aFeaturesToDelete); std::map > aBaseRefAttributes; std::list aRefsToFeature; getRefAttributes(aBaseFeature, aBaseRefAttributes, aRefsToFeature); + + // coincidence to result points + // find coincidences to the base object, it should be used when attribute is found + // in myObjectToPoints + std::map aCoincidencesToBaseFeature; + getCoincidencesToObject(aBaseObject, aCoincidencesToBaseFeature); + std::set aFurtherCoincidences; - std::set aCreatedFeatures; std::set> aModifiedAttributes; const std::string& aKind = aBaseFeature->getKind(); + FeaturePtr aReplacingFeature; if (aKind == SketchPlugin_Circle::ID()) { - trimCircle(aStartShapePoint2d, aLastShapePoint2d, - aFurtherCoincidences, aCreatedFeatures, aModifiedAttributes); - updateRefFeatureConstraints(getFeatureResult(aBaseFeature), aRefsToFeature); + aReplacingFeature = trimCircle(aStartShapePoint2d, aLastShapePoint2d, + aFurtherCoincidences, aModifiedAttributes); aFeaturesToDelete.insert(aBaseFeature); // as circle is removed, temporary fill this attribute @@ -198,14 +204,14 @@ void SketchPlugin_Trim::execute() } else if (aKind == SketchPlugin_Line::ID()) { trimLine(aStartShapePoint2d, aLastShapePoint2d, - aFurtherCoincidences, aCreatedFeatures, aModifiedAttributes); + aFurtherCoincidences, aModifiedAttributes); } else if (aKind == SketchPlugin_Arc::ID()) { trimArc(aStartShapePoint2d, aLastShapePoint2d, - aFurtherCoincidences, aCreatedFeatures, aModifiedAttributes); + aFurtherCoincidences, aModifiedAttributes); } - // coincidence to result points + // const PointToRefsMap& aRefsMap = myObjectToPoints.at(aBaseObject); std::set::const_iterator anIt = aFurtherCoincidences.begin(), aLast = aFurtherCoincidences.end(); @@ -233,8 +239,25 @@ void SketchPlugin_Trim::execute() } const std::list& anAttributes = anInfo.first; for (std::list::const_iterator anAttrIt = anAttributes.begin(); - anAttrIt != anAttributes.end(); anAttrIt++) { - createConstraint(SketchPlugin_ConstraintCoincidence::ID(), aPointAttribute, *anAttrIt); + anAttrIt != anAttributes.end(); anAttrIt++) { + AttributePtr anAttribute = *anAttrIt; + if (aCoincidencesToBaseFeature.find(anAttribute) != aCoincidencesToBaseFeature.end()) + { + FeaturePtr anAttrFeature = aCoincidencesToBaseFeature.at(anAttribute); + AttributePtr anOtherAttribute; + if (std::dynamic_pointer_cast + (anAttrFeature->attribute(SketchPlugin_Constraint::ENTITY_A()))->attr() == anAttribute) + anOtherAttribute = anAttrFeature->attribute(SketchPlugin_Constraint::ENTITY_B()); + else if (std::dynamic_pointer_cast + (anAttrFeature->attribute(SketchPlugin_Constraint::ENTITY_B()))->attr() == anAttribute) + anOtherAttribute = anAttrFeature->attribute(SketchPlugin_Constraint::ENTITY_A()); + else + continue; + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast + (anOtherAttribute); + if (aRefAttr.get()) + aRefAttr->setAttr(aPointAttribute); + } } const std::list& anObjects = anInfo.second; @@ -245,6 +268,28 @@ void SketchPlugin_Trim::execute() } } + // move constraints from base feature to replacing feature: ignore coincidences to feature + // if attributes of coincidence participated in split + if (aReplacingFeature.get()) { + ResultPtr aReplacingResult = getFeatureResult(aReplacingFeature); + std::list::const_iterator anIt = aRefsToFeature.begin(), + aLast = aRefsToFeature.end(); + for (; anIt != aLast; anIt++) { + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(*anIt); + if (!aRefAttr.get()) + continue; + FeaturePtr anAttrFeature = ModelAPI_Feature::feature(aRefAttr->owner()); + if (anAttrFeature.get() && + anAttrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) + { + if (anAttrFeature->attribute(SketchPlugin_Constraint::ENTITY_A()) == aRefAttr || + anAttrFeature->attribute(SketchPlugin_Constraint::ENTITY_B()) == aRefAttr) + continue; + } + aRefAttr->setObject(aReplacingResult); + } + } + // Wait all constraints being created, then send update events static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent); @@ -363,8 +408,7 @@ void SketchPlugin_Trim::getFeaturePoints(const FeaturePtr& theFeature, } } -void SketchPlugin_Trim::getConstraints(std::set& theFeaturesToDelete, - std::set& theFeaturesToUpdate) +void SketchPlugin_Trim::getConstraints(std::set& theFeaturesToDelete) { std::shared_ptr aData = data(); @@ -388,45 +432,6 @@ void SketchPlugin_Trim::getConstraints(std::set& theFeaturesToDelete aRefFeatureKind == SketchPlugin_MultiTranslation::ID() || aRefFeatureKind == SketchPlugin_ConstraintMiddle::ID()) theFeaturesToDelete.insert(aRefFeature); - else if (aRefFeatureKind == SketchPlugin_ConstraintLength::ID()) - theFeaturesToUpdate.insert(aRefFeature); - else if (aRefFeatureKind == SketchPlugin_ConstraintTangent::ID()) { - if (aBaseFeature->getKind() == SketchPlugin_Circle::ID()) /// TEMPORARY limitaion - /// until tangency between arc and line is implemented - theFeaturesToDelete.insert(aRefFeature); - else { - std::string anAttributeToBeModified; - AttributePoint2DPtr aTangentPoint; - ObjectPtr aResult1 = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_A())->object(); - ObjectPtr aResult2 = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_B())->object(); - if (aResult1.get() && aResult2.get()) { - FeaturePtr aCoincidenceFeature = - SketchPlugin_ConstraintCoincidence::findCoincidenceFeature - (ModelAPI_Feature::feature(aResult1), - ModelAPI_Feature::feature(aResult2)); - // get the point not lying on the splitting feature - for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) { - AttributeRefAttrPtr aRefAttr = aCoincidenceFeature->refattr( - SketchPlugin_Trim::BASE_OBJECT()); - if (!aRefAttr || aRefAttr->isObject()) - continue; - AttributePoint2DPtr aPoint = - std::dynamic_pointer_cast(aRefAttr->attr()); - if (!aPoint) - continue; - if (aPoint->owner() != aBaseFeature) { - aTangentPoint = aPoint; - break; - } - } - } - if (aTangentPoint.get()) { - // collect tangent feaures - } - else /// there is not coincident point between tangent constraint - theFeaturesToDelete.insert(aRefFeature); - } - } } } @@ -476,16 +481,39 @@ void SketchPlugin_Trim::getRefAttributes(const FeaturePtr& theFeature, } } -void SketchPlugin_Trim::updateRefFeatureConstraints( - const ResultPtr& theFeatureBaseResult, - const std::list& theRefsToFeature) +void SketchPlugin_Trim::getCoincidencesToObject(const ObjectPtr& theObject, + std::map& theCoincidencesToBaseFeature) { - std::list::const_iterator anIt = theRefsToFeature.begin(), - aLast = theRefsToFeature.end(); - for (; anIt != aLast; anIt++) { - AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(*anIt); - if (aRefAttr.get()) - aRefAttr->setObject(theFeatureBaseResult); + const std::set& aRefsList = theObject->data()->refsToMe(); + std::set::const_iterator aIt; + for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) { + std::shared_ptr aAttr = (*aIt); + FeaturePtr aRefFeature = std::dynamic_pointer_cast(aAttr->owner()); + if (aRefFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID()) + continue; + AttributePtr anAttribute; + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast + (aRefFeature->attribute(SketchPlugin_Constraint::ENTITY_A())); + if (aRefAttr->isObject() && aRefAttr->object() == theObject) + { + anAttribute = aRefFeature->attribute(SketchPlugin_Constraint::ENTITY_B()); + } + else { + aRefAttr = std::dynamic_pointer_cast + (aRefFeature->attribute(SketchPlugin_Constraint::ENTITY_B())); + if (aRefAttr->isObject() && aRefAttr->object() == theObject) + { + anAttribute = aRefFeature->attribute(SketchPlugin_Constraint::ENTITY_A()); + } + if (anAttribute.get()) + { + aRefAttr = std::dynamic_pointer_cast + (anAttribute); + anAttribute = aRefAttr->attr(); + if (anAttribute.get()) + theCoincidencesToBaseFeature[anAttribute] = aRefFeature; + } + } } } @@ -530,7 +558,6 @@ void SketchPlugin_Trim::updateRefAttConstraints( void SketchPlugin_Trim::trimLine(const std::shared_ptr& theStartShapePoint, const std::shared_ptr& theLastShapePoint, std::set& thePoints, - std::set& theCreatedFeatures, std::set>& theModifiedAttributes) { // Check the base objects are initialized. @@ -612,7 +639,6 @@ void SketchPlugin_Trim::trimLine(const std::shared_ptr& theStartS void SketchPlugin_Trim::trimArc(const std::shared_ptr& theStartShapePoint, const std::shared_ptr& theLastShapePoint, std::set& thePoints, - std::set& theCreatedFeatures, std::set>& theModifiedAttributes) { // Check the base objects are initialized. @@ -694,10 +720,9 @@ void SketchPlugin_Trim::trimArc(const std::shared_ptr& theStartSh } } -void SketchPlugin_Trim::trimCircle(const std::shared_ptr& theStartShapePoint, +FeaturePtr SketchPlugin_Trim::trimCircle(const std::shared_ptr& theStartShapePoint, const std::shared_ptr& theLastShapePoint, std::set& thePoints, - std::set& theCreatedFeatures, std::set>& theModifiedAttributes) { // Check the base objects are initialized. @@ -707,8 +732,8 @@ void SketchPlugin_Trim::trimCircle(const std::shared_ptr& theStar FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value()); /// points of trim - AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase; - getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase); + //AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase; + //getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase); /// trim feature FeaturePtr anArcFeature = createArcFeature(aBaseFeature, theStartShapePoint, theLastShapePoint); @@ -721,6 +746,8 @@ void SketchPlugin_Trim::trimCircle(const std::shared_ptr& theStar (anArcFeature->attribute(SketchPlugin_Arc::START_ID()))); thePoints.insert(std::dynamic_pointer_cast (anArcFeature->attribute(SketchPlugin_Arc::END_ID()))); + + return anArcFeature; } void SketchPlugin_Trim::arrangePointsOnLine(const AttributePoint2DPtr& theStartPointAttr, diff --git a/src/SketchPlugin/SketchPlugin_Trim.h b/src/SketchPlugin/SketchPlugin_Trim.h index b31503128..9f3702f84 100644 --- a/src/SketchPlugin/SketchPlugin_Trim.h +++ b/src/SketchPlugin/SketchPlugin_Trim.h @@ -91,9 +91,7 @@ private: /// Obtains those constraints of the feature that should be modified. output maps contain /// point of coincidence and attribute id to be modified after split /// \param theFeaturesToDelete [out] constrains that will be deleted after split - /// \param theFeaturesToUpdate [out] constrains that will be updated after split - void getConstraints(std::set>& theFeaturesToDelete, - std::set>& theFeaturesToUpdate); + void getConstraints(std::set>& theFeaturesToDelete); /// Obtains references to feature point attributes and to feature, /// e.g. for feature line: 1st container is @@ -106,11 +104,12 @@ private: std::map >& theRefs, std::list& theRefsToFeature); - /// Move constraints from base feature to given feature - /// \param theFeature a base feature - /// \param theRefsToFeature list of attributes referenced to base feature - void updateRefFeatureConstraints(const std::shared_ptr& theFeatureBaseResult, - const std::list& theRefsToFeature); + /// Obtains coincident features to the given object. It is collected in a container + /// by the coincident attribute + /// \param theObject an investigated object + /// \param theCoincidencesToBaseFeature a container of list of referenced attributes + void getCoincidencesToObject(const ObjectPtr& theObject, + std::map& theCoincidencesToBaseFeature); /// Move constraints from attribute of base feature to attribute after modification /// \param theBaseRefAttributes container of references to the attributes of base feature @@ -121,18 +120,16 @@ private: const std::set >& theModifiedAttributes, std::set>& theFeaturesToDelete); -// /// Make the base object is splitted by the point attributes -// /// \param theSplitFeature a result split feature -// /// \param theBeforeFeature a feature between start point and the 1st point of split feature -// /// \param theAfterFeature a feature between last point of split feature and the end point -// /// \param thePoints a list of points where coincidences will be build -// /// \param theCreatedFeatures a container of created features -// /// \param theModifiedAttributes a container of attribute on base -// /// feature to attribute on new feature + /// Make the base object is splitted by the point attributes + /// \param theSplitFeature a result split feature + /// \param theBeforeFeature a feature between start point and the 1st point of split feature + /// \param theAfterFeature a feature between last point of split feature and the end point + /// \param thePoints a list of points where coincidences will be build + /// \param theModifiedAttributes a container of attribute on base + /// feature to attribute on new feature void trimLine(const std::shared_ptr& theStartShapePoint, const std::shared_ptr& theLastShapePoint, std::set >& thePoints, - std::set>& theCreatedFeatures, std::set>& theModifiedAttributes); /// Make the base object is splitted by the point attributes @@ -140,11 +137,9 @@ private: /// \param theBeforeFeature a feature between start point and the 1st point of split feature /// \param theAfterFeature a feature between last point of split feature and the end point /// \param thePoints a list of points where coincidences will be build - /// \param theCreatedFeatures a container of created features void trimArc(const std::shared_ptr& theStartShapePoint, const std::shared_ptr& theLastShapePoint, std::set >& thePoints, - std::set>& theCreatedFeatures, std::set>& theModifiedAttributes); /// Make the base object is splitted by the point attributes @@ -152,11 +147,9 @@ private: /// \param theBeforeFeature a feature between start point and the 1st point of split feature /// \param theAfterFeature a feature between last point of split feature and the end point /// \param thePoints a list of points where coincidences will be build - /// \param theCreatedFeatures a container of created features - void trimCircle(const std::shared_ptr& theStartShapePoint, + FeaturePtr trimCircle(const std::shared_ptr& theStartShapePoint, const std::shared_ptr& theLastShapePoint, std::set >& thePoints, - std::set>& theCreatedFeatures, std::set>& theModifiedAttributes); /// Correct the first and the second point to provide condition that the first is closer to diff --git a/src/SketchPlugin/Test/TestSplit.py b/src/SketchPlugin/Test/TestSplit.py index addf8e462..9d81de1cd 100644 --- a/src/SketchPlugin/Test/TestSplit.py +++ b/src/SketchPlugin/Test/TestSplit.py @@ -30,7 +30,7 @@ for index in range(Sketch_1_feature.numberOfSubs()): assert(idList.count(SketchLineId) == 2) assert(idList.count(SketchPointId) == 1) assert(idList.count(SketchConstraintCoincidenceId) == 3) -assert(idList.count(SketchConstraintParallelId) == 1) +assert(idList.count(SketchConstraintParallelId) == 0) # Test end # Test split on line with two points @@ -51,7 +51,7 @@ for index in range(Sketch_2_feature.numberOfSubs()): assert(idList.count(SketchLineId) == 3) assert(idList.count(SketchPointId) == 2) assert(idList.count(SketchConstraintCoincidenceId) == 6) -assert(idList.count(SketchConstraintParallelId) == 2) +assert(idList.count(SketchConstraintParallelId) == 0) # Test end # Test split on circle with two points @@ -72,7 +72,7 @@ for index in range(Sketch_3_feature.numberOfSubs()): assert(idList.count(SketchArcId) == 2) assert(idList.count(SketchPointId) == 2) assert(idList.count(SketchConstraintCoincidenceId) == 6) -assert(idList.count(SketchConstraintTangentId) == 1) +assert(idList.count(SketchConstraintTangentId) == 0) # Test end # Test split on arc with one point @@ -94,8 +94,8 @@ for index in range(Sketch_4_feature.numberOfSubs()): assert(idList.count(SketchArcId) == 2) assert(idList.count(SketchPointId) == 1) assert(idList.count(SketchConstraintCoincidenceId) == 3) -assert(idList.count(SketchConstraintEqualId) == 1) -assert(idList.count(SketchConstraintTangentId) == 1) +assert(idList.count(SketchConstraintEqualId) == 0) +assert(idList.count(SketchConstraintTangentId) == 0) # Test end # Test split on arc with two points @@ -120,8 +120,8 @@ for index in range(Sketch_5_feature.numberOfSubs()): assert(idList.count(SketchArcId) == 3) assert(idList.count(SketchPointId) == 0) assert(idList.count(SketchConstraintCoincidenceId) == 6) -assert(idList.count(SketchConstraintEqualId) == 2) -assert(idList.count(SketchConstraintTangentId) == 2) +assert(idList.count(SketchConstraintEqualId) == 0) +assert(idList.count(SketchConstraintTangentId) == 0) # Test end model.end() diff --git a/src/SketchPlugin/Test/TestTrimArc.py b/src/SketchPlugin/Test/TestTrimArc.py new file mode 100644 index 000000000..24c24ed3a --- /dev/null +++ b/src/SketchPlugin/Test/TestTrimArc.py @@ -0,0 +1,180 @@ +from salome.shaper import model + +from ModelAPI import * +from GeomDataAPI import * +from salome.shaper import geom +import math + +TOLERANCE = 1.e-7 + +SketchPointId = 'SketchPoint' +SketchLineId = 'SketchLine' +SketchArcId = 'SketchArc' +SketchCircleId = 'SketchCircle' +SketchConstraintCoincidenceId = 'SketchConstraintCoincidence' +SketchConstraintMirrorId = 'SketchConstraintMirror' +SketchConstraintTangentId = 'SketchConstraintTangent' +SketchConstraintEqualId = 'SketchConstraintEqual' + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() + +# Test1:begin split on circle with coincident point and intersection line : smaller part +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchArc_1_1 = Sketch_1.addArc(50, 50, 55, 70, 30, 45, True) +SketchLine_1_1 = Sketch_1.addLine(50, 30, 100, 30) +SketchLine_1_2 = Sketch_1.addLine(60, 50, 100, 30) + +SketchConstraintCoincidence_1_1 = Sketch_1.setCoincident(SketchLine_1_1.startPoint(), SketchArc_1_1.results()[1]) +SketchConstraintCoincidence_1_2 = Sketch_1.setCoincident(SketchLine_1_1.endPoint(), SketchLine_1_2.endPoint()) +GeomPoint_1_1 = geom.Pnt2d(60, 35) + +#check number of features before trim +Sketch_1_feature = featureToCompositeFeature(Sketch_1.feature()) +idList_before_1 = [] +for index in range(Sketch_1_feature.numberOfSubs()): + idList_before_1.append(Sketch_1_feature.subFeature(index).getKind()) +assert(idList_before_1.count(SketchArcId) == 1) +assert(idList_before_1.count(SketchLineId) == 2) +assert(idList_before_1.count(SketchConstraintCoincidenceId) == 2) +assert(idList_before_1.count(SketchConstraintEqualId) == 0) + +#perform trim +SketchTrim_1_1 = Sketch_1.addTrim(SketchArc_1_1, GeomPoint_1_1) +SketchTrim_1_1.execute() +model.do() + +#check number of features after trim +SketchFeatures = featureToCompositeFeature(Sketch_1.feature()) +idList_after_1 = [] +for SubIndex in range(SketchFeatures.numberOfSubs()): + SubFeature = SketchFeatures.subFeature(SubIndex) + idList_after_1.append(SubFeature.getKind()) + +assert(idList_after_1.count(SketchArcId) == 2) +assert(idList_after_1.count(SketchLineId) == 2) +aCount = idList_after_1.count(SketchConstraintCoincidenceId) + +assert(idList_after_1.count(SketchConstraintCoincidenceId) == 4) +assert(idList_after_1.count(SketchConstraintEqualId) == 1) +# Test1:end + +# Test2: split on circle with coincident point and intersection line : largest part +Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +move_test_delta_y = 100 +move_test_delta_x = 0 +SketchCircle_2_1 = Sketch_2.addCircle(50, 50 + move_test_delta_y, 20) +SketchLine_2_1 = Sketch_2.addLine(50, 30 + move_test_delta_y, 100, 30 + move_test_delta_y) +SketchLine_2_2 = Sketch_2.addLine(60, 50 + move_test_delta_y, 100, 30 + move_test_delta_y) + +SketchConstraintCoincidence_2_1 = Sketch_2.setCoincident(SketchLine_2_1.startPoint(), SketchCircle_2_1.results()[1]) +SketchConstraintCoincidence_2_2 = Sketch_2.setCoincident(SketchLine_2_1.endPoint(), SketchLine_2_2.endPoint()) +GeomPoint_2_1 = geom.Pnt2d(50, 75 + move_test_delta_y) + +#check number of features before trim +Sketch_2_feature = featureToCompositeFeature(Sketch_2.feature()) +idList_before_2 = [] +for index in range(Sketch_2_feature.numberOfSubs()): + idList_before_2.append(Sketch_2_feature.subFeature(index).getKind()) +assert(idList_before_2.count(SketchCircleId) == 1) +assert(idList_before_2.count(SketchArcId) == 0) +assert(idList_before_2.count(SketchLineId) == 2) +assert(idList_before_2.count(SketchConstraintCoincidenceId) == 2) + +#perform trim +SketchTrim_2_1 = Sketch_2.addTrim(SketchCircle_2_1, GeomPoint_2_1) +SketchTrim_2_1.execute() +model.do() + +#check number of features after trim +SketchFeatures = featureToCompositeFeature(Sketch_2.feature()) +idList_after_2 = [] +for SubIndex in range(SketchFeatures.numberOfSubs()): + SubFeature = SketchFeatures.subFeature(SubIndex) + idList_after_2.append(SubFeature.getKind()) + if SubFeature.getKind() == SketchArcId: + ArcFeature_2 = SubFeature + + +assert(idList_after_2.count(SketchCircleId) == 0) +assert(idList_after_2.count(SketchArcId) == 1) +assert(idList_after_2.count(SketchLineId) == 2) +assert(idList_after_2.count(SketchConstraintCoincidenceId) == 3) + +#test created arc : it is not inversed, has coincidence to start line point +anInversed_2 = ArcFeature_2.boolean("InversedArc").value() +assert(anInversed_2 == False) +ArcPoint_2 = geomDataAPI_Point2D(ArcFeature_2.attribute("ArcStartPoint")) +LinePoint_2 = geomDataAPI_Point2D(SketchLine_2_1.startPoint()) +aDistance_2 = math.hypot(LinePoint_2.x() - ArcPoint_2.x(), LinePoint_2.y() - ArcPoint_2.y()) +#print "Distance " + repr(aDistance_2) +assert (math.fabs(aDistance_2) <= TOLERANCE) +# Test2:end + + +# Test3: constraints to circle +Sketch_3 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchCircle_3_1 = Sketch_3.addCircle(150, 50, 25) +SketchLine_3_1 = Sketch_3.addLine(160, 30, 200, 30) +SketchLine_3_2 = Sketch_3.addLine(160, 50, 200, 30) +SketchLine_3_3 = Sketch_3.addLine(240, 120, 280, 100) +SketchCircle_3_2 = Sketch_3.addCircle(150, 120, 20) +aSketchPoint_3 = Sketch_3.addPoint(145, 70) +SketchLine_3_4 = Sketch_3.addLine(120, 25, 120, 70) + +SketchConstraintCoincidence_3_1 = Sketch_3.setCoincident(SketchLine_3_1.startPoint(), SketchCircle_3_1.results()[1]) +SketchConstraintCoincidence_3_2 = Sketch_3.setCoincident(SketchLine_3_1.endPoint(), SketchLine_3_2.endPoint()) +GeomPoint_3_1 = geom.Pnt2d(165, 40) + +#Constraints +aConstraint_3_1 = Sketch_3.setDistance(SketchLine_3_1.endPoint(), SketchCircle_3_1.center(), 50) +aConstraint_3_2 = Sketch_3.setEqual(SketchCircle_3_1.results()[1], SketchCircle_3_2.results()[1]) +aConstraint_3_3 = Sketch_3.setRadius(SketchCircle_3_1.results()[1], 25) +aConstraint_3_4 = Sketch_3.setCoincident(SketchCircle_3_1.results()[1], aSketchPoint_3.results()[0]) +aConstraint_3_4 = Sketch_3.setTangent(SketchCircle_3_1.results()[1], SketchLine_3_4.results()[0]) + +MirrorObjects_3 = [SketchCircle_3_1.results()[1], SketchCircle_3_2.results()[1]] +aConstraint_3_5 = Sketch_3.addMirror(SketchLine_3_3.result(), MirrorObjects_3) + +#check number of features before trim +Sketch_3_feature = featureToCompositeFeature(Sketch_3.feature()) +idList_before_3 = [] +for index in range(Sketch_3_feature.numberOfSubs()): + idList_before_3.append(Sketch_3_feature.subFeature(index).getKind()) + +assert(idList_before_3.count(SketchCircleId) == 4) +assert(idList_before_3.count(SketchArcId) == 0) +assert(idList_before_3.count(SketchLineId) == 4) +assert(idList_before_3.count(SketchConstraintCoincidenceId) == 3) +assert(idList_before_3.count(SketchConstraintMirrorId) == 1) +assert(idList_before_3.count(SketchConstraintTangentId) == 1) +assert(idList_before_3.count(SketchConstraintEqualId) == 1) + +#perform trim +SketchTrim_3_1 = Sketch_3.addTrim(SketchCircle_3_1, GeomPoint_3_1) +SketchTrim_3_1.execute() +model.do() + +#check number of features after trim +SketchFeatures = featureToCompositeFeature(Sketch_3.feature()) +idList_after_3 = [] +for SubIndex in range(SketchFeatures.numberOfSubs()): + SubFeature = SketchFeatures.subFeature(SubIndex) + idList_after_3.append(SubFeature.getKind()) + + +assert(idList_after_3.count(SketchCircleId) == 3) +assert(idList_after_3.count(SketchArcId) == 1) +assert(idList_after_3.count(SketchLineId) == 4) +assert(idList_after_3.count(SketchConstraintCoincidenceId) == 3) +assert(idList_after_3.count(SketchConstraintMirrorId) == 0) +assert(idList_after_3.count(SketchConstraintTangentId) == 1) +assert(idList_after_3.count(SketchConstraintEqualId) == 1) +# Test3:end + + +model.end() + +#assert(model.checkPythonDump()) diff --git a/src/SketchPlugin/Test/TestTrimCircle.py b/src/SketchPlugin/Test/TestTrimCircle.py index aecbb4efa..b8acec087 100644 --- a/src/SketchPlugin/Test/TestTrimCircle.py +++ b/src/SketchPlugin/Test/TestTrimCircle.py @@ -12,7 +12,7 @@ SketchLineId = 'SketchLine' SketchArcId = 'SketchArc' SketchCircleId = 'SketchCircle' SketchConstraintCoincidenceId = 'SketchConstraintCoincidence' -SketchConstraintParallelId = 'SketchConstraintParallel' +SketchConstraintMirrorId = 'SketchConstraintMirror' SketchConstraintTangentId = 'SketchConstraintTangent' SketchConstraintEqualId = 'SketchConstraintEqual' @@ -124,6 +124,68 @@ aDistance_2 = math.hypot(LinePoint_2.x() - ArcPoint_2.x(), LinePoint_2.y() - Arc assert (math.fabs(aDistance_2) <= TOLERANCE) # Test2:end + +# Test3: constraints to circle +Sketch_3 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchCircle_3_1 = Sketch_3.addCircle(150, 50, 25) +SketchLine_3_1 = Sketch_3.addLine(160, 30, 200, 30) +SketchLine_3_2 = Sketch_3.addLine(160, 50, 200, 30) +SketchLine_3_3 = Sketch_3.addLine(240, 120, 280, 100) +SketchCircle_3_2 = Sketch_3.addCircle(150, 120, 20) +aSketchPoint_3 = Sketch_3.addPoint(145, 70) +SketchLine_3_4 = Sketch_3.addLine(120, 25, 120, 70) + +SketchConstraintCoincidence_3_1 = Sketch_3.setCoincident(SketchLine_3_1.startPoint(), SketchCircle_3_1.results()[1]) +SketchConstraintCoincidence_3_2 = Sketch_3.setCoincident(SketchLine_3_1.endPoint(), SketchLine_3_2.endPoint()) +GeomPoint_3_1 = geom.Pnt2d(165, 40) + +#Constraints +aConstraint_3_1 = Sketch_3.setDistance(SketchLine_3_1.endPoint(), SketchCircle_3_1.center(), 50) +aConstraint_3_2 = Sketch_3.setEqual(SketchCircle_3_1.results()[1], SketchCircle_3_2.results()[1]) +aConstraint_3_3 = Sketch_3.setRadius(SketchCircle_3_1.results()[1], 25) +aConstraint_3_4 = Sketch_3.setCoincident(SketchCircle_3_1.results()[1], aSketchPoint_3.results()[0]) +aConstraint_3_4 = Sketch_3.setTangent(SketchCircle_3_1.results()[1], SketchLine_3_4.results()[0]) + +MirrorObjects_3 = [SketchCircle_3_1.results()[1], SketchCircle_3_2.results()[1]] +aConstraint_3_5 = Sketch_3.addMirror(SketchLine_3_3.result(), MirrorObjects_3) + +#check number of features before trim +Sketch_3_feature = featureToCompositeFeature(Sketch_3.feature()) +idList_before_3 = [] +for index in range(Sketch_3_feature.numberOfSubs()): + idList_before_3.append(Sketch_3_feature.subFeature(index).getKind()) + +assert(idList_before_3.count(SketchCircleId) == 4) +assert(idList_before_3.count(SketchArcId) == 0) +assert(idList_before_3.count(SketchLineId) == 4) +assert(idList_before_3.count(SketchConstraintCoincidenceId) == 3) +assert(idList_before_3.count(SketchConstraintMirrorId) == 1) +assert(idList_before_3.count(SketchConstraintTangentId) == 1) +assert(idList_before_3.count(SketchConstraintEqualId) == 1) + +#perform trim +SketchTrim_3_1 = Sketch_3.addTrim(SketchCircle_3_1, GeomPoint_3_1) +SketchTrim_3_1.execute() +model.do() + +#check number of features after trim +SketchFeatures = featureToCompositeFeature(Sketch_3.feature()) +idList_after_3 = [] +for SubIndex in range(SketchFeatures.numberOfSubs()): + SubFeature = SketchFeatures.subFeature(SubIndex) + idList_after_3.append(SubFeature.getKind()) + + +assert(idList_after_3.count(SketchCircleId) == 3) +assert(idList_after_3.count(SketchArcId) == 1) +assert(idList_after_3.count(SketchLineId) == 4) +assert(idList_after_3.count(SketchConstraintCoincidenceId) == 3) +assert(idList_after_3.count(SketchConstraintMirrorId) == 0) +assert(idList_after_3.count(SketchConstraintTangentId) == 1) +assert(idList_after_3.count(SketchConstraintEqualId) == 1) +# Test3:end + + model.end() #assert(model.checkPythonDump()) diff --git a/src/SketchPlugin/Test/TestTrimLine.py b/src/SketchPlugin/Test/TestTrimLine.py new file mode 100644 index 000000000..b8acec087 --- /dev/null +++ b/src/SketchPlugin/Test/TestTrimLine.py @@ -0,0 +1,191 @@ +from salome.shaper import model + +from ModelAPI import * +from GeomDataAPI import * +from salome.shaper import geom +import math + +TOLERANCE = 1.e-7 + +SketchPointId = 'SketchPoint' +SketchLineId = 'SketchLine' +SketchArcId = 'SketchArc' +SketchCircleId = 'SketchCircle' +SketchConstraintCoincidenceId = 'SketchConstraintCoincidence' +SketchConstraintMirrorId = 'SketchConstraintMirror' +SketchConstraintTangentId = 'SketchConstraintTangent' +SketchConstraintEqualId = 'SketchConstraintEqual' + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() + +# Test1:begin split on circle with coincident point and intersection line : smaller part +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchCircle_1_1 = Sketch_1.addCircle(50, 50, 20) +SketchLine_1_1 = Sketch_1.addLine(50, 30, 100, 30) +SketchLine_1_2 = Sketch_1.addLine(60, 50, 100, 30) + +SketchConstraintCoincidence_1_1 = Sketch_1.setCoincident(SketchLine_1_1.startPoint(), SketchCircle_1_1.results()[1]) +SketchConstraintCoincidence_1_2 = Sketch_1.setCoincident(SketchLine_1_1.endPoint(), SketchLine_1_2.endPoint()) +GeomPoint_1_1 = geom.Pnt2d(60, 35) + +#check number of features before trim +Sketch_1_feature = featureToCompositeFeature(Sketch_1.feature()) +idList_before_1 = [] +for index in range(Sketch_1_feature.numberOfSubs()): + idList_before_1.append(Sketch_1_feature.subFeature(index).getKind()) +assert(idList_before_1.count(SketchCircleId) == 1) +assert(idList_before_1.count(SketchArcId) == 0) +assert(idList_before_1.count(SketchLineId) == 2) +assert(idList_before_1.count(SketchConstraintCoincidenceId) == 2) + +#perform trim +SketchTrim_1_1 = Sketch_1.addTrim(SketchCircle_1_1, GeomPoint_1_1) +SketchTrim_1_1.execute() +model.do() + +#check number of features after trim +SketchFeatures = featureToCompositeFeature(Sketch_1.feature()) +idList_after_1 = [] +for SubIndex in range(SketchFeatures.numberOfSubs()): + SubFeature = SketchFeatures.subFeature(SubIndex) + idList_after_1.append(SubFeature.getKind()) + if SubFeature.getKind() == SketchArcId: + ArcFeature_1 = SubFeature + + +assert(idList_after_1.count(SketchCircleId) == 0) +assert(idList_after_1.count(SketchArcId) == 1) +assert(idList_after_1.count(SketchLineId) == 2) +assert(idList_after_1.count(SketchConstraintCoincidenceId) == 3) + +#test created arc: it is not inversed, has coincidence to end line point +anInversed_1 = ArcFeature_1.boolean("InversedArc").value() +assert(anInversed_1 == False) +ArcPoint_1 = geomDataAPI_Point2D(ArcFeature_1.attribute("ArcEndPoint")) +LinePoint_1 = geomDataAPI_Point2D(SketchLine_1_1.startPoint()) +aDistance_1 = math.hypot(LinePoint_1.x() - ArcPoint_1.x(), LinePoint_1.y() - ArcPoint_1.y()) +#print "Distance " + repr(aDistance) +assert (math.fabs(aDistance_1) <= TOLERANCE) +# Test1:end + + +# Test2: split on circle with coincident point and intersection line : largest part +Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +move_test_delta_y = 100 +move_test_delta_x = 0 +SketchCircle_2_1 = Sketch_2.addCircle(50, 50 + move_test_delta_y, 20) +SketchLine_2_1 = Sketch_2.addLine(50, 30 + move_test_delta_y, 100, 30 + move_test_delta_y) +SketchLine_2_2 = Sketch_2.addLine(60, 50 + move_test_delta_y, 100, 30 + move_test_delta_y) + +SketchConstraintCoincidence_2_1 = Sketch_2.setCoincident(SketchLine_2_1.startPoint(), SketchCircle_2_1.results()[1]) +SketchConstraintCoincidence_2_2 = Sketch_2.setCoincident(SketchLine_2_1.endPoint(), SketchLine_2_2.endPoint()) +GeomPoint_2_1 = geom.Pnt2d(50, 75 + move_test_delta_y) + +#check number of features before trim +Sketch_2_feature = featureToCompositeFeature(Sketch_2.feature()) +idList_before_2 = [] +for index in range(Sketch_2_feature.numberOfSubs()): + idList_before_2.append(Sketch_2_feature.subFeature(index).getKind()) +assert(idList_before_2.count(SketchCircleId) == 1) +assert(idList_before_2.count(SketchArcId) == 0) +assert(idList_before_2.count(SketchLineId) == 2) +assert(idList_before_2.count(SketchConstraintCoincidenceId) == 2) + +#perform trim +SketchTrim_2_1 = Sketch_2.addTrim(SketchCircle_2_1, GeomPoint_2_1) +SketchTrim_2_1.execute() +model.do() + +#check number of features after trim +SketchFeatures = featureToCompositeFeature(Sketch_2.feature()) +idList_after_2 = [] +for SubIndex in range(SketchFeatures.numberOfSubs()): + SubFeature = SketchFeatures.subFeature(SubIndex) + idList_after_2.append(SubFeature.getKind()) + if SubFeature.getKind() == SketchArcId: + ArcFeature_2 = SubFeature + + +assert(idList_after_2.count(SketchCircleId) == 0) +assert(idList_after_2.count(SketchArcId) == 1) +assert(idList_after_2.count(SketchLineId) == 2) +assert(idList_after_2.count(SketchConstraintCoincidenceId) == 3) + +#test created arc : it is not inversed, has coincidence to start line point +anInversed_2 = ArcFeature_2.boolean("InversedArc").value() +assert(anInversed_2 == False) +ArcPoint_2 = geomDataAPI_Point2D(ArcFeature_2.attribute("ArcStartPoint")) +LinePoint_2 = geomDataAPI_Point2D(SketchLine_2_1.startPoint()) +aDistance_2 = math.hypot(LinePoint_2.x() - ArcPoint_2.x(), LinePoint_2.y() - ArcPoint_2.y()) +#print "Distance " + repr(aDistance_2) +assert (math.fabs(aDistance_2) <= TOLERANCE) +# Test2:end + + +# Test3: constraints to circle +Sketch_3 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchCircle_3_1 = Sketch_3.addCircle(150, 50, 25) +SketchLine_3_1 = Sketch_3.addLine(160, 30, 200, 30) +SketchLine_3_2 = Sketch_3.addLine(160, 50, 200, 30) +SketchLine_3_3 = Sketch_3.addLine(240, 120, 280, 100) +SketchCircle_3_2 = Sketch_3.addCircle(150, 120, 20) +aSketchPoint_3 = Sketch_3.addPoint(145, 70) +SketchLine_3_4 = Sketch_3.addLine(120, 25, 120, 70) + +SketchConstraintCoincidence_3_1 = Sketch_3.setCoincident(SketchLine_3_1.startPoint(), SketchCircle_3_1.results()[1]) +SketchConstraintCoincidence_3_2 = Sketch_3.setCoincident(SketchLine_3_1.endPoint(), SketchLine_3_2.endPoint()) +GeomPoint_3_1 = geom.Pnt2d(165, 40) + +#Constraints +aConstraint_3_1 = Sketch_3.setDistance(SketchLine_3_1.endPoint(), SketchCircle_3_1.center(), 50) +aConstraint_3_2 = Sketch_3.setEqual(SketchCircle_3_1.results()[1], SketchCircle_3_2.results()[1]) +aConstraint_3_3 = Sketch_3.setRadius(SketchCircle_3_1.results()[1], 25) +aConstraint_3_4 = Sketch_3.setCoincident(SketchCircle_3_1.results()[1], aSketchPoint_3.results()[0]) +aConstraint_3_4 = Sketch_3.setTangent(SketchCircle_3_1.results()[1], SketchLine_3_4.results()[0]) + +MirrorObjects_3 = [SketchCircle_3_1.results()[1], SketchCircle_3_2.results()[1]] +aConstraint_3_5 = Sketch_3.addMirror(SketchLine_3_3.result(), MirrorObjects_3) + +#check number of features before trim +Sketch_3_feature = featureToCompositeFeature(Sketch_3.feature()) +idList_before_3 = [] +for index in range(Sketch_3_feature.numberOfSubs()): + idList_before_3.append(Sketch_3_feature.subFeature(index).getKind()) + +assert(idList_before_3.count(SketchCircleId) == 4) +assert(idList_before_3.count(SketchArcId) == 0) +assert(idList_before_3.count(SketchLineId) == 4) +assert(idList_before_3.count(SketchConstraintCoincidenceId) == 3) +assert(idList_before_3.count(SketchConstraintMirrorId) == 1) +assert(idList_before_3.count(SketchConstraintTangentId) == 1) +assert(idList_before_3.count(SketchConstraintEqualId) == 1) + +#perform trim +SketchTrim_3_1 = Sketch_3.addTrim(SketchCircle_3_1, GeomPoint_3_1) +SketchTrim_3_1.execute() +model.do() + +#check number of features after trim +SketchFeatures = featureToCompositeFeature(Sketch_3.feature()) +idList_after_3 = [] +for SubIndex in range(SketchFeatures.numberOfSubs()): + SubFeature = SketchFeatures.subFeature(SubIndex) + idList_after_3.append(SubFeature.getKind()) + + +assert(idList_after_3.count(SketchCircleId) == 3) +assert(idList_after_3.count(SketchArcId) == 1) +assert(idList_after_3.count(SketchLineId) == 4) +assert(idList_after_3.count(SketchConstraintCoincidenceId) == 3) +assert(idList_after_3.count(SketchConstraintMirrorId) == 0) +assert(idList_after_3.count(SketchConstraintTangentId) == 1) +assert(idList_after_3.count(SketchConstraintEqualId) == 1) +# Test3:end + + +model.end() + +#assert(model.checkPythonDump()) diff --git a/src/SketchPlugin/plugin-Sketch.xml b/src/SketchPlugin/plugin-Sketch.xml index 6ad62415b..fd88188f4 100644 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@ -86,7 +86,7 @@ + enable_value="enable_by_preferences" reference_attribute="ArcCenterRef"/>