From b6e3fa204695d05e599df9425f9ab5f0ac42c179 Mon Sep 17 00:00:00 2001 From: nds Date: Thu, 9 Mar 2017 08:05:34 +0300 Subject: [PATCH] Issue #2027 Sketcher Trim Feature: split shapes by highlighted point is moved from GUI to Trim feature. Trim Circle feature. --- src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp | 47 + src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h | 15 +- src/ModelGeomAlgo/ModelGeomAlgo_Point2D.cpp | 69 +- src/ModelGeomAlgo/ModelGeomAlgo_Point2D.h | 24 +- .../PartSet_WidgetFeaturePointSelector.cpp | 7 +- .../PartSet_WidgetSubShapeSelector.cpp | 8 +- src/SketchAPI/SketchAPI_Sketch.cpp | 19 + src/SketchAPI/SketchAPI_Sketch.h | 6 + src/SketchPlugin/CMakeLists.txt | 3 +- .../SketchPlugin_ConstraintSplit.cpp | 2 +- src/SketchPlugin/SketchPlugin_Trim.cpp | 1262 ++++++++++------- src/SketchPlugin/SketchPlugin_Trim.h | 246 ++-- src/SketchPlugin/SketchPlugin_Validators.cpp | 33 +- src/SketchPlugin/Test/TestTrimCircle.py | 129 ++ src/SketchPlugin/plugin-Sketch.xml | 4 +- 15 files changed, 1230 insertions(+), 644 deletions(-) create mode 100644 src/SketchPlugin/Test/TestTrimCircle.py diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp index 14b2fbc41..7f7c8765e 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp @@ -695,6 +695,53 @@ bool GeomAlgoAPI_ShapeTools::isParallel(const std::shared_ptr theE //================================================================================================== void GeomAlgoAPI_ShapeTools::splitShape(const std::shared_ptr& theBaseShape, + const GeomAlgoAPI_ShapeTools::PointToRefsMap& thePointsInfo, + std::set >& theShapes) +{ + // General Fuse to split edge by vertices + BOPAlgo_Builder aBOP; + TopoDS_Edge aBaseEdge = theBaseShape->impl(); + // Rebuild closed edge to place vertex to one of split points. + // This will prevent edge to be split on same vertex. + if (BRep_Tool::IsClosed(aBaseEdge)) + { + Standard_Real aFirst, aLast; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aBaseEdge, aFirst, aLast); + + PointToRefsMap::const_iterator aPIt = thePointsInfo.begin(); + std::shared_ptr aPnt = aPIt->first; + gp_Pnt aPoint(aPnt->x(), aPnt->y(), aPnt->z()); + + TopAbs_Orientation anOrientation = aBaseEdge.Orientation(); + aBaseEdge = BRepBuilderAPI_MakeEdge(aCurve, aPoint, aPoint).Edge(); + aBaseEdge.Orientation(anOrientation); + } + aBOP.AddArgument(aBaseEdge); + + //std::list >::const_iterator aPtIt = thePoints.begin(); + PointToRefsMap::const_iterator aPIt = thePointsInfo.begin(); + for (; aPIt != thePointsInfo.end(); ++aPIt) { + std::shared_ptr aPnt = aPIt->first; + TopoDS_Vertex aV = BRepBuilderAPI_MakeVertex(gp_Pnt(aPnt->x(), aPnt->y(), aPnt->z())); + aBOP.AddArgument(aV); + } + + aBOP.Perform(); + if (aBOP.ErrorStatus()) + return; + + // Collect splits + const TopTools_ListOfShape& aSplits = aBOP.Modified(aBaseEdge); + TopTools_ListIteratorOfListOfShape anIt(aSplits); + for (; anIt.More(); anIt.Next()) { + std::shared_ptr anEdge(new GeomAPI_Shape); + anEdge->setImpl(new TopoDS_Shape(anIt.Value())); + theShapes.insert(anEdge); + } +} + +//================================================================================================== +void GeomAlgoAPI_ShapeTools::splitShape_p(const std::shared_ptr& theBaseShape, const std::list >& thePoints, std::set >& theShapes) { diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h index 22c886787..d3b712585 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h @@ -12,6 +12,7 @@ #include #include +#include #include class GeomAPI_Edge; @@ -20,6 +21,8 @@ class GeomAPI_Face; class GeomAPI_PlanarEdges; class GeomAPI_Pln; class GeomAPI_Pnt; +class GeomDataAPI_Point2D; +class ModelAPI_Object; /// \class GeomAlgoAPI_ShapeTools /// \ingroup DataAlgo @@ -116,14 +119,24 @@ public: GEOMALGOAPI_EXPORT static bool isParallel(const std::shared_ptr theEdge, const std::shared_ptr theFace); + typedef std::map, + std::pair >, + std::list > > > PointToRefsMap; /// \brief Performs the split of the shape by points. /// \param[in] theBaseShape shape that should be splitted. /// \param[in] thePoints container of points to split /// \param[out] theShapes container of shapes after split GEOMALGOAPI_EXPORT static void splitShape(const std::shared_ptr& theBaseShape, - const std::list >& thePoints, + const PointToRefsMap& thePointsInfo, std::set >& theShapes); + /// \brief Performs the split of the shape by points. + /// \param[in] theBaseShape shape that should be splitted. + /// \param[in] thePoints container of points to split + /// \param[out] theShapes container of shapes after split + GEOMALGOAPI_EXPORT static void splitShape_p(const std::shared_ptr& theBaseShape, + const std::list >& thePoints, + std::set >& theShapes); GEOMALGOAPI_EXPORT static std::shared_ptr findShape( const std::list >& thePoints, diff --git a/src/ModelGeomAlgo/ModelGeomAlgo_Point2D.cpp b/src/ModelGeomAlgo/ModelGeomAlgo_Point2D.cpp index 5d1a2cf74..e65a2786e 100755 --- a/src/ModelGeomAlgo/ModelGeomAlgo_Point2D.cpp +++ b/src/ModelGeomAlgo/ModelGeomAlgo_Point2D.cpp @@ -125,23 +125,21 @@ namespace ModelGeomAlgo_Point2D { void appendPoint(const std::shared_ptr& thePoint, const std::shared_ptr& theResult, - std::list >& thePoints, - std::map, - std::list< std::shared_ptr > >& theObjectToPoint) + PointToRefsMap& thePointToAttributeOrObject) { - std::list< std::shared_ptr > anObjects; - if (theObjectToPoint.find(thePoint) != theObjectToPoint.end()) - anObjects = theObjectToPoint[thePoint]; - thePoints.push_back(thePoint); - anObjects.push_back(theResult); - theObjectToPoint[thePoint].push_back(theResult); + if (thePointToAttributeOrObject.find(thePoint) != thePointToAttributeOrObject.end()) + thePointToAttributeOrObject.at(thePoint).second.push_back(theResult); + else { + std::list > anAttributes; + std::list > anObjects; + anObjects.push_back(theResult); + thePointToAttributeOrObject[thePoint] = std::make_pair(anAttributes, anObjects); + } } void appendShapePoints(GeomShapePtr& theShape, const std::shared_ptr& theResult, - std::list >& thePoints, - std::map, - std::list< std::shared_ptr > >& theObjectToPoint) + PointToRefsMap& thePointToAttributeOrObject) { if (!theShape.get()) return; @@ -151,19 +149,19 @@ namespace ModelGeomAlgo_Point2D { std::shared_ptr aVertex = std::shared_ptr(new GeomAPI_Vertex(theShape)); std::shared_ptr aPnt = aVertex->point(); - appendPoint(aPnt, theResult, thePoints, theObjectToPoint); + appendPoint(aPnt, theResult, thePointToAttributeOrObject); } break; case GeomAPI_Shape::EDGE: { std::shared_ptr anEdge = std::shared_ptr(new GeomAPI_Edge(theShape)); - appendPoint(anEdge->firstPoint(), theResult, thePoints, theObjectToPoint); - appendPoint(anEdge->lastPoint(), theResult, thePoints, theObjectToPoint); + appendPoint(anEdge->firstPoint(), theResult, thePointToAttributeOrObject); + appendPoint(anEdge->lastPoint(), theResult, thePointToAttributeOrObject); } break; case GeomAPI_Shape::COMPOUND: { for(GeomAPI_ShapeIterator anIt(theShape); anIt.more(); anIt.next()) { - appendShapePoints(anIt.current(), theResult, thePoints, theObjectToPoint); + appendShapePoints(anIt.current(), theResult, thePointToAttributeOrObject); } } break; @@ -173,9 +171,7 @@ namespace ModelGeomAlgo_Point2D { void getPointsIntersectedShape(const std::shared_ptr& theBaseFeature, const std::list >& theFeatures, - std::list >& thePoints, - std::map, - std::list< std::shared_ptr > >& theObjectToPoint) + PointToRefsMap& thePointToAttributeOrObject) { GeomShapePtr aFeatureShape; { @@ -201,12 +197,45 @@ namespace ModelGeomAlgo_Point2D { GeomShapePtr aShape = aResult->shape(); GeomShapePtr aShapeOfIntersection = aFeatureShape->intersect(aShape); - appendShapePoints(aShapeOfIntersection, aResult, thePoints, theObjectToPoint); + appendShapePoints(aShapeOfIntersection, aResult, thePointToAttributeOrObject); } } } void getPointsInsideShape(const std::shared_ptr theBaseShape, + const std::set >& theAttributes, + const std::shared_ptr& theOrigin, + const std::shared_ptr& theDirX, + const std::shared_ptr& theDirY, + PointToRefsMap& thePointToAttributeOrObject) + { + std::set >::const_iterator anIt = theAttributes.begin(), + aLast = theAttributes.end(); + for (; anIt != aLast; anIt++) { + std::shared_ptr anAttribute = *anIt; + std::shared_ptr aPnt2d = anAttribute->pnt(); + std::shared_ptr aPoint = aPnt2d->to3D(theOrigin, theDirX, theDirY); + std::shared_ptr aProjectedPoint; + if (isPointOnEdge(theBaseShape, aPoint, aProjectedPoint)) { + if (thePointToAttributeOrObject.find(aProjectedPoint) != thePointToAttributeOrObject.end()) + thePointToAttributeOrObject.at(aProjectedPoint).first.push_back(anAttribute); + else { + //std::list< std::shared_ptr > anAttributes; + //anAttributes.push_back(anAttribute); + //thePointToAttributeOrObject.insert(aProjectedPoint, anAttributes); + + std::list > anAttributes; + std::list > anObjects; + anAttributes.push_back(anAttribute); + thePointToAttributeOrObject[aProjectedPoint] = std::make_pair(anAttributes, anObjects); + } + //thePoints.push_back(aProjectedPoint); + //theAttributeToPoint[anAttribute] = aProjectedPoint; + } + } + } + + void getPointsInsideShape_p(const std::shared_ptr theBaseShape, const std::set >& theAttributes, const std::shared_ptr& theOrigin, const std::shared_ptr& theDirX, diff --git a/src/ModelGeomAlgo/ModelGeomAlgo_Point2D.h b/src/ModelGeomAlgo/ModelGeomAlgo_Point2D.h index b5c005bd5..6e717c10e 100755 --- a/src/ModelGeomAlgo/ModelGeomAlgo_Point2D.h +++ b/src/ModelGeomAlgo/ModelGeomAlgo_Point2D.h @@ -62,12 +62,14 @@ namespace ModelGeomAlgo_Point2D { /// \param theFeatures a container of features to intersect with the base feature /// \param thePoints a container of 3D points belong to the shape /// \param theObjectToPoint a container of object to point + typedef std::map, + std::pair >, + std::list > > > PointToRefsMap; + MODELGEOMALGO_EXPORT void getPointsIntersectedShape( const std::shared_ptr& theBaseFeature, const std::list >& theFeatures, - std::list >& thePoints, - std::map, - std::list< std::shared_ptr > >& theObjectToPoint); + PointToRefsMap& thePointToAttributeOrObject); /// Removes attributes which points are out of the base shape /// \param theBaseShape a shape of check @@ -78,6 +80,22 @@ namespace ModelGeomAlgo_Point2D { /// \param thePoints a container of 3D points belong to the shape /// \param theAttributeToPoint a container of attribute to point MODELGEOMALGO_EXPORT void getPointsInsideShape( + const std::shared_ptr theBaseShape, + const std::set >& theAttributes, + const std::shared_ptr& theOrigin, + const std::shared_ptr& theDirX, + const std::shared_ptr& theDirY, + PointToRefsMap& thePointToAttributeOrObject); + + /// Removes attributes which points are out of the base shape + /// \param theBaseShape a shape of check + /// \param theAttributes a container of point 2D attributes + /// \param theOrigin origin of a plane to generate 3D point by 2D attribute point + /// \param theDirX plane X direction to generate 3D point by 2D attribute point + /// \param theDirY plane X direction to generate 3D point by 2D attribute point + /// \param thePoints a container of 3D points belong to the shape + /// \param theAttributeToPoint a container of attribute to point + MODELGEOMALGO_EXPORT void getPointsInsideShape_p( const std::shared_ptr theBaseShape, const std::set >& theAttributes, const std::shared_ptr& theOrigin, diff --git a/src/PartSet/PartSet_WidgetFeaturePointSelector.cpp b/src/PartSet/PartSet_WidgetFeaturePointSelector.cpp index 92c522464..e72db6c83 100644 --- a/src/PartSet/PartSet_WidgetFeaturePointSelector.cpp +++ b/src/PartSet/PartSet_WidgetFeaturePointSelector.cpp @@ -163,7 +163,7 @@ bool PartSet_WidgetFeaturePointSelector::fillFeature( std::shared_ptr aRef = std::dynamic_pointer_cast( - feature()->data()->attribute(SketchPlugin_Constraint::VALUE())); + feature()->data()->attribute(SketchPlugin_Trim::BASE_OBJECT())); aRef->setValue(anObject); std::shared_ptr anAttributePoint = @@ -176,10 +176,7 @@ bool PartSet_WidgetFeaturePointSelector::fillFeature( // an attempt to clear highlighted item in the viewer: but of OCCT XGUI_Tools::workshop(myWorkshop)->displayer()->clearSelected(true); #endif - static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED); - ModelAPI_EventCreator::get()->sendUpdated(feature(), anEvent); - Events_Loop::loop()->flush(anEvent); - + updateObject(feature()); aFilled = true; /* diff --git a/src/PartSet/PartSet_WidgetSubShapeSelector.cpp b/src/PartSet/PartSet_WidgetSubShapeSelector.cpp index 0e0a41a2e..e9d157a1d 100755 --- a/src/PartSet/PartSet_WidgetSubShapeSelector.cpp +++ b/src/PartSet/PartSet_WidgetSubShapeSelector.cpp @@ -302,11 +302,11 @@ void PartSet_WidgetSubShapeSelector::fillObjectShapes(const ObjectPtr& theObject std::shared_ptr aNorm = std::dynamic_pointer_cast( aData->attribute(SketchPlugin_Sketch::NORM_ID())); std::shared_ptr aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir()))); - ModelGeomAlgo_Point2D::getPointsInsideShape(aFeatureShape, aRefAttributes, aC->pnt(), + ModelGeomAlgo_Point2D::getPointsInsideShape_p(aFeatureShape, aRefAttributes, aC->pnt(), aX->dir(), aY, aPoints, aPointToAttributes); // intersection points - if (myUseGraphicIntersection) { + /*if (myUseGraphicIntersection) { std::list aFeatures; for (int i = 0; i < aSketch->numberOfSubs(); i++) { FeaturePtr aFeature = aSketch->subFeature(i); @@ -315,8 +315,8 @@ void PartSet_WidgetSubShapeSelector::fillObjectShapes(const ObjectPtr& theObject } ModelGeomAlgo_Point2D::getPointsIntersectedShape(aFeature, aFeatures, aPoints, aPointToObjects); - } - GeomAlgoAPI_ShapeTools::splitShape(aFeatureShape, aPoints, aShapes); + }*/ + GeomAlgoAPI_ShapeTools::splitShape_p(aFeatureShape, aPoints, aShapes); } myCashedShapes[theObject] = aShapes; myCashedReferences[theObject] = aPointToAttributes; diff --git a/src/SketchAPI/SketchAPI_Sketch.cpp b/src/SketchAPI/SketchAPI_Sketch.cpp index bacc3c147..fdc8a71fb 100644 --- a/src/SketchAPI/SketchAPI_Sketch.cpp +++ b/src/SketchAPI/SketchAPI_Sketch.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -481,6 +482,24 @@ std::shared_ptr SketchAPI_Sketch::addSplit( return InterfacePtr(new ModelHighAPI_Interface(aFeature)); } +//-------------------------------------------------------------------------------------- +std::shared_ptr SketchAPI_Sketch::addTrim( + const ModelHighAPI_Reference& theFeature, + const std::shared_ptr& thePositionPoint) +{ + std::shared_ptr aFeature = + compositeFeature()->addFeature(SketchPlugin_Trim::ID()); + fillAttribute(theFeature, aFeature->reference(SketchPlugin_Trim::BASE_OBJECT())); + + AttributePtr anAttribute = aFeature->attribute(SketchPlugin_Trim::ENTITY_POINT()); + if (anAttribute->attributeType() == GeomDataAPI_Point2D::typeId()) { + AttributePoint2DPtr aPointAttr = std::dynamic_pointer_cast(anAttribute); + fillAttribute(thePositionPoint, aPointAttr); + } + + return InterfacePtr(new ModelHighAPI_Interface(aFeature)); +} + //-------------------------------------------------------------------------------------- std::shared_ptr SketchAPI_Sketch::setAngle( const ModelHighAPI_RefAttr & theLine1, diff --git a/src/SketchAPI/SketchAPI_Sketch.h b/src/SketchAPI/SketchAPI_Sketch.h index 500c06a68..216474474 100644 --- a/src/SketchAPI/SketchAPI_Sketch.h +++ b/src/SketchAPI/SketchAPI_Sketch.h @@ -263,6 +263,12 @@ public: const ModelHighAPI_RefAttr& thePoint1, const ModelHighAPI_RefAttr& thePoint2); + /// Add trim + SKETCHAPI_EXPORT + std::shared_ptr addTrim( + const ModelHighAPI_Reference& theFeature, + const std::shared_ptr& thePositionPoint); + /// Set angle SKETCHAPI_EXPORT std::shared_ptr setAngle( diff --git a/src/SketchPlugin/CMakeLists.txt b/src/SketchPlugin/CMakeLists.txt index a8d4c5579..32f47bb34 100644 --- a/src/SketchPlugin/CMakeLists.txt +++ b/src/SketchPlugin/CMakeLists.txt @@ -146,4 +146,5 @@ ADD_UNIT_TESTS(TestSketchPointLine.py TestHighload.py TestSnowflake.py TestArcBehavior.py - Test1924.py ) + Test1924.py + TestTrimCircle.py ) diff --git a/src/SketchPlugin/SketchPlugin_ConstraintSplit.cpp b/src/SketchPlugin/SketchPlugin_ConstraintSplit.cpp index b8a7102d9..08be7f169 100755 --- a/src/SketchPlugin/SketchPlugin_ConstraintSplit.cpp +++ b/src/SketchPlugin/SketchPlugin_ConstraintSplit.cpp @@ -360,7 +360,7 @@ AISObjectPtr SketchPlugin_ConstraintSplit::getAISObject(AISObjectPtr thePrevious std::set > aSplitShapes; - GeomAlgoAPI_ShapeTools::splitShape(aBaseShape, aPoints, aSplitShapes); + GeomAlgoAPI_ShapeTools::splitShape_p(aBaseShape, aPoints, aSplitShapes); std::shared_ptr aShape = GeomAlgoAPI_ShapeTools::findShape(aPoints, aSplitShapes); diff --git a/src/SketchPlugin/SketchPlugin_Trim.cpp b/src/SketchPlugin/SketchPlugin_Trim.cpp index 0dfe4a88a..df4b238c1 100644 --- a/src/SketchPlugin/SketchPlugin_Trim.cpp +++ b/src/SketchPlugin/SketchPlugin_Trim.cpp @@ -7,6 +7,7 @@ #include "SketchPlugin_Trim.h" #include +#include #include #include #include @@ -22,8 +23,8 @@ #include #include -#include #include +#include #include #include #include @@ -31,9 +32,10 @@ #include #include #include +#include #include #include -#include +#include #include #include @@ -45,6 +47,11 @@ #include +#define DEBUG_TRIM +#ifdef DEBUG_TRIM +#include +#endif + //#define DEBUG_SPLIT #ifdef DEBUG_SPLIT #include @@ -52,13 +59,15 @@ //static const double PI = 3.141592653589793238463; +static const std::string OPERATION_HIGHLIGHT_COLOR() { return "128, 0, 0"; } + SketchPlugin_Trim::SketchPlugin_Trim() { } void SketchPlugin_Trim::initAttributes() { - data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeReference::typeId()); + data()->addAttribute(SketchPlugin_Trim::BASE_OBJECT(), ModelAPI_AttributeReference::typeId()); //data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId()); //data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId()); data()->addAttribute(ENTITY_POINT(), GeomDataAPI_Point2D::typeId()); @@ -76,23 +85,211 @@ void SketchPlugin_Trim::initAttributes() // return aConstraint; //} +void SketchPlugin_Trim::findShapePoints(std::shared_ptr& aStartPoint, + std::shared_ptr& aLastPoint) +{ + AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast( + data()->attribute(SketchPlugin_Trim::BASE_OBJECT())); + ObjectPtr aBaseObject = aBaseObjectAttr->value(); + + AttributePoint2DPtr aPoint = std::dynamic_pointer_cast( + data()->attribute(ENTITY_POINT())); + std::shared_ptr anAttributePnt2d = aPoint->pnt(); + std::shared_ptr anAttributePnt = sketch()->to3D(anAttributePnt2d->x(), + anAttributePnt2d->y()); + + if (myCashedShapes.find(aBaseObject) == myCashedShapes.end()) + fillObjectShapes(aBaseObject); + + const std::set& aShapes = myCashedShapes[aBaseObject]; + if (!aShapes.empty()) { + std::set::const_iterator anIt = aShapes.begin(), aLast = aShapes.end(); + for (; anIt != aLast; anIt++) { + GeomShapePtr aBaseShape = *anIt; + std::shared_ptr aProjectedPoint; + if (ModelGeomAlgo_Point2D::isPointOnEdge(aBaseShape, anAttributePnt, aProjectedPoint)) { + + if (aBaseShape->shapeType() == GeomAPI_Shape::EDGE) { + std::shared_ptr anEdge(new GeomAPI_Edge(aBaseShape)); + aStartPoint = anEdge->lastPoint(); + aLastPoint = anEdge->firstPoint(); + } + } + } + } +#ifdef DEBUG_TRIM + std::cout << " => " + << "Start Point: [" + << aStartPoint->x() << ", " << aStartPoint->y() << ", " << aStartPoint->z() << "]" + << "Last Point: [" + << aLastPoint->x() << ", " << aLastPoint->y() << ", " << aLastPoint->z() << "]" + << std::endl; +#endif +} + +std::shared_ptr SketchPlugin_Trim::convertPoint( + const std::shared_ptr& thePoint) +{ + std::shared_ptr aPoint; + + AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast( + data()->attribute(SketchPlugin_Trim::BASE_OBJECT())); + ObjectPtr aBaseObject = aBaseObjectAttr->value(); + //std::map myObjectToPoints; + if (myObjectToPoints.find(aBaseObject) == myObjectToPoints.end()) + return aPoint; + + bool aFound = false; + const PointToRefsMap& aRefsMap = myObjectToPoints.at(aBaseObject); + for (PointToRefsMap::const_iterator aPointIt = aRefsMap.begin(); + aPointIt != aRefsMap.end() && !aFound; aPointIt++) { + if (aPointIt->first->isEqual(thePoint)) { + const std::pair, + std::list >& anInfo = aPointIt->second; + const std::list& anAttributes = anInfo.first; + if (!anAttributes.empty()) { + aPoint = anAttributes.front()->pnt(); + aFound = true; + } + else { + std::shared_ptr aPlane = sketch()->plane(); + aPoint = thePoint->to2D(aPlane); + aFound = true; + } + } + } + if (!aFound) + return aPoint; + //if (aRefsMap.find(thePoint) == aRefsMap.end()) + // return aPoint; + + //const std::pair, + // std::list >& anInfo = aRefsMap.at(thePoint); + + //const std::list& anAttributes = anInfo.first; + //if (!anAttributes.empty()) + // aPoint = anAttributes.front()->pnt(); + //else { + // std::shared_ptr aPlane = sketch()->plane(); + // aPoint = thePoint->to2D(aPlane); + //} + return aPoint; +} + void SketchPlugin_Trim::execute() { - std::shared_ptr aData = data(); +#ifdef DEBUG_SPLIT + std::cout << "SketchPlugin_Trim::execute" << std::endl; +#endif + + SketchPlugin_Sketch* aSketch = sketch(); + if (!aSketch) + return; // Check the base objects are initialized. AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast( - aData->attribute(SketchPlugin_Constraint::VALUE())); + data()->attribute(SketchPlugin_Trim::BASE_OBJECT())); if(!aBaseObjectAttr->isInitialized()) { setError("Error: Base object is not initialized."); return; } + ObjectPtr aBaseObject = aBaseObjectAttr->value(); + if (!aBaseObject.get()) + return; + FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value()); + +//#ifdef DEBUG_TRIM +// const PointToRefsMap& aRefsMap = myObjectToPoints.at(aBaseObject); +//#endif + /// points of trim + //std::map, std::shared_ptr > aPntMap; + + std::shared_ptr aStartShapePoint, aLastShapePoint; + findShapePoints(aStartShapePoint, aLastShapePoint); + std::shared_ptr aStartShapePoint2d = convertPoint(aStartShapePoint); + //aPntMap[aStartShapePoint2d] = aStartShapePoint; + + std::shared_ptr aLastShapePoint2d = convertPoint(aLastShapePoint); + //aPntMap[aLastShapePoint2d] = aLastShapePoint; + + /*AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase; + getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase); + if (!aStartPointAttrOfBase.get() && !anEndPointAttrOfBase.get()) { + setError("Error: Feature has no start and end points."); + return; + }*/ + + std::set aFeaturesToDelete, aFeaturesToUpdate; + //std::map aTangentFeatures; + //std::map aCoincidenceToFeature; + getConstraints(aFeaturesToDelete, aFeaturesToUpdate);//, aTangentFeatures, aCoincidenceToFeature); + + std::map > aBaseRefAttributes; + std::list aRefsToFeature; + getRefAttributes(aBaseFeature, aBaseRefAttributes, aRefsToFeature); + + std::set aFurtherCoincidences; + std::set aCreatedFeatures; + std::set> aModifiedAttributes; + const std::string& aKind = aBaseFeature->getKind(); + if (aKind == SketchPlugin_Circle::ID()) { + trimCircle(aStartShapePoint2d, aLastShapePoint2d, + aFurtherCoincidences, aCreatedFeatures, aModifiedAttributes); + updateRefFeatureConstraints(getFeatureResult(aBaseFeature), aRefsToFeature); + + //AttributePtr aCenterAttr = aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()); + aFeaturesToDelete.insert(aBaseFeature); + // as circle is removed, temporary fill this attribute + aBaseObjectAttr->setObject(ResultPtr()); + } + else if (aKind == SketchPlugin_Line::ID()) { + } + else if (aKind == SketchPlugin_Arc::ID()) { + } + + // coincidence to result points + const PointToRefsMap& aRefsMap = myObjectToPoints.at(aBaseObject); + std::set::const_iterator anIt = aFurtherCoincidences.begin(), + aLast = aFurtherCoincidences.end(); + for (; anIt != aLast; anIt++) { + AttributePoint2DPtr aPointAttribute = (*anIt); + std::shared_ptr aPoint2d = aPointAttribute->pnt(); + + std::shared_ptr aPoint; + if (aPoint2d->isEqual(aStartShapePoint2d)) + aPoint = aStartShapePoint; + else if (aPoint2d->isEqual(aLastShapePoint2d)) + aPoint = aLastShapePoint; + else + continue; - /*std::shared_ptr anAPoint = std::dynamic_pointer_cast( + std::pair, std::list > anInfo; + for (PointToRefsMap::const_iterator aRefIt = aRefsMap.begin(); aRefIt != aRefsMap.end(); + aRefIt++) + { + if (aRefIt->first->isEqual(aPoint)) { + anInfo = aRefIt->second; + break; + } + } + const std::list& anAttributes = anInfo.first; + for (std::list::const_iterator anAttrIt = anAttributes.begin(); + anAttrIt != anAttributes.end(); anAttrIt++) { + createConstraint(SketchPlugin_ConstraintCoincidence::ID(), aPointAttribute, *anAttrIt); + } + + const std::list& anObjects = anInfo.second; + for (std::list::const_iterator anObjectIt = anObjects.begin(); + anObjectIt != anObjects.end(); anObjectIt++) { + createConstraint(SketchPlugin_ConstraintCoincidence::ID(), aPointAttribute, *anObjectIt); + } + } + + /*AttributePoint2DPtr anAPoint = std::dynamic_pointer_cast( aData->attribute(ENTITY_A_POINT())); std::shared_ptr anAttributeStartPnt2d = anAPoint->pnt(); - std::shared_ptr aBPoint = std::dynamic_pointer_cast( + AttributePoint2DPtr aBPoint = std::dynamic_pointer_cast( aData->attribute(ENTITY_B_POINT())); std::shared_ptr anAttributeEndPnt2d = aBPoint->pnt(); @@ -122,16 +319,16 @@ void SketchPlugin_Trim::execute() // // Find feature constraints /*FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value()); - std::set > aNewCoincidencesToSplitFeature; + std::set aNewCoincidencesToSplitFeature; AttributePoint2DPtr aFeatureStartPointAttr, aFeatureEndPointAttr; getFeaturePoints(aBaseFeature, aFeatureStartPointAttr, aFeatureEndPointAttr); if (aFeatureStartPointAttr.get() && aFeatureStartPointAttr.get()) { // line or arc - std::shared_ptr aStartPointAttribute = + AttributePoint2DPtr aStartPointAttribute = std::dynamic_pointer_cast( aFeatureStartPointAttr); std::shared_ptr aFeatureStartPnt2d = aStartPointAttribute->pnt(); - std::shared_ptr anEndPointAttribute = + AttributePoint2DPtr anEndPointAttribute = std::dynamic_pointer_cast( aFeatureEndPointAttr); std::shared_ptr aFeatureEndPnt2d = anEndPointAttribute->pnt(); @@ -156,9 +353,9 @@ void SketchPlugin_Trim::execute() // std::map aCoincidenceToFeature; // getConstraints(aFeaturesToDelete, aFeaturesToUpdate, aTangentFeatures, aCoincidenceToFeature); // -// std::map > aBaseRefAttributes; -// std::list aRefsToFeature; -// getRefAttributes(aBaseFeature, aBaseRefAttributes, aRefsToFeature); +//std::map > aBaseRefAttributes; +//std::list aRefsToFeature; +//getRefAttributes(aBaseFeature, aBaseRefAttributes, aRefsToFeature); // // std::map aBasePointModifiedAttributes; // @@ -186,7 +383,7 @@ void SketchPlugin_Trim::execute() // for (int i = 1; anIt != aLast; anIt++, i++) { // FeaturePtr aFeature = (*anIt).first; // std::string anAttributeId = (*anIt).second.first; -// std::shared_ptr aPointAttr = (*anIt).second.second; +// AttributePoint2DPtr aPointAttr = (*anIt).second.second; // // std::cout << i << "-" << getFeatureInfo(aFeature) << std::endl; // std::cout << " -Attribute to correct:" << anAttributeId << std::endl; @@ -203,7 +400,7 @@ void SketchPlugin_Trim::execute() // for (int i = 1; anIt != aLast; anIt++, i++) { // FeaturePtr aFeature = (*anIt).first; // std::string anAttributeId = (*anIt).second.first; -// std::shared_ptr aPointAttr = (*anIt).second.second; +// AttributePoint2DPtr aPointAttr = (*anIt).second.second; // // std::cout << i << "-" << getFeatureInfo(aFeature) << std::endl; // std::cout << " -Attribute to correct:" << anAttributeId << std::endl; @@ -230,7 +427,7 @@ void SketchPlugin_Trim::execute() // FeaturePtr aRFeature = ModelAPI_Feature::feature(aRAttr->owner()); // aRefsInfo.append("(" + aRFeature->name() + ") "); // } -// std::shared_ptr aPointAttr = +// AttributePoint2DPtr aPointAttr = // std::dynamic_pointer_cast(aBaseAttr); // std::cout << aPointAttr->id().c_str() << // ": " << "[" << aRefAttributes.size() << "] " << aRefsInfo << std::endl; @@ -342,21 +539,21 @@ void SketchPlugin_Trim::execute() // // tangency // updateTangentConstraintsToFeature(aTangentFeatures, aFurtherCoincidences); // -// updateRefAttConstraints(aBaseRefAttributes, aModifiedAttributes); -// -// // delete constraints -//#ifdef DEBUG_SPLIT -// std::cout << "remove features and references:" << std::endl; -// std::set::const_iterator aDIt = aFeaturesToDelete.begin(), -// aDLast = aFeaturesToDelete.end(); -// for (; aDIt != aDLast; aDIt++) { -// std::cout << getFeatureInfo(*aDIt, false) << std::endl; -// std::cout << std::endl; -// } -//#endif -// ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToDelete); -// Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED)); -// + updateRefAttConstraints(aBaseRefAttributes, aModifiedAttributes); + + // delete constraints +#ifdef DEBUG_SPLIT + std::cout << "remove features and references:" << std::endl; + std::set::const_iterator aDIt = aFeaturesToDelete.begin(), + aDLast = aFeaturesToDelete.end(); + for (; aDIt != aDLast; aDIt++) { + std::cout << getFeatureInfo(*aDIt, false) << std::endl; + std::cout << std::endl; + } +#endif + ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToDelete); + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED)); + //#ifdef DEBUG_SPLIT // std::cout << "update features after split:" << std::endl; // std::set::const_iterator anUIt = aFeaturesToUpdate.begin(), @@ -379,6 +576,10 @@ void SketchPlugin_Trim::execute() // std::cout << getFeatureInfo(aSketch->subFeature(i), false) << std::endl; // } //#endif + +#ifdef DEBUG_SPLIT + std::cout << "SketchPlugin_Trim::done" << std::endl; +#endif } bool SketchPlugin_Trim::isMacro() const @@ -386,21 +587,19 @@ bool SketchPlugin_Trim::isMacro() const return true; } -static const std::string OPERATION_HIGHLIGHT_COLOR() { return "128, 0, 0"; } AISObjectPtr SketchPlugin_Trim::getAISObject(AISObjectPtr thePrevious) { AISObjectPtr anAIS = thePrevious; // feature for trim AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast( - data()->attribute(SketchPlugin_Constraint::VALUE())); + data()->attribute(SketchPlugin_Trim::BASE_OBJECT())); ObjectPtr aBaseObject = aBaseObjectAttr->value(); if (!aBaseObject.get()) return anAIS; - FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value()); // point on feature - std::shared_ptr aPoint = std::dynamic_pointer_cast( + AttributePoint2DPtr aPoint = std::dynamic_pointer_cast( data()->attribute(ENTITY_POINT())); std::shared_ptr anAttributePnt2d = aPoint->pnt(); std::shared_ptr anAttributePnt = sketch()->to3D(anAttributePnt2d->x(), anAttributePnt2d->y()); @@ -516,7 +715,7 @@ AISObjectPtr SketchPlugin_Trim::getAISObject(AISObjectPtr thePrevious) return anAIS; } -//std::shared_ptr SketchPlugin_Trim::getPointOfRefAttr( +//AttributePoint2DPtr SketchPlugin_Trim::getPointOfRefAttr( // const AttributePtr& theAttribute) //{ // AttributePoint2DPtr aPointAttribute; @@ -533,198 +732,200 @@ AISObjectPtr SketchPlugin_Trim::getAISObject(AISObjectPtr thePrevious) // return aPointAttribute; //} // -//void SketchPlugin_Trim::getFeaturePoints(const FeaturePtr& theFeature, -// AttributePoint2DPtr& theStartPointAttr, -// AttributePoint2DPtr& theEndPointAttr) -//{ -// std::string aFeatureKind = theFeature->getKind(); -// std::string aStartAttributeName, anEndAttributeName; -// if (aFeatureKind == SketchPlugin_Line::ID()) { -// aStartAttributeName = SketchPlugin_Line::START_ID(); -// anEndAttributeName = SketchPlugin_Line::END_ID(); -// } -// else if (aFeatureKind == SketchPlugin_Arc::ID()) { -// aStartAttributeName = SketchPlugin_Arc::START_ID(); -// anEndAttributeName = SketchPlugin_Arc::END_ID(); -// } -// if (!aStartAttributeName.empty() && !anEndAttributeName.empty()) { -// theStartPointAttr = std::dynamic_pointer_cast( -// theFeature->attribute(aStartAttributeName)); -// theEndPointAttr = std::dynamic_pointer_cast( -// theFeature->attribute(anEndAttributeName)); -// } -//} -// -//void SketchPlugin_Trim::getConstraints(std::set& theFeaturesToDelete, -// std::set& theFeaturesToUpdate, -// std::map& theTangentFeatures, -// std::map& theCoincidenceToFeature) -//{ -// std::shared_ptr aData = data(); -// -// // Check the base objects are initialized. -// AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast( -// aData->attribute(SketchPlugin_Constraint::VALUE())); -// FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value()); -// ResultPtr aBaseFeatureResult = getFeatureResult(aBaseFeature); -// -// std::set aRefsList = aBaseFeatureResult->data()->refsToMe(); -// std::set aFRefsList = aBaseFeature->data()->refsToMe(); -// aRefsList.insert(aFRefsList.begin(), aFRefsList.end()); -// -// 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()); -// std::string aRefFeatureKind = aRefFeature->getKind(); -// if (aRefFeatureKind == SketchPlugin_ConstraintMirror::ID() || -// aRefFeatureKind == SketchPlugin_MultiRotation::ID() || -// 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(ATTRIBUTE(i)); -// 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()) { -// FeaturePtr aFeature1 = ModelAPI_Feature::feature(aResult1); -// std::string anAttributeToBeModified = aFeature1 == aBaseFeature -// ? SketchPlugin_Constraint::ENTITY_A() : SketchPlugin_Constraint::ENTITY_B(); -// theTangentFeatures[aRefFeature] = std::make_pair(anAttributeToBeModified, aTangentPoint); -// } -// else /// there is not coincident point between tangent constraint -// theFeaturesToDelete.insert(aRefFeature); -// } -// } -// else if (aRefFeatureKind == SketchPlugin_ConstraintCoincidence::ID()) { -// std::string anAttributeToBeModified; -// AttributePoint2DPtr aCoincidentPoint; -// AttributeRefAttrPtr anAttrA = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_A()); -// AttributeRefAttrPtr anAttrB = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_B()); -// bool isToFeature = false; -// if (anAttrA->isObject() || anAttrB->isObject()) { /// coincidence to base feature -// FeaturePtr aFeature = anAttrA->isObject() ? ModelAPI_Feature::feature(anAttrA->object()) -// : FeaturePtr(); -// isToFeature = aFeature.get() && aFeature == aBaseFeature; -// anAttributeToBeModified = anAttrA->id(); -// if (!isToFeature) { -// aFeature = anAttrB->isObject() ? ModelAPI_Feature::feature(anAttrB->object()) -// : FeaturePtr(); -// isToFeature = aFeature.get() && aFeature == aBaseFeature; -// anAttributeToBeModified = anAttrB->id(); -// } -// if (isToFeature) -// aCoincidentPoint = SketchPlugin_ConstraintCoincidence::getPoint(aRefFeature); -// } -// if (!isToFeature) { /// coincidence to point on base feature -// AttributePtr anAttribute; -// -// if (!anAttrA->isObject()) { -// AttributePtr aCurAttribute = anAttrA->attr(); -// if (aCurAttribute.get()) { -// FeaturePtr aCurFeature = ModelAPI_Feature::feature(aCurAttribute->owner()); -// if (aCurFeature.get() && aCurFeature == aBaseFeature) { -// anAttribute = anAttrB->attr(); -// anAttributeToBeModified = anAttrA->id(); -// } -// } -// } -// if (!anAttribute.get() && !anAttrB->isObject()) { -// AttributePtr aCurAttribute = anAttrB->attr(); -// if (aCurAttribute.get()) { -// FeaturePtr aCurFeature = ModelAPI_Feature::feature(aCurAttribute->owner()); -// if (aCurFeature.get() && aCurFeature == aBaseFeature) { -// anAttribute = anAttrA->attr(); -// anAttributeToBeModified = anAttrB->id(); -// } -// } -// } -// if (anAttribute.get()) -// aCoincidentPoint = std::dynamic_pointer_cast(anAttribute); -// } -// if (aCoincidentPoint.get() && isToFeature) -// theCoincidenceToFeature[aRefFeature] = std::make_pair(anAttributeToBeModified, -// aCoincidentPoint); -// } -// } -//} -// -//void SketchPlugin_Trim::getRefAttributes(const FeaturePtr& theFeature, -// std::map >& theRefs, -// std::list& theRefsToFeature) -//{ -// theRefs.clear(); -// -// std::list aPointAttributes = -// theFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); -// std::set aPointAttributesSet; -// -// std::list::const_iterator aPIt = -// aPointAttributes.begin(), aPLast = aPointAttributes.end(); -// for (; aPIt != aPLast; aPIt++) -// aPointAttributesSet.insert(*aPIt); -// -// std::set aRefsAttributes = getFeatureResult(theFeature)->data()->refsToMe(); -// std::set aFRefsList = theFeature->data()->refsToMe(); -// aRefsAttributes.insert(aFRefsList.begin(), aFRefsList.end()); -// -// std::set::const_iterator aIt; -// for (aIt = aRefsAttributes.cbegin(); aIt != aRefsAttributes.cend(); ++aIt) { -// AttributePtr anAttr = (*aIt); -// FeaturePtr anAttrFeature = ModelAPI_Feature::feature(anAttr->owner()); -// if (anAttrFeature.get() != this && -// anAttr.get() && anAttr->attributeType() == ModelAPI_AttributeRefAttr::typeId()) { -// AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(anAttr); -// if (!aRefAttr->isObject()) { /// find attributes referenced to feature point attributes -// AttributePtr anAttrInRef = aRefAttr->attr(); -// if (anAttrInRef.get() && -// aPointAttributesSet.find(anAttrInRef) != aPointAttributesSet.end()) { -// if (theRefs.find(anAttrInRef) != theRefs.end()) -// theRefs[anAttrInRef].push_back(aRefAttr); -// else { -// std::list anAttrList; -// anAttrList.push_back(aRefAttr); -// theRefs[anAttrInRef] = anAttrList; -// } -// } -// } -// else { /// find attributes referenced to feature itself -// theRefsToFeature.push_back(anAttr); -// } -// } -// } -//} -// + +void SketchPlugin_Trim::getFeaturePoints(const FeaturePtr& theFeature, + AttributePoint2DPtr& theStartPointAttr, + AttributePoint2DPtr& theEndPointAttr) +{ + std::string aFeatureKind = theFeature->getKind(); + std::string aStartAttributeName, anEndAttributeName; + if (aFeatureKind == SketchPlugin_Line::ID()) { + aStartAttributeName = SketchPlugin_Line::START_ID(); + anEndAttributeName = SketchPlugin_Line::END_ID(); + } + else if (aFeatureKind == SketchPlugin_Arc::ID()) { + aStartAttributeName = SketchPlugin_Arc::START_ID(); + anEndAttributeName = SketchPlugin_Arc::END_ID(); + } + if (!aStartAttributeName.empty() && !anEndAttributeName.empty()) { + theStartPointAttr = std::dynamic_pointer_cast( + theFeature->attribute(aStartAttributeName)); + theEndPointAttr = std::dynamic_pointer_cast( + theFeature->attribute(anEndAttributeName)); + } +} + +void SketchPlugin_Trim::getConstraints(std::set& theFeaturesToDelete, + std::set& theFeaturesToUpdate//, + //std::map& theTangentFeatures, + //std::map& theCoincidenceToFeature + ) +{ + std::shared_ptr aData = data(); + + // Check the base objects are initialized. + AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Trim::BASE_OBJECT())); + FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value()); + ResultPtr aBaseFeatureResult = getFeatureResult(aBaseFeature); + + std::set aRefsList = aBaseFeatureResult->data()->refsToMe(); + std::set aFRefsList = aBaseFeature->data()->refsToMe(); + aRefsList.insert(aFRefsList.begin(), aFRefsList.end()); + + 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()); + std::string aRefFeatureKind = aRefFeature->getKind(); + if (aRefFeatureKind == SketchPlugin_ConstraintMirror::ID() || + aRefFeatureKind == SketchPlugin_MultiRotation::ID() || + 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()) { + //FeaturePtr aFeature1 = ModelAPI_Feature::feature(aResult1); + //std::string anAttributeToBeModified = aFeature1 == aBaseFeature + // ? SketchPlugin_Constraint::ENTITY_A() : SketchPlugin_Constraint::ENTITY_B(); + //theTangentFeatures[aRefFeature] = std::make_pair(anAttributeToBeModified, aTangentPoint); + } + else /// there is not coincident point between tangent constraint + theFeaturesToDelete.insert(aRefFeature); + } + } + /*else if (aRefFeatureKind == SketchPlugin_ConstraintCoincidence::ID()) { + std::string anAttributeToBeModified; + AttributePoint2DPtr aCoincidentPoint; + AttributeRefAttrPtr anAttrA = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_A()); + AttributeRefAttrPtr anAttrB = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_B()); + bool isToFeature = false; + if (anAttrA->isObject() || anAttrB->isObject()) { /// coincidence to base feature + FeaturePtr aFeature = anAttrA->isObject() ? ModelAPI_Feature::feature(anAttrA->object()) + : FeaturePtr(); + isToFeature = aFeature.get() && aFeature == aBaseFeature; + anAttributeToBeModified = anAttrA->id(); + if (!isToFeature) { + aFeature = anAttrB->isObject() ? ModelAPI_Feature::feature(anAttrB->object()) + : FeaturePtr(); + isToFeature = aFeature.get() && aFeature == aBaseFeature; + anAttributeToBeModified = anAttrB->id(); + } + if (isToFeature) + aCoincidentPoint = SketchPlugin_ConstraintCoincidence::getPoint(aRefFeature); + } + if (!isToFeature) { /// coincidence to point on base feature + AttributePtr anAttribute; + + if (!anAttrA->isObject()) { + AttributePtr aCurAttribute = anAttrA->attr(); + if (aCurAttribute.get()) { + FeaturePtr aCurFeature = ModelAPI_Feature::feature(aCurAttribute->owner()); + if (aCurFeature.get() && aCurFeature == aBaseFeature) { + anAttribute = anAttrB->attr(); + anAttributeToBeModified = anAttrA->id(); + } + } + } + if (!anAttribute.get() && !anAttrB->isObject()) { + AttributePtr aCurAttribute = anAttrB->attr(); + if (aCurAttribute.get()) { + FeaturePtr aCurFeature = ModelAPI_Feature::feature(aCurAttribute->owner()); + if (aCurFeature.get() && aCurFeature == aBaseFeature) { + anAttribute = anAttrA->attr(); + anAttributeToBeModified = anAttrB->id(); + } + } + } + if (anAttribute.get()) + aCoincidentPoint = std::dynamic_pointer_cast(anAttribute); + } + //if (aCoincidentPoint.get() && isToFeature) + // theCoincidenceToFeature[aRefFeature] = std::make_pair(anAttributeToBeModified, + // aCoincidentPoint); + }*/ + } +} + +void SketchPlugin_Trim::getRefAttributes(const FeaturePtr& theFeature, + std::map >& theRefs, + std::list& theRefsToFeature) +{ + theRefs.clear(); + + std::list aPointAttributes = + theFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); + std::set aPointAttributesSet; + + std::list::const_iterator aPIt = + aPointAttributes.begin(), aPLast = aPointAttributes.end(); + for (; aPIt != aPLast; aPIt++) + aPointAttributesSet.insert(*aPIt); + + std::set aRefsAttributes = getFeatureResult(theFeature)->data()->refsToMe(); + std::set aFRefsList = theFeature->data()->refsToMe(); + aRefsAttributes.insert(aFRefsList.begin(), aFRefsList.end()); + + std::set::const_iterator aIt; + for (aIt = aRefsAttributes.cbegin(); aIt != aRefsAttributes.cend(); ++aIt) { + AttributePtr anAttr = (*aIt); + FeaturePtr anAttrFeature = ModelAPI_Feature::feature(anAttr->owner()); + if (anAttrFeature.get() != this && + anAttr.get() && anAttr->attributeType() == ModelAPI_AttributeRefAttr::typeId()) { + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(anAttr); + if (!aRefAttr->isObject()) { /// find attributes referenced to feature point attributes + AttributePtr anAttrInRef = aRefAttr->attr(); + if (anAttrInRef.get() && + aPointAttributesSet.find(anAttrInRef) != aPointAttributesSet.end()) { + if (theRefs.find(anAttrInRef) != theRefs.end()) + theRefs[anAttrInRef].push_back(aRefAttr); + else { + std::list anAttrList; + anAttrList.push_back(aRefAttr); + theRefs[anAttrInRef] = anAttrList; + } + } + } + else { /// find attributes referenced to feature itself + theRefsToFeature.push_back(anAttr); + } + } + } +} + //void SketchPlugin_Trim::updateCoincidenceConstraintsToFeature( // const std::map, IdToPointPair>& theCoincidenceToFeature, -// const std::set >& theFurtherCoincidences, +// const std::set& theFurtherCoincidences, // const std::set& theFeatureResults, // const FeaturePtr& theSplitFeature) //{ @@ -732,7 +933,7 @@ AISObjectPtr SketchPlugin_Trim::getAISObject(AISObjectPtr thePrevious) // return; // // // we should build coincidence constraints to end of the split feature -// std::set > aNewCoincidencesToSplitFeature; +// std::set aNewCoincidencesToSplitFeature; // AttributePoint2DPtr aStartPointAttr, anEndPointAttr; // getFeaturePoints(theSplitFeature, aStartPointAttr, anEndPointAttr); // if (theFurtherCoincidences.find(aStartPointAttr) == theFurtherCoincidences.end()) @@ -801,7 +1002,7 @@ AISObjectPtr SketchPlugin_Trim::getAISObject(AISObjectPtr thePrevious) // //void SketchPlugin_Trim::updateTangentConstraintsToFeature( // const std::map, IdToPointPair>& theTangentFeatures, -// const std::set >& theFurtherCoincidences) +// const std::set& theFurtherCoincidences) //{ // if (theTangentFeatures.empty()) // return; @@ -836,54 +1037,54 @@ AISObjectPtr SketchPlugin_Trim::getAISObject(AISObjectPtr thePrevious) //#endif // } //} -// -//void SketchPlugin_Trim::updateRefFeatureConstraints( -// const ResultPtr& theFeatureBaseResult, -// const std::list& theRefsToFeature) -//{ -// 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); -// } -//} -// -//void SketchPlugin_Trim::updateRefAttConstraints( -// const std::map >& theBaseRefAttributes, -// const std::set >& theModifiedAttributes) -//{ -//#ifdef DEBUG_SPLIT -// std::cout << "SketchPlugin_Trim::updateRefAttConstraints" << std::endl; -//#endif -// -// std::set >::const_iterator -// anIt = theModifiedAttributes.begin(), aLast = theModifiedAttributes.end(); -// for (; anIt != aLast; anIt++) { -// AttributePtr anAttribute = anIt->first; -// -// /// not found in references -// if (theBaseRefAttributes.find(anAttribute) == theBaseRefAttributes.end()) -// continue; -// std::list aRefAttributes = theBaseRefAttributes.at(anAttribute); -// std::list::const_iterator aRefIt = aRefAttributes.begin(), -// aRLast = aRefAttributes.end(); -// -// AttributePtr aNewAttribute = anIt->second; -// for (; aRefIt != aRLast; aRefIt++) { -// AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(*aRefIt); -// if (aRefAttr.get()) { -// aRefAttr->setAttr(aNewAttribute); -//#ifdef DEBUG_SPLIT -// FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->owner()); -// std::cout << " -" << getFeatureInfo(aFeature) << std::endl; -//#endif -// } -// } -// } -//} -// + +void SketchPlugin_Trim::updateRefFeatureConstraints( + const ResultPtr& theFeatureBaseResult, + const std::list& theRefsToFeature) +{ + 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); + } +} + +void SketchPlugin_Trim::updateRefAttConstraints( + const std::map >& theBaseRefAttributes, + const std::set >& theModifiedAttributes) +{ +#ifdef DEBUG_SPLIT + std::cout << "SketchPlugin_Trim::updateRefAttConstraints" << std::endl; +#endif + + std::set >::const_iterator + anIt = theModifiedAttributes.begin(), aLast = theModifiedAttributes.end(); + for (; anIt != aLast; anIt++) { + AttributePtr anAttribute = anIt->first; + + /// not found in references + if (theBaseRefAttributes.find(anAttribute) == theBaseRefAttributes.end()) + continue; + std::list aRefAttributes = theBaseRefAttributes.at(anAttribute); + std::list::const_iterator aRefIt = aRefAttributes.begin(), + aRLast = aRefAttributes.end(); + + AttributePtr aNewAttribute = anIt->second; + for (; aRefIt != aRLast; aRefIt++) { + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(*aRefIt); + if (aRefAttr.get()) { + aRefAttr->setAttr(aNewAttribute); +#ifdef DEBUG_SPLIT + FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->owner()); + std::cout << " -" << getFeatureInfo(aFeature) << std::endl; +#endif + } + } + } +} + //void SketchPlugin_Trim::splitLine(FeaturePtr& theSplitFeature, // FeaturePtr& theBaseFeatureModified, // FeaturePtr& theAfterFeature, @@ -900,7 +1101,7 @@ AISObjectPtr SketchPlugin_Trim::getAISObject(AISObjectPtr thePrevious) // return; // // AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast( -// data()->attribute(SketchPlugin_Constraint::VALUE())); +// data()->attribute(SketchPlugin_Trim::BASE_OBJECT())); // FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value()); // std::string aFeatureKind = aBaseFeature->getKind(); // if (aFeatureKind != SketchPlugin_Line::ID()) @@ -1034,7 +1235,7 @@ AISObjectPtr SketchPlugin_Trim::getAISObject(AISObjectPtr thePrevious) // return; // // AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast( -// data()->attribute(SketchPlugin_Constraint::VALUE())); +// data()->attribute(SketchPlugin_Trim::BASE_OBJECT())); // FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value()); // std::string aFeatureKind = aBaseFeature->getKind(); // if (aFeatureKind != SketchPlugin_Arc::ID()) @@ -1160,74 +1361,83 @@ AISObjectPtr SketchPlugin_Trim::getAISObject(AISObjectPtr thePrevious) // theCreatedFeatures.insert(aConstraintFeature); // } //} -// -//void SketchPlugin_Trim::splitCircle(FeaturePtr& theSplitFeature, -// FeaturePtr& theBaseFeatureModified, -// FeaturePtr& theAfterFeature, -// std::set& thePoints, -// std::set& theCreatedFeatures, -// std::set>& theModifiedAttributes) -//{ -// std::set aCreatedFeatures; -// FeaturePtr aConstraintFeature; -// theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature -// -// SketchPlugin_Sketch* aSketch = sketch(); -// if (!aSketch) -// return; -// -// AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast( -// data()->attribute(SketchPlugin_Constraint::VALUE())); -// FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value()); -// std::string aFeatureKind = aBaseFeature->getKind(); -// if (aFeatureKind != SketchPlugin_Circle::ID()) -// return; -// -// AttributePoint2DPtr aFirstPointAttrOfSplit = -// getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_A())); -// AttributePoint2DPtr aSecondPointAttrOfSplit = -// getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_B())); -// -// /// split feature -// theSplitFeature = -// createArcFeature(aBaseFeature, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit); -// bool aSplitReversed = std::dynamic_pointer_cast(theSplitFeature)->isReversed(); -// theCreatedFeatures.insert(theSplitFeature); -// -// /// base feature is a left part of the circle -// theBaseFeatureModified = createArcFeature(aBaseFeature, -// aFirstPointAttrOfSplit, aSecondPointAttrOfSplit); -// std::dynamic_pointer_cast( -// theBaseFeatureModified)->setReversed(!aSplitReversed); -// theBaseFeatureModified->execute(); -// -// theModifiedAttributes.insert( -// std::make_pair(aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()), -// theBaseFeatureModified->attribute(SketchPlugin_Arc::CENTER_ID()))); -// -// theCreatedFeatures.insert(theBaseFeatureModified); -// -// thePoints.insert(std::dynamic_pointer_cast -// (theBaseFeatureModified->attribute(SketchPlugin_Arc::START_ID()))); -// thePoints.insert(std::dynamic_pointer_cast -// (theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID()))); -// -// // additional constraints between split and base features -// aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(), -// theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID()), -// theSplitFeature->attribute(SketchPlugin_Arc::END_ID())); -// theCreatedFeatures.insert(aConstraintFeature); -// aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(), -// theBaseFeatureModified->attribute(SketchPlugin_Arc::START_ID()), -// theSplitFeature->attribute(SketchPlugin_Arc::START_ID())); -// theCreatedFeatures.insert(aConstraintFeature); -// -// aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintTangent::ID(), -// getFeatureResult(theSplitFeature), -// getFeatureResult(theBaseFeatureModified)); -// theCreatedFeatures.insert(aConstraintFeature); -//} -// + +void SketchPlugin_Trim::trimCircle(const std::shared_ptr& theStartShapePoint, + const std::shared_ptr& theLastShapePoint, + /*FeaturePtr& theSplitFeature, + FeaturePtr& theBaseFeatureModified, + FeaturePtr& theAfterFeature,*/ + std::set& thePoints, + std::set& theCreatedFeatures, + std::set>& theModifiedAttributes) +{ + // Check the base objects are initialized. + AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast( + data()->attribute(SketchPlugin_Trim::BASE_OBJECT())); + ObjectPtr aBaseObject = aBaseObjectAttr->value(); + FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value()); + + /// points of trim + //std::shared_ptr aStartShapePoint, aLastShapePoint; + //findShapePoints(aStartShapePoint, aLastShapePoint); + //std::shared_ptr aStartShapePoint2d = convertPoint(aStartShapePoint); + //std::shared_ptr aLastShapePoint2d = convertPoint(aLastShapePoint); + AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase; + getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase); + + //std::set aCreatedFeatures; + //FeaturePtr aConstraintFeature; + //theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature + + SketchPlugin_Sketch* aSketch = sketch(); + //if (!aSketch) + // return; + + //AttributePoint2DPtr aFirstPointAttrOfSplit = + // getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_A())); + //AttributePoint2DPtr aSecondPointAttrOfSplit = + // getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_B())); + + /// split feature + //theSplitFeature = + // createArcFeature(aBaseFeature, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit); + //bool aSplitReversed = std::dynamic_pointer_cast(theSplitFeature)->isReversed(); + //theCreatedFeatures.insert(theSplitFeature); + + /// base feature is a left part of the circle + /*theBaseFeatureModified =*/ + FeaturePtr anArcFeature = createArcFeature(aBaseFeature, theStartShapePoint, theLastShapePoint); + //std::dynamic_pointer_cast( + // theBaseFeatureModified)->setReversed(!aSplitReversed); + //theBaseFeatureModified->execute(); + + theModifiedAttributes.insert( + std::make_pair(aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()), + anArcFeature->attribute(SketchPlugin_Arc::CENTER_ID()))); + + //theCreatedFeatures.insert(theBaseFeatureModified); + + thePoints.insert(std::dynamic_pointer_cast + (anArcFeature->attribute(SketchPlugin_Arc::START_ID()))); + thePoints.insert(std::dynamic_pointer_cast + (anArcFeature->attribute(SketchPlugin_Arc::END_ID()))); + + // additional constraints between split and base features + /*aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(), + theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID()), + theSplitFeature->attribute(SketchPlugin_Arc::END_ID())); + theCreatedFeatures.insert(aConstraintFeature); + aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(), + theBaseFeatureModified->attribute(SketchPlugin_Arc::START_ID()), + theSplitFeature->attribute(SketchPlugin_Arc::START_ID())); + theCreatedFeatures.insert(aConstraintFeature); + + aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintTangent::ID(), + getFeatureResult(theSplitFeature), + getFeatureResult(theBaseFeatureModified)); + theCreatedFeatures.insert(aConstraintFeature);*/ +} + //void SketchPlugin_Trim::arrangePointsOnLine( // const AttributePoint2DPtr& theStartPointAttr, // const AttributePoint2DPtr& theEndPointAttr, @@ -1245,10 +1455,10 @@ AISObjectPtr SketchPlugin_Trim::getAISObject(AISObjectPtr thePrevious) // //void SketchPlugin_Trim::arrangePointsOnArc( // const FeaturePtr& theArc, -// const std::shared_ptr& theStartPointAttr, -// const std::shared_ptr& theEndPointAttr, -// std::shared_ptr& theFirstPointAttr, -// std::shared_ptr& theSecondPointAttr) const +// const AttributePoint2DPtr& theStartPointAttr, +// const AttributePoint2DPtr& theEndPointAttr, +// AttributePoint2DPtr& theFirstPointAttr, +// AttributePoint2DPtr& theSecondPointAttr) const //{ // static const double anAngleTol = 1.e-12; // @@ -1279,45 +1489,61 @@ AISObjectPtr SketchPlugin_Trim::getAISObject(AISObjectPtr thePrevious) // theSecondPointAttr = aTmpPoint; // } //} -// -//void SketchPlugin_Trim::fillAttribute(const AttributePtr& theModifiedAttribute, -// const AttributePtr& theSourceAttribute) -//{ -// std::string anAttributeType = theModifiedAttribute->attributeType(); -// if (anAttributeType == GeomDataAPI_Point2D::typeId()) { -// AttributePoint2DPtr aModifiedAttribute = std::dynamic_pointer_cast( -// theModifiedAttribute); -// AttributePoint2DPtr aSourceAttribute = std::dynamic_pointer_cast( -// theSourceAttribute); -// -// if (aModifiedAttribute.get() && aSourceAttribute.get()) -// aModifiedAttribute->setValue(aSourceAttribute->pnt()); -// } -// else if (anAttributeType == ModelAPI_AttributeBoolean::typeId()) { -// AttributeBooleanPtr aModifiedAttribute = std::dynamic_pointer_cast( -// theModifiedAttribute); -// AttributeBooleanPtr aSourceAttribute = std::dynamic_pointer_cast( -// theSourceAttribute); -// -// if (aModifiedAttribute.get() && aSourceAttribute.get()) -// aModifiedAttribute->setValue(aSourceAttribute->value()); -// } -// else if (anAttributeType == ModelAPI_AttributeRefAttr::typeId()) { -// AttributeRefAttrPtr aRefAttributeToFill = std::dynamic_pointer_cast( -// theModifiedAttribute); -// AttributeRefAttrPtr aSourceRefAttr = std::dynamic_pointer_cast( -// theSourceAttribute); -// if (!aSourceRefAttr.get()) -// aRefAttributeToFill->setAttr(theSourceAttribute); -// else { -// if (aSourceRefAttr->isObject()) -// aRefAttributeToFill->setObject(aSourceRefAttr->object()); -// else -// aRefAttributeToFill->setAttr(aSourceRefAttr->attr()); -// } -// } -//} -// + +void SketchPlugin_Trim::fillPointAttribute(const AttributePtr& theModifiedAttribute, + const std::shared_ptr& thePoint) +{ + std::string anAttributeType = theModifiedAttribute->attributeType(); + if (anAttributeType == GeomDataAPI_Point2D::typeId()) { + AttributePoint2DPtr aModifiedAttribute = std::dynamic_pointer_cast( + theModifiedAttribute); + aModifiedAttribute->setValue(thePoint); + +#ifdef DEBUG_TRIM + std::cout << " => Pnt2d - [" << thePoint->x() << ", " << thePoint->y() << "]" << std::endl; +#endif + } +} + + +void SketchPlugin_Trim::fillAttribute(const AttributePtr& theModifiedAttribute, + const AttributePtr& theSourceAttribute) +{ + std::string anAttributeType = theModifiedAttribute->attributeType(); + if (anAttributeType == GeomDataAPI_Point2D::typeId()) { + AttributePoint2DPtr aModifiedAttribute = std::dynamic_pointer_cast( + theModifiedAttribute); + AttributePoint2DPtr aSourceAttribute = std::dynamic_pointer_cast( + theSourceAttribute); + + if (aModifiedAttribute.get() && aSourceAttribute.get()) + aModifiedAttribute->setValue(aSourceAttribute->pnt()); + } + else if (anAttributeType == ModelAPI_AttributeBoolean::typeId()) { + AttributeBooleanPtr aModifiedAttribute = std::dynamic_pointer_cast( + theModifiedAttribute); + AttributeBooleanPtr aSourceAttribute = std::dynamic_pointer_cast( + theSourceAttribute); + + if (aModifiedAttribute.get() && aSourceAttribute.get()) + aModifiedAttribute->setValue(aSourceAttribute->value()); + } + else if (anAttributeType == ModelAPI_AttributeRefAttr::typeId()) { + AttributeRefAttrPtr aRefAttributeToFill = std::dynamic_pointer_cast( + theModifiedAttribute); + AttributeRefAttrPtr aSourceRefAttr = std::dynamic_pointer_cast( + theSourceAttribute); + if (!aSourceRefAttr.get()) + aRefAttributeToFill->setAttr(theSourceAttribute); + else { + if (aSourceRefAttr->isObject()) + aRefAttributeToFill->setObject(aSourceRefAttr->object()); + else + aRefAttributeToFill->setAttr(aSourceRefAttr->attr()); + } + } +} + //FeaturePtr SketchPlugin_Trim::createLineFeature(const FeaturePtr& theBaseFeature, // const AttributePtr& theFirstPointAttr, // const AttributePtr& theSecondPointAttr) @@ -1340,68 +1566,100 @@ AISObjectPtr SketchPlugin_Trim::getAISObject(AISObjectPtr thePrevious) // return aFeature; //} // -//FeaturePtr SketchPlugin_Trim::createArcFeature(const FeaturePtr& theBaseFeature, -// const AttributePtr& theFirstPointAttr, -// const AttributePtr& theSecondPointAttr) -//{ -// FeaturePtr aFeature; -// SketchPlugin_Sketch* aSketch = sketch(); -// if (!aSketch || !theBaseFeature.get()) -// return aFeature; -// -// std::string aCenterAttributeId; -// if (theBaseFeature->getKind() == SketchPlugin_Arc::ID()) -// aCenterAttributeId = SketchPlugin_Arc::CENTER_ID(); -// else if (theBaseFeature->getKind() == SketchPlugin_Circle::ID()) -// aCenterAttributeId = SketchPlugin_Circle::CENTER_ID(); -// -// if (aCenterAttributeId.empty()) -// return aFeature; -// -// aFeature = aSketch->addFeature(SketchPlugin_Arc::ID()); -// // update fillet arc: make the arc correct for sure, so, it is not needed to process -// // the "attribute updated" -// // by arc; moreover, it may cause cyclicity in hte mechanism of updater -// bool aWasBlocked = aFeature->data()->blockSendAttributeUpdated(true); -// -// aFeature->string(SketchPlugin_Arc::ARC_TYPE())->setValue( -// SketchPlugin_Arc::ARC_TYPE_CENTER_START_END()); -// -// fillAttribute(aFeature->attribute(SketchPlugin_Arc::CENTER_ID()), -// theBaseFeature->attribute(aCenterAttributeId)); -// fillAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), theFirstPointAttr); -// fillAttribute(aFeature->attribute(SketchPlugin_Arc::END_ID()), theSecondPointAttr); -// -// fillAttribute(aFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()), -// theBaseFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID())); -// -// /// fill referersed state of created arc as it is on the base arc -// if (theBaseFeature->getKind() == SketchPlugin_Arc::ID()) { -// bool aReversed = theBaseFeature->boolean(SketchPlugin_Arc::INVERSED_ID())->value(); -// aFeature->boolean(SketchPlugin_Arc::INVERSED_ID())->setValue(aReversed); -// } -// aFeature->data()->blockSendAttributeUpdated(aWasBlocked); -// aFeature->execute(); // to obtain result -// -// return aFeature; -//} -// -//FeaturePtr SketchPlugin_Trim::createConstraint(const std::string& theConstraintId, -// const AttributePtr& theFirstAttribute, -// const AttributePtr& theSecondAttribute) -//{ -// FeaturePtr aConstraint = sketch()->addFeature(theConstraintId); -// AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( -// aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A())); -// aRefAttr->setAttr(theFirstAttribute); -// -// aRefAttr = std::dynamic_pointer_cast( -// aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B())); -// aRefAttr->setAttr(theSecondAttribute); -// -// return aConstraint; -//} -// + +FeaturePtr SketchPlugin_Trim::createArcFeature(const FeaturePtr& theBaseFeature, + const std::shared_ptr& theFirstPoint, + const std::shared_ptr& theSecondPoint) +{ + FeaturePtr aFeature; + SketchPlugin_Sketch* aSketch = sketch(); + if (!aSketch || !theBaseFeature.get()) + return aFeature; + + std::string aCenterAttributeId; + if (theBaseFeature->getKind() == SketchPlugin_Arc::ID()) + aCenterAttributeId = SketchPlugin_Arc::CENTER_ID(); + else if (theBaseFeature->getKind() == SketchPlugin_Circle::ID()) + aCenterAttributeId = SketchPlugin_Circle::CENTER_ID(); + + if (aCenterAttributeId.empty()) + return aFeature; + + aFeature = aSketch->addFeature(SketchPlugin_Arc::ID()); + // update fillet arc: make the arc correct for sure, so, it is not needed to process + // the "attribute updated" + // by arc; moreover, it may cause cyclicity in hte mechanism of updater + bool aWasBlocked = aFeature->data()->blockSendAttributeUpdated(true); + + aFeature->string(SketchPlugin_Arc::ARC_TYPE())->setValue( + SketchPlugin_Arc::ARC_TYPE_CENTER_START_END()); + + fillAttribute(aFeature->attribute(SketchPlugin_Arc::CENTER_ID()), + theBaseFeature->attribute(aCenterAttributeId)); + fillPointAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), theFirstPoint); + fillPointAttribute(aFeature->attribute(SketchPlugin_Arc::END_ID()), theSecondPoint); + + fillAttribute(aFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()), + theBaseFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID())); + + /// fill referersed state of created arc as it is on the base arc + if (theBaseFeature->getKind() == SketchPlugin_Arc::ID()) { + bool aReversed = theBaseFeature->boolean(SketchPlugin_Arc::INVERSED_ID())->value(); + aFeature->boolean(SketchPlugin_Arc::INVERSED_ID())->setValue(aReversed); + } + aFeature->execute(); // to obtain result + aFeature->data()->blockSendAttributeUpdated(aWasBlocked); + + return aFeature; +} + +FeaturePtr SketchPlugin_Trim::createConstraint(const std::string& theConstraintId, + const AttributePtr& theFirstAttribute, + const AttributePtr& theSecondAttribute) +{ + FeaturePtr aConstraint = sketch()->addFeature(theConstraintId); + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( + aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A())); + aRefAttr->setAttr(theFirstAttribute); + + aRefAttr = std::dynamic_pointer_cast( + aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B())); + aRefAttr->setAttr(theSecondAttribute); + +#ifdef DEBUG_TRIM + std::cout << " :" + << "first attribute - " << theFirstAttribute->id() + << "second attribute - " << theSecondAttribute->id() + << std::endl; +#endif + + return aConstraint; +} + +FeaturePtr SketchPlugin_Trim::createConstraint(const std::string& theConstraintId, + const AttributePtr& theFirstAttribute, + const ObjectPtr& theSecondObject) +{ + FeaturePtr aConstraint = sketch()->addFeature(theConstraintId); + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( + aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A())); + aRefAttr->setAttr(theFirstAttribute); + + aRefAttr = std::dynamic_pointer_cast( + aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B())); + aRefAttr->setObject(theSecondObject); + +#ifdef DEBUG_TRIM + std::cout << " :" + << "first attribute - " << theFirstAttribute->id() + << "second object - " << ModelAPI_Feature::feature(theSecondObject)->getKind() + << std::endl; +#endif + + return aConstraint; +} + + // //FeaturePtr SketchPlugin_Trim::createConstraintForObjects( // const std::string& theConstraintId, // const ObjectPtr& theFirstObject, @@ -1432,7 +1690,7 @@ AISObjectPtr SketchPlugin_Trim::getAISObject(AISObjectPtr thePrevious) // std::dynamic_pointer_cast(*anIt); // if (aLenghtFeature.get()) { // std::shared_ptr aValueAttr = std::dynamic_pointer_cast< -// ModelAPI_AttributeDouble>(aLenghtFeature->attribute(SketchPlugin_Constraint::VALUE())); +// ModelAPI_AttributeDouble>(aLenghtFeature->attribute(SketchPlugin_Trim::BASE_OBJECT())); // double aValue; // if (aLenghtFeature->computeLenghtValue(aValue) && aValueAttr.get()) // aValueAttr->setValue(aValue); @@ -1440,23 +1698,23 @@ AISObjectPtr SketchPlugin_Trim::getAISObject(AISObjectPtr thePrevious) // } // } //} -// -//std::shared_ptr SketchPlugin_Trim::getFeatureResult( -// const std::shared_ptr& theFeature) -//{ -// std::shared_ptr aResult; -// -// std::string aFeatureKind = theFeature->getKind(); -// if (aFeatureKind == SketchPlugin_Line::ID()) -// aResult = theFeature->firstResult(); -// else if (aFeatureKind == SketchPlugin_Arc::ID()) -// aResult = theFeature->lastResult(); -// else if (aFeatureKind == SketchPlugin_Circle::ID()) -// aResult = theFeature->lastResult(); -// -// return aResult; -//} -// + +std::shared_ptr SketchPlugin_Trim::getFeatureResult( + const std::shared_ptr& theFeature) +{ + std::shared_ptr aResult; + + std::string aFeatureKind = theFeature->getKind(); + if (aFeatureKind == SketchPlugin_Line::ID()) + aResult = theFeature->firstResult(); + else if (aFeatureKind == SketchPlugin_Arc::ID()) + aResult = theFeature->lastResult(); + else if (aFeatureKind == SketchPlugin_Circle::ID()) + aResult = theFeature->lastResult(); + + return aResult; +} + //std::set > SketchPlugin_Trim::getEdgeAttributes( // const std::shared_ptr& theFeature) //{ @@ -1547,15 +1805,18 @@ bool SketchPlugin_Trim::useGraphicIntersection() const } //******************************************************************** -#include void SketchPlugin_Trim::fillObjectShapes(const ObjectPtr& theObject) { + PointToRefsMap aPointsInfo; + std::set > aShapes; - std::map, std::shared_ptr > aPointToAttributes; - std::map, - std::list< std::shared_ptr > > aPointToObjects; + //std::map > aPointToAttributes; + std::map, + std::list< AttributePoint2DPtr > > aPointToAttributes; + std::map, + std::list< ObjectPtr > > aPointToObjects; - std::set > aRefAttributes; + std::set aRefAttributes; // current feature FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); std::set anEdgeShapes; @@ -1565,7 +1826,7 @@ void SketchPlugin_Trim::fillObjectShapes(const ObjectPtr& theObject) GeomShapePtr aFeatureShape = (*anEdgeShapes.begin())->shape(); // coincidences to the feature - std::list > aPoints; + //std::list > aPoints; ModelGeomAlgo_Point2D::getPointsOfReference(aFeature, SketchPlugin_ConstraintCoincidence::ID(), aRefAttributes, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID()); @@ -1580,8 +1841,9 @@ void SketchPlugin_Trim::fillObjectShapes(const ObjectPtr& theObject) std::shared_ptr aNorm = std::dynamic_pointer_cast( aData->attribute(SketchPlugin_Sketch::NORM_ID())); std::shared_ptr aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir()))); + ModelGeomAlgo_Point2D::getPointsInsideShape(aFeatureShape, aRefAttributes, aC->pnt(), - aX->dir(), aY, aPoints, aPointToAttributes); + aX->dir(), aY, aPointsInfo);//aPoints, aPointToAttributes); // intersection points if (useGraphicIntersection()) { @@ -1591,13 +1853,49 @@ void SketchPlugin_Trim::fillObjectShapes(const ObjectPtr& theObject) if (aFeature.get()) aFeatures.push_back(aFeature); } - ModelGeomAlgo_Point2D::getPointsIntersectedShape(aFeature, aFeatures, aPoints, - aPointToObjects); + ModelGeomAlgo_Point2D::getPointsIntersectedShape(aFeature, aFeatures,// aPoints, + aPointsInfo); } - GeomAlgoAPI_ShapeTools::splitShape(aFeatureShape, aPoints, aShapes); + GeomAlgoAPI_ShapeTools::splitShape(aFeatureShape, aPointsInfo, aShapes); + } + + myObjectToPoints[theObject] = aPointsInfo; myCashedShapes[theObject] = aShapes; - myCashedReferences[theObject] = aPointToAttributes; - if (useGraphicIntersection()) - myCashedObjects[theObject] = aPointToObjects; + //myCashedReferences[theObject] = aPointToAttributes; + //if (useGraphicIntersection()) + // myCashedObjects[theObject] = aPointToObjects; +} + +//******************************************************************** +void SketchPlugin_Trim::attributeChanged(const std::string& theID) +{ + //data()->addAttribute(SketchPlugin_Trim::BASE_OBJECT(), ModelAPI_AttributeReference::typeId()); + if (theID == SketchPlugin_Trim::BASE_OBJECT()) { + bool isValidAttribute = false; + // feature for trim + AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast( + data()->attribute(SketchPlugin_Trim::BASE_OBJECT())); + ObjectPtr aBaseObject = aBaseObjectAttr->value(); + if (aBaseObject.get()) { + FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value()); + // point on feature + AttributePoint2DPtr aPoint = std::dynamic_pointer_cast( + data()->attribute(ENTITY_POINT())); + std::shared_ptr anAttributePnt2d = aPoint->pnt(); + std::shared_ptr anAttributePnt = sketch()->to3D(anAttributePnt2d->x(), anAttributePnt2d->y()); + + if (myCashedShapes.find(aBaseObject) == myCashedShapes.end()) + fillObjectShapes(aBaseObject); + + const std::set& aShapes = myCashedShapes[aBaseObject]; + isValidAttribute = !aShapes.empty(); + + if (!isValidAttribute) { + bool aWasBlocked = data()->blockSendAttributeUpdated(true); + aBaseObjectAttr->setValue(ObjectPtr()); + data()->blockSendAttributeUpdated(aWasBlocked); + } + } + } } diff --git a/src/SketchPlugin/SketchPlugin_Trim.h b/src/SketchPlugin/SketchPlugin_Trim.h index bebc8b8c2..a1e1387f7 100644 --- a/src/SketchPlugin/SketchPlugin_Trim.h +++ b/src/SketchPlugin/SketchPlugin_Trim.h @@ -47,7 +47,7 @@ typedef std::pair > IdToPointP * SketchPlugin_Constraint::ENTITY_A() and SketchPlugin_Constraint::ENTITY_B() for the points of split; * */ -class SketchPlugin_Trim : public SketchPlugin_ConstraintBase +class SketchPlugin_Trim : public SketchPlugin_Feature, public GeomAPI_IPresentable { public: /// Split constraint kind @@ -63,6 +63,13 @@ class SketchPlugin_Trim : public SketchPlugin_ConstraintBase return MY_KIND; } + /// The value parameter for the constraint + inline static const std::string& BASE_OBJECT() + { + static const std::string MY_CONSTRAINT_BASE_OBJECT("BaseObject"); + return MY_CONSTRAINT_BASE_OBJECT; + } + /// Start 2D point of the split segment inline static const std::string& ENTITY_POINT() { @@ -90,6 +97,10 @@ class SketchPlugin_Trim : public SketchPlugin_ConstraintBase /// This is necessary to perform execute only by apply the feature SKETCHPLUGIN_EXPORT virtual bool isPreviewNeeded() const { return false; } + /// Called on change of any argument-attribute of this object + /// \param theID identifier of changed attribute + SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID); + /// \brief Use plugin manager for features creation SketchPlugin_Trim(); @@ -101,16 +112,19 @@ class SketchPlugin_Trim : public SketchPlugin_ConstraintBase /// Returns the AIS preview SKETCHPLUGIN_EXPORT virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious); -//private: -// /// Returns geom point attribute of the feature bounds. It processes line or arc. -// /// For circle feature, the result attributes are null -// /// \param theFeature a source feature -// /// \param theStartPointAttr an out attribute to start point -// /// \param theStartPointAttr an out attribute to end point -// void getFeaturePoints(const FeaturePtr& theFeature, -// std::shared_ptr& theStartPointAttr, -// std::shared_ptr& theEndPointAttr); -// + /// Moves the feature : Empty + SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY) {}; + +private: + /// Returns geom point attribute of the feature bounds. It processes line or arc. + /// For circle feature, the result attributes are null + /// \param theFeature a source feature + /// \param theStartPointAttr an out attribute to start point + /// \param theStartPointAttr an out attribute to end point + void getFeaturePoints(const FeaturePtr& theFeature, + std::shared_ptr& theStartPointAttr, + std::shared_ptr& theEndPointAttr); + // FeaturePtr createCoincidenceConstraint(const AttributePtr& theFirstAttribute, // const AttributePtr& theSecondAttribute); // @@ -118,31 +132,31 @@ class SketchPlugin_Trim : public SketchPlugin_ConstraintBase // /// \param theAttribute an attribute // /// \param geom point 2D or NULL // std::shared_ptr getPointOfRefAttr(const AttributePtr& theAttribute); -// -// /// 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 -// /// \param theTangentFeatures [out] tangent feature to be connected to new feature -// /// \param theCoincidenceToFeature [out] coincidence to feature to be connected to new feature -// /// \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>& theCoincidenceToFeature/*, -// std::map, IdToPointPair>& theCoincidenceToPoint*/); -// -// /// Obtains references to feature point attributes and to feature, -// /// e.g. for feature line: 1st container is -// /// <1st line point, list > -// /// <2nd line point, list<> > -// /// for feature circle 2nd container is -// /// \param theFeature an investigated feature -// /// \param theRefs a container of list of referenced attributes -// void getRefAttributes(const FeaturePtr& theFeature, -// std::map >& theRefs, -// std::list& theRefsToFeature); -// + + /// 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 + /// \param theTangentFeatures [out] tangent feature to be connected to new feature + /// \param theCoincidenceToFeature [out] coincidence to feature to be connected to new feature + /// \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>& theCoincidenceToFeature/*, + //std::map, IdToPointPair>& theCoincidenceToPoint*/); + + /// Obtains references to feature point attributes and to feature, + /// e.g. for feature line: 1st container is + /// <1st line point, list > + /// <2nd line point, list<> > + /// for feature circle 2nd container is + /// \param theFeature an investigated feature + /// \param theRefs a container of list of referenced attributes + void getRefAttributes(const FeaturePtr& theFeature, + std::map >& theRefs, + std::list& theRefsToFeature); + // /// Move coincidence constraint from feature to point if it is found // /// \param theCoincidenceToFeature coincidence to feature to be connected to new feature // /// \param theFurtherCoincidences a list of points where coincidences will be build @@ -161,22 +175,21 @@ class SketchPlugin_Trim : public SketchPlugin_ConstraintBase // void updateTangentConstraintsToFeature( // const std::map, IdToPointPair>& theTangentFeatures, // const std::set >& theFurtherCoincidences); -// -// -// /// 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); -// -// /// Move constraints from attribute of base feature to attribute after modification -// /// \param theBaseRefAttributes container of references to the attributes of base feature -// /// \param theModifiedAttributes container of attributes placed instead of base attributes -// /// at the same place -// void updateRefAttConstraints( -// const std::map >& theBaseRefAttributes, -// const std::set >& theModifiedAttributes); -// + + /// 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); + + /// Move constraints from attribute of base feature to attribute after modification + /// \param theBaseRefAttributes container of references to the attributes of base feature + /// \param theModifiedAttributes container of attributes placed instead of base attributes + /// at the same place + void updateRefAttConstraints( + const std::map >& theBaseRefAttributes, + const std::set >& theModifiedAttributes); + // /// 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 @@ -204,20 +217,22 @@ class SketchPlugin_Trim : public SketchPlugin_ConstraintBase // std::set >& thePoints, // std::set>& theCreatedFeatures, // std::set>& theModifiedAttributes); -// -// /// 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 -// void splitCircle(std::shared_ptr& theSplitFeature, -// std::shared_ptr& theBeforeFeature, -// std::shared_ptr& theAfterFeature, -// std::set >& thePoints, -// std::set>& theCreatedFeatures, -// std::set>& theModifiedAttributes); -// + + /// 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 + void trimCircle(const std::shared_ptr& theStartShapePoint, + const std::shared_ptr& theLastShapePoint, + /*std::shared_ptr& theSplitFeature, + std::shared_ptr& theBeforeFeature, + std::shared_ptr& theAfterFeature,*/ + 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 // /// the start point and the second point - to the last end of current segment. To rearrange // /// them if this condition is not satisfied. @@ -225,11 +240,11 @@ class SketchPlugin_Trim : public SketchPlugin_ConstraintBase // /// \param theEndPointAttr an end point of a segment // /// \param theFirstPointAttr a start point of a segment // /// \param theSecondPointAttr an end point of a segment -// void arrangePointsOnLine(const std::shared_ptr& theStartPointAttr, -// const std::shared_ptr& theEndPointAttr, -// std::shared_ptr& theFirstPointAttr, -// std::shared_ptr& theSecondPointAttr) const; -// + void arrangePointsOnLine(const std::shared_ptr& theStartPointAttr, + const std::shared_ptr& theEndPointAttr, + std::shared_ptr& theFirstPointAttr, + std::shared_ptr& theSecondPointAttr) const; + // /// Correct the first and the second point to provide condition that the first is closer to // /// the start point and the second point - to the last end of current segment. To rearrange // /// them if this condition is not satisfied. @@ -243,13 +258,19 @@ class SketchPlugin_Trim : public SketchPlugin_ConstraintBase // const std::shared_ptr& theEndPointAttr, // std::shared_ptr& theFirstPointAttr, // std::shared_ptr& theSecondPointAttr) const; -// -// /// Fill attribute by value of another attribute. It processes only Point 2D attributes. -// /// \param theModifiedAttribute an attribute of GeomDataAPI_Point2D on feature to be modified -// /// \param theSourceAttribute an attribute of GeomDataAPI_Point2D to obtain data -// void fillAttribute(const AttributePtr& theModifiedAttribute, -// const AttributePtr& theSourceAttribute); -// + + /// Fill attribute by value of another attribute. It processes only Point 2D attributes. + /// \param theModifiedAttribute an attribute of GeomDataAPI_Point2D on feature to be modified + /// \param theSourceAttribute an attribute of GeomDataAPI_Point2D to obtain data + void fillAttribute(const AttributePtr& theModifiedAttribute, + const AttributePtr& theSourceAttribute); + + /// Fill attribute by value of another attribute. It processes only Point 2D attributes. + /// \param theModifiedAttribute an attribute of GeomDataAPI_Point2D on feature to be modified + /// \param thePoint a point value + void fillPointAttribute(const AttributePtr& theModifiedAttribute, + const std::shared_ptr& thePoint); + // /// Creates a line feature filled by center of base feature and given points // /// \param theBaseFeature another arc feature // /// \param theFirstAttribute an attribute with coordinates for the start point @@ -258,22 +279,30 @@ class SketchPlugin_Trim : public SketchPlugin_ConstraintBase // const AttributePtr& theFirstPointAttr, // const AttributePtr& theSecondPointAttr); // -// /// Creates an arc feature filled by center of base feature and given points -// /// \param theBaseFeature another arc feature -// /// \param theFirstAttribute an attribute with coordinates for the start point -// /// \param theSecondAttribute an attribute with coordinates for the end point -// FeaturePtr createArcFeature(const FeaturePtr& theBaseFeature, -// const AttributePtr& theFirstPointAttr, -// const AttributePtr& theSecondPointAttr); -// -// /// Add feature coincidence constraint between given attributes -// /// \param theConstraintId a constraint index -// /// \param theFirstAttribute an attribute of further coincidence -// /// \param theSecondAttribute an attribute of further coincidence -// std::shared_ptr createConstraint(const std::string& theConstraintId, -// const std::shared_ptr& theFirstAttribute, -// const std::shared_ptr& theSecondAttribute); -// + /// Creates an arc feature filled by center of base feature and given points + /// \param theBaseFeature another arc feature + /// \param theFirstAttribute an attribute with coordinates for the start point + /// \param theSecondAttribute an attribute with coordinates for the end point + FeaturePtr createArcFeature(const FeaturePtr& theBaseFeature, + const std::shared_ptr& theFirstPoint, + const std::shared_ptr& theSecondPoint); + + /// Add feature coincidence constraint between given attributes + /// \param theConstraintId a constraint index + /// \param theFirstAttribute an attribute of further coincidence + /// \param theSecondAttribute an attribute of further coincidence + std::shared_ptr createConstraint(const std::string& theConstraintId, + const std::shared_ptr& theFirstAttribute, + const std::shared_ptr& theSecondAttribute); + + /// Add feature coincidence constraint between given attributes + /// \param theConstraintId a constraint index + /// \param theFirstAttribute an attribute of further coincidence + /// \param theSecondObject an object of further coincidence + std::shared_ptr createConstraint(const std::string& theConstraintId, + const std::shared_ptr& theFirstAttribute, + const std::shared_ptr& theSecondObject); + // /// Add feature coincidence constraint between given attributes // /// \param theConstraintId a constraint index // /// \param theFirstAttribute an attribute of further coincidence @@ -286,12 +315,12 @@ class SketchPlugin_Trim : public SketchPlugin_ConstraintBase // /// \param theFeaturesToUpdate a constraint index // void updateFeaturesAfterSplit(const std::set& theFeaturesToUpdate); // -// /// Result result of the feature to build constraint with. For arc, circle it is an edge result. -// /// \param theFeature a feature -// /// \return result object -// std::shared_ptr getFeatureResult( -// const std::shared_ptr& theFeature); -// + /// Result result of the feature to build constraint with. For arc, circle it is an edge result. + /// \param theFeature a feature + /// \return result object + std::shared_ptr getFeatureResult( + const std::shared_ptr& theFeature); + // /// Returns attributes of the feature, used in edge build, for arc it is end and start points // /// \param theFeature a feature // /// \return container of attributes @@ -311,17 +340,24 @@ private: void fillObjectShapes(const ObjectPtr& theObject); + void findShapePoints(std::shared_ptr& aStartPoint, + std::shared_ptr& aLastPoint); + + std::shared_ptr convertPoint(const std::shared_ptr& thePoint); + private: //std::shared_ptr myCurrentSubShape; std::map > myCashedShapes; - typedef std::map, - std::shared_ptr > PntToAttributesMap; - std::map myCashedReferences; + //typedef std::map, + // std::shared_ptr > PntToAttributesMap; + //std::map myCashedReferences; typedef std::map, - std::list< std::shared_ptr > > PntToObjectsMap; - std::map myCashedObjects; + std::pair >, + std::list > > > PointToRefsMap; + + std::map myObjectToPoints; }; #endif diff --git a/src/SketchPlugin/SketchPlugin_Validators.cpp b/src/SketchPlugin/SketchPlugin_Validators.cpp index 5884fa6bb..ff1689e16 100755 --- a/src/SketchPlugin/SketchPlugin_Validators.cpp +++ b/src/SketchPlugin/SketchPlugin_Validators.cpp @@ -940,27 +940,20 @@ bool SketchPlugin_SplitValidator::isValid(const AttributePtr& theAttribute, aData->attribute(SketchPlugin_Sketch::NORM_ID())); std::shared_ptr aDirY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir()))); - std::list > aPoints; - std::map, std::shared_ptr > - aPointToAttributes; + typedef std::map, + std::pair >, + std::list > > > PointToRefsMap; + PointToRefsMap aPointsInfo; + + //std::list > aPoints; + //std::map, std::shared_ptr > + // aPointToAttributes; + //std::map, + // std::list< std::shared_ptr > > aPointToAttributes; ModelGeomAlgo_Point2D::getPointsInsideShape(anAttrShape, aRefAttributes, aC->pnt(), - aX->dir(), aDirY, aPoints, aPointToAttributes); - - if (theArguments.size() > 0) { // use graphic intersection - // intersection points - //std::shared_ptr aCompositeFeature(aSketch); - std::map, - std::list< std::shared_ptr > > aPointToObjects; - std::list aFeatures; - for (int i = 0; i < aSketch->numberOfSubs(); i++) { - FeaturePtr aFeature = aSketch->subFeature(i); - if (aFeature.get()) - aFeatures.push_back(aFeature); - } - ModelGeomAlgo_Point2D::getPointsIntersectedShape(aSFeature, aFeatures, aPoints, - aPointToObjects); - } - int aCoincidentToFeature = (int)aPoints.size(); + aX->dir(), aDirY, aPointsInfo);//aPoints, aPointToAttributes); + + int aCoincidentToFeature = (int)aPointsInfo.size();//aPoints.size(); if (aKind == SketchPlugin_Circle::ID()) aValid = aCoincidentToFeature >= 2; else diff --git a/src/SketchPlugin/Test/TestTrimCircle.py b/src/SketchPlugin/Test/TestTrimCircle.py new file mode 100644 index 000000000..aecbb4efa --- /dev/null +++ b/src/SketchPlugin/Test/TestTrimCircle.py @@ -0,0 +1,129 @@ +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' +SketchConstraintParallelId = 'SketchConstraintParallel' +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 + +model.end() + +#assert(model.checkPythonDump()) diff --git a/src/SketchPlugin/plugin-Sketch.xml b/src/SketchPlugin/plugin-Sketch.xml index 265d61aa6..5c33b28cc 100644 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@ -159,13 +159,13 @@ tooltip="Trim selected segment arc or circle on intersection points nearest to the graphic selection" icon="icons/Sketch/trim.png"> - + -- 2.39.2