]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Issue #2083: Creation of sketch arc by center have unexpected behavior
authorazv <azv@opencascade.com>
Mon, 3 Apr 2017 11:38:13 +0000 (14:38 +0300)
committerazv <azv@opencascade.com>
Mon, 3 Apr 2017 11:38:29 +0000 (14:38 +0300)
Use intersection point as end point of an arc if the any feature has been selected

src/GeomAlgoAPI/GeomAlgoAPI_Circ2dBuilder.cpp
src/SketchPlugin/SketchPlugin_MacroArc.cpp
src/SketchPlugin/SketchPlugin_MacroArc.h
src/SketchPlugin/SketchPlugin_MacroCircle.cpp
src/SketchPlugin/SketchPlugin_Validators.cpp

index dbe5cbaa27d96f27938086ca410c088e8a7c5a94..754ef43a27d85edc962b50049ad0808715ac65be 100644 (file)
@@ -125,9 +125,11 @@ private:
   Circ2dPtr circleByCenterAndPassingPoint()
   {
     const gp_Pnt2d& aCenter = myCenter->impl<gp_Pnt2d>();
-    GccAna_Circ2dTanCen aBuilder(myPassingPoints[0], aCenter);
-    if (aBuilder.NbSolutions() > 0)
-      return Circ2dPtr(new gp_Circ2d(aBuilder.ThisSolution(1)));
+    if (aCenter.SquareDistance(myPassingPoints[0]) > Precision::SquareConfusion()) {
+      GccAna_Circ2dTanCen aBuilder(myPassingPoints[0], aCenter);
+      if (aBuilder.NbSolutions() > 0)
+        return Circ2dPtr(new gp_Circ2d(aBuilder.ThisSolution(1)));
+    }
     return Circ2dPtr();
   }
 
index 1c83718531ae691f2138d16f517761ee03dc0954..e2d9940f327cdc845c6e33d140987dcca701f73a 100644 (file)
@@ -29,6 +29,7 @@
 #include <GeomAPI_Pnt2d.h>
 #include <GeomAPI_Vertex.h>
 #include <GeomAPI_XY.h>
+#include <GeomAPI_ShapeIterator.h>
 
 #include <GeomDataAPI_Point2D.h>
 #include <GeomDataAPI_Dir.h>
@@ -52,6 +53,69 @@ static void projectPointOnCircle(AttributePoint2DPtr& thePoint, const GeomAPI_Ci
     thePoint->setValue(aProjection);
 }
 
+static void intersectShapeAndCircle(const GeomShapePtr& theShape,
+                                    const GeomAPI_Circ2d& theCircle,
+                                    const SketchPlugin_Sketch* theSketch,
+                                    AttributePoint2DPtr& theIntersection)
+{
+  if (!theShape->isEdge())
+    return projectPointOnCircle(theIntersection, theCircle);
+
+  // convert shape to unbounded
+  std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(theShape));
+  if (anEdge->isLine()) {
+    static const double HALF_SIZE = 1.e6;
+    std::shared_ptr<GeomAPI_XYZ> aLoc = anEdge->line()->location()->xyz();
+    std::shared_ptr<GeomAPI_XYZ> aDir = anEdge->line()->direction()->xyz();
+
+    std::shared_ptr<GeomAPI_Pnt> aStart(
+        new GeomAPI_Pnt(aLoc->added(aDir->multiplied(-HALF_SIZE))));
+    std::shared_ptr<GeomAPI_Pnt> aEnd(
+        new GeomAPI_Pnt(aLoc->added(aDir->multiplied(HALF_SIZE))));
+    anEdge = GeomAlgoAPI_EdgeBuilder::line(aStart, aEnd);
+  } else if (anEdge->isArc()) {
+    std::shared_ptr<GeomAPI_Circ> aCircle = anEdge->circle();
+    anEdge = GeomAlgoAPI_EdgeBuilder::lineCircle(
+        aCircle->center(), aCircle->normal(), aCircle->radius());
+  }
+
+  // convert 2D circle to 3D object
+  std::shared_ptr<GeomAPI_Pnt2d> aCenter2d = theCircle.center();
+  std::shared_ptr<GeomAPI_Pnt> aCenter(theSketch->to3D(aCenter2d->x(), aCenter2d->y()));
+  std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+      const_cast<SketchPlugin_Sketch*>(theSketch)->attribute(SketchPlugin_Sketch::NORM_ID()));
+  std::shared_ptr<GeomAPI_Dir> aNormal(new GeomAPI_Dir(aNDir->x(), aNDir->y(), aNDir->z()));
+
+  GeomShapePtr aCircleShape =
+      GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, theCircle.radius());
+
+  GeomShapePtr anInter = anEdge->intersect(aCircleShape);
+  std::shared_ptr<GeomAPI_Pnt2d> anInterPnt;
+  if (!anInter)
+    return projectPointOnCircle(theIntersection, theCircle);
+  if (anInter->isVertex()) {
+    std::shared_ptr<GeomAPI_Vertex> aVertex(new GeomAPI_Vertex(anInter));
+    anInterPnt = theSketch->to2D(aVertex->point());
+  } else if (anInter->isCompound()) {
+    double aMinDist = 1.e300;
+
+    GeomAPI_ShapeIterator anIt(anInter);
+    for (; anIt.more(); anIt.next()) {
+      GeomShapePtr aCurrent = anIt.current();
+      if (!aCurrent->isVertex())
+        continue;
+      std::shared_ptr<GeomAPI_Vertex> aVertex(new GeomAPI_Vertex(aCurrent));
+      std::shared_ptr<GeomAPI_Pnt2d> aPnt = theSketch->to2D(aVertex->point());
+      double aDist = aPnt->distance(theIntersection->pnt());
+      if (aDist < aMinDist) {
+        aMinDist = aDist;
+        anInterPnt = aPnt;
+      }
+    }
+  }
+  theIntersection->setValue(anInterPnt);
+}
+
 
 SketchPlugin_MacroArc::SketchPlugin_MacroArc()
 : SketchPlugin_SketchEntity(),
@@ -156,7 +220,7 @@ void SketchPlugin_MacroArc::attributeChanged(const std::string& theID)
   data()->blockSendAttributeUpdated(aWasBlocked, false);
 }
 
-GeomShapePtr SketchPlugin_MacroArc::getArcShape()
+GeomShapePtr SketchPlugin_MacroArc::getArcShape(bool isBound)
 {
   if(!myStart.get() || !myEnd.get() || !myCenter.get()) {
     return GeomShapePtr();
@@ -174,9 +238,15 @@ GeomShapePtr SketchPlugin_MacroArc::getArcShape()
     std::dynamic_pointer_cast<GeomDataAPI_Dir>(aSketch->attribute(SketchPlugin_Sketch::NORM_ID()));
   std::shared_ptr<GeomAPI_Dir> aNormal(new GeomAPI_Dir(aNDir->x(), aNDir->y(), aNDir->z()));
 
-  GeomShapePtr anArcShape = boolean(REVERSED_ID())->value() ?
-      GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, anEnd, aStart, aNormal)
-    : GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, aStart, anEnd, aNormal);
+  GeomShapePtr anArcShape;
+  if (isBound) {
+    anArcShape = boolean(REVERSED_ID())->value() ?
+        GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, anEnd, aStart, aNormal)
+      : GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, aStart, anEnd, aNormal);
+  } else {
+    double aRadius = aCenter->distance(aStart);
+    anArcShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, aRadius);
+  }
 
   return anArcShape;
 }
@@ -393,9 +463,24 @@ void SketchPlugin_MacroArc::fillByCenterAndTwoPassed()
 
   GeomAPI_Circ2d aCircleForArc(myCenter, myStart);
 
-  // End point should be a projection on circle.
   bool aWasBlocked = data()->blockSendAttributeUpdated(true);
-  projectPointOnCircle(anEndPointAttr, aCircleForArc);
+  // check the end point is referred to another feature
+  GeomShapePtr aRefShape;
+  AttributeRefAttrPtr aEndPointRefAttr = refattr(END_POINT_REF_ID());
+  if (aEndPointRefAttr && aEndPointRefAttr->isInitialized()) {
+    if (aEndPointRefAttr->isObject()) {
+      FeaturePtr aFeature = ModelAPI_Feature::feature(aEndPointRefAttr->object());
+      if (aFeature)
+        aRefShape = aFeature->lastResult()->shape();
+    }
+  }
+  if (aRefShape) {
+    // Calculate end point as an intersection between circle and another shape
+    intersectShapeAndCircle(aRefShape, aCircleForArc, sketch(), anEndPointAttr);
+  } else {
+    // End point should be a projection on circle.
+    projectPointOnCircle(anEndPointAttr, aCircleForArc);
+  }
   data()->blockSendAttributeUpdated(aWasBlocked, false);
   myEnd = anEndPointAttr->pnt();
 
index 81297838169f9353daa124d3abfb99ad70f31a47..e36fc5d9c0ab65387e5ab9fbe81cfaab39599c83 100644 (file)
@@ -206,7 +206,8 @@ class SketchPlugin_MacroArc: public SketchPlugin_SketchEntity,
   SketchPlugin_MacroArc();
 
   /// Returns shape of arc.
-  GeomShapePtr getArcShape();
+  /// \param isBound  if true prepare arc, otherwice create circle containing this arc
+  GeomShapePtr getArcShape(bool isBound = true);
 
 private:
   /// Set fields for center, start and end points
index 078543b7d803ad527fc2b34eac103c984ca3f76b..b14bc1420c0a5c00e7bf443880aad79a10b0d7f5 100644 (file)
@@ -282,6 +282,7 @@ void SketchPlugin_MacroCircle::fillByTwoPassedPoints()
   GeomAlgoAPI_Circ2dBuilder aCircBuilder(SketchPlugin_Sketch::plane(sketch()));
 
   std::shared_ptr<GeomAPI_Pnt2d> aPassedPoints[2]; // there is possible only two passed points
+  bool hasTangentCurve = false;
   int aPntIndex = 0;
   for (; aPntIndex < 2; ++aPntIndex) {
     AttributePtr aPassedAttr = attribute(aPointAttr[aPntIndex]);
@@ -299,6 +300,7 @@ void SketchPlugin_MacroCircle::fillByTwoPassedPoints()
       aCircBuilder.addPassingPoint(aPassedPoint);
       aPassedPoints[aPntIndex] = aPassedPoint;
     } else {
+      hasTangentCurve = true;
       aCircBuilder.addTangentCurve(aTangentCurve);
       // if the circle is tangent to any curve,
       // the third point will be initialized by the tangent point
@@ -306,12 +308,14 @@ void SketchPlugin_MacroCircle::fillByTwoPassedPoints()
           std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aPassedAttr)->pnt());
     }
   }
+  if (aPntIndex <= 1)
+    return;
 
   std::shared_ptr<GeomAPI_Circ2d> aCircle;
 
-  if (aPntIndex == 3)
+  if (hasTangentCurve)
     aCircle = aCircBuilder.circle();
-  else if (aPntIndex == 2) {
+  else {
     // the circle is defined by two points, calculate its parameters manually
     std::shared_ptr<GeomAPI_Pnt2d> aCenter(new GeomAPI_Pnt2d(
         (aPassedPoints[0]->x() + aPassedPoints[1]->x()) * 0.5,
index bb142b319036064e27f6483f72212bc1c44fa663..236a104d1f5f94bf2aba41e777dddea9c5be425d 100755 (executable)
@@ -1338,7 +1338,7 @@ bool SketchPlugin_ArcEndPointIntersectionValidator::isValid(
     return true;
   }
 
-  GeomShapePtr anArcShape = anArcFeature->getArcShape();
+  GeomShapePtr anArcShape = anArcFeature->getArcShape(false);
 
   if(!anArcShape.get() || anArcShape->isNull()) {
     return true;