Salome HOME
Merge branch 'Dev_1.1.0' of newgeom:newgeom into Dev_1.1.0
[modules/shaper.git] / src / SketchSolver / SketchSolver_Constraint.cpp
index f831c170b530197631577a77e3955334bff83615..e4af2a0643970b1518b35cd344566ccaffdce20a 100644 (file)
@@ -1,3 +1,5 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
 // File:    SketchSolver_Constraint.cpp
 // Created: 27 May 2014
 // Author:  Artem ZHIDKOV
 #include <SketchPlugin_Arc.h>
 #include <SketchPlugin_ConstraintCoincidence.h>
 #include <SketchPlugin_ConstraintDistance.h>
+#include <SketchPlugin_ConstraintEqual.h>
+#include <SketchPlugin_ConstraintHorizontal.h>
 #include <SketchPlugin_ConstraintLength.h>
 #include <SketchPlugin_ConstraintParallel.h>
 #include <SketchPlugin_ConstraintPerpendicular.h>
 #include <SketchPlugin_ConstraintRadius.h>
+#include <SketchPlugin_ConstraintRigid.h>
+#include <SketchPlugin_ConstraintTangent.h>
+#include <SketchPlugin_ConstraintVertical.h>
 
 #include <ModelAPI_AttributeRefAttr.h>
 #include <ModelAPI_Data.h>
@@ -30,7 +37,7 @@
 /// Possible types of attributes (used to determine constraint type)
 enum AttrType
 {
-  UNKNOWN, // Something wrong during type determination
+  UNKNOWN,  // Something wrong during type determination
   POINT2D,
   POINT3D,
   LINE,
@@ -39,31 +46,34 @@ enum AttrType
 };
 
 /// Calculate type of the attribute
-static AttrType typeOfAttribute(boost::shared_ptr<ModelAPI_Attribute> theAttribute);
-
-
+static AttrType typeOfAttribute(std::shared_ptr<ModelAPI_Attribute> theAttribute);
 
 SketchSolver_Constraint::SketchSolver_Constraint()
-  : myConstraint(boost::shared_ptr<SketchPlugin_Constraint>()),
-    myType(SLVS_C_UNKNOWN),
-    myAttributesList()
+    : myConstraint(std::shared_ptr<SketchPlugin_Constraint>()),
+      myType(SLVS_C_UNKNOWN),
+      myAttributesList()
 {
 }
 
 SketchSolver_Constraint::SketchSolver_Constraint(
-                boost::shared_ptr<SketchPlugin_Constraint> theConstraint)
-  : myConstraint(theConstraint),
-    myAttributesList()
+    std::shared_ptr<SketchPlugin_Constraint> theConstraint)
+    : myConstraint(theConstraint),
+      myAttributesList()
 {
   myType = getType(myConstraint);
 }
 
-const int& SketchSolver_Constraint::getType(boost::shared_ptr<SketchPlugin_Constraint> theConstraint)
+const int& SketchSolver_Constraint::getType(
+    std::shared_ptr<SketchPlugin_Constraint> theConstraint)
 {
   myType = SLVS_C_UNKNOWN;
   if (!theConstraint)
     return getType();
 
+  DataPtr aConstrData = theConstraint->data();
+  if (!aConstrData || !aConstrData->isValid())
+    return getType();
+
   // Assign empty names of attributes
   myAttributesList.clear();
   for (int i = 0; i < CONSTRAINT_ATTR_SIZE; i++)
@@ -71,29 +81,28 @@ const int& SketchSolver_Constraint::getType(boost::shared_ptr<SketchPlugin_Const
 
   const std::string& aConstraintKind = theConstraint->getKind();
   // Constraint for coincidence of two points
-  if (aConstraintKind.compare(SketchPlugin_ConstraintCoincidence::ID()) == 0)
-  {
+  if (aConstraintKind.compare(SketchPlugin_ConstraintCoincidence::ID()) == 0) {
     int anAttrPos = 0;
     // Verify the constraint has only two attributes and they are points
-    int aPt2d = 0; // bit-mapped field, each bit indicates whether the attribute is 2D point
-    int aPt3d = 0; // bit-mapped field, the same information for 3D points
-    for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
-    {
-      boost::shared_ptr<ModelAPI_Attribute> anAttr =
-        theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
-      switch (typeOfAttribute(anAttr))
-      {
-      case POINT2D: // the attribute is a 2D point
-        aPt2d |= (1 << indAttr);
-        myAttributesList[anAttrPos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
-        break;
-      case POINT3D: // the attribute is a 3D point
-        aPt3d |= (1 << indAttr);
-        myAttributesList[anAttrPos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
-        break;
-      default:
-        // Attribute neither 2D nor 3D point is not supported by this type of constraint
-        return getType();
+    int aPt2d = 0;  // bit-mapped field, each bit indicates whether the attribute is 2D point
+    int aPt3d = 0;  // bit-mapped field, the same information for 3D points
+    for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
+      std::shared_ptr<ModelAPI_Attribute> anAttr = 
+          aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
+      if (!anAttr)
+        continue;
+      switch (typeOfAttribute(anAttr)) {
+        case POINT2D:  // the attribute is a 2D point
+          aPt2d |= (1 << indAttr);
+          myAttributesList[anAttrPos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
+          break;
+        case POINT3D:  // the attribute is a 3D point
+          aPt3d |= (1 << indAttr);
+          myAttributesList[anAttrPos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
+          break;
+        default:
+          // Attribute neither 2D nor 3D point is not supported by this type of constraint
+          return getType();
       }
     }
     // The constrained points should be in first and second positions,
@@ -105,21 +114,18 @@ const int& SketchSolver_Constraint::getType(boost::shared_ptr<SketchPlugin_Const
   }
 
   // Constraint for distance between point and another entity
-  if (aConstraintKind.compare(SketchPlugin_ConstraintDistance::ID()) == 0)
-  {
+  if (aConstraintKind.compare(SketchPlugin_ConstraintDistance::ID()) == 0) {
     int aNbPoints = 0;
     int aNbEntities = 0;
-    for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
-    {
-      boost::shared_ptr<ModelAPI_Attribute> anAttr =
-        theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
-      switch (typeOfAttribute(anAttr))
-      {
-      case POINT2D:
-      case POINT3D:
+    for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
+      std::shared_ptr<ModelAPI_Attribute> anAttr = 
+          aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
+      switch (typeOfAttribute(anAttr)) {
+        case POINT2D:
+        case POINT3D:
           myAttributesList[aNbPoints++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
           break;
-      case LINE:
+        case LINE:
           // entities are placed starting from SketchPlugin_Constraint::ENTITY_C() attribute
           myAttributesList[2 + aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
           myType = SLVS_C_PT_LINE_DISTANCE;
@@ -127,7 +133,7 @@ const int& SketchSolver_Constraint::getType(boost::shared_ptr<SketchPlugin_Const
       }
     }
     // Verify the correctness of constraint arguments
-    if (aNbPoints == 2 && aNbEntities ==0)
+    if (aNbPoints == 2 && aNbEntities == 0)
       myType = SLVS_C_PT_PT_DISTANCE;
     else if (aNbPoints != 1 || aNbEntities != 1)
       myType = SLVS_C_UNKNOWN;
@@ -135,13 +141,11 @@ const int& SketchSolver_Constraint::getType(boost::shared_ptr<SketchPlugin_Const
   }
 
   // Constraint for the given length of a line
-  if (aConstraintKind.compare(SketchPlugin_ConstraintLength::ID()) == 0)
-  {
+  if (aConstraintKind.compare(SketchPlugin_ConstraintLength::ID()) == 0) {
     int aNbLines = 0;
-    for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
-    {
-      boost::shared_ptr<ModelAPI_Attribute> anAttr =
-        theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
+    for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
+      std::shared_ptr<ModelAPI_Attribute> anAttr = 
+          aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
       if (typeOfAttribute(anAttr) == LINE)
         myAttributesList[aNbLines++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
     }
@@ -153,13 +157,11 @@ const int& SketchSolver_Constraint::getType(boost::shared_ptr<SketchPlugin_Const
   // Constraint for two parallel/perpendicular lines
   bool isParallel = (aConstraintKind.compare(SketchPlugin_ConstraintParallel::ID()) == 0);
   bool isPerpendicular = (aConstraintKind.compare(SketchPlugin_ConstraintPerpendicular::ID()) == 0);
-  if (isParallel || isPerpendicular)
-  {
-    int aNbEntities = 2; // lines in SolveSpace constraints should start from SketchPlugin_Constraint::ENTITY_C() attribute
-    for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
-    {
-      boost::shared_ptr<ModelAPI_Attribute> anAttr =
-        theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
+  if (isParallel || isPerpendicular) {
+    int aNbEntities = 2;  // lines in SolveSpace constraints should start from SketchPlugin_Constraint::ENTITY_C() attribute
+    for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
+      std::shared_ptr<ModelAPI_Attribute> anAttr = 
+          aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
       if (typeOfAttribute(anAttr) == LINE)
         myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
     }
@@ -169,13 +171,11 @@ const int& SketchSolver_Constraint::getType(boost::shared_ptr<SketchPlugin_Const
   }
 
   // Constraint for radius of a circle or an arc of circle
-  if (aConstraintKind.compare(SketchPlugin_ConstraintRadius::ID()) == 0)
-  {
-    int aNbEntities = 2; // lines in SolveSpace constraints should started from SketchPlugin_Constraint::ENTITY_C() attribute
-    for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
-    {
-      boost::shared_ptr<ModelAPI_Attribute> anAttr =
-        theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
+  if (aConstraintKind.compare(SketchPlugin_ConstraintRadius::ID()) == 0) {
+    int aNbEntities = 2;  // lines in SolveSpace constraints should started from SketchPlugin_Constraint::ENTITY_C() attribute
+    for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
+      std::shared_ptr<ModelAPI_Attribute> anAttr = 
+          aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
       AttrType aType = typeOfAttribute(anAttr);
       if (aType == CIRCLE || aType == ARC)
         myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
@@ -185,31 +185,107 @@ const int& SketchSolver_Constraint::getType(boost::shared_ptr<SketchPlugin_Const
     return getType();
   }
 
+  // Constraint for fixed entity
+  if (aConstraintKind.compare(SketchPlugin_ConstraintRigid::ID()) == 0) {
+    // Verify that only one entity is filled
+    int aNbAttrs = 0;
+    for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
+      std::shared_ptr<ModelAPI_Attribute> anAttr = 
+          aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
+      AttrType aType = typeOfAttribute(anAttr);
+      if (aType != UNKNOWN)
+        myAttributesList[aNbAttrs++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
+    }
+    if (aNbAttrs == 1)
+      myType = SLVS_C_WHERE_DRAGGED;
+    return getType();
+  }
+
+  // Constraint for horizontal/vertical line
+  bool isHorizontal = (aConstraintKind.compare(SketchPlugin_ConstraintHorizontal::ID()) == 0);
+  bool isVertical = (aConstraintKind.compare(SketchPlugin_ConstraintVertical::ID()) == 0);
+  if (isHorizontal || isVertical) {
+    int aNbEntities = 2;  // lines in SolveSpace constraints should start from SketchPlugin_Constraint::ENTITY_C() attribute
+    for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
+      std::shared_ptr<ModelAPI_Attribute> anAttr = 
+          aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
+      if (typeOfAttribute(anAttr) == LINE)
+        myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
+    }
+    if (aNbEntities == 3)
+      myType = isHorizontal ? SLVS_C_HORIZONTAL : SLVS_C_VERTICAL;
+    return getType();
+  }
+
+  if (aConstraintKind.compare(SketchPlugin_ConstraintEqual::ID()) == 0)
+  {
+    static const int aConstrType[3] = {
+        SLVS_C_EQUAL_RADIUS,
+        SLVS_C_EQUAL_LINE_ARC_LEN,
+        SLVS_C_EQUAL_LENGTH_LINES
+    };
+    int aNbLines = 0;
+    int aNbEntities = 2;  // lines and circles in SolveSpace constraints should start from SketchPlugin_Constraint::ENTITY_C() attribute
+    for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
+      std::shared_ptr<ModelAPI_Attribute> anAttr = 
+          aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
+      AttrType aType = typeOfAttribute(anAttr);
+      if (aType == LINE) {
+        myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
+        aNbLines++;
+      }
+      else if (aType == CIRCLE || aType == ARC)
+        myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
+    }
+    if (aNbEntities == 4)
+      myType = aConstrType[aNbLines];
+    return getType();
+  }
+
+  if (aConstraintKind.compare(SketchPlugin_ConstraintTangent::ID()) == 0)
+  {
+    static const int anArcPosDefault = 2;
+    static const int aLinePosDefault = 3;
+    int anArcPos = anArcPosDefault; // arc in tangency constraint should be placed before line
+    int aLinePos = aLinePosDefault;
+    for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
+      std::shared_ptr<ModelAPI_Attribute> anAttr = 
+          aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
+      AttrType aType = typeOfAttribute(anAttr);
+      if (aType == LINE && aLinePos < CONSTRAINT_ATTR_SIZE)
+        myAttributesList[aLinePos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
+      else if (aType == ARC)
+        myAttributesList[anArcPos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
+    }
+    if (anArcPos - anArcPosDefault + aLinePos - aLinePosDefault == 2)
+      myType = aLinePos > 3 ? SLVS_C_ARC_LINE_TANGENT : SLVS_C_CURVE_CURVE_TANGENT;
+    return getType();
+  }
+
   /// \todo Implement other kind of constraints
 
   return getType();
 }
 
-
 // ================= Auxiliary functions ==============================
-AttrType typeOfAttribute(boost::shared_ptr<ModelAPI_Attribute> theAttribute)
+AttrType typeOfAttribute(std::shared_ptr<ModelAPI_Attribute> theAttribute)
 {
-  boost::shared_ptr<ModelAPI_AttributeRefAttr> anAttrRef =
-    boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
-  if (!anAttrRef) return UNKNOWN;
+  std::shared_ptr<ModelAPI_AttributeRefAttr> anAttrRef = std::dynamic_pointer_cast<
+      ModelAPI_AttributeRefAttr>(theAttribute);
+  if (!anAttrRef)
+    return UNKNOWN;
 
-  if (anAttrRef->isObject())
-  {
-    ResultConstructionPtr aRC = 
-      boost::dynamic_pointer_cast<ModelAPI_ResultConstruction>(anAttrRef->object());
-    if (!aRC) return UNKNOWN;
+  if (anAttrRef->isObject()) {
+    ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
+        anAttrRef->object());
+    if (!aRC || !aRC->shape())
+      return UNKNOWN;
 
     if (aRC->shape()->isVertex())
       return POINT3D;
-    else if (aRC->shape()->isEdge())
-    {
-      boost::shared_ptr<GeomAPI_Edge> anEdge = 
-        boost::dynamic_pointer_cast<GeomAPI_Edge>(aRC->shape());
+    else if (aRC->shape()->isEdge()) {
+      std::shared_ptr<GeomAPI_Edge> anEdge = std::dynamic_pointer_cast<GeomAPI_Edge>(
+          aRC->shape());
       if (anEdge->isLine())
         return LINE;
       else if (anEdge->isCircle())
@@ -217,14 +293,14 @@ AttrType typeOfAttribute(boost::shared_ptr<ModelAPI_Attribute> theAttribute)
       else if (anEdge->isArc())
         return ARC;
     }
-  }
-  else
-  {
-    const std::string aType = anAttrRef->attr()->attributeType();
-    if (aType == GeomDataAPI_Point2D::type())
-      return POINT2D;
-    if (aType == GeomDataAPI_Point2D::type())
-      return POINT2D;
+  } else {
+    if (anAttrRef->attr().get() != NULL) {
+      const std::string aType = anAttrRef->attr()->attributeType();
+      if (aType == GeomDataAPI_Point2D::type())
+        return POINT2D;
+      if (aType == GeomDataAPI_Point2D::type())
+        return POINT2D;
+    }
   }
 
   return UNKNOWN;