Salome HOME
Issue #3231: Convert Offset curves to b-splines. Order wires.
authorjfa <jfa@opencascade.com>
Tue, 23 Jun 2020 12:24:10 +0000 (15:24 +0300)
committerjfa <jfa@opencascade.com>
Tue, 23 Jun 2020 12:24:10 +0000 (15:24 +0300)
src/GeomAPI/GeomAPI_BSpline.cpp
src/GeomAPI/GeomAPI_BSpline.h
src/SketchPlugin/SketchPlugin_Offset.cpp
src/SketchPlugin/SketchPlugin_Offset.h
src/SketchPlugin/SketchPlugin_Tools.cpp

index cb2aef956615926a3dc704c2ef10e3eb16ce8910..6b4c0fe84e83fc96d812f7f3025633f4fbfedf4b 100644 (file)
 
 #include <Geom_BSplineCurve.hxx>
 
+#include <GeomConvert.hxx>
+
 #define MY_BSPLINE (*(implPtr<Handle_Geom_BSplineCurve>()))
 
-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_Curve)>();
   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));
index 95468bec452e447402013653e038af3e95fb636d..275b94dda46ff98b968ffad96b5cc70382120f39 100644 (file)
@@ -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;
index 0183cec9b6740ca898fef1a64dad48ee2bf92e18..6ff21485855b0813970661562843bceae48f862f 100644 (file)
@@ -120,9 +120,9 @@ void SketchPlugin_Offset::execute()
       std::list<FeaturePtr> 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<FeaturePtr>::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<GeomDataAPI_Point2D>& theEndPoint,
                                           std::set<FeaturePtr>& theEdgesSet,
-                                          std::list<FeaturePtr>& theChain)
+                                          std::list<FeaturePtr>& 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<ModelAPI_Feature>(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<FeaturePtr>::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<GeomAPI_Shape>& anOffsetShape)
@@ -340,6 +347,8 @@ void SketchPlugin_Offset::addToSketch(const std::shared_ptr<GeomAPI_Shape>& 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<GeomAPI_Shape>& 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<FeaturePtr> 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<FeaturePtr>::iterator aChainIt = aChain.begin();
       for (; aChainIt != aChain.end(); ++aChainIt) {
index 7ed4e379494fdbe3a0bb66c793f0a7da8d45c202..f8a86036df6f80d8356ef4d3f870c95d20b4dc90 100644 (file)
@@ -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<GeomDataAPI_Point2D>& theEndPoint,
                        std::set<FeaturePtr>& theEdgesSet,
-                       std::list<FeaturePtr>& theChain);
+                       std::list<FeaturePtr>& theChain,
+                       const bool isPrepend = false);
 
   // tmp
   std::set<FeaturePtr> myCreatedFeatures;
index 6209b788d14ee0e2bd5e11ebbed34e2ae0085a04..874d05e8ef46e92ec58231e2e048102cca14220c 100644 (file)
@@ -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<GeomDataAPI_Point2D>(
         theFeature->attribute(aStartAttributeName));