]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Tangency constraint between circle and linear segment
authorazv <azv@opencascade.com>
Wed, 27 Jan 2016 12:08:07 +0000 (15:08 +0300)
committerdbv <dbv@opencascade.com>
Tue, 16 Feb 2016 14:04:31 +0000 (17:04 +0300)
src/SketchPlugin/SketchPlugin_Validators.cpp
src/SketchPlugin/plugin-Sketch.xml
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Builder.cpp
src/SketchSolver/SketchSolver_ConstraintDistance.cpp
src/SketchSolver/SketchSolver_ConstraintTangent.cpp
src/SketchSolver/SketchSolver_ConstraintTangent.h
src/SketchSolver/SketchSolver_Group.cpp
src/SketchSolver/SketchSolver_IConstraintWrapper.h
src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Builder.cpp

index 3b79ad68cae45a90022ea0093a0bb4cddb89c0af..66fc18d8b5ea5f3ef0063e3961473ad084dbf172 100755 (executable)
@@ -89,6 +89,47 @@ bool SketchPlugin_DistanceAttrValidator::isValid(const AttributePtr& theAttribut
   return true;
 }
 
+
+static bool hasCoincidentPoint(FeaturePtr theFeature1, FeaturePtr theFeature2)
+{
+  FeaturePtr aConstrFeature;
+  std::list<AttributePtr> anAttrList;
+  if (theFeature1->getKind() == SketchPlugin_Circle::ID() ||
+      theFeature2->getKind() == SketchPlugin_Circle::ID())
+    return false;
+  if (theFeature2->getKind() == SketchPlugin_Line::ID()) {
+    anAttrList.push_back(theFeature2->attribute(SketchPlugin_Line::START_ID()));
+    anAttrList.push_back(theFeature2->attribute(SketchPlugin_Line::END_ID()));
+  } else if (theFeature2->getKind() == SketchPlugin_Arc::ID()) {
+    anAttrList.push_back(theFeature2->attribute(SketchPlugin_Arc::START_ID()));
+    anAttrList.push_back(theFeature2->attribute(SketchPlugin_Arc::END_ID()));
+  }
+
+  const std::set<AttributePtr>& aRefsList = theFeature1->data()->refsToMe();
+  std::set<AttributePtr>::const_iterator aRefIt = aRefsList.begin();
+  for (; aRefIt != aRefsList.end(); ++aRefIt) {
+    aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIt)->owner());
+    if (aConstrFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID())
+      continue;
+    AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefIt);
+    AttributePtr anAttr = aRefAttr->attr();
+    if (anAttr->id() == SketchPlugin_Arc::CENTER_ID())
+      continue;
+
+    anAttr = aConstrFeature->attribute(SketchPlugin_Constraint::ENTITY_A());
+    if (anAttr == *aRefIt)
+      anAttr = aConstrFeature->attribute(SketchPlugin_Constraint::ENTITY_B());
+
+    aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
+    anAttr = aRefAttr->attr();
+    for (std::list<AttributePtr>::const_iterator anIt = anAttrList.begin();
+         anIt != anAttrList.end(); ++anIt)
+      if (*anIt == anAttr)
+        return true;
+  }
+  return false;
+}
+
 bool SketchPlugin_TangentAttrValidator::isValid(const AttributePtr& theAttribute, 
                                                 const std::list<std::string>& theArguments,
                                                 std::string& theError) const
@@ -114,11 +155,19 @@ bool SketchPlugin_TangentAttrValidator::isValid(const AttributePtr& theAttribute
     AttributeRefAttrPtr aOtherAttr = anAttributeFeature->data()->refattr(aParamA);
     ObjectPtr aOtherObject = aOtherAttr->object();
     FeaturePtr aOtherFea = ModelAPI_Feature::feature(aOtherObject);
+    if (!aOtherFea)
+      return true;
+
+    if ((aRefFea->getKind() == SketchPlugin_Arc::ID() ||
+        aOtherFea->getKind() == SketchPlugin_Arc::ID()) &&
+        !hasCoincidentPoint(aRefFea, aOtherFea))
+      return false;
 
     if (aRefFea->getKind() == SketchPlugin_Line::ID()) {
-      if (aOtherFea->getKind() != SketchPlugin_Arc::ID()) {
-        theError = "It refers to a " + SketchPlugin_Line::ID() + ", but " + aParamA + " is not an "
-          + SketchPlugin_Arc::ID();
+      if (aOtherFea->getKind() != SketchPlugin_Arc::ID() &&
+          aOtherFea->getKind() != SketchPlugin_Circle::ID()) {
+        theError = "It refers to a " + SketchPlugin_Line::ID() + ", but " + aParamA + " is neither an "
+          + SketchPlugin_Arc::ID() + " nor " + SketchPlugin_Circle::ID();
         return false;
       }
     }
@@ -130,9 +179,16 @@ bool SketchPlugin_TangentAttrValidator::isValid(const AttributePtr& theAttribute
         return false;
       }
     }
+    else if (aRefFea->getKind() == SketchPlugin_Circle::ID()) {
+      if (aOtherFea->getKind() != SketchPlugin_Line::ID()) {
+        theError = "It refers to an " + SketchPlugin_Circle::ID() + ", but " + aParamA + " is not a "
+          + SketchPlugin_Line::ID();
+        return false;
+      }
+    }
     else {
-      theError = "It refers to " + aRefFea->getKind() + "but should refer to " + SketchPlugin_Line::ID()
-        + " or " + SketchPlugin_Arc::ID();
+      theError = "It refers to " + aRefFea->getKind() + "but should refer to " + SketchPlugin_Line::ID()
+        + " or " + SketchPlugin_Arc::ID() + " or " + SketchPlugin_Circle::ID();
       return false;
     }
     return true;
@@ -279,7 +335,6 @@ bool SketchPlugin_MirrorAttrValidator::isValid(const AttributePtr& theAttribute,
   return true;
 }
 
-
 bool SketchPlugin_CoincidenceAttrValidator::isValid(const AttributePtr& theAttribute, 
                                                     const std::list<std::string>& theArguments,
                                                     std::string& theError) const
index b28114bf932657212933383470e36e5a844b77cc..fd1d6f4e5caa3697d81f0198514070285a970219 100644 (file)
       <feature id="SketchConstraintTangent" title="Tangent" tooltip="Create constraint defining tangency of two objects with common coincident point" icon=":icons/tangent.png">
         <sketch_shape_selector id="ConstraintEntityA" 
             label="First object" tooltip="Select line or arc" shape_types="edge">
-          <validator id="PartSet_CoincidentAttr" parameters="ConstraintEntityB"/>
+          <validator id="SketchPlugin_TangentAttr" parameters="ConstraintEntityB"/>
           <validator id="PartSet_DifferentObjects"/>
         </sketch_shape_selector>
         
         <sketch_shape_selector id="ConstraintEntityB"
             label="Second object" tooltip="Select line or arc" shape_types="edge">
-          <validator id="PartSet_CoincidentAttr" parameters="ConstraintEntityA"/>
           <validator id="SketchPlugin_TangentAttr" parameters="ConstraintEntityA"/>
           <validator id="PartSet_DifferentObjects"/>
         </sketch_shape_selector>
index dd1d542fbdb80acf6478c9d32df7ebd2b6e4889a..95e01be607b8598a7a2b81e7642bb3f3e08283d8 100644 (file)
@@ -135,6 +135,8 @@ static ConstraintWrapperPtr
 static void adjustAngle(ConstraintWrapperPtr theConstraint);
 /// \brief Update mirror points
 static void adjustMirror(ConstraintWrapperPtr theConstraint);
+/// \brief Update a sign of the point-line distance constraint
+static void adjustPtLineDistance(ConstraintWrapperPtr theConstraint);
 
 /// \brief Transform points to be symmetric regarding to the mirror line
 static void makeMirrorPoints(EntityWrapperPtr theOriginal,
@@ -240,6 +242,7 @@ std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createConstraint(
                   GCS_PARAMETER_WRAPPER(anIntermediate));
     break;
   case CONSTRAINT_TANGENT_ARC_LINE:
+  case CONSTRAINT_TANGENT_CIRCLE_LINE:
   case CONSTRAINT_TANGENT_ARC_ARC:
     aResult = createConstraintTangent(theConstraint, theGroupID, theType,
                   GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
@@ -439,6 +442,8 @@ void PlaneGCSSolver_Builder::adjustConstraint(ConstraintWrapperPtr theConstraint
   // Update flags and parameters in constraints
   if (aType == CONSTRAINT_ANGLE)
     adjustAngle(theConstraint);
+  else if (aType == CONSTRAINT_PT_LINE_DISTANCE)
+    adjustPtLineDistance(theConstraint);
 }
 
 EntityWrapperPtr PlaneGCSSolver_Builder::createFeature(
@@ -990,7 +995,7 @@ ConstraintWrapperPtr createConstraintTangent(
     std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
 {
   GCSConstraintPtr aNewConstr;
-  if (theType == CONSTRAINT_TANGENT_ARC_LINE) {
+  if (theType == CONSTRAINT_TANGENT_ARC_LINE || theType == CONSTRAINT_TANGENT_CIRCLE_LINE) {
     std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
     std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
 
@@ -1113,3 +1118,24 @@ void makeMirrorPoints(EntityWrapperPtr theOriginal,
   }
 }
 
+void adjustPtLineDistance(ConstraintWrapperPtr theConstraint)
+{
+  BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
+
+  std::shared_ptr<GeomAPI_Pnt2d> aPoint;
+  std::shared_ptr<GeomAPI_Lin2d> aLine;
+  std::list<EntityWrapperPtr> aSubs = theConstraint->entities();
+  std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
+  for (; aSIt != aSubs.end(); ++aSIt) {
+    if ((*aSIt)->type() == ENTITY_POINT)
+      aPoint = aBuilder->point(*aSIt);
+    else if ((*aSIt)->type() == ENTITY_LINE)
+      aLine = aBuilder->line(*aSIt);
+  }
+
+  std::shared_ptr<GeomAPI_XY> aLineVec = aLine->direction()->xy();
+  std::shared_ptr<GeomAPI_XY> aPtLineVec = aPoint->xy()->decreased(aLine->location()->xy());
+  if (aPtLineVec->cross(aLineVec) * theConstraint->value() < 0.0)
+    theConstraint->setValue(theConstraint->value() * (-1.0));
+}
+
index 2a75e1293f85b4e1c4d69331fb2af61c4e5c6891..5bbcd791977b6d9736ec7ee7d50cfec2a4d7d8c4 100644 (file)
@@ -54,26 +54,10 @@ void SketchSolver_ConstraintDistance::adjustConstraint()
     return;
   }
 
-  // Get constraint parameters and check the sign of constraint value
+  // Adjust the sign of constraint value
   BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-  std::shared_ptr<GeomAPI_Pnt2d> aPoint;
-  std::shared_ptr<GeomAPI_Lin2d> aLine;
-  std::list<EntityWrapperPtr> aSubs = aConstraint->entities();
-  std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
-  for (; aSIt != aSubs.end(); ++aSIt) {
-    if ((*aSIt)->type() == ENTITY_POINT)
-      aPoint = aBuilder->point(*aSIt);
-    else if ((*aSIt)->type() == ENTITY_LINE)
-      aLine = aBuilder->line(*aSIt);
-  }
-
-  std::shared_ptr<GeomAPI_XY> aLineVec = aLine->direction()->xy();
-  std::shared_ptr<GeomAPI_XY> aPtLineVec = aPoint->xy()->decreased(aLine->location()->xy());
-  if (aPtLineVec->cross(aLineVec) * aConstraint->value() < 0.0 || myIsNegative) {
-    aConstraint->setValue(aConstraint->value() * (-1.0));
-    myStorage->addConstraint(myBaseConstraint, aConstraint);
-    myIsNegative = true;
-  }
+  aBuilder->adjustConstraint(aConstraint);
+  myStorage->addConstraint(myBaseConstraint, aConstraint);
 }
 
 void SketchSolver_ConstraintDistance::update()
index 51d87e276de239089abf6586a30f22e6e3e3cee7..0bd02bf0b5d2b7b77254ff7f514888bdcd851dd3 100644 (file)
@@ -3,6 +3,9 @@
 #include <SketchSolver_Manager.h>
 
 #include <GeomAPI_Pnt2d.h>
+#include <SketchPlugin_Circle.h>
+
+#include <cmath>
 
 
 /// \brief Check whether the entities has only one shared point
@@ -49,6 +52,7 @@ void SketchSolver_ConstraintTangent::getAttributes(
   // Check the quantity of entities of each type and their order (arcs first)
   int aNbLines = 0;
   int aNbArcs = 0;
+  int aNbCircles = 0;
   bool isSwap = false; // whether need to swap arguments (arc goes before line)
   std::vector<EntityWrapperPtr>::iterator anEntIt = theAttributes.begin() + 2;
   for (; anEntIt != theAttributes.end(); ++anEntIt) {
@@ -58,14 +62,22 @@ void SketchSolver_ConstraintTangent::getAttributes(
       ++aNbArcs;
       isSwap = aNbLines > 0;
     }
+    else if ((*anEntIt)->type() == ENTITY_CIRCLE) {
+      ++aNbCircles;
+      isSwap = aNbLines > 0;
+    }
   }
 
-  if (aNbArcs < 1) {
+  if (aNbArcs < 1 && aNbCircles < 1) {
     myErrorMsg = SketchSolver_Error::INCORRECT_TANGENCY_ATTRIBUTE();
     return;
   }
-  if (aNbLines == 1 && aNbArcs == 1)
-    myType = CONSTRAINT_TANGENT_ARC_LINE;
+  if (aNbLines == 1) {
+    if (aNbArcs == 1)
+      myType = CONSTRAINT_TANGENT_ARC_LINE;
+    else if (aNbCircles == 1)
+      myType = CONSTRAINT_TANGENT_CIRCLE_LINE;
+  }
   else if (aNbArcs == 2)
     myType = CONSTRAINT_TANGENT_ARC_ARC;
   else {
@@ -73,7 +85,8 @@ void SketchSolver_ConstraintTangent::getAttributes(
     return;
   }
 
-  if (!hasSingleCoincidence(theAttributes[2], theAttributes[3]))
+  if (myType != CONSTRAINT_TANGENT_CIRCLE_LINE && 
+      !hasSingleCoincidence(theAttributes[2], theAttributes[3]))
     myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
 
   if (isSwap) {
@@ -82,3 +95,27 @@ void SketchSolver_ConstraintTangent::getAttributes(
     theAttributes[3] = aTemp;
   }
 }
+
+void SketchSolver_ConstraintTangent::adjustConstraint()
+{
+  if (myType != CONSTRAINT_TANGENT_CIRCLE_LINE)
+    return;
+
+  ConstraintWrapperPtr aConstraint = myStorage->constraint(myBaseConstraint).front();
+  AttributePtr aCircleCenter = aConstraint->entities().front()->baseAttribute();
+  if (!aCircleCenter)
+    return;
+  FeaturePtr aCircle = ModelAPI_Feature::feature(aCircleCenter->owner());
+  AttributeDoublePtr aRadius = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+      aCircle->attribute(SketchPlugin_Circle::RADIUS_ID()));
+
+  if (fabs(aRadius->value()) == fabs(aConstraint->value()))
+    return;
+
+  aConstraint->setValue(aRadius->value());
+
+  // Adjust the sign of constraint value
+  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
+  aBuilder->adjustConstraint(aConstraint);
+  myStorage->addConstraint(myBaseConstraint, aConstraint);
+}
index e1716bf74b5c4c493d20ec4c6a298c101b684122..2ffa8de02977b700bbe887cec63c8957047b7463 100644 (file)
@@ -27,6 +27,10 @@ protected:
   /// \param[out] theValue      numerical characteristic of constraint (e.g. distance)
   /// \param[out] theAttributes list of attributes to be filled
   virtual void getAttributes(double& theValue, std::vector<EntityWrapperPtr>& theAttributes);
+
+  /// \brief This method is used in derived objects to check consistency of constraint.
+  ///        E.g. the distance between line and point may be signed.
+  virtual void adjustConstraint();
 };
 
 #endif
index 4b50f02532082c5586615698da11a02032d6a584..84d6a0bb26e523c00813d148781295018fa9a0c3 100644 (file)
@@ -190,6 +190,9 @@ static void updateMultiConstraints(ConstraintConstraintMap& theConstraints, Feat
          aCIt->second->getType() == CONSTRAINT_MULTI_TRANSLATION)
         && aCIt->second->isUsed(theFeature))
       std::dynamic_pointer_cast<SketchSolver_ConstraintMulti>(aCIt->second)->update(true);
+    else if (aCIt->second->getType() == CONSTRAINT_TANGENT_CIRCLE_LINE
+             && aCIt->second->isUsed(theFeature))
+      aCIt->second->update();
   }
 }
 
index 813e8dede94d5ff0638122d9327b17c35f2b7a75..01020e9231681957cf7fa0c6fcae559876415cf9 100644 (file)
@@ -38,6 +38,7 @@ enum SketchSolver_ConstraintType {
   CONSTRAINT_EQUAL_RADIUS,
   CONSTRAINT_TANGENT,         // base tangency if we don't know the measured objects yet
   CONSTRAINT_TANGENT_ARC_LINE,
+  CONSTRAINT_TANGENT_CIRCLE_LINE,
   CONSTRAINT_TANGENT_ARC_ARC,
   CONSTRAINT_MULTI_TRANSLATION,
   CONSTRAINT_MULTI_ROTATION
index 9d7339ac7223e10813a2931ae2bd302eeeaaec99..11b634a89b13d6da105b76f106bb03dbac91ec31 100644 (file)
@@ -51,6 +51,8 @@ static void adjustTangency(ConstraintWrapperPtr theConstraint);
 static void adjustAngle(ConstraintWrapperPtr theConstraint);
 /// \brief Update mirror points
 static void adjustMirror(ConstraintWrapperPtr theConstraint);
+/// \brief Update a sign of the point-line distance constraint
+static void adjustPtLineDistance(ConstraintWrapperPtr theConstraint);
 
 /// \brief Transform points to be symmetric regarding to the mirror line
 static void makeMirrorPoints(EntityWrapperPtr theOriginal,
@@ -96,6 +98,15 @@ std::list<ConstraintWrapperPtr> SolveSpaceSolver_Builder::createConstraint(
   if (theType == CONSTRAINT_SYMMETRIC)
     return createMirror(theConstraint, theGroupID, theSketchID,
                         thePoint1, thePoint2, theEntity1);
+  else if (theType == CONSTRAINT_TANGENT_CIRCLE_LINE) {
+    // replace by distance from center of circle to the line
+    const std::list<EntityWrapperPtr>& aSubs = theEntity1->subEntities();
+    EntityWrapperPtr aCenter = aSubs.front();
+    AttributeDoublePtr aRadius = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+        aSubs.back()->baseAttribute());
+    return createConstraint(theConstraint, theGroupID, theSketchID,
+        CONSTRAINT_PT_LINE_DISTANCE, aRadius->value(), aCenter, EntityWrapperPtr(), theEntity2);
+  }
 
   int aType = ConstraintType::toSolveSpace(theType);
   if (aType == SLVS_C_UNKNOWN)
@@ -264,6 +275,8 @@ void SolveSpaceSolver_Builder::adjustConstraint(ConstraintWrapperPtr theConstrai
     adjustAngle(theConstraint);
   else if (aType == CONSTRAINT_SYMMETRIC)
     adjustMirror(theConstraint);
+  else if (aType == CONSTRAINT_PT_LINE_DISTANCE)
+    adjustPtLineDistance(theConstraint);
 }
 
 EntityWrapperPtr SolveSpaceSolver_Builder::createFeature(
@@ -294,10 +307,10 @@ EntityWrapperPtr SolveSpaceSolver_Builder::createFeature(
     return createLine(theFeature, theAttributes, theGroupID, theSketchID);
   // Circle
   else if (aFeatureKind == SketchPlugin_Circle::ID())
-    return createCircle(theFeature, theAttributes,theGroupID, theSketchID);
+    return createCircle(theFeature, theAttributes, theGroupID, theSketchID);
   // Arc
   else if (aFeatureKind == SketchPlugin_Arc::ID())
-    return createArc(theFeature, theAttributes,theGroupID, theSketchID);
+    return createArc(theFeature, theAttributes, theGroupID, theSketchID);
   // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
   else if (aFeatureKind == SketchPlugin_Point::ID()) {
     AttributePtr aPoint = theFeature->attribute(SketchPlugin_Point::COORD_ID());
@@ -784,3 +797,24 @@ void makeMirrorPoints(EntityWrapperPtr theOriginal,
     aMirroredPnt->setValue(aCoord[0], aCoord[1]);
   }
 }
+
+void adjustPtLineDistance(ConstraintWrapperPtr theConstraint)
+{
+  BuilderPtr aBuilder = SolveSpaceSolver_Builder::getInstance();
+
+  std::shared_ptr<GeomAPI_Pnt2d> aPoint;
+  std::shared_ptr<GeomAPI_Lin2d> aLine;
+  std::list<EntityWrapperPtr> aSubs = theConstraint->entities();
+  std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
+  for (; aSIt != aSubs.end(); ++aSIt) {
+    if ((*aSIt)->type() == ENTITY_POINT)
+      aPoint = aBuilder->point(*aSIt);
+    else if ((*aSIt)->type() == ENTITY_LINE)
+      aLine = aBuilder->line(*aSIt);
+  }
+
+  std::shared_ptr<GeomAPI_XY> aLineVec = aLine->direction()->xy();
+  std::shared_ptr<GeomAPI_XY> aPtLineVec = aPoint->xy()->decreased(aLine->location()->xy());
+  if (aPtLineVec->cross(aLineVec) * theConstraint->value() < 0.0)
+    theConstraint->setValue(theConstraint->value() * (-1.0));
+}