From 29726bcc1b3ff76fe8ce69be9db0191b59975e11 Mon Sep 17 00:00:00 2001 From: Artem Zhidkov Date: Fri, 26 Jun 2020 11:56:40 +0300 Subject: [PATCH] Task #3231: Sketcher Offset of a curve Redesign storing the offset entities. --- src/GeomAlgoAPI/GeomAlgoAPI.i | 1 + src/GeomAlgoAPI/GeomAlgoAPI_Offset.cpp | 37 +- src/GeomAlgoAPI/GeomAlgoAPI_Offset.h | 20 +- src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.cpp | 76 ++- src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.h | 9 +- src/SketchAPI/SketchAPI_Offset.cpp | 27 +- src/SketchAPI/SketchAPI_Offset.h | 13 +- src/SketchAPI/SketchAPI_Sketch.cpp | 5 +- src/SketchAPI/SketchAPI_Sketch.h | 3 +- src/SketchPlugin/SketchPlugin_Offset.cpp | 433 ++++++++++++------ src/SketchPlugin/SketchPlugin_Offset.h | 63 ++- src/SketchPlugin/plugin-Sketch.xml | 6 - src/SketchSolver/CMakeLists.txt | 2 + .../PlaneGCSSolver/PlaneGCSSolver_Tools.cpp | 4 + .../SketchSolver_ConstraintOffset.cpp | 40 ++ .../SketchSolver_ConstraintOffset.h | 48 ++ 16 files changed, 522 insertions(+), 265 deletions(-) create mode 100644 src/SketchSolver/SketchSolver_ConstraintOffset.cpp create mode 100644 src/SketchSolver/SketchSolver_ConstraintOffset.h diff --git a/src/GeomAlgoAPI/GeomAlgoAPI.i b/src/GeomAlgoAPI/GeomAlgoAPI.i index f2076869f..fcca5e7d9 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI.i +++ b/src/GeomAlgoAPI/GeomAlgoAPI.i @@ -58,6 +58,7 @@ %shared_ptr(GeomAlgoAPI_Copy) %shared_ptr(GeomAlgoAPI_Symmetry) %shared_ptr(GeomAlgoAPI_MapShapesAndAncestors) +%shared_ptr(GeomAlgoAPI_WireBuilder) // all supported interfaces %include "GeomAlgoAPI_MakeShape.h" diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Offset.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Offset.cpp index b86bb42bc..4b0bb4031 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Offset.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Offset.cpp @@ -19,6 +19,8 @@ #include "GeomAlgoAPI_Offset.h" +#include + #include #include @@ -60,18 +62,10 @@ void GeomAlgoAPI_Offset::generated(const GeomShapePtr theOldShape, } } -//GeomShapePtr GeomAlgoAPI_Offset::OffsetInPlane (const std::shared_ptr& thePlane, -// const ListOfShape& theEdgesAndWires, -// const double theOffsetValue) -//{ -//} - -GeomShapePtr GeomAlgoAPI_Offset::OffsetInPlane (const std::shared_ptr& thePlane, - const GeomShapePtr& theEdgeOrWire, - const double theOffsetValue) +GeomAlgoAPI_Offset::GeomAlgoAPI_Offset(const GeomPlanePtr& thePlane, + const GeomShapePtr& theEdgeOrWire, + const double theOffsetValue) { - GeomShapePtr aResult; - // 1. Make wire from edge, if need TopoDS_Wire aWire; TopoDS_Shape anEdgeOrWire = theEdgeOrWire->impl(); @@ -87,21 +81,24 @@ GeomShapePtr GeomAlgoAPI_Offset::OffsetInPlane (const std::shared_ptrimpl(), aWire); const TopoDS_Face& aFace = aFaceBuilder.Face(); // 3. Make Offset - BRepOffsetAPI_MakeOffset aParal; - aParal.Init(aFace, GeomAbs_Arc, Standard_True); - aParal.Perform(theOffsetValue, 0.); - if (aParal.IsDone()) { - TopoDS_Shape anOffset = aParal.Shape(); - aResult.reset(new GeomAPI_Shape()); + BRepOffsetAPI_MakeOffset* aParal = new BRepOffsetAPI_MakeOffset; + setImpl(aParal); + setBuilderType(OCCT_BRepBuilderAPI_MakeShape); + + aParal->Init(aFace, GeomAbs_Arc, Standard_True); + aParal->Perform(theOffsetValue, 0.); + if (aParal->IsDone()) { + TopoDS_Shape anOffset = aParal->Shape(); + GeomShapePtr aResult(new GeomAPI_Shape()); aResult->setImpl(new TopoDS_Shape(anOffset)); + setShape(aResult); + setDone(true); } - - return aResult; } diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Offset.h b/src/GeomAlgoAPI/GeomAlgoAPI_Offset.h index ee6d51062..608939d90 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Offset.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Offset.h @@ -23,7 +23,7 @@ #include #include -#include +class GeomAPI_Pln; /// \class GeomAlgoAPI_Offset /// \ingroup DataAlgo @@ -35,22 +35,20 @@ public: GEOMALGOAPI_EXPORT GeomAlgoAPI_Offset(const GeomShapePtr& theShape, const double theOffsetValue); + /// \brief Perform the offset algorithm on the plane + /// \param[in] thePlane base plane for all offsets + /// \param[in] theEdgesOrWire base shapes + /// \param[in] theOffsetValue offset distance, it can be negative + GEOMALGOAPI_EXPORT GeomAlgoAPI_Offset(const std::shared_ptr& thePlane, + const GeomShapePtr& theEdgeOrWire, + const double theOffsetValue); + /// \return the list of shapes generated from the shape \a theShape. /// \param[in] theOldShape base shape. /// \param[out] theNewShapes shapes generated from \a theShape. Does not cleared! GEOMALGOAPI_EXPORT virtual void generated(const GeomShapePtr theOldShape, ListOfShape& theNewShapes); - /// \return a compound of offset wires - /// \param[in] thePlane base plane for all offsets - /// \param[in] theEdgesAndWires base shapes - /// \param[in] theOffsetValue offset distance, it can be negative - //GEOMALGOAPI_EXPORT static GeomShapePtr OffsetInPlane (const std::shared_ptr& thePlane, - // const ListOfShape& theEdgesAndWires, - // const double theOffsetValue); - GEOMALGOAPI_EXPORT static GeomShapePtr OffsetInPlane (const std::shared_ptr& thePlane, - const GeomShapePtr& theEdgeOrWire, - const double theOffsetValue); private: /// \brief Perform offset operation diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.cpp index 00c1e79d1..53bc674a4 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.cpp @@ -24,45 +24,77 @@ #include #include +#include #include +#include #include #include #include -//================================================================================================= -GeomShapePtr GeomAlgoAPI_WireBuilder::wire(const ListOfShape& theShapes) +static GeomShapePtr fromTopoDS(const TopoDS_Shape& theShape) +{ + GeomShapePtr aResultShape(new GeomAPI_Shape()); + aResultShape->setImpl(new TopoDS_Shape(theShape)); + return aResultShape; +} + +GeomAlgoAPI_WireBuilder::GeomAlgoAPI_WireBuilder(const ListOfShape& theShapes) { TopTools_ListOfShape aListOfEdges; ListOfShape::const_iterator anIt = theShapes.cbegin(); - for(; anIt != theShapes.cend(); ++anIt) { + for (; anIt != theShapes.cend(); ++anIt) { const TopoDS_Shape& aShape = (*anIt)->impl(); - switch(aShape.ShapeType()) { - case TopAbs_EDGE: { - aListOfEdges.Append(aShape); - break; + switch (aShape.ShapeType()) { + case TopAbs_EDGE: { + aListOfEdges.Append(aShape); + break; + } + case TopAbs_WIRE: { + for (TopExp_Explorer anExp(aShape, TopAbs_EDGE); anExp.More(); anExp.Next()) { + aListOfEdges.Append(anExp.Current()); } - case TopAbs_WIRE: { - for(TopExp_Explorer anExp(aShape, TopAbs_EDGE); anExp.More(); anExp.Next()) { - aListOfEdges.Append(anExp.Current()); + break; + } + default: + break; + } + } + + BRepBuilderAPI_MakeWire* aWireBuilder = new BRepBuilderAPI_MakeWire; + aWireBuilder->Add(aListOfEdges); + if (aWireBuilder->Error() == BRepBuilderAPI_WireDone) { + setImpl(aWireBuilder); + setBuilderType(OCCT_BRepBuilderAPI_MakeShape); + + // store generated/modified shapes + TopoDS_Wire aWire = aWireBuilder->Wire(); + for (TopTools_ListOfShape::Iterator aBaseIt(aListOfEdges); aBaseIt.More(); aBaseIt.Next()) { + TopoDS_Edge aBaseCurrent = TopoDS::Edge(aBaseIt.Value()); + Standard_Real aFirst, aLast; + Handle(Geom_Curve) aBaseCurve = BRep_Tool::Curve(aBaseCurrent, aFirst, aLast); + + for (TopExp_Explorer anExp(aWire, TopAbs_EDGE); anExp.More(); anExp.Next()) { + TopoDS_Edge aNewCurrent = TopoDS::Edge(anExp.Current()); + Handle(Geom_Curve) aNewCurve = BRep_Tool::Curve(aNewCurrent, aFirst, aLast); + if (aBaseCurve == aNewCurve) { + GeomShapePtr aBaseShape = fromTopoDS(aBaseCurrent); + GeomShapePtr aNewShape = fromTopoDS(aNewCurrent); + addGenerated(aBaseShape, aNewShape); + addModified(aBaseShape, aNewShape); } - break; - } - default: { - return GeomShapePtr(); } } - } - BRepBuilderAPI_MakeWire aWireBuilder; - aWireBuilder.Add(aListOfEdges); - if(aWireBuilder.Error() != BRepBuilderAPI_WireDone) { - return GeomShapePtr(); + setShape(fromTopoDS(aWire)); + setDone(true); } +} - GeomShapePtr aResultShape(new GeomAPI_Shape()); - aResultShape->setImpl(new TopoDS_Shape(aWireBuilder.Wire())); - return aResultShape; +//================================================================================================= +GeomShapePtr GeomAlgoAPI_WireBuilder::wire(const ListOfShape& theShapes) +{ + return GeomAlgoAPI_WireBuilder(theShapes).shape(); } //================================================================================================= diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.h b/src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.h index 8de0888e6..6824c1550 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.h @@ -21,15 +21,22 @@ #define GeomAlgoAPI_WireBuilder_H_ #include "GeomAlgoAPI.h" +#include "GeomAlgoAPI_MakeShapeCustom.h" #include /// \class GeomAlgoAPI_WireBuilder /// \ingroup DataAlgo /// \brief Allows to create wire-shapes by different parameters. -class GeomAlgoAPI_WireBuilder +class GeomAlgoAPI_WireBuilder : public GeomAlgoAPI_MakeShapeCustom { public: + /// \brief Creates a wire from edges and wires. + /// \param[in] theShapes list of shapes. Only edges and wires allowed. + /// The edges are not to be consecutive. + /// But they are to be all connected geometrically or topologically. + GEOMALGOAPI_EXPORT GeomAlgoAPI_WireBuilder(const ListOfShape& theShapes); + /// \brief Creates a wire from edges and wires. /// \param[in] theShapes list of shapes. Only edges and wires allowed. /// The edges are not to be consecutive. diff --git a/src/SketchAPI/SketchAPI_Offset.cpp b/src/SketchAPI/SketchAPI_Offset.cpp index 6d4f24e4e..392d07fe0 100644 --- a/src/SketchAPI/SketchAPI_Offset.cpp +++ b/src/SketchAPI/SketchAPI_Offset.cpp @@ -34,15 +34,13 @@ SketchAPI_Offset::SketchAPI_Offset (const std::shared_ptr & th SketchAPI_Offset::SketchAPI_Offset (const std::shared_ptr & theFeature, const std::list > & theObjects, const ModelHighAPI_Double & theOffsetValue, - bool theIsReversed, - bool theIsAuxiliary) + bool theIsReversed) : ModelHighAPI_Interface(theFeature) { if (initialize()) { fillAttribute(theObjects, edgesList()); fillAttribute(theOffsetValue, value()); fillAttribute(theIsReversed, reversed()); - fillAttribute(theIsAuxiliary, auxiliary()); execute(); } @@ -54,7 +52,7 @@ SketchAPI_Offset::~SketchAPI_Offset() std::list > SketchAPI_Offset::offset() const { - std::list aList = createdList()->list(); + std::list aList = feature()->reflist(SketchPlugin_Constraint::ENTITY_B())->list(); std::list anIntermediate; std::list::const_iterator anIt = aList.begin(); for (; anIt != aList.end(); ++anIt) { @@ -74,7 +72,6 @@ void SketchAPI_Offset::dump (ModelHighAPI_Dumper& theDumper) const AttributeRefListPtr aOffsetObjects = edgesList(); AttributeDoublePtr aValue = value(); AttributeBooleanPtr aReversed = reversed(); - AttributeBooleanPtr anAux = auxiliary(); // Check all attributes are already dumped. If not, store the feature as postponed. if (!theDumper.isDumped(aOffsetObjects)) { @@ -83,7 +80,7 @@ void SketchAPI_Offset::dump (ModelHighAPI_Dumper& theDumper) const } theDumper << aBase << " = " << aSketchName << ".addOffset(" << aOffsetObjects << ", " - << aValue << ", " << aReversed << ", " << anAux << ")" << std::endl; + << aValue << ", " << aReversed << ")" << std::endl; // Dump variables for a list of created features theDumper << "["; @@ -96,13 +93,13 @@ void SketchAPI_Offset::dump (ModelHighAPI_Dumper& theDumper) const } theDumper << "] = " << theDumper.name(aBase) << ".offset()" << std::endl; - // Set necessary "auxiliary" flag for created features - // (flag is set if it differs to anAux) - for (anIt = aList.begin(); anIt != aList.end(); ++anIt) { - FeaturePtr aFeature = (*anIt)->feature(); - bool aFeatAux = aFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value(); - if (aFeatAux != anAux->value()) - theDumper << theDumper.name((*anIt)->feature(), false) - << ".setAuxiliary(" << aFeatAux << ")" <feature(); +//// bool aFeatAux = aFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value(); +//// if (aFeatAux != anAux->value()) +//// theDumper << theDumper.name((*anIt)->feature(), false) +//// << ".setAuxiliary(" << aFeatAux << ")" < & theFeature, const std::list > & theObjects, const ModelHighAPI_Double & theOffsetValue, - bool theIsReversed, - bool theIsAuxiliary); + bool theIsReversed); /// Destructor SKETCHAPI_EXPORT virtual ~SketchAPI_Offset(); - INTERFACE_5(SketchPlugin_Offset::ID(), + INTERFACE_3(SketchPlugin_Offset::ID(), edgesList, SketchPlugin_Offset::EDGES_ID(), ModelAPI_AttributeRefList, /** Offset edges list */, @@ -65,13 +64,7 @@ public: ModelAPI_AttributeDouble, /** Value */, reversed, SketchPlugin_Offset::REVERSED_ID(), - ModelAPI_AttributeBoolean, /** Negative value */, - - auxiliary, SketchPlugin_Offset::AUXILIARY_ID(), - ModelAPI_AttributeBoolean, /** Auxiliary */, - - createdList, SketchPlugin_Offset::CREATED_ID(), - ModelAPI_AttributeRefList, /** Created edges list */ + ModelAPI_AttributeBoolean, /** Negative value */ ) /// List of created objects diff --git a/src/SketchAPI/SketchAPI_Sketch.cpp b/src/SketchAPI/SketchAPI_Sketch.cpp index 2046d5103..a3efd9ef5 100644 --- a/src/SketchAPI/SketchAPI_Sketch.cpp +++ b/src/SketchAPI/SketchAPI_Sketch.cpp @@ -895,12 +895,11 @@ std::shared_ptr SketchAPI_Sketch::addMirror( std::shared_ptr SketchAPI_Sketch::addOffset( const std::list > & theObjects, const ModelHighAPI_Double & theValue, - const bool theReversed, - const bool theAuxiliary) + const bool theReversed) { std::shared_ptr aFeature = compositeFeature()->addFeature(SketchPlugin_Offset::ID()); - return OffsetPtr(new SketchAPI_Offset(aFeature, theObjects, theValue, theReversed, theAuxiliary)); + return OffsetPtr(new SketchAPI_Offset(aFeature, theObjects, theValue, theReversed)); } //-------------------------------------------------------------------------------------- diff --git a/src/SketchAPI/SketchAPI_Sketch.h b/src/SketchAPI/SketchAPI_Sketch.h index 6174ca23f..3115cadf5 100644 --- a/src/SketchAPI/SketchAPI_Sketch.h +++ b/src/SketchAPI/SketchAPI_Sketch.h @@ -376,8 +376,7 @@ public: std::shared_ptr addOffset( const std::list > & theObjects, const ModelHighAPI_Double & theValue, - const bool theReversed, - const bool theAuxiliary); + const bool theReversed); /// Add translation SKETCHAPI_EXPORT diff --git a/src/SketchPlugin/SketchPlugin_Offset.cpp b/src/SketchPlugin/SketchPlugin_Offset.cpp index 0bdbb7f06..2d82f0153 100644 --- a/src/SketchPlugin/SketchPlugin_Offset.cpp +++ b/src/SketchPlugin/SketchPlugin_Offset.cpp @@ -38,20 +38,23 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include -#include +#include #include +#include #include -#include +#include #include #include @@ -59,24 +62,32 @@ #include SketchPlugin_Offset::SketchPlugin_Offset() - : SketchPlugin_SketchEntity() { } -void SketchPlugin_Offset::initDerivedClassAttributes() +void SketchPlugin_Offset::initAttributes() { data()->addAttribute(EDGES_ID(), ModelAPI_AttributeRefList::typeId()); data()->addAttribute(VALUE_ID(), ModelAPI_AttributeDouble::typeId()); data()->addAttribute(REVERSED_ID(), ModelAPI_AttributeBoolean::typeId()); - data()->addAttribute(CREATED_ID(), ModelAPI_AttributeRefList::typeId()); - ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CREATED_ID()); + // store original entities + data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefList::typeId()); + // store offset entities + data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefList::typeId()); + // store mapping between original entity and index of the corresponding offset entity + data()->addAttribute(SketchPlugin_Constraint::ENTITY_C(), ModelAPI_AttributeIntArray::typeId()); + + ModelAPI_Session::get()->validators()-> + registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_A()); + ModelAPI_Session::get()->validators()-> + registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_B()); + ModelAPI_Session::get()->validators()-> + registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_C()); } void SketchPlugin_Offset::execute() { - removeCreated(); // remove created objects - SketchPlugin_Sketch* aSketch = sketch(); if (!aSketch) return; @@ -116,6 +127,7 @@ void SketchPlugin_Offset::execute() Events_Loop::loop()->setFlushed(anUpdateEvent, false); // 5. Gather wires and make offset for each wire + ListOfMakeShape anOffsetAlgos; for (anEdgesIt = anEdgesList.begin(); anEdgesIt != anEdgesList.end(); anEdgesIt++) { FeaturePtr aFeature = ModelAPI_Feature::feature(*anEdgesIt); if (aFeature.get()) { @@ -148,19 +160,25 @@ void SketchPlugin_Offset::execute() aTopoChain.push_back(aTopoEdge); } } - GeomShapePtr anEdgeOrWire = GeomAlgoAPI_WireBuilder::wire(aTopoChain); + std::shared_ptr aWireBuilder( + new GeomAlgoAPI_WireBuilder(aTopoChain)); // 5.d. Make offset for each wire - std::shared_ptr anOffsetShape = - GeomAlgoAPI_Offset::OffsetInPlane(aPlane, anEdgeOrWire, aValue); + std::shared_ptr anOffsetShape( + new GeomAlgoAPI_Offset(aPlane, aWireBuilder->shape(), aValue)); - // 5.e. Store offset results. - // Create sketch feature for each edge of anOffsetShape, and also store - // created features in CREATED_ID() to remove them on next execute() - addToSketch(anOffsetShape); + std::shared_ptr aMakeList(new GeomAlgoAPI_MakeShapeList); + aMakeList->appendAlgo(aWireBuilder); + aMakeList->appendAlgo(anOffsetShape); + anOffsetAlgos.push_back(aMakeList); } } + // 6. Store offset results. + // Create sketch feature for each edge of anOffsetShape, and also store + // created features in CREATED_ID() to remove them on next execute() + addToSketch(anOffsetAlgos); + // send events to update the sub-features by the solver if (isUpdateFlushed) Events_Loop::loop()->setFlushed(anUpdateEvent, true); @@ -267,129 +285,280 @@ bool SketchPlugin_Offset::findWireOneWay (const FeaturePtr& theFirstEdge, return findWireOneWay (theFirstEdge, aNextEdgeFeature, aP2, theEdgesSet, theChain, isPrepend); } -void SketchPlugin_Offset::addToSketch(const std::shared_ptr& anOffsetShape) +static void setRefListValue(AttributeRefListPtr theList, int theListSize, + ObjectPtr theValue, int theIndex) { - AttributeRefListPtr aRefListOfCreated = - std::dynamic_pointer_cast - (data()->attribute(SketchPlugin_Offset::CREATED_ID())); - - ListOfShape aResEdges = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(anOffsetShape); - std::list::const_iterator aResEdgesIt = aResEdges.begin(); - for (; aResEdgesIt != aResEdges.end(); aResEdgesIt++) { - GeomShapePtr aResShape = (*aResEdgesIt); - if (aResShape->shapeType() == GeomAPI_Shape::EDGE) { - // Add new feature - FeaturePtr aResFeature; - std::shared_ptr aResEdge (new GeomAPI_Edge(aResShape)); - - std::shared_ptr aFP, aLP; - std::shared_ptr aFP3d = aResEdge->firstPoint(); - std::shared_ptr aLP3d = aResEdge->lastPoint(); - //if (aFP3d.get() && aLP3d.get()) { - if (aFP3d && aLP3d) { - aFP = sketch()->to2D(aFP3d); - aLP = sketch()->to2D(aLP3d); - } + if (theIndex < theListSize) { + ObjectPtr aCur = theList->object(theIndex); + if (aCur != theValue) + theList->substitute(aCur, theValue); + } + else + theList->append(theValue); +} - if (aResEdge->isLine()) { - aResFeature = sketch()->addFeature(SketchPlugin_Line::ID()); +static void removeLastFromIndex(AttributeRefListPtr theList, int theListSize, int& theLastIndex) +{ + if (theLastIndex < theListSize) { + std::set anIndicesToRemove; + for (; theLastIndex < theListSize; ++theLastIndex) + anIndicesToRemove.insert(theLastIndex); + theList->remove(anIndicesToRemove); + } +} - std::dynamic_pointer_cast - (aResFeature->attribute(SketchPlugin_Line::START_ID()))->setValue(aFP); - std::dynamic_pointer_cast - (aResFeature->attribute(SketchPlugin_Line::END_ID()))->setValue(aLP); - } - else if (aResEdge->isArc()) { - std::shared_ptr aCircEdge = aResEdge->circle(); - std::shared_ptr aCP3d = aCircEdge->center(); - std::shared_ptr aCP = sketch()->to2D(aCP3d); - - aResFeature = sketch()->addFeature(SketchPlugin_Arc::ID()); - - bool aWasBlocked = aResFeature->data()->blockSendAttributeUpdated(true); - std::dynamic_pointer_cast - (aResFeature->attribute(SketchPlugin_Arc::CENTER_ID()))->setValue(aCP); - std::dynamic_pointer_cast - (aResFeature->attribute(SketchPlugin_Arc::START_ID()))->setValue(aFP); - std::dynamic_pointer_cast - (aResFeature->attribute(SketchPlugin_Arc::END_ID()))->setValue(aLP); - aResFeature->data()->blockSendAttributeUpdated(aWasBlocked); - } - else if (aResEdge->isCircle()) { - std::shared_ptr aCircEdge = aResEdge->circle(); - std::shared_ptr aCP3d = aCircEdge->center(); - std::shared_ptr aCP = sketch()->to2D(aCP3d); - - aResFeature = sketch()->addFeature(SketchPlugin_Circle::ID()); - std::dynamic_pointer_cast - (aResFeature->attribute(SketchPlugin_Circle::CENTER_ID()))->setValue(aCP); - aResFeature->real(SketchPlugin_Circle::RADIUS_ID())->setValue(aCircEdge->radius()); - } - else if (aResEdge->isEllipse()) { - std::shared_ptr anEllipseEdge = aResEdge->ellipse(); - - GeomPointPtr aCP3d = anEllipseEdge->center(); - GeomPnt2dPtr aCP = sketch()->to2D(aCP3d); - - GeomPointPtr aFocus3d = anEllipseEdge->firstFocus(); - GeomPnt2dPtr aFocus = sketch()->to2D(aFocus3d); - - if (aFP3d && aLP3d) { - // Elliptic arc - aResFeature = sketch()->addFeature(SketchPlugin_EllipticArc::ID()); - - bool aWasBlocked = aResFeature->data()->blockSendAttributeUpdated(true); - std::dynamic_pointer_cast - (aResFeature->attribute(SketchPlugin_EllipticArc::CENTER_ID()))->setValue(aCP); - std::dynamic_pointer_cast - (aResFeature->attribute(SketchPlugin_EllipticArc::FIRST_FOCUS_ID()))->setValue(aFocus); - std::dynamic_pointer_cast - (aResFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID()))->setValue(aFP); - std::dynamic_pointer_cast - (aResFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID()))->setValue(aLP); - aResFeature->data()->blockSendAttributeUpdated(aWasBlocked); - } - else { - // Ellipse - aResFeature = sketch()->addFeature(SketchPlugin_Ellipse::ID()); - - std::dynamic_pointer_cast - (aResFeature->attribute(SketchPlugin_Ellipse::CENTER_ID()))->setValue(aCP); - std::dynamic_pointer_cast - (aResFeature->attribute(SketchPlugin_Ellipse::FIRST_FOCUS_ID()))->setValue(aFocus); - aResFeature->real(SketchPlugin_Ellipse::MINOR_RADIUS_ID())->setValue(anEllipseEdge->minorRadius()); - } - } - else if (aResEdge->isBSpline()) { - mkBSpline(aResFeature, aResEdge); - } - else { - // convert to b-spline - mkBSpline(aResFeature, aResEdge); +void SketchPlugin_Offset::addToSketch(const ListOfMakeShape& theOffsetAlgos) +{ + AttributeRefListPtr aSelectedRefList = reflist(EDGES_ID()); + AttributeRefListPtr aBaseRefList = reflist(ENTITY_A()); + AttributeRefListPtr anOffsetRefList = reflist(ENTITY_B()); + AttributeIntArrayPtr anOffsetToBaseMap = intArray(ENTITY_C()); + + // compare the list of selected edges and the previously stored, + // and store maping between them + std::map > aMapExistent; + std::list anObjectsToRemove; + std::list aSelectedList = aSelectedRefList->list(); + for (std::list::iterator aSIt = aSelectedList.begin(); + aSIt != aSelectedList.end(); ++aSIt) { + aMapExistent[*aSIt] = std::list(); + } + for (int anIndex = 0, aSize = anOffsetRefList->size(); anIndex < aSize; ++anIndex) { + ObjectPtr aCurrent = anOffsetRefList->object(anIndex); + int aBaseIndex = anOffsetToBaseMap->value(anIndex); + if (aBaseIndex >= 0) { + ObjectPtr aBaseObj = aBaseRefList->object(aBaseIndex); + std::map >::iterator aFound = aMapExistent.find(aBaseObj); + if (aFound != aMapExistent.end()) + aFound->second.push_back(aCurrent); + else + anObjectsToRemove.push_back(aCurrent); + } + else + anObjectsToRemove.push_back(aCurrent); + } + + // update lists of base shapes and of offset shapes + int aBaseListSize = aBaseRefList->size(); + int anOffsetListSize = anOffsetRefList->size(); + int aBaseListIndex = 0, anOffsetListIndex = 0; + std::list anOffsetBaseBackRefs; + std::set aProcessedOffsets; + for (std::list::iterator aSIt = aSelectedList.begin(); + aSIt != aSelectedList.end(); ++aSIt) { + // find an offseted edge + FeaturePtr aBaseFeature = ModelAPI_Feature::feature(*aSIt); + GeomShapePtr aBaseShape = aBaseFeature->lastResult()->shape(); + ListOfShape aNewShapes; + for (ListOfMakeShape::const_iterator anAlgoIt = theOffsetAlgos.begin(); + anAlgoIt != theOffsetAlgos.end() && aNewShapes.empty(); ++anAlgoIt) { + (*anAlgoIt)->generated(aBaseShape, aNewShapes); + } + + // store base feature + setRefListValue(aBaseRefList, aBaseListSize, *aSIt, aBaseListIndex); + + // create or update an offseted feature + const std::list& anImages = aMapExistent[*aSIt]; + std::list::const_iterator anImgIt = anImages.begin(); + for (ListOfShape::iterator aNewIt = aNewShapes.begin(); aNewIt != aNewShapes.end(); ++aNewIt) { + FeaturePtr aNewFeature; + if (anImgIt != anImages.end()) + aNewFeature = ModelAPI_Feature::feature(*anImgIt++); + updateExistentOrCreateNew(*aNewIt, aNewFeature, anObjectsToRemove); + aProcessedOffsets.insert(*aNewIt); + + // store an offseted feature + setRefListValue(anOffsetRefList, anOffsetListSize, aNewFeature, anOffsetListIndex); + + anOffsetBaseBackRefs.push_back(aBaseListIndex); + ++anOffsetListIndex; + } + ++aBaseListIndex; + anObjectsToRemove.insert(anObjectsToRemove.end(), anImgIt, anImages.end()); + } + // create arcs generated from vertices + for (ListOfMakeShape::const_iterator anAlgoIt = theOffsetAlgos.begin(); + anAlgoIt != theOffsetAlgos.end(); ++anAlgoIt) { + GeomShapePtr aCurWire = (*anAlgoIt)->shape(); + GeomAPI_ShapeExplorer anExp(aCurWire, GeomAPI_Shape::EDGE); + for (; anExp.more(); anExp.next()) { + GeomShapePtr aCurEdge = anExp.current(); + if (aProcessedOffsets.find(aCurEdge) == aProcessedOffsets.end()) { + FeaturePtr aNewFeature; + updateExistentOrCreateNew(aCurEdge, aNewFeature, anObjectsToRemove); + aProcessedOffsets.insert(aCurEdge); + + // store an offseted feature + setRefListValue(anOffsetRefList, anOffsetListSize, aNewFeature, anOffsetListIndex); + + anOffsetBaseBackRefs.push_back(-1); + ++anOffsetListIndex; } + } + } - if (aResFeature.get()) { - aRefListOfCreated->append(aResFeature); + removeLastFromIndex(aBaseRefList, aBaseListSize, aBaseListIndex); + removeLastFromIndex(anOffsetRefList, anOffsetListSize, anOffsetListIndex); + + anOffsetToBaseMap->setSize((int)anOffsetBaseBackRefs.size(), false); + int anIndex = 0; + for (std::list::iterator anIt = anOffsetBaseBackRefs.begin(); + anIt != anOffsetBaseBackRefs.end(); ++anIt) { + anOffsetToBaseMap->setValue(anIndex++, *anIt, false); + } - aResFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue - (boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value()); - aResFeature->execute(); + // remove unused objects + std::set aSet; + for (std::list::iterator anIt = anObjectsToRemove.begin(); + anIt != anObjectsToRemove.end(); ++anIt) { + FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt); + if (aFeature) + aSet.insert(aFeature); + } + ModelAPI_Tools::removeFeaturesAndReferences(aSet); +} + +static void findOrCreateFeatureByKind(SketchPlugin_Sketch* theSketch, + const std::string& theFeatureKind, + FeaturePtr& theFeature, + std::list& thePoolOfFeatures) +{ + if (!theFeature) { + // try to find appropriate feature in the pool + for (std::list::iterator it = thePoolOfFeatures.begin(); + it != thePoolOfFeatures.end(); ++it) { + FeaturePtr aCurFeature = ModelAPI_Feature::feature(*it); + if (aCurFeature->getKind() == theFeatureKind) { + theFeature = aCurFeature; + thePoolOfFeatures.erase(it); + break; } } + // feature not found, create new + if (!theFeature) + theFeature = theSketch->addFeature(theFeatureKind); + } +} + +void SketchPlugin_Offset::updateExistentOrCreateNew(const GeomShapePtr& theShape, + FeaturePtr& theFeature, + std::list& thePoolOfFeatures) +{ + if (theShape->shapeType() != GeomAPI_Shape::EDGE) + return; + + std::shared_ptr aResEdge(new GeomAPI_Edge(theShape)); + + std::shared_ptr aFP, aLP; + std::shared_ptr aFP3d = aResEdge->firstPoint(); + std::shared_ptr aLP3d = aResEdge->lastPoint(); + if (aFP3d && aLP3d) { + aFP = sketch()->to2D(aFP3d); + aLP = sketch()->to2D(aLP3d); + } + + if (aResEdge->isLine()) { + findOrCreateFeatureByKind(sketch(), SketchPlugin_Line::ID(), theFeature, thePoolOfFeatures); + + std::dynamic_pointer_cast + (theFeature->attribute(SketchPlugin_Line::START_ID()))->setValue(aFP); + std::dynamic_pointer_cast + (theFeature->attribute(SketchPlugin_Line::END_ID()))->setValue(aLP); + } + else if (aResEdge->isArc()) { + std::shared_ptr aCircEdge = aResEdge->circle(); + std::shared_ptr aCP3d = aCircEdge->center(); + std::shared_ptr aCP = sketch()->to2D(aCP3d); + + findOrCreateFeatureByKind(sketch(), SketchPlugin_Arc::ID(), theFeature, thePoolOfFeatures); + + bool aWasBlocked = theFeature->data()->blockSendAttributeUpdated(true); + std::dynamic_pointer_cast + (theFeature->attribute(SketchPlugin_Arc::CENTER_ID()))->setValue(aCP); + std::dynamic_pointer_cast + (theFeature->attribute(SketchPlugin_Arc::START_ID()))->setValue(aFP); + std::dynamic_pointer_cast + (theFeature->attribute(SketchPlugin_Arc::END_ID()))->setValue(aLP); + theFeature->data()->blockSendAttributeUpdated(aWasBlocked); + } + else if (aResEdge->isCircle()) { + std::shared_ptr aCircEdge = aResEdge->circle(); + std::shared_ptr aCP3d = aCircEdge->center(); + std::shared_ptr aCP = sketch()->to2D(aCP3d); + + findOrCreateFeatureByKind(sketch(), SketchPlugin_Circle::ID(), theFeature, thePoolOfFeatures); + + std::dynamic_pointer_cast + (theFeature->attribute(SketchPlugin_Circle::CENTER_ID()))->setValue(aCP); + theFeature->real(SketchPlugin_Circle::RADIUS_ID())->setValue(aCircEdge->radius()); + } + else if (aResEdge->isEllipse()) { + std::shared_ptr anEllipseEdge = aResEdge->ellipse(); + + GeomPointPtr aCP3d = anEllipseEdge->center(); + GeomPnt2dPtr aCP = sketch()->to2D(aCP3d); + + GeomPointPtr aFocus3d = anEllipseEdge->firstFocus(); + GeomPnt2dPtr aFocus = sketch()->to2D(aFocus3d); + + if (aFP3d && aLP3d) { + // Elliptic arc + findOrCreateFeatureByKind(sketch(), SketchPlugin_EllipticArc::ID(), + theFeature, thePoolOfFeatures); + + bool aWasBlocked = theFeature->data()->blockSendAttributeUpdated(true); + std::dynamic_pointer_cast + (theFeature->attribute(SketchPlugin_EllipticArc::CENTER_ID()))->setValue(aCP); + std::dynamic_pointer_cast + (theFeature->attribute(SketchPlugin_EllipticArc::FIRST_FOCUS_ID()))->setValue(aFocus); + std::dynamic_pointer_cast + (theFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID()))->setValue(aFP); + std::dynamic_pointer_cast + (theFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID()))->setValue(aLP); + theFeature->data()->blockSendAttributeUpdated(aWasBlocked); + } + else { + // Ellipse + findOrCreateFeatureByKind(sketch(), SketchPlugin_Ellipse::ID(), + theFeature, thePoolOfFeatures); + + std::dynamic_pointer_cast + (theFeature->attribute(SketchPlugin_Ellipse::CENTER_ID()))->setValue(aCP); + std::dynamic_pointer_cast + (theFeature->attribute(SketchPlugin_Ellipse::FIRST_FOCUS_ID()))->setValue(aFocus); + theFeature->real(SketchPlugin_Ellipse::MINOR_RADIUS_ID())->setValue(anEllipseEdge->minorRadius()); + } + } + else { + // convert to b-spline + mkBSpline(theFeature, aResEdge, thePoolOfFeatures); + } + + if (theFeature.get()) { + theFeature->boolean(SketchPlugin_SketchEntity::COPY_ID())->setValue(true); + theFeature->execute(); + + static Events_ID aRedisplayEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY); + ModelAPI_EventCreator::get()->sendUpdated(theFeature, aRedisplayEvent); + const std::list& aResults = theFeature->results(); + for (std::list::const_iterator anIt = aResults.begin(); + anIt != aResults.end(); ++anIt) + ModelAPI_EventCreator::get()->sendUpdated(*anIt, aRedisplayEvent); } } void SketchPlugin_Offset::mkBSpline (FeaturePtr& theResult, - const GeomEdgePtr& theEdge) + const GeomEdgePtr& theEdge, + std::list& thePoolOfFeatures) { GeomCurvePtr aCurve (new GeomAPI_Curve (theEdge)); // Forced conversion to b-spline, if aCurve is not b-spline GeomAPI_BSpline aBSpline (aCurve, /*isForced*/true); - if (aBSpline.isPeriodic()) - theResult = sketch()->addFeature(SketchPlugin_BSplinePeriodic::ID()); - else - theResult = sketch()->addFeature(SketchPlugin_BSpline::ID()); + const std::string& aBSplineKind = aBSpline.isPeriodic() ? SketchPlugin_BSplinePeriodic::ID() + : SketchPlugin_BSpline::ID(); + findOrCreateFeatureByKind(sketch(), aBSplineKind, theResult, thePoolOfFeatures); theResult->integer(SketchPlugin_BSpline::DEGREE_ID())->setValue(aBSpline.degree()); @@ -440,26 +609,8 @@ void SketchPlugin_Offset::mkBSpline (FeaturePtr& theResult, void SketchPlugin_Offset::attributeChanged(const std::string& theID) { -// removeCreated(); -} - -void SketchPlugin_Offset::removeCreated() -{ - if (!sketch()) return; - - // Remove all created objects - AttributeRefListPtr aRefListOfCreated = - std::dynamic_pointer_cast - (data()->attribute(SketchPlugin_Offset::CREATED_ID())); - std::list aList = aRefListOfCreated->list(); - std::set aSet; - std::list::iterator anIter = aList.begin(); - for (; anIter != aList.end(); anIter++) { - FeaturePtr aFeature = ModelAPI_Feature::feature(*anIter); - aSet.insert(aFeature); - } - aRefListOfCreated->clear(); - ModelAPI_Tools::removeFeaturesAndReferences(aSet); +//// if (theID == EDGES_ID()) +//// removeCreated(); } bool SketchPlugin_Offset::customAction(const std::string& theActionId) diff --git a/src/SketchPlugin/SketchPlugin_Offset.h b/src/SketchPlugin/SketchPlugin_Offset.h index 482a75245..355e1e58f 100644 --- a/src/SketchPlugin/SketchPlugin_Offset.h +++ b/src/SketchPlugin/SketchPlugin_Offset.h @@ -21,18 +21,19 @@ #define SketchPlugin_Offset_H_ #include -#include +#include #include #include -#include + +class GeomAlgoAPI_MakeShape; /**\class SketchPlugin_Offset * \ingroup Plugins * \brief Builds offset curves in the sketch. */ -class SketchPlugin_Offset : public SketchPlugin_SketchEntity, public GeomAPI_IPresentable +class SketchPlugin_Offset : public SketchPlugin_ConstraintBase { public: /// Offset macro feature kind @@ -70,13 +71,6 @@ public: return ID; } - /// attribute to store the created objects - inline static const std::string& CREATED_ID() - { - static const std::string ID("created"); - return ID; - } - /// name for add wire action inline static const std::string& ADD_WIRE_ACTION_ID() { @@ -90,11 +84,6 @@ public: /// Creates a new part document if needed SKETCHPLUGIN_EXPORT virtual void execute(); - /// Reimplemented from ModelAPI_Feature::isMacro(). - /// \returns true - //SKETCHPLUGIN_EXPORT virtual bool isMacro() const { return false; } - - //SKETCHPLUGIN_EXPORT virtual bool isPreviewNeeded() const { return false; } SKETCHPLUGIN_EXPORT virtual bool isPreviewNeeded() const { return true; } /// Find edges connected by coincident boundary constraint and composing a wire with @@ -112,30 +101,36 @@ public: protected: /// \brief Initializes attributes of derived class. - virtual void initDerivedClassAttributes(); + virtual void initAttributes(); private: /// Find all wires connected with the selected edges bool findWires(); - // Create sketch feature for each edge of theOffsetResult, - // and store it in CREATED_ID() - void addToSketch (const std::shared_ptr& theOffsetResult); - - // Remove created features - void removeCreated (); - - // Create BSpline or BSplinePeriodic sketch feature from theEdge - void mkBSpline (FeaturePtr& theResult, const GeomEdgePtr& theEdge); - - // Find edges that prolongate theEdgeFeature (in a chain) at theEndPoint - // Recursive method. - // \param[in] theFirstEdge Start edge of wire searching - // \param[in] theEdge Current edge - // \param[in] theEndPoint Point of the Current edge, not belonging to a previous edge - // \param[in/out] theEdgesSet All edges to find among. If empty, all sketch edges assumed. - // \param[in/out] theChain Resulting edges - // \param[in] isPrepend if true, push new found edges to theChain front, else to the back + /// Create sketch feature for each edge of the offset result, + /// and store it in ENTITY_B(). Original edges are copied to ENTITY_A() to update + /// correctly if original selection is modified. + void addToSketch (const std::list< std::shared_ptr >& theOffsetAlgos); + + /// Create BSpline or BSplinePeriodic sketch feature from theEdge + void mkBSpline (FeaturePtr& theResult, const GeomEdgePtr& theEdge, + std::list& thePoolOfFeatures); + + /// Update existent feature by the parameters of the given edge or create a new feature. + /// \param[in] theShape a shape to be converted to sketch feature + /// \param[in,out] theFeature sketch feature to be updated or created from scratch + /// \param[in,out] thePoolOfFeatures list of features to be removed (may be used as a new feature) + void updateExistentOrCreateNew (const GeomShapePtr& theShape, FeaturePtr& theFeature, + std::list& thePoolOfFeatures); + + /// Find edges that prolongate theEdgeFeature (in a chain) at theEndPoint + /// Recursive method. + /// \param[in] theFirstEdge Start edge of wire searching + /// \param[in] theEdge Current edge + /// \param[in] theEndPoint Point of the Current edge, not belonging to a previous edge + /// \param[in/out] theEdgesSet All edges to find among. If empty, all sketch edges assumed. + /// \param[in/out] theChain Resulting edges + /// \param[in] isPrepend if true, push new found edges to theChain front, else to the back /// \return \c true if the chain is closed bool findWireOneWay (const FeaturePtr& theFirstEdge, const FeaturePtr& theEdge, diff --git a/src/SketchPlugin/plugin-Sketch.xml b/src/SketchPlugin/plugin-Sketch.xml index b0bc33328..2295a3f5e 100644 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@ -1021,12 +1021,6 @@ tooltip="Reverse the offset" default="false" obligatory="0"/> - diff --git a/src/SketchSolver/CMakeLists.txt b/src/SketchSolver/CMakeLists.txt index fafa0372a..0786930b7 100644 --- a/src/SketchSolver/CMakeLists.txt +++ b/src/SketchSolver/CMakeLists.txt @@ -56,6 +56,7 @@ SET(SKETCHSOLVER_CONSTRAINT_HEADERS SketchSolver_ConstraintMultiRotation.h SketchSolver_ConstraintMultiTranslation.h SketchSolver_ConstraintMovement.h + SketchSolver_ConstraintOffset.h ) SET(SKETCHSOLVER_SOURCES @@ -81,6 +82,7 @@ SET(SKETCHSOLVER_CONSTRAINT_SOURCES SketchSolver_ConstraintMultiRotation.cpp SketchSolver_ConstraintMultiTranslation.cpp SketchSolver_ConstraintMovement.cpp + SketchSolver_ConstraintOffset.cpp ) SET(SKETCHSOLVER_LIBRARIES diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp index 5cc2e86c1..aa433a9c4 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -63,6 +64,7 @@ #include #include #include +#include #include #include @@ -186,6 +188,8 @@ SolverConstraintPtr PlaneGCSSolver_Tools::createConstraint(ConstraintPtr theCons return SolverConstraintPtr(new SketchSolver_ConstraintAngle(theConstraint)); } else if (theConstraint->getKind() == SketchPlugin_ConstraintPerpendicular::ID()) { return SolverConstraintPtr(new SketchSolver_ConstraintPerpendicular(theConstraint)); + } else if (theConstraint->getKind() == SketchPlugin_Offset::ID()) { + return SolverConstraintPtr(new SketchSolver_ConstraintOffset(theConstraint)); } // All other types of constraints return SolverConstraintPtr(new SketchSolver_Constraint(theConstraint)); diff --git a/src/SketchSolver/SketchSolver_ConstraintOffset.cpp b/src/SketchSolver/SketchSolver_ConstraintOffset.cpp new file mode 100644 index 000000000..dbe419741 --- /dev/null +++ b/src/SketchSolver/SketchSolver_ConstraintOffset.cpp @@ -0,0 +1,40 @@ +// Copyright (C) 2020 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include + + +void SketchSolver_ConstraintOffset::getAttributes( + EntityWrapperPtr&, + std::vector&) +{ +} + +void SketchSolver_ConstraintOffset::process() +{ + cleanErrorMsg(); +} + + +void SketchSolver_ConstraintOffset::update() +{ + cleanErrorMsg(); + remove(); + process(); +} diff --git a/src/SketchSolver/SketchSolver_ConstraintOffset.h b/src/SketchSolver/SketchSolver_ConstraintOffset.h new file mode 100644 index 000000000..45d760b08 --- /dev/null +++ b/src/SketchSolver/SketchSolver_ConstraintOffset.h @@ -0,0 +1,48 @@ +// Copyright (C) 2020 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#ifndef SketchSolver_ConstraintOffset_H_ +#define SketchSolver_ConstraintOffset_H_ + +#include + +/** \class SketchSolver_ConstraintOffset + * \ingroup Plugins + * \brief Convert offset to the solver's data model + */ +class SketchSolver_ConstraintOffset : public SketchSolver_Constraint +{ +public: + /// Constructor based on SketchPlugin constraint + SketchSolver_ConstraintOffset(ConstraintPtr theConstraint) : + SketchSolver_Constraint(theConstraint) + {} + + /// \brief Update constraint + virtual void update(); + +protected: + /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints + virtual void process(); + + /// \brief Generate list of entities of mirror constraint + virtual void getAttributes(EntityWrapperPtr&, std::vector&); +}; + +#endif -- 2.39.2