Salome HOME
rectangle feature: complete rectangle type by center and end points
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_Rectangle.cpp
index 3933f997c9d5d2a841dbaa55e3a64ea464ccfe7a..0518bdd33a224a48b6c859b0c34534eeb476bedb 100644 (file)
 
 #include "SketchPlugin_Rectangle.h"
 #include "SketchPlugin_Sketch.h"
-#include <ModelAPI_Data.h>
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_AttributeSelection.h>
 #include <ModelAPI_Validator.h>
-#include <ModelAPI_Session.h>
 #include <ModelAPI_AttributeRefList.h>
 #include <ModelAPI_AttributeRefAttr.h>
 #include <GeomDataAPI_Point2D.h>
 #include <GeomAlgoAPI_CompoundBuilder.h>
 
 #include <SketchPlugin_Line.h>
+#include <SketchPlugin_Point.h>
+#include <SketchPlugin_Tools.h>
 #include <SketchPlugin_ConstraintCoincidence.h>
 #include <SketchPlugin_ConstraintHorizontal.h>
 #include <SketchPlugin_ConstraintVertical.h>
+#include <SketchPlugin_ConstraintCoincidenceInternal.h>
 
 #include <cmath>
 
+
 const double tolerance = 1e-7;
 
 
@@ -44,24 +46,35 @@ SketchPlugin_Rectangle::SketchPlugin_Rectangle()
 {
 }
 
+
 void SketchPlugin_Rectangle::initDerivedClassAttributes()
 {
+  data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId());
   data()->addAttribute(START_ID(), GeomDataAPI_Point2D::typeId());
   data()->addAttribute(END_ID(), GeomDataAPI_Point2D::typeId());
-  data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId());
-  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID());
+  data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_ID());
+  data()->addAttribute(CENTER_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_REF_ID());
   data()->addAttribute(LINES_LIST_ID(), ModelAPI_AttributeRefList::typeId());
   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), LINES_LIST_ID());
+  data()->addAttribute(DIAGONAL_LIST_ID(), ModelAPI_AttributeRefList::typeId());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), DIAGONAL_LIST_ID());
   data()->addAttribute(ISHV_LIST_ID(), ModelAPI_AttributeIntArray::typeId());
-
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), ISHV_LIST_ID());
   data()->addAttribute(NOT_TO_DUMP_LIST_ID(), ModelAPI_AttributeRefList::typeId());
   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), NOT_TO_DUMP_LIST_ID());
+}
 
-  AttributeIntArrayPtr isHVList = intArray(ISHV_LIST_ID());
-  isHVList->setSize(4, false);
-  for(int i = 0; i< 4;)
-    isHVList->setValue(i++, 0, false);
- }
+namespace {
+  static const std::pair<unsigned, std::string> cornerToDiagonalLinePoints[4]
+  = {
+    {0, SketchPlugin_Line::START_ID()},
+    {1, SketchPlugin_Line::START_ID()},
+    {0, SketchPlugin_Line::END_ID()},
+    {1, SketchPlugin_Line::END_ID()}
+  };
+}
 
 void SketchPlugin_Rectangle::updateLines()
 {
@@ -73,14 +86,17 @@ void SketchPlugin_Rectangle::updateLines()
   std::shared_ptr<GeomDataAPI_Point2D> aEndPoint =
       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(END_ID()));
 
-  double xMin = std::min(aStartPoint->x(),  aEndPoint->x());
-  double xMax = std::max(aStartPoint->x(),  aEndPoint->x());
-  double yMin = std::min(aStartPoint->y(),  aEndPoint->y());
-  double yMax = std::max(aStartPoint->y(),  aEndPoint->y());
-  std::vector<double> aX = {xMin, xMax, xMax, xMin};
-  std::vector<double> aY = {yMin, yMin, yMax, yMax};
+  double aXStart = aStartPoint->x();
+  double aYStart = aStartPoint->y();
+  double aXEnd = aEndPoint->x();
+  double aYEnd = aEndPoint->y();
+
+  std::vector<double> aX = {aXStart, aXStart, aXEnd, aXEnd};
+  std::vector<double> aY = {aYStart, aYEnd, aYEnd, aYStart};
 
   bool anAuxiliary = data()->boolean(AUXILIARY_ID())->value();
+  AttributeRefListPtr aDiagonalList =  reflist(DIAGONAL_LIST_ID());
+
 
   /// Update coordinates of rectangle lines
   for(unsigned  i = 0; i < aNbLines; i++)
@@ -90,9 +106,37 @@ void SketchPlugin_Rectangle::updateLines()
         std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aLine->attribute(SketchPlugin_Line::START_ID()));
     std::shared_ptr<GeomDataAPI_Point2D> aLineEnd =
         std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aLine->attribute(SketchPlugin_Line::END_ID()));
-       aLineStart->setValue(aX[i], aY[i]);
-    aLineEnd->setValue(aX[(i+1)%4], aY[(i+1)%4]);
+    aLineStart->setValue(aX[(i+3)%4], aY[(i+3)%4]);
+    aLineEnd->setValue(aX[i], aY[i]);
     aLine->data()->boolean(AUXILIARY_ID())->setValue(anAuxiliary);
+    /// Cooordinates of diagonals
+    if(aDiagonalList->size())
+    {
+      auto aDiagonalPoint = cornerToDiagonalLinePoints[i];
+      FeaturePtr aDiagonal = std::dynamic_pointer_cast<ModelAPI_Feature>(aDiagonalList->object(aDiagonalPoint.first));
+      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aDiagonal->attribute(aDiagonalPoint.second))->setValue(aX[(i+3)%4], aY[(i+3)%4]);
+    }
+  }
+}
+
+void SketchPlugin_Rectangle::updateStartPoint()
+{
+  /// Retrieving list of already created lines
+  AttributeRefListPtr aLinesList = reflist(LINES_LIST_ID());
+  unsigned  aNbLines = aLinesList->size();
+  std::shared_ptr<GeomDataAPI_Point2D> aStartPoint =
+      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(START_ID()));
+
+  double aXStart = aStartPoint->x();
+  double aYStart = aStartPoint->y();
+
+  /// Update coordinates of rectangle lines
+  for(unsigned  i = 0; i < aNbLines; i++)
+  {
+    FeaturePtr aLine = std::dynamic_pointer_cast<ModelAPI_Feature>(aLinesList->object(i));
+    std::shared_ptr<GeomDataAPI_Point2D> aLineStart =
+        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aLine->attribute(SketchPlugin_Line::END_ID()));
+    aLineStart->setValue(aXStart, aYStart);
   }
 }
 
@@ -118,6 +162,7 @@ void SketchPlugin_Rectangle::execute()
   unsigned aNbLines = aLinesList->size();
   AttributeIntArrayPtr isHVList = intArray(ISHV_LIST_ID());
   AttributeRefListPtr aNotToDumpList = reflist(NOT_TO_DUMP_LIST_ID());
+  AttributeRefListPtr aDiagonalList =  reflist(DIAGONAL_LIST_ID());
 
   if(aNbLines == 1)
   {
@@ -128,8 +173,35 @@ void SketchPlugin_Rectangle::execute()
       aLinesList->append(aLine);
       aNotToDumpList->append(aLine);
     }
+
     updateLines();
+
     aNbLines = aLinesList->size();
+    FeaturePtr aCenterPointFeature;
+
+    if(aDiagonalList->size())
+    {
+      /// compute diagonals intersection point
+      std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
+          std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
+
+      aCenterPointFeature = aSketch->addFeature(SketchPlugin_Point::ID());
+      aNotToDumpList->append(aCenterPointFeature);
+      AttributePoint2DPtr aCoord = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+            aCenterPointFeature->attribute(SketchPlugin_Point::COORD_ID()));
+      aCoord->setValue(aCenterAttr->x(), aCenterAttr->y());
+      aCenterPointFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
+      refattr(CENTER_REF_ID())->setObject(aCenterPointFeature);
+
+      for(int i = 0; i < 2; i++)
+      {
+        FeaturePtr aDiagonal = std::dynamic_pointer_cast<ModelAPI_Feature>(aDiagonalList->object(i));
+        FeaturePtr aConstraint = SketchPlugin_Tools::createConstraintAttrObject(aSketch, SketchPlugin_ConstraintCoincidenceInternal::ID(),
+                                                                                aCoord, aDiagonal);
+        aNotToDumpList->append(aConstraint);
+      }
+    }
+
     /// Create constraints to keep the rectangle
     for( unsigned i = 0; i < aNbLines; i++)
     {
@@ -137,19 +209,34 @@ void SketchPlugin_Rectangle::execute()
       /// connect neighbor lines by coincidence
       unsigned iPrev = (i+3)%4;
       FeaturePtr aPrevLine = std::dynamic_pointer_cast<ModelAPI_Feature>(aLinesList->object(iPrev));
-      FeaturePtr aCoincidence = aSketch->addFeature(SketchPlugin_ConstraintCoincidence::ID());
-      aNotToDumpList->append(aCoincidence);
-      AttributeRefAttrPtr aRefAttrA = aCoincidence->refattr(SketchPlugin_ConstraintCoincidence::ENTITY_A());
-      AttributeRefAttrPtr aRefAttrB = aCoincidence->refattr(SketchPlugin_ConstraintCoincidence::ENTITY_B());
-      aRefAttrA->setAttr(aPrevLine->attribute(SketchPlugin_Line::END_ID()));
-      aRefAttrB->setAttr(aLine->attribute(SketchPlugin_Line::START_ID()));
+      FeaturePtr aConstraint = SketchPlugin_Tools::createConstraintAttrAttr(aSketch, SketchPlugin_ConstraintCoincidence::ID(),
+                                                                            aPrevLine->attribute(SketchPlugin_Line::END_ID()),
+                                                                            aLine->attribute(SketchPlugin_Line::START_ID()));
+      aNotToDumpList->append(aConstraint);
+
+      /// case of  rectangle created from its center
+      if(aDiagonalList->size())
+      {
+        auto aDiagonalPoint = cornerToDiagonalLinePoints[i];
+        FeaturePtr aDiagonal = std::dynamic_pointer_cast<ModelAPI_Feature>(aDiagonalList->object(aDiagonalPoint.first));
+        FeaturePtr aConstraint = SketchPlugin_Tools::createConstraintAttrAttr(aSketch, SketchPlugin_ConstraintCoincidenceInternal::ID(),
+                                                                              aDiagonal->attribute(aDiagonalPoint.second),
+                                                                              aLine->attribute(SketchPlugin_Line::START_ID()));
+        aNotToDumpList->append(aConstraint);
+      }
     }
-
     /// Update coordinates of created lines
     updateLines();
   }
 
   /// Add horizontal and vertical constraint for the lines which already have result
+  if(isHVList->size() == 0)
+  {
+    isHVList->setSize(4, false);
+    for(int i = 0; i< 4;)
+      isHVList->setValue(i++, 0, false);
+  }
+
   for(unsigned i = 0; i< aNbLines; i++)
   {
     if(isHVList->value(i))
@@ -163,7 +250,7 @@ void SketchPlugin_Rectangle::execute()
       aHVName = SketchPlugin_ConstraintVertical::ID();
     FeaturePtr aHVConstraint = aSketch->addFeature(aHVName);
     aNotToDumpList->append(aHVConstraint);
-    AttributeRefAttrPtr aRefAttrA = aHVConstraint->refattr(SketchPlugin_ConstraintCoincidence::ENTITY_A());
+    AttributeRefAttrPtr aRefAttrA = aHVConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
     aRefAttrA->setObject(aLine->lastResult());
     isHVList->setValue(i, 1, false);
   }
@@ -175,8 +262,7 @@ void SketchPlugin_Rectangle::execute()
     return;
   }
 
-  // store results.
-
+  /// store results.
   GeomShapePtr aRectangleShape;
   ListOfShape aSubs;
 
@@ -189,25 +275,36 @@ void SketchPlugin_Rectangle::execute()
     aSubs.push_back(aLineResult->shape());
   }
 
-  aRectangleShape = aSubs.empty() ? GeomShapePtr() : GeomAlgoAPI_CompoundBuilder::compound(aSubs);
+  for(int i = 0; i< aDiagonalList->size(); i++)
+  {
+    FeaturePtr aDiagonal = std::dynamic_pointer_cast<ModelAPI_Feature>(aDiagonalList->object(i));
+    ResultPtr aDiagonalResult = aDiagonal->lastResult();
+    if(!aDiagonalResult.get())
+      continue;
+    aSubs.push_back(aDiagonalResult->shape());
+  }
 
+  FeaturePtr aCenterPointFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(refattr(CENTER_REF_ID())->object());
+  if(aCenterPointFeature)
+  {
+    ResultPtr aCenterResult = aCenterPointFeature->lastResult();
+    if(aCenterResult.get())
+      aSubs.push_back(aCenterResult->shape());
+  }
+
+  aRectangleShape = aSubs.empty() ? GeomShapePtr() : GeomAlgoAPI_CompoundBuilder::compound(aSubs);
   std::shared_ptr<ModelAPI_ResultConstruction> aResult = document()->createConstruction(data(), 0);
   aResult->setShape(aRectangleShape);
   aResult->setIsInHistory(false);
   setResult(aResult, 1);
 }
 
-
-bool SketchPlugin_Rectangle::isFixed() {
-  return data()->selection(EXTERNAL_ID())->context().get() != NULL;
-}
-
 void SketchPlugin_Rectangle::attributeChanged(const std::string& theID)
 {
   if (theID == START_ID() || theID == END_ID())
   {
     AttributeRefListPtr aLinesList = reflist(LINES_LIST_ID());
-    AttributeRefListPtr aNotToDumpList =  reflist(NOT_TO_DUMP_LIST_ID());
+    AttributeRefListPtr aNotToDumpList = reflist(NOT_TO_DUMP_LIST_ID());
     unsigned  aNbLines = aLinesList->size();
     if(aNbLines == 0)
     {
@@ -219,16 +316,33 @@ void SketchPlugin_Rectangle::attributeChanged(const std::string& theID)
       FeaturePtr aLine = aSketch->addFeature(SketchPlugin_Line::ID());
       aLinesList->append(aLine);
       aNotToDumpList->append(aLine);
-    }
 
+      /// if rectangle has center, add 2 iagonals
+      std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
+          std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
+      if(aCenterAttr->isInitialized())
+      {
+        AttributeRefListPtr aDiagonalList = reflist(DIAGONAL_LIST_ID());
+        for(int i = 0; i < 2; i++)
+        {
+          FeaturePtr aDiagonalLine = aSketch->addFeature(SketchPlugin_Line::ID());
+          aDiagonalLine->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
+          aDiagonalList->append(aDiagonalLine);
+          aNotToDumpList->append(aDiagonalLine);
+        }
+      }
+    }
     std::shared_ptr<GeomDataAPI_Point2D> aStartPoint =
         std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(START_ID()));
     std::shared_ptr<GeomDataAPI_Point2D> aEndPoint =
         std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(END_ID()));
 
     if (aStartPoint->isInitialized() && aEndPoint->isInitialized())
-      updateLines();    
+      updateLines();
+    else
+      updateStartPoint();
   }
+
   if (theID == AUXILIARY_ID())
   {
     bool anAuxiliary = data()->boolean(AUXILIARY_ID())->value();