Salome HOME
Fix pipe to avoid moving of the path, if it is passed through the first face.
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_Validators.cpp
index 714ec64e781f6e130ac9066be7ee8d1fc5753903..68817c53b83ed521bb5557044cbe81fb5b544d4d 100755 (executable)
@@ -30,6 +30,7 @@
 #include "SketchPlugin_Line.h"
 #include "SketchPlugin_MacroArc.h"
 #include "SketchPlugin_MacroCircle.h"
+#include "SketchPlugin_MultiRotation.h"
 #include "SketchPlugin_Point.h"
 #include "SketchPlugin_Sketch.h"
 #include "SketchPlugin_Trim.h"
@@ -42,8 +43,8 @@
 #include <ModelAPI_Data.h>
 #include <ModelAPI_Validator.h>
 #include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
 #include <ModelAPI_AttributeRefAttr.h>
-
 #include <ModelAPI_AttributeRefAttrList.h>
 #include <ModelAPI_AttributeRefList.h>
 #include <ModelAPI_AttributeSelectionList.h>
@@ -467,6 +468,8 @@ static bool hasSameTangentFeature(const std::set<AttributePtr>& theRefsList,
       anIt = theRefsList.cbegin(); anIt != theRefsList.cend(); ++anIt) {
     std::shared_ptr<ModelAPI_Attribute> aAttr = (*anIt);
     FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
+    if (!aFeature)
+      continue;
     if (aFeature->getKind() == SketchPlugin_ConstraintTangent::ID()) {
       AttributeRefAttrPtr anAttrRefA = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
         aFeature->attribute(SketchPlugin_ConstraintTangent::ENTITY_A()));
@@ -577,18 +580,20 @@ bool SketchPlugin_FilletVertexValidator::isValid(const AttributePtr& theAttribut
   std::set<FeaturePtr> aCoinsides;
   SketchPlugin_Tools::findCoincidences(aConstraintCoincidence,
                                         SketchPlugin_ConstraintCoincidence::ENTITY_A(),
-                                        aCoinsides);
+                                        aCoinsides,
+                                        true);
   SketchPlugin_Tools::findCoincidences(aConstraintCoincidence,
                                         SketchPlugin_ConstraintCoincidence::ENTITY_B(),
-                                        aCoinsides);
+                                        aCoinsides,
+                                        true);
 
-  // Remove points from set of coincides.
+  // Remove points and external lines from set of coincides.
   std::set<FeaturePtr> aNewSetOfCoincides;
   for(std::set<FeaturePtr>::iterator anIt = aCoinsides.begin();
       anIt != aCoinsides.end(); ++anIt) {
     std::shared_ptr<SketchPlugin_SketchEntity> aSketchEntity =
       std::dynamic_pointer_cast<SketchPlugin_SketchEntity>(*anIt);
-    if(aSketchEntity.get() && aSketchEntity->isCopy()) {
+    if(aSketchEntity.get() && (aSketchEntity->isCopy() || aSketchEntity->isExternal())) {
       continue;
     }
     if((*anIt)->getKind() != SketchPlugin_Line::ID() &&
@@ -798,27 +803,25 @@ bool SketchPlugin_IntersectionValidator::isValid(const AttributePtr& theAttribut
     theError.arg(theAttribute->attributeType());
     return false;
   }
-  AttributeSelectionPtr aLineAttr =
-                       std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
+  AttributeSelectionPtr anExternalAttr =
+      std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
   std::shared_ptr<GeomAPI_Edge> anEdge;
-  if(aLineAttr && aLineAttr->value() && aLineAttr->value()->isEdge()) {
-    anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aLineAttr->value()));
-  } else if(aLineAttr->context() &&
-            aLineAttr->context()->shape() && aLineAttr->context()->shape()->isEdge()) {
-    anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aLineAttr->context()->shape()));
+  if (anExternalAttr && anExternalAttr->value() && anExternalAttr->value()->isEdge()) {
+    anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anExternalAttr->value()));
+  } else if(anExternalAttr->context() && anExternalAttr->context()->shape() &&
+            anExternalAttr->context()->shape()->isEdge()) {
+    anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anExternalAttr->context()->shape()));
   }
 
-  if (!anEdge || !anEdge->isLine()) {
-    theError = "The attribute %1 should be a line";
+  if (!anEdge) {
+    theError = "The attribute %1 should be an edge";
     theError.arg(theAttribute->id());
     return false;
   }
 
-  std::shared_ptr<GeomAPI_Dir> aLineDir = anEdge->line()->direction();
-
   // find a sketch
   std::shared_ptr<SketchPlugin_Sketch> aSketch;
-  std::set<AttributePtr> aRefs = aLineAttr->owner()->data()->refsToMe();
+  std::set<AttributePtr> aRefs = anExternalAttr->owner()->data()->refsToMe();
   std::set<AttributePtr>::const_iterator anIt = aRefs.begin();
   for (; anIt != aRefs.end(); ++anIt) {
     CompositeFeaturePtr aComp =
@@ -833,9 +836,16 @@ bool SketchPlugin_IntersectionValidator::isValid(const AttributePtr& theAttribut
     return false;
   }
 
+  // check the edge is intersected with sketch plane
   std::shared_ptr<GeomAPI_Pln> aPlane = aSketch->plane();
-  std::shared_ptr<GeomAPI_Dir> aNormal = aPlane->direction();
-  return fabs(aNormal->dot(aLineDir)) > tolerance * tolerance;
+
+  std::list<GeomPointPtr> anIntersectionsPoints;
+  anEdge->intersectWithPlane(aPlane, anIntersectionsPoints);
+  if (anIntersectionsPoints.empty()) {
+    theError = "The edge is not intersected with sketch plane";
+    return false;
+  }
+  return true;
 }
 
 bool SketchPlugin_SplitValidator::isValid(const AttributePtr& theAttribute,
@@ -981,10 +991,15 @@ bool SketchPlugin_ProjectionValidator::isValid(const AttributePtr& theAttribute,
   if (aFeatureAttr.get()) {
     GeomShapePtr aVal = aFeatureAttr->value();
     ResultPtr aRes = aFeatureAttr->context();
-    if(aVal && aVal->isEdge()) {
+    if (aVal && aVal->isVertex())
+      return true; // vertex is always could be projected
+    if (aVal && aVal->isEdge()) {
       anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aFeatureAttr->value()));
-    } else if(aRes && aRes->shape() && aRes->shape()->isEdge()) {
-      anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aFeatureAttr->context()->shape()));
+    } else if(aRes && aRes->shape()) {
+      if (aRes->shape()->isVertex())
+        return true; // vertex is always could be projected
+      else if (aRes->shape()->isEdge())
+        anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aFeatureAttr->context()->shape()));
     }
 
     // try to convert result to sketch feature
@@ -994,15 +1009,6 @@ bool SketchPlugin_ProjectionValidator::isValid(const AttributePtr& theAttribute,
     }
   }
   if (!anEdge) {
-    // check a vertex has been selected
-    if (aFeatureAttr->value() && aFeatureAttr->value()->isVertex())
-      return true;
-    else {
-      ResultPtr aRes = aFeatureAttr->context();
-      if (aRes && aRes->shape() && aRes->shape()->isVertex())
-        return true;
-    }
-
     theError = "The attribute %1 should be an edge or vertex";
     theError.arg(theAttribute->id());
     return false;
@@ -1563,3 +1569,119 @@ bool SketchPlugin_HasNoConstraint::isValid(const AttributePtr& theAttribute,
   }
   return true;
 }
+
+bool SketchPlugin_ReplicationReferenceValidator::isValid(
+    const AttributePtr& theAttribute,
+    const std::list<std::string>& theArguments,
+    Events_InfoMessage& theError) const
+{
+  AttributeRefAttrPtr aRefAttr =
+      std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
+  if (!aRefAttr)
+  {
+    theError = "Incorrect attribute";
+    return false;
+  }
+
+  ObjectPtr anOwner;
+  if (aRefAttr->isObject())
+    anOwner = aRefAttr->object();
+  else
+  {
+    AttributePtr anAttr = aRefAttr->attr();
+    anOwner = anAttr->owner();
+  }
+  FeaturePtr anAttrOwnerFeature = ModelAPI_Feature::feature(anOwner);
+  if (!anAttrOwnerFeature)
+    return true;
+  AttributeBooleanPtr aCopyAttr = anAttrOwnerFeature->boolean(SketchPlugin_SketchEntity::COPY_ID());
+  if (!aCopyAttr || !aCopyAttr->value())
+    return true; // feature is not a copy, thus valid
+
+  // check the copy feature is already referred by the "Multi" feature
+  FeaturePtr aMultiFeature = ModelAPI_Feature::feature(theAttribute->owner());
+  AttributeRefListPtr aRefList = aMultiFeature->reflist(theArguments.front());
+  for (int i = 0; i < aRefList->size(); ++i)
+  {
+    FeaturePtr aRefOwner = ModelAPI_Feature::feature(aRefList->object(i));
+    if (aRefOwner == anAttrOwnerFeature)
+    {
+      theError = "Attribute refers to the object generated by this feature";
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool SketchPlugin_SketchFeatureValidator::isValid(const AttributePtr& theAttribute,
+                                                  const std::list<std::string>& theArguments,
+                                                  Events_InfoMessage& theError) const
+{
+  if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) {
+    theError = "The attribute with the %1 type is not processed";
+    theError.arg(theAttribute->attributeType());
+    return false;
+  }
+
+  // check the attribute refers to a sketch feature
+  AttributeRefAttrPtr aRefAttr =
+      std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
+  bool isSketchFeature = aRefAttr->isObject();
+  if (isSketchFeature) {
+    FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+    isSketchFeature = aFeature.get() != NULL;
+    if (isSketchFeature) {
+      std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
+          std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
+      isSketchFeature = aSketchFeature.get() != NULL;
+    }
+  }
+
+  if (isSketchFeature)
+    return true;
+
+  theError = "The object selected is not a sketch feature";
+  return false;
+}
+
+bool SketchPlugin_MultiRotationAngleValidator::isValid(const AttributePtr& theAttribute,
+                                                       const std::list<std::string>& theArguments,
+                                                       Events_InfoMessage& theError) const
+{
+  if (theAttribute->attributeType() != ModelAPI_AttributeDouble::typeId()) {
+    theError = "The attribute with the %1 type is not processed";
+    theError.arg(theAttribute->attributeType());
+    return false;
+  }
+
+  AttributeDoublePtr anAngleAttr =
+    std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
+
+  FeaturePtr aMultiRotation = ModelAPI_Feature::feature(theAttribute->owner());
+  AttributeStringPtr anAngleType =
+      aMultiRotation->string(SketchPlugin_MultiRotation::ANGLE_TYPE());
+  AttributeIntegerPtr aNbCopies =
+      aMultiRotation->integer(SketchPlugin_MultiRotation::NUMBER_OF_OBJECTS_ID());
+
+  if (anAngleType->value() != "FullAngle")
+  {
+    double aFullAngleValue = anAngleAttr->value() * (aNbCopies->value() - 1);
+    if (aFullAngleValue < -1.e-7 || aFullAngleValue > 359.9999999)
+    {
+      theError = "Rotation single angle should produce full angle less than 360 degree";
+      return false;
+    }
+  }
+  else
+  {
+    double aFullAngleValue = anAngleAttr->value();
+    if (aFullAngleValue < -1.e-7 || aFullAngleValue > 360.0000001)
+    {
+      theError = "Rotation full angle should be in range [0, 360]";
+      return false;
+    }
+  }
+
+  return true;
+}