Salome HOME
Refresh menu size after chnges in preferences
[modules/shaper.git] / src / SketchSolver / SketchSolver_Constraint.cpp
index 83bc31671beaec0e09b32b932946e4774d546d8f..e44e1390b8b17e078077cd03cf0297fc827c3d23 100644 (file)
@@ -5,11 +5,42 @@
 #include "SketchSolver_Constraint.h"
 #include <SketchSolver_Solver.h>
 
+#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Point.h>
+#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_ConstraintCoincidence.h>
+#include <SketchPlugin_ConstraintDistance.h>
+#include <SketchPlugin_ConstraintLength.h>
+#include <SketchPlugin_ConstraintParallel.h>
+#include <SketchPlugin_ConstraintPerpendicular.h>
+#include <SketchPlugin_ConstraintRadius.h>
+
 #include <ModelAPI_AttributeRefAttr.h>
 #include <ModelAPI_Data.h>
+#include <ModelAPI_Document.h>
+#include <ModelAPI_Object.h>
+#include <ModelAPI_ResultConstruction.h>
 
 #include <GeomDataAPI_Point.h>
 #include <GeomDataAPI_Point2D.h>
+#include <GeomAPI_Edge.h>
+#include <GeomAPI_Shape.h>
+
+/// Possible types of attributes (used to determine constraint type)
+enum AttrType
+{
+  UNKNOWN, // Something wrong during type determination
+  POINT2D,
+  POINT3D,
+  LINE,
+  CIRCLE,
+  ARC
+};
+
+/// Calculate type of the attribute
+static AttrType typeOfAttribute(boost::shared_ptr<ModelAPI_Attribute> theAttribute);
+
 
 
 SketchSolver_Constraint::SketchSolver_Constraint()
@@ -40,7 +71,7 @@ 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("SketchConstraintCoincidence") == 0)
+  if (aConstraintKind.compare(SketchPlugin_ConstraintCoincidence::ID()) == 0)
   {
     int anAttrPos = 0;
     // Verify the constraint has only two attributes and they are points
@@ -48,31 +79,23 @@ const int& SketchSolver_Constraint::getType(boost::shared_ptr<SketchPlugin_Const
     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_AttributeRefAttr> anAttr =
-        boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-          theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr])
-        );
+      boost::shared_ptr<ModelAPI_Attribute> anAttr =
+        theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
       if (!anAttr) continue;
-      // Verify the attribute is a 2D point
-      boost::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
-        boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
-      if (aPoint2D)
+      switch (typeOfAttribute(anAttr))
       {
+      case POINT2D: // the attribute is a 2D point
         aPt2d |= (1 << indAttr);
-        myAttributesList[anAttrPos++] = CONSTRAINT_ATTRIBUTES[indAttr];
-        continue;
-      }
-      // Verify the attribute is a 3D point
-      boost::shared_ptr<GeomDataAPI_Point> aPoint3D =
-        boost::dynamic_pointer_cast<GeomDataAPI_Point>(anAttr->attr());
-      if (aPoint3D)
-      {
+        myAttributesList[anAttrPos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
+        break;
+      case POINT3D: // the attribute is a 3D point
         aPt3d |= (1 << indAttr);
-        myAttributesList[anAttrPos++] = CONSTRAINT_ATTRIBUTES[indAttr];
-        continue;
+        myAttributesList[anAttrPos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
+        break;
+      default:
+        // Attribute neither 2D nor 3D point is not supported by this type of constraint
+        return getType();
       }
-      // 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,
     // so the expected value of aPt2d or aPt3d is 3
@@ -83,78 +106,45 @@ const int& SketchSolver_Constraint::getType(boost::shared_ptr<SketchPlugin_Const
   }
 
   // Constraint for distance between point and another entity
-  if (aConstraintKind.compare("SketchConstraintDistance") == 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_AttributeRefAttr> anAttr =
-        boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-          theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr])
-        );
-      if (!anAttr) continue;
-      if (anAttr->isFeature() && anAttr->feature())
-      { // verify posiible entities
-        const std::string& aKind = anAttr->feature()->getKind();
-        if (aKind.compare("SketchPoint") == 0)
-        {
-          myAttributesList[aNbPoints++] = CONSTRAINT_ATTRIBUTES[indAttr];
-          continue;
-        }
-        else if(aKind.compare("SketchLine") == 0)
-        {
-          // entities are placed starting from CONSTRAINT_ATTR_ENTITY_C attribute
-          myAttributesList[2 + aNbEntities++] = CONSTRAINT_ATTRIBUTES[indAttr];
+      boost::shared_ptr<ModelAPI_Attribute> anAttr =
+        theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
+      switch (typeOfAttribute(anAttr))
+      {
+      case POINT2D:
+      case POINT3D:
+          myAttributesList[aNbPoints++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
+          break;
+      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;
-          continue;
-        }
-      }
-      else
-      { // verify points
-        // Verify the attribute is a 2D point
-        boost::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
-          boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
-        if (aPoint2D)
-        {
-          myAttributesList[aNbPoints++] = CONSTRAINT_ATTRIBUTES[indAttr];
-          continue;
-        }
-        // Verify the attribute is a 3D point
-        boost::shared_ptr<GeomDataAPI_Point> aPoint3D =
-          boost::dynamic_pointer_cast<GeomDataAPI_Point>(anAttr->attr());
-        if (aPoint3D)
-        {
-          myAttributesList[aNbPoints++] = CONSTRAINT_ATTRIBUTES[indAttr];
-          continue;
-        }
+          break;
       }
     }
     // Verify the correctness of constraint arguments
     if (aNbPoints == 2 && aNbEntities ==0)
       myType = SLVS_C_PT_PT_DISTANCE;
-    else if (aNbPoints == 1 && aNbEntities == 1)
+    else if (aNbPoints != 1 || aNbEntities != 1)
       myType = SLVS_C_UNKNOWN;
     return getType();
   }
 
   // Constraint for the given length of a line
-  if (aConstraintKind.compare("SketchConstraintLength") == 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_AttributeRefAttr> anAttr =
-        boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-          theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr])
-        );
-      if (!anAttr) continue;
-      if (anAttr->isFeature() && anAttr->feature() &&
-          anAttr->feature()->getKind().compare("SketchLine") == 0)
-      {
-        myAttributesList[aNbLines++] = CONSTRAINT_ATTRIBUTES[indAttr];
-        break;
-      }
+      boost::shared_ptr<ModelAPI_Attribute> anAttr =
+        theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
+      if (typeOfAttribute(anAttr) == LINE)
+        myAttributesList[aNbLines++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
     }
     if (aNbLines == 1)
       myType = SLVS_C_PT_PT_DISTANCE;
@@ -162,24 +152,17 @@ const int& SketchSolver_Constraint::getType(boost::shared_ptr<SketchPlugin_Const
   }
 
   // Constraint for two parallel/perpendicular lines
-  bool isParallel = (aConstraintKind.compare("SketchConstraintParallel") == 0);
-  bool isPerpendicular = (aConstraintKind.compare("SketchConstraintPerpendicular") == 0);
+  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 started from CONSTRAINT_ATTR_ENTITY_C attribute
+    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_AttributeRefAttr> anAttr =
-        boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-          theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr])
-        );
-      if (!anAttr || !anAttr->isFeature()) continue;
-      const std::string& aKind = anAttr->feature()->getKind();
-      if (aKind.compare("SketchLine") == 0)
-      {
-        myAttributesList[aNbEntities++] = CONSTRAINT_ATTRIBUTES[indAttr];
-        continue;
-      }
+      boost::shared_ptr<ModelAPI_Attribute> anAttr =
+        theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
+      if (typeOfAttribute(anAttr) == LINE)
+        myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
     }
     if (aNbEntities == 4)
       myType = isParallel ? SLVS_C_PARALLEL : SLVS_C_PERPENDICULAR;
@@ -187,29 +170,64 @@ const int& SketchSolver_Constraint::getType(boost::shared_ptr<SketchPlugin_Const
   }
 
   // Constraint for radius of a circle or an arc of circle
-  if (aConstraintKind.compare("SketchConstraintRadius") == 0)
+  if (aConstraintKind.compare(SketchPlugin_ConstraintRadius::ID()) == 0)
   {
-    int aNbEntities = 2; // lines in SolveSpace constraints should started from CONSTRAINT_ATTR_ENTITY_C attribute
+    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_AttributeRefAttr> anAttr =
-        boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-          theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr])
-        );
-      if (!anAttr || !anAttr->isFeature()) continue;
-      const std::string& aKind = anAttr->feature()->getKind();
-      if (aKind.compare("SketchCircle") == 0 || aKind.compare("SketchArc") == 0)
-      {
-        myAttributesList[aNbEntities++] = CONSTRAINT_ATTRIBUTES[indAttr];
-        continue;
-      }
+      boost::shared_ptr<ModelAPI_Attribute> anAttr =
+        theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
+      AttrType aType = typeOfAttribute(anAttr);
+      if (aType == CIRCLE || aType == ARC)
+        myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
     }
     if (aNbEntities == 3)
       myType = SLVS_C_DIAMETER;
     return getType();
   }
 
-  /// \todo Implement other kind of constrtaints
+  /// \todo Implement other kind of constraints
 
   return getType();
 }
+
+
+// ================= Auxiliary functions ==============================
+AttrType typeOfAttribute(boost::shared_ptr<ModelAPI_Attribute> theAttribute)
+{
+  boost::shared_ptr<ModelAPI_AttributeRefAttr> anAttrRef =
+    boost::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 (aRC->shape()->isVertex())
+      return POINT3D;
+    else if (aRC->shape()->isEdge())
+    {
+      boost::shared_ptr<GeomAPI_Edge> anEdge = 
+        boost::dynamic_pointer_cast<GeomAPI_Edge>(aRC->shape());
+      if (anEdge->isLine())
+        return LINE;
+      else if (anEdge->isCircle())
+        return CIRCLE;
+      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;
+  }
+
+  return UNKNOWN;
+}
+