]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Issue #2208: Intermediate solution
authorvsv <vsv@opencascade.com>
Wed, 26 Jul 2017 13:47:20 +0000 (16:47 +0300)
committervsv <vsv@opencascade.com>
Wed, 26 Jul 2017 13:47:20 +0000 (16:47 +0300)
src/SketcherPrs/SketcherPrs_PositionMgr.cpp
src/SketcherPrs/SketcherPrs_PositionMgr.h

index c92f1a0abdf521a25719da908401f20a90774c99..219cc31cc7ddfa2a5fc6c97fb2726ecd8f8d5522 100644 (file)
@@ -33,6 +33,8 @@
 #include <SketchPlugin_Line.h>
 #include <SketchPlugin_Circle.h>
 #include <SketchPlugin_Arc.h>
+#include <SketchPlugin_ConstraintTangent.h>
+#include <SketchPlugin_ConstraintPerpendicular.h>
 
 #include <BRepExtrema_ExtPC.hxx>
 #include <TopoDS_Vertex.hxx>
 #include <TColGeom_SequenceOfCurve.hxx>
 #include <gp_Dir.hxx>
 
+#include <array>
+
 static SketcherPrs_PositionMgr* MyPosMgr = NULL;
 
+#define PI 3.1415926535897932
+
 // The class is implemented as a singlton
 SketcherPrs_PositionMgr* SketcherPrs_PositionMgr::get()
 {
@@ -80,6 +86,103 @@ int SketcherPrs_PositionMgr::getPositionIndex(ObjectPtr theLine,
 }
 
 
+bool SketcherPrs_PositionMgr::isPntConstraint(const std::string& theName)
+{
+  static std::list<std::string> aConstraints;
+  if (aConstraints.size() == 0) {
+    aConstraints.push_back(SketchPlugin_ConstraintTangent::ID());
+    aConstraints.push_back(SketchPlugin_ConstraintPerpendicular::ID());
+  }
+  std::list<std::string>::const_iterator aIt;
+  for (aIt = aConstraints.cbegin(); aIt != aConstraints.cend(); ++aIt) {
+    if ((*aIt) == theName)
+      return true;
+  }
+  return false;
+}
+
+bool containsPoint(const FeaturePtr& theFeature, GeomPnt2dPtr thePnt2d, GeomPointPtr thePos)
+{
+  if (theFeature->getKind() == SketchPlugin_Line::ID()) {
+    AttributePoint2DPtr aSPnt1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+      theFeature->data()->attribute(SketchPlugin_Line::START_ID()));
+    AttributePoint2DPtr aSPnt2 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+      theFeature->data()->attribute(SketchPlugin_Line::END_ID()));
+
+    GeomPnt2dPtr aPnt1 = aSPnt1->pnt();
+    GeomPnt2dPtr aPnt2 = aSPnt2->pnt();
+
+    if (aPnt1->isEqual(thePnt2d) || aPnt2->isEqual(thePnt2d))
+      return true;
+  } else if ((theFeature->getKind() == SketchPlugin_Circle::ID()) ||
+             (theFeature->getKind() == SketchPlugin_Arc::ID())) {
+    GeomCurvePtr aCurve;
+    ObjectPtr aResObj;
+    std::list<ResultPtr> aResults = theFeature->results();
+    std::list<ResultPtr>::const_iterator aIt;
+    for (aIt = aResults.cbegin(); aIt != aResults.cend(); aIt++) {
+      GeomShapePtr aShp = SketcherPrs_Tools::getShape((*aIt));
+      if (aShp->isEdge()) {
+        aResObj = (*aIt);
+        aCurve = std::shared_ptr<GeomAPI_Curve>(new GeomAPI_Curve(aShp));
+        break;
+      }
+    }
+    if (aCurve.get()) {
+      double aStart = aCurve->startParam();
+      double aEnd = aCurve->endParam();
+      GeomCirclePtr  aCircle = GeomCirclePtr(new GeomAPI_Circ(aCurve));
+      double aParam;
+      if (aCircle->parameter(thePos, 1.e-4, aParam) && (aParam >= aStart) && (aParam <= aEnd))
+        return true;
+    }
+  }
+  return false;
+}
+
+int SketcherPrs_PositionMgr::getPositionIndex(GeomPointPtr thePos, const SketcherPrs_SymbolPrs* thePrs)
+{
+  if (myPntShapes.count(thePrs->feature()) == 0) {
+    // Renumerate positions around the specified constraint point for all constraints
+    GeomAx3Ptr aAx3 = thePrs->plane();
+    ModelAPI_CompositeFeature* aOwner = thePrs->sketcher();
+    GeomPnt2dPtr aPnt2d = thePos->to2D(aAx3->origin(), aAx3->dirX(), aAx3->dirY());
+
+    int aNbSubs = aOwner->numberOfSubs();
+    int aId = 0;
+    for (int i = 0; i < aNbSubs; i++) {
+      FeaturePtr aFeature = aOwner->subFeature(i);
+
+      if (myPntShapes.count(aFeature.get()) == 1) {
+        myPntShapes[aFeature.get()] = aId;
+        aId++;
+      } else {
+        if (isPntConstraint(aFeature->getKind())) {
+          DataPtr aData = aFeature->data();
+          AttributeRefAttrPtr aObjRef = aData->refattr(SketchPlugin_Constraint::ENTITY_A());
+          FeaturePtr aObj = ModelAPI_Feature::feature(aObjRef->object());
+          bool aContains = false;
+          if (containsPoint(aObj, aPnt2d, thePos)) {
+            aContains = true;
+          } else {
+            aObjRef = aData->refattr(SketchPlugin_Constraint::ENTITY_B());
+            aObj = ModelAPI_Feature::feature(aObjRef->object());
+            if (containsPoint(aObj, aPnt2d, thePos)) {
+              aContains = true;
+            }
+          }
+          if (aContains) {
+            myPntShapes[aFeature.get()] = aId;
+            aId++;
+          }
+        }
+      }
+    }
+  }
+  return myPntShapes[thePrs->feature()];
+}
+
+
 gp_Vec getVector(ObjectPtr theShape, GeomDirPtr theDir, gp_Pnt theP)
 {
   gp_Vec aVec;
@@ -106,9 +209,8 @@ gp_Vec getVector(ObjectPtr theShape, GeomDirPtr theDir, gp_Pnt theP)
         }
       }
     } else {
-      double aMidParam = (aCurve->startParam() + aCurve->endParam()) / 2.;
-      GeomPointPtr aPnt1 = aCurve->getPoint((aMidParam + aCurve->endParam()) / 2.);
-      GeomPointPtr aPnt2 = aCurve->getPoint((aMidParam + aCurve->startParam()) / 2.);
+      GeomPointPtr aPnt1 = aCurve->getPoint(aCurve->endParam());
+      GeomPointPtr aPnt2 = aCurve->getPoint(aCurve->startParam());
 
       gp_Pnt aPn2 = aPnt2->impl<gp_Pnt>();
       if (aPn2.IsEqual(theP, Precision::Confusion()))
@@ -199,6 +301,9 @@ std::list<ObjectPtr> getCurves(const GeomPointPtr& thePnt, const SketcherPrs_Sym
   int aNbSubs = aOwner->numberOfSubs();
   for (int i = 0; i < aNbSubs; i++) {
     FeaturePtr aFeature = aOwner->subFeature(i);
+    if (!aFeature->firstResult().get()) // There is no result
+      continue;
+
     if (aFeature->getKind() == SketchPlugin_Line::ID()) {
       AttributePoint2DPtr aSPnt1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
         aFeature->data()->attribute(SketchPlugin_Line::START_ID()));
@@ -245,32 +350,73 @@ gp_Pnt SketcherPrs_PositionMgr::getPointPosition(
   ObjectPtr theLine, const SketcherPrs_SymbolPrs* thePrs,
   double theStep, GeomPointPtr thePnt)
 {
-  std::list<ObjectPtr> aCurves = getCurves(thePnt, thePrs);
-
   gp_Pnt aP = thePnt->impl<gp_Pnt>();
-  //gp_Vec aVec1 = getVector(theLine, thePrs->plane()->dirX(), aP);
-  std::list<gp_Vec> aVectors;
+  GeomDirPtr aNormal = thePrs->plane()->normal();
+  gp_Dir aNormDir = aNormal->impl<gp_Dir>();
+
+  std::list<ObjectPtr> aCurves = getCurves(thePnt, thePrs);
   std::list<ObjectPtr>::const_iterator aItCurv;
+  std::list<gp_Vec> aVectorsList;
+  // Calculate all vectors
   for (aItCurv = aCurves.cbegin(); aItCurv != aCurves.cend(); aItCurv++) {
-    ObjectPtr aObject = (*aItCurv);
-    gp_Vec aVec = getVector(aObject, thePrs->plane()->dirX(), aP);
-    aVectors.push_back(aVec);
+    aVectorsList.push_back(getVector((*aItCurv), thePrs->plane()->dirX(), aP));
   }
 
-  gp_Vec aBase = getVector(theLine, thePrs->plane()->dirX(), aP);
-  std::list<double> aAngles;
   std::list<gp_Vec>::const_iterator aItVec;
-  for (aItVec = aVectors.cbegin(); aItVec != aVectors.cend(); aItVec++) {
-    gp_Vec aVec = (*aItVec);
-    double aAngle = aBase.Angle(aVec);
-    aAngles.push_back(aAngle);
+  std::map<double, gp_Vec> aAngVectors;
+  // Select closest vectors and calculate angles between base vector and closest vector
+  for (aItVec = aVectorsList.cbegin(); aItVec != aVectorsList.cend(); aItVec++) {
+    std::list<gp_Vec>::const_iterator aIt;
+    double aMinAng = 0;
+    gp_Vec aVec = *aItVec;
+    for (aIt = aVectorsList.cbegin(); aIt != aVectorsList.cend(); aIt++) {
+      double aAng = aVec.AngleWithRef(*aIt, aNormDir);
+      if (aAng != 0) {
+        if (aAng < 0)
+          aAng = 2 * PI + aAng;
+
+        if (aMinAng == 0)
+          aMinAng = aAng;
+        else if (aAng < aMinAng) {
+          aMinAng = aAng;
+        }
+      }
+    }
+    aAngVectors[aMinAng] = aVec;
   }
-  // Compute shifting vector for a one symbol
-  //gp_Vec aShift = aVec1.Crossed(thePrs->plane()->normal()->impl<gp_Dir>());
-  //aShift.Normalize();
-  //aShift.Multiply(theStep * 1.5);
-  //aP.Translate(aShift);
-  return aP;
+
+  // Angle size of a symbol for a first level
+  static const double aAngleStep = PI * 50./180.;
+
+  // Position of the symbol
+  int aPos = getPositionIndex(thePnt, thePrs);
+
+  //std::list<double>::const_iterator aItAng;
+  gp_Ax1 aRotAx(aP, aNormDir);
+  int aPosId = 0; // Last used position
+  double aAng;
+  gp_Vec aPrevVec;
+  std::map<double, gp_Vec>::const_iterator aItAng;
+  for (aItAng = aAngVectors.cbegin(); aItAng != aAngVectors.cend(); ++aItAng) {
+    aAng = aItAng->first;
+    aPrevVec = aItAng->second;
+    if (aAng >= aAngleStep) {
+      gp_Vec aShift;
+      int Nb = int(aAng / aAngleStep);
+      if ((aPos >= aPosId) && (aPos < (aPosId + Nb))) {
+        // rotate base vector on a necessary angle
+        aShift = aPrevVec.Rotated(aRotAx, aAngleStep + aAngleStep * (aPos - aPosId));
+        aShift.Normalize();
+        aShift.Multiply(theStep * 1.5);
+        return aP.Translated(aShift);
+      }
+      aPosId += Nb;
+    }
+  }
+  gp_Vec aShift = aPrevVec.Rotated(aRotAx, aAngleStep);
+  aShift.Normalize();
+  aShift.Multiply(theStep * 1.5);
+  return aP.Translated(aShift);
 }
 
 //*****************************************************************
index 272092989524c4d9a8f032035e257bcd51ae3b54..34529101a92af4f02fb9e139d5141826c863d206 100644 (file)
@@ -61,17 +61,33 @@ private:
   /// \param thePrs a presentation of constraint
   int getPositionIndex(ObjectPtr theLine, const SketcherPrs_SymbolPrs* thePrs);
 
+  /// Returns position index of the given constraint around a point
+  /// \param theLine constrained object
+  /// \param thePrs a presentation of constraint
+  int getPositionIndex(GeomPointPtr thePos, const SketcherPrs_SymbolPrs* thePrs);
+
+  /// Returns position of a constraint around a point
+  /// \param theLine a base object of the constraint
+  /// \param thePrs a presentation of the constraint symbol
+  /// \param theStep step from base point
+  /// \param thePnt a base point
   gp_Pnt getPointPosition(ObjectPtr theLine, const SketcherPrs_SymbolPrs* thePrs,
                           double theStep, GeomPointPtr thePnt);
 
+  static bool isPntConstraint(const std::string& theName);
+
 private:
   typedef std::map<const SketcherPrs_SymbolPrs*, int> PositionsMap;
+  typedef std::map<const ModelAPI_Feature*, int> FeaturesMap;
 
   /// The map which contains position of presentation
   PositionsMap myIndexes;
 
   /// The map contains position index
   std::map<ObjectPtr, PositionsMap> myShapes;
+
+  /// The map contains position of index for constraints around a point
+  FeaturesMap myPntShapes;
 };
 
 #endif
\ No newline at end of file