From ce8790c562518903c21f4a8ccff1745634a3a390 Mon Sep 17 00:00:00 2001 From: jfa Date: Tue, 23 Jun 2020 15:24:10 +0300 Subject: [PATCH] Issue #3231: Convert Offset curves to b-splines. Order wires. --- src/GeomAPI/GeomAPI_BSpline.cpp | 9 +++++++- src/GeomAPI/GeomAPI_BSpline.h | 5 +++- src/SketchPlugin/SketchPlugin_Offset.cpp | 29 +++++++++++++++--------- src/SketchPlugin/SketchPlugin_Offset.h | 4 +++- src/SketchPlugin/SketchPlugin_Tools.cpp | 5 ++++ 5 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/GeomAPI/GeomAPI_BSpline.cpp b/src/GeomAPI/GeomAPI_BSpline.cpp index cb2aef956..6b4c0fe84 100644 --- a/src/GeomAPI/GeomAPI_BSpline.cpp +++ b/src/GeomAPI/GeomAPI_BSpline.cpp @@ -22,13 +22,20 @@ #include +#include + #define MY_BSPLINE (*(implPtr())) -GeomAPI_BSpline::GeomAPI_BSpline(const GeomCurvePtr& theCurve) +GeomAPI_BSpline::GeomAPI_BSpline (const GeomCurvePtr& theCurve, + const bool isForced) { GeomCurvePtr anUntrimmedCurve = theCurve->basisCurve(); Handle(Geom_Curve) aCurve = anUntrimmedCurve->impl(); Handle(Geom_BSplineCurve) aBSpl = Handle(Geom_BSplineCurve)::DownCast(aCurve); + if (aBSpl.IsNull() && isForced) { + // convert to b-spline + aBSpl = GeomConvert::CurveToBSplineCurve(aCurve); + } if (aBSpl.IsNull()) throw Standard_ConstructionError("GeomAPI_BSpline: Curve is not a B-spline"); setImpl(new Handle_Geom_BSplineCurve(aBSpl)); diff --git a/src/GeomAPI/GeomAPI_BSpline.h b/src/GeomAPI/GeomAPI_BSpline.h index 95468bec4..275b94dda 100644 --- a/src/GeomAPI/GeomAPI_BSpline.h +++ b/src/GeomAPI/GeomAPI_BSpline.h @@ -36,7 +36,10 @@ class GeomAPI_BSpline : public GeomAPI_Interface { public: /// Creation of B-spline defined by a curve - GEOMAPI_EXPORT GeomAPI_BSpline(const GeomCurvePtr& theCurve); + /// \param isForced if true and theCurve is not a b-spline + /// curve, theCurve is converted to b-spline + GEOMAPI_EXPORT GeomAPI_BSpline (const GeomCurvePtr& theCurve, + const bool isForced = false); /// Degree of B-spline curve GEOMAPI_EXPORT int degree() const; diff --git a/src/SketchPlugin/SketchPlugin_Offset.cpp b/src/SketchPlugin/SketchPlugin_Offset.cpp index 0183cec9b..6ff214858 100644 --- a/src/SketchPlugin/SketchPlugin_Offset.cpp +++ b/src/SketchPlugin/SketchPlugin_Offset.cpp @@ -120,9 +120,9 @@ void SketchPlugin_Offset::execute() std::list aChain; aChain.push_back(aFeature); if (aStartPoint && anEndPoint) { // not closed edge - bool isClosed = findWireOneWay(aFeature, aFeature, aStartPoint, anEdgesSet, aChain); + bool isClosed = findWireOneWay(aFeature, aFeature, aStartPoint, anEdgesSet, aChain, true); if (!isClosed) - findWireOneWay(aFeature, aFeature, anEndPoint, anEdgesSet, aChain); + findWireOneWay(aFeature, aFeature, anEndPoint, anEdgesSet, aChain, false); } std::set::iterator aPos = anEdgesSet.find(aFeature); if (aPos != anEdgesSet.end()) @@ -156,7 +156,8 @@ bool SketchPlugin_Offset::findWireOneWay (const FeaturePtr& theFirstEdge, const FeaturePtr& theEdge, const std::shared_ptr& theEndPoint, std::set& theEdgesSet, - std::list& theChain) + std::list& theChain, + const bool isPrepend) { // 1. Find a single edge, coincident to theEndPoint by one of its ends if (!theEndPoint) return false; @@ -181,6 +182,9 @@ bool SketchPlugin_Offset::findWireOneWay (const FeaturePtr& theFirstEdge, AttributePtr aP = (*aPointsIt); FeaturePtr aCoincFeature = std::dynamic_pointer_cast(aP->owner()); + // Condition 0: not auxiliary + if (aCoincFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value()) continue; + // Condition 1: not a point feature if (aCoincFeature->getKind() != SketchPlugin_Point::ID()) { // Condition 2: it is not the current edge @@ -226,7 +230,10 @@ bool SketchPlugin_Offset::findWireOneWay (const FeaturePtr& theFirstEdge, return true; // 3. Add the found edge to the chain - theChain.push_back(aNextEdgeFeature); + if (isPrepend) + theChain.push_front(aNextEdgeFeature); + else + theChain.push_back(aNextEdgeFeature); // remove from the set, if the set is used if (theEdgesSet.size()) { std::set::iterator aPos = theEdgesSet.find(aNextEdgeFeature); @@ -243,7 +250,7 @@ bool SketchPlugin_Offset::findWireOneWay (const FeaturePtr& theFirstEdge, } // 5. Continue gathering the chain (recursive) - return findWireOneWay (theFirstEdge, aNextEdgeFeature, aP2, theEdgesSet, theChain); + return findWireOneWay (theFirstEdge, aNextEdgeFeature, aP2, theEdgesSet, theChain, isPrepend); } void SketchPlugin_Offset::addToSketch(const std::shared_ptr& anOffsetShape) @@ -340,6 +347,8 @@ void SketchPlugin_Offset::addToSketch(const std::shared_ptr& anOf mkBSpline(aResFeature, aResEdge); } else { + // convert to b-spline + mkBSpline(aResFeature, aResEdge); } if (aResFeature.get()) { @@ -356,11 +365,9 @@ void SketchPlugin_Offset::addToSketch(const std::shared_ptr& anOf void SketchPlugin_Offset::mkBSpline (FeaturePtr& theResult, const GeomEdgePtr& theEdge) { - if (!theEdge->isBSpline()) - return; - GeomCurvePtr aCurve (new GeomAPI_Curve (theEdge)); - GeomAPI_BSpline aBSpline (aCurve); + // 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()); @@ -468,9 +475,9 @@ bool SketchPlugin_Offset::findWires() std::list aChain; aChain.push_back(aFeature); - bool isClosed = findWireOneWay(aFeature, aFeature, aStartPoint, anEdgesSet, aChain); + bool isClosed = findWireOneWay(aFeature, aFeature, aStartPoint, anEdgesSet, aChain, true); if (!isClosed) - findWireOneWay(aFeature, aFeature, anEndPoint, anEdgesSet, aChain); + findWireOneWay(aFeature, aFeature, anEndPoint, anEdgesSet, aChain, false); std::list::iterator aChainIt = aChain.begin(); for (; aChainIt != aChain.end(); ++aChainIt) { diff --git a/src/SketchPlugin/SketchPlugin_Offset.h b/src/SketchPlugin/SketchPlugin_Offset.h index 7ed4e3794..f8a86036d 100644 --- a/src/SketchPlugin/SketchPlugin_Offset.h +++ b/src/SketchPlugin/SketchPlugin_Offset.h @@ -125,12 +125,14 @@ private: // \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, const std::shared_ptr& theEndPoint, std::set& theEdgesSet, - std::list& theChain); + std::list& theChain, + const bool isPrepend = false); // tmp std::set myCreatedFeatures; diff --git a/src/SketchPlugin/SketchPlugin_Tools.cpp b/src/SketchPlugin/SketchPlugin_Tools.cpp index 6209b788d..874d05e8e 100644 --- a/src/SketchPlugin/SketchPlugin_Tools.cpp +++ b/src/SketchPlugin/SketchPlugin_Tools.cpp @@ -20,6 +20,7 @@ #include "SketchPlugin_Tools.h" #include "SketchPlugin_Arc.h" +#include "SketchPlugin_BSpline.h" #include "SketchPlugin_Circle.h" #include "SketchPlugin_ConstraintCoincidence.h" #include "SketchPlugin_ConstraintCoincidenceInternal.h" @@ -661,6 +662,10 @@ void SketchPlugin_SegmentationTools::getFeaturePoints(const FeaturePtr& theFeatu aStartAttributeName = SketchPlugin_EllipticArc::START_POINT_ID(); anEndAttributeName = SketchPlugin_EllipticArc::END_POINT_ID(); } + else if (aFeatureKind == SketchPlugin_BSpline::ID()) { + aStartAttributeName = SketchPlugin_BSpline::START_ID(); + anEndAttributeName = SketchPlugin_BSpline::END_ID(); + } if (!aStartAttributeName.empty() && !anEndAttributeName.empty()) { theStartPointAttr = std::dynamic_pointer_cast( theFeature->attribute(aStartAttributeName)); -- 2.39.2