X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchPlugin%2FSketchPlugin_Validators.cpp;h=a541519adbc838f38c73c7ff6346b07b6fce7fa5;hb=98a69c29b5f7357846d88f74166bbc2eef552c59;hp=c95474a5575df96647edc2a9d2b3c3b4cf678fc5;hpb=b0bb3759a49150670a2092701cafb055e11c1818;p=modules%2Fshaper.git diff --git a/src/SketchPlugin/SketchPlugin_Validators.cpp b/src/SketchPlugin/SketchPlugin_Validators.cpp old mode 100755 new mode 100644 index c95474a55..a541519ad --- a/src/SketchPlugin/SketchPlugin_Validators.cpp +++ b/src/SketchPlugin/SketchPlugin_Validators.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 CEA/DEN, EDF R&D +// Copyright (C) 2014-2019 CEA/DEN, EDF R&D // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -12,24 +12,29 @@ // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or -// email : webmaster.salome@opencascade.com +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // #include "SketchPlugin_Validators.h" #include "SketchPlugin_Arc.h" +#include "SketchPlugin_BSpline.h" +#include "SketchPlugin_BSplinePeriodic.h" #include "SketchPlugin_Circle.h" #include "SketchPlugin_ConstraintCoincidence.h" +#include "SketchPlugin_ConstraintCoincidenceInternal.h" #include "SketchPlugin_ConstraintDistance.h" #include "SketchPlugin_ConstraintRigid.h" #include "SketchPlugin_ConstraintTangent.h" +#include "SketchPlugin_Ellipse.h" +#include "SketchPlugin_EllipticArc.h" #include "SketchPlugin_Fillet.h" #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,9 +47,8 @@ #include #include #include +#include #include - -#include #include #include #include @@ -60,16 +64,26 @@ #include #include +#include #include #include #include + #include +#include #include #include const double tolerance = 1.e-7; +static bool isSpline(FeaturePtr theFeature) +{ + return theFeature && (theFeature->getKind() == SketchPlugin_BSpline::ID() || + theFeature->getKind() == SketchPlugin_BSplinePeriodic::ID()); +} + + bool SketchPlugin_DistanceAttrValidator::isValid(const AttributePtr& theAttribute, const std::list& theArguments, Events_InfoMessage& theError) const @@ -151,45 +165,122 @@ bool SketchPlugin_TangentAttrValidator::isValid(const AttributePtr& theAttribute AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(theAttribute); + bool isObject = aRefAttr->isObject(); + ObjectPtr anObject = aRefAttr->object(); + if (!isObject || !anObject.get()) { + theError = "It uses an empty object"; + return false; + } + + FeaturePtr aRefFea = ModelAPI_Feature::feature(anObject); + + AttributeRefAttrPtr aOtherAttr = anAttributeFeature->data()->refattr(aParamA); + ObjectPtr aOtherObject = aOtherAttr->object(); + FeaturePtr aOtherFea = ModelAPI_Feature::feature(aOtherObject); + if (!aOtherFea) + return true; + + if (aRefFea->getKind() == SketchPlugin_Line::ID() && + aOtherFea->getKind() == SketchPlugin_Line::ID()) { + theError = "Two segments cannot be tangent"; + return false; + } + else if (isSpline(aRefFea) && isSpline(aOtherFea)) { + theError = "Two B-splines cannot be tangent"; + return false; + } + + bool isValid = true; + bool hasSpline = isSpline(aRefFea); + if (!hasSpline && isSpline(aOtherFea)) { + hasSpline = true; + std::swap(aRefFea, aOtherFea); + } + if (hasSpline) { + auto isApplicableCoincidence = [](FeaturePtr theFeature, const std::string& theAttrName) { + AttributeRefAttrPtr aRefAttr = theFeature->refattr(theAttrName); + if (aRefAttr->isObject()) + return false; + AttributePtr anAttr = aRefAttr->attr(); + FeaturePtr anOwner = ModelAPI_Feature::feature(anAttr->owner()); + AttributePoint2DPtr aPointAttr = std::dynamic_pointer_cast(anAttr); + if (aPointAttr) { + return anOwner->getKind() == SketchPlugin_BSpline::ID() && + (aPointAttr->id() == SketchPlugin_BSpline::START_ID() || + aPointAttr->id() == SketchPlugin_BSpline::END_ID()); + } + + AttributePoint2DArrayPtr aPntArray = + std::dynamic_pointer_cast(anAttr); + if (aPntArray && anOwner->getKind() == SketchPlugin_BSpline::ID()) { + // check index of the pole + AttributeIntegerPtr anIndex = theAttrName == SketchPlugin_Constraint::ENTITY_A() ? + theFeature->integer(SketchPlugin_ConstraintCoincidenceInternal::INDEX_ENTITY_A()) : + theFeature->integer(SketchPlugin_ConstraintCoincidenceInternal::INDEX_ENTITY_B()); + return anIndex && (anIndex->value() == 0 || anIndex->value() == aPntArray->size() - 1); + } + return false; + }; + + isValid = false; + AttributePoint2DArrayPtr aBSplinePoles = std::dynamic_pointer_cast( + aRefFea->attribute(SketchPlugin_BSplineBase::POLES_ID())); + // additional check the B-spline edge and the other edge have a coincident boundary point + std::set aCoincidences = SketchPlugin_Tools::findCoincidentConstraints(aRefFea); + for (std::set::iterator anIt = aCoincidences.begin(); + anIt != aCoincidences.end() && !isValid; ++anIt) { + std::set aCoinc; + if (isApplicableCoincidence(*anIt, SketchPlugin_Constraint::ENTITY_A())) + SketchPlugin_Tools::findCoincidences(*anIt, SketchPlugin_Constraint::ENTITY_B(), + aCoinc, true); + else if (isApplicableCoincidence(*anIt, SketchPlugin_Constraint::ENTITY_B())) + SketchPlugin_Tools::findCoincidences(*anIt, SketchPlugin_Constraint::ENTITY_A(), + aCoinc, true); + + isValid = aCoinc.find(aOtherFea) != aCoinc.end(); + } + } + + return isValid; +} + +bool SketchPlugin_PerpendicularAttrValidator::isValid(const AttributePtr& theAttribute, + const std::list& 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; + } + + std::string aParamA = theArguments.front(); + SessionPtr aMgr = ModelAPI_Session::get(); + ModelAPI_ValidatorsFactory* aFactory = aMgr->validators(); + + FeaturePtr anOwner = std::dynamic_pointer_cast(theAttribute->owner()); + AttributeRefAttrPtr aRefAttr = + std::dynamic_pointer_cast(theAttribute); + bool isObject = aRefAttr->isObject(); ObjectPtr anObject = aRefAttr->object(); if (isObject && anObject.get()) { FeaturePtr aRefFea = ModelAPI_Feature::feature(anObject); - AttributeRefAttrPtr aOtherAttr = anAttributeFeature->data()->refattr(aParamA); + AttributeRefAttrPtr aOtherAttr = anOwner->refattr(aParamA); ObjectPtr aOtherObject = aOtherAttr->object(); FeaturePtr aOtherFea = ModelAPI_Feature::feature(aOtherObject); - if (!aOtherFea) - return true; - if (aRefFea->getKind() == SketchPlugin_Line::ID()) { - if (aOtherFea->getKind() != SketchPlugin_Arc::ID() && - aOtherFea->getKind() != SketchPlugin_Circle::ID()) { - theError = "It refers to a %1, but %2 is neither an %3 nor %4"; - theError.arg(SketchPlugin_Line::ID()).arg(aParamA) - .arg(SketchPlugin_Arc::ID()).arg(SketchPlugin_Circle::ID()); - return false; - } - } - else if (aRefFea->getKind() == SketchPlugin_Arc::ID() || - aRefFea->getKind() == SketchPlugin_Circle::ID()) { - if (aOtherFea->getKind() != SketchPlugin_Line::ID() && - aOtherFea->getKind() != SketchPlugin_Arc::ID() && - aOtherFea->getKind() != SketchPlugin_Circle::ID()) { - theError = "It refers to an %1, but %2 is not a %3 or an %4 or a %5"; - theError.arg(SketchPlugin_Arc::ID()).arg(aParamA) - .arg(SketchPlugin_Line::ID()).arg(SketchPlugin_Arc::ID()) - .arg(SketchPlugin_Circle::ID()); - return false; - } + // at least one feature should be a line + if (aRefFea->getKind() != SketchPlugin_Line::ID() && + aOtherFea && aOtherFea->getKind() != SketchPlugin_Line::ID()) { + theError = "At least one feature should be a line"; + return false; } - else { - theError = "It refers to %1, but should refer to %2 or %3 or %4"; - theError.arg(aRefFea->getKind()).arg(SketchPlugin_Line::ID()) - .arg(SketchPlugin_Arc::ID()).arg(SketchPlugin_Circle::ID()); + else if (isSpline(aRefFea) || isSpline(aOtherFea)) { + theError = "B-spline is not supported"; return false; } - return true; } else { theError = "It uses an empty object"; @@ -268,33 +359,36 @@ bool SketchPlugin_EqualAttrValidator::isValid(const AttributePtr& theAttribute, std::string aType[2]; std::list anArguments; for (int i = 0; i < 2; i++) { - ObjectPtr anObject = aRefAttr[i]->object(); - if (!anObject.get()) { - theError = "An empty object is used."; - return false; - } - - aFeature = ModelAPI_Feature::feature(anObject); - if (!aFeature.get()) { - theError = "An empty feature is used."; - return false; - } + aFeature = ModelAPI_Feature::feature(aRefAttr[i]->object()); + if (!aFeature.get()) + return true; aType[i] = aFeature->getKind(); if (aFeature->getKind() != SketchPlugin_Line::ID() && aFeature->getKind() != SketchPlugin_Circle::ID() && - aFeature->getKind() != SketchPlugin_Arc::ID()) { - theError = "The %1 feature kind of attribute is wrong. It should be %2 or %3 or %4"; - theError.arg(aFeature->getKind()).arg(SketchPlugin_Line::ID()) - .arg(SketchPlugin_Circle::ID()).arg(SketchPlugin_Arc::ID()); + aFeature->getKind() != SketchPlugin_Arc::ID() && + aFeature->getKind() != SketchPlugin_Ellipse::ID() && + aFeature->getKind() != SketchPlugin_EllipticArc::ID()) { + theError = "The %1 feature is not supported by the Equal constraint."; + theError.arg(aFeature->getKind()); // wrong type of attribute return false; } } - if ((aType[0] == SketchPlugin_Line::ID() || aType[1] == SketchPlugin_Line::ID()) && - aType[0] != aType[1]) { - theError = "Feature with kinds %1 and %2 can not be equal."; + bool isOk = aType[0] == aType[1]; + if (!isOk) { + // circle and arc may be equal + isOk = (aType[0] == SketchPlugin_Arc::ID() && aType[1] == SketchPlugin_Circle::ID()) + || (aType[0] == SketchPlugin_Circle::ID() && aType[1] == SketchPlugin_Arc::ID()); + } + if (!isOk) { + // ellipse and elliptic arc may be equal + isOk = (aType[0] == SketchPlugin_EllipticArc::ID() && aType[1] == SketchPlugin_Ellipse::ID()) + || (aType[0] == SketchPlugin_Ellipse::ID() && aType[1] == SketchPlugin_EllipticArc::ID()); + } + if (!isOk) { + theError = "Features with kinds %1 and %2 can not be equal."; theError.arg(aType[0]).arg(aType[1]); return false; } @@ -467,6 +561,8 @@ static bool hasSameTangentFeature(const std::set& theRefsList, anIt = theRefsList.cbegin(); anIt != theRefsList.cend(); ++anIt) { std::shared_ptr aAttr = (*anIt); FeaturePtr aFeature = std::dynamic_pointer_cast(aAttr->owner()); + if (!aFeature) + continue; if (aFeature->getKind() == SketchPlugin_ConstraintTangent::ID()) { AttributeRefAttrPtr anAttrRefA = std::dynamic_pointer_cast( aFeature->attribute(SketchPlugin_ConstraintTangent::ENTITY_A())); @@ -569,7 +665,7 @@ bool SketchPlugin_FilletVertexValidator::isValid(const AttributePtr& theAttribut } if(!aConstraintCoincidence.get()) { - theError = "Error: one of the selected point does not have coicidence."; + theError = "Error: one of the selected point does not have coincidence."; return false; } @@ -733,7 +829,9 @@ bool SketchPlugin_MiddlePointAttrValidator::isValid(const AttributePtr& theAttri if (aFeature->getKind() == SketchPlugin_Point::ID()) ++aNbPoints; - else if (aFeature->getKind() == SketchPlugin_Line::ID()) + else if (aFeature->getKind() == SketchPlugin_Line::ID() || + aFeature->getKind() == SketchPlugin_Arc::ID() || + aFeature->getKind() == SketchPlugin_EllipticArc::ID()) ++aNbLines; } } @@ -754,6 +852,11 @@ bool SketchPlugin_ArcTangentPointValidator::isValid(const AttributePtr& theAttri theError.arg(theAttribute->attributeType()); return false; } + FeaturePtr anOwner = std::dynamic_pointer_cast(theAttribute->owner()); + AttributeStringPtr anArcTypeAttr = anOwner->string(SketchPlugin_MacroArc::ARC_TYPE()); + if (anArcTypeAttr && anArcTypeAttr->value() != SketchPlugin_MacroArc::ARC_TYPE_BY_TANGENT_EDGE()) + return true; // not applicable for non-tangent arcs + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(theAttribute); AttributePtr anAttr = aRefAttr->attr(); if (!anAttr) { @@ -791,6 +894,50 @@ bool SketchPlugin_ArcTangentPointValidator::isValid(const AttributePtr& theAttri return true; } +bool SketchPlugin_ArcTransversalPointValidator::isValid( + const AttributePtr& theAttribute, + const std::list& /*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; + } + FeaturePtr anOwner = std::dynamic_pointer_cast(theAttribute->owner()); + AttributeStringPtr anArcTypeAttr = anOwner->string(SketchPlugin_MacroArc::ARC_TYPE()); + if (anArcTypeAttr && + anArcTypeAttr->value() != SketchPlugin_MacroArc::ARC_TYPE_BY_TRANSVERSAL_LINE()) + return true; // not applicable for non-transversal arcs + + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(theAttribute); + AttributePtr anAttr = aRefAttr->attr(); + if (!anAttr) { + theError = "The attribute %1 should be a point"; + theError.arg(theAttribute->id()); + return false; + } + + FeaturePtr anAttrFeature = std::dynamic_pointer_cast(anAttr->owner()); + const std::string& aFeatureType = anAttrFeature->getKind(); + if (aFeatureType == SketchPlugin_Line::ID()) { + // selected point should be bound point of line + const std::string& aPntId = anAttr->id(); + if (aPntId != SketchPlugin_Line::START_ID() && aPntId != SketchPlugin_Line::END_ID()) { + theError = "The attribute %1 is not supported"; + theError.arg(aPntId); + return false; + } + } + else { + theError = "Unable to build perpendicular arc on %1"; + theError.arg(anAttrFeature->getKind()); + return false; + } + + return true; +} + bool SketchPlugin_IntersectionValidator::isValid(const AttributePtr& theAttribute, const std::list& theArguments, Events_InfoMessage& theError) const @@ -800,27 +947,25 @@ bool SketchPlugin_IntersectionValidator::isValid(const AttributePtr& theAttribut theError.arg(theAttribute->attributeType()); return false; } - AttributeSelectionPtr aLineAttr = - std::dynamic_pointer_cast(theAttribute); + AttributeSelectionPtr anExternalAttr = + std::dynamic_pointer_cast(theAttribute); std::shared_ptr anEdge; - if(aLineAttr && aLineAttr->value() && aLineAttr->value()->isEdge()) { - anEdge = std::shared_ptr(new GeomAPI_Edge(aLineAttr->value())); - } else if(aLineAttr->context() && - aLineAttr->context()->shape() && aLineAttr->context()->shape()->isEdge()) { - anEdge = std::shared_ptr(new GeomAPI_Edge(aLineAttr->context()->shape())); + if (anExternalAttr && anExternalAttr->value() && anExternalAttr->value()->isEdge()) { + anEdge = std::shared_ptr(new GeomAPI_Edge(anExternalAttr->value())); + } else if(anExternalAttr->context() && anExternalAttr->context()->shape() && + anExternalAttr->context()->shape()->isEdge()) { + anEdge = std::shared_ptr(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 aLineDir = anEdge->line()->direction(); - // find a sketch std::shared_ptr aSketch; - std::set aRefs = aLineAttr->owner()->data()->refsToMe(); + std::set aRefs = anExternalAttr->owner()->data()->refsToMe(); std::set::const_iterator anIt = aRefs.begin(); for (; anIt != aRefs.end(); ++anIt) { CompositeFeaturePtr aComp = @@ -835,9 +980,16 @@ bool SketchPlugin_IntersectionValidator::isValid(const AttributePtr& theAttribut return false; } + // check the edge is intersected with sketch plane std::shared_ptr aPlane = aSketch->plane(); - std::shared_ptr aNormal = aPlane->direction(); - return fabs(aNormal->dot(aLineDir)) > tolerance * tolerance; + + std::list 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, @@ -853,55 +1005,60 @@ bool SketchPlugin_SplitValidator::isValid(const AttributePtr& theAttribute, } AttributeReferencePtr aFeatureAttr = std::dynamic_pointer_cast(theAttribute); + std::shared_ptr aSplitFeature = + std::dynamic_pointer_cast(theAttribute->owner()); ObjectPtr anAttrObject = aFeatureAttr->value(); + if (!anAttrObject) { + AttributePtr aPreviewAttr = aSplitFeature->attribute(SketchPlugin_Trim::PREVIEW_OBJECT()); + aFeatureAttr = std::dynamic_pointer_cast(aPreviewAttr); + anAttrObject = aFeatureAttr->value(); + } + FeaturePtr anAttrFeature = ModelAPI_Feature::feature(anAttrObject); if (!anAttrFeature) return aValid; - std::string aKind = anAttrFeature->getKind(); - if (aKind == SketchPlugin_Line::ID() || - aKind == SketchPlugin_Arc::ID() || - aKind == SketchPlugin_Circle::ID()) { - - std::set anEdgeShapes; - ModelGeomAlgo_Shape::shapesOfType(anAttrFeature, GeomAPI_Shape::EDGE, anEdgeShapes); - if (anEdgeShapes.empty() || anEdgeShapes.size() > 1 /*there case has not existed yet*/) - return aValid; - - // coincidences to the feature - std::set > aRefAttributes; - ModelGeomAlgo_Point2D::getPointsOfReference(anAttrFeature, - SketchPlugin_ConstraintCoincidence::ID(), - aRefAttributes, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID()); - - GeomShapePtr anAttrShape = (*anEdgeShapes.begin())->shape(); - std::shared_ptr aSFeature = - std::dynamic_pointer_cast(anAttrFeature); - SketchPlugin_Sketch* aSketch = aSFeature->sketch(); - - std::shared_ptr aData = aSketch->data(); - std::shared_ptr aC = std::dynamic_pointer_cast( - aData->attribute(SketchPlugin_Sketch::ORIGIN_ID())); - std::shared_ptr aX = std::dynamic_pointer_cast( - aData->attribute(SketchPlugin_Sketch::DIRX_ID())); - std::shared_ptr aNorm = std::dynamic_pointer_cast( - aData->attribute(SketchPlugin_Sketch::NORM_ID())); - std::shared_ptr aDirY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir()))); - - typedef std::map, - std::pair >, - std::list > > > PointToRefsMap; - PointToRefsMap aPointsInfo; - - ModelGeomAlgo_Point2D::getPointsInsideShape(anAttrShape, aRefAttributes, aC->pnt(), - aX->dir(), aDirY, aPointsInfo); - int aCoincidentToFeature = (int)aPointsInfo.size(); - if (aKind == SketchPlugin_Circle::ID()) - aValid = aCoincidentToFeature >= 2; - else - aValid = aCoincidentToFeature >= 1; - } + std::set anEdgeShapes; + ModelGeomAlgo_Shape::shapesOfType(anAttrFeature, GeomAPI_Shape::EDGE, anEdgeShapes); + if (anEdgeShapes.empty() || anEdgeShapes.size() > 1 /*there case has not existed yet*/) + return aValid; + + // coincidences to the feature + std::set > aRefAttributes; + ModelGeomAlgo_Point2D::getPointsOfReference(anAttrFeature, + SketchPlugin_ConstraintCoincidence::ID(), + aRefAttributes, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID()); + + GeomShapePtr anAttrShape = (*anEdgeShapes.begin())->shape(); + std::shared_ptr aSFeature = + std::dynamic_pointer_cast(anAttrFeature); + if (!aSFeature || aSFeature->isCopy()) + return false; + SketchPlugin_Sketch* aSketch = aSFeature->sketch(); + + std::shared_ptr aData = aSketch->data(); + std::shared_ptr aC = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Sketch::ORIGIN_ID())); + std::shared_ptr aX = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Sketch::DIRX_ID())); + std::shared_ptr aNorm = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Sketch::NORM_ID())); + std::shared_ptr aDirY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir()))); + + typedef std::map, + std::pair >, + std::list > > > PointToRefsMap; + PointToRefsMap aPointsInfo; + + ModelGeomAlgo_Point2D::getPointsInsideShape(anAttrShape, aRefAttributes, aC->pnt(), + aX->dir(), aDirY, aPointsInfo); + int aCoincidentToFeature = (int)aPointsInfo.size(); + if (anAttrFeature->getKind() == SketchPlugin_Circle::ID() || + anAttrFeature->getKind() == SketchPlugin_Ellipse::ID()) + aValid = aCoincidentToFeature >= 2; + else + aValid = aCoincidentToFeature >= 1; return aValid; } @@ -939,12 +1096,6 @@ bool SketchPlugin_TrimValidator::isValid(const AttributePtr& theAttribute, if (!aSketchFeature.get() || aSketchFeature->isCopy()) return aValid; - std::string aKind = aBaseFeature->getKind(); - if (aKind != SketchPlugin_Line::ID() && - aKind != SketchPlugin_Arc::ID() && - aKind != SketchPlugin_Circle::ID()) - return aValid; - // point on feature AttributePoint2DPtr aPoint = std::dynamic_pointer_cast( aTrimFeature->data()->attribute(SketchPlugin_Trim::PREVIEW_POINT())); @@ -959,8 +1110,8 @@ bool SketchPlugin_TrimValidator::isValid(const AttributePtr& theAttribute, std::map, std::pair >, std::list > > > > anObjectToPoints; - SketchPlugin_Trim::fillObjectShapes(aBaseObject, aSketch->data()->owner(), - aCashedShapes, anObjectToPoints); + SketchPlugin_SegmentationTools::fillObjectShapes( + aTrimFeature.get(), aBaseObject, aCashedShapes, anObjectToPoints); const std::set& aShapes = aCashedShapes[aBaseObject]; return aShapes.size() > 1; @@ -983,10 +1134,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(new GeomAPI_Edge(aFeatureAttr->value())); - } else if(aRes && aRes->shape() && aRes->shape()->isEdge()) { - anEdge = std::shared_ptr(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(new GeomAPI_Edge(aFeatureAttr->context()->shape())); } // try to convert result to sketch feature @@ -996,15 +1152,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; @@ -1035,28 +1182,35 @@ bool SketchPlugin_ProjectionValidator::isValid(const AttributePtr& theAttribute, std::shared_ptr aNormal = aPlane->direction(); std::shared_ptr anOrigin = aPlane->location(); + bool aValid = true; if (anEdge->isLine()) { std::shared_ptr aLine = anEdge->line(); std::shared_ptr aLineDir = aLine->direction(); double aDot = fabs(aNormal->dot(aLineDir)); - bool aValid = fabs(aDot - 1.0) >= tolerance * tolerance; + aValid = fabs(aDot - 1.0) >= tolerance * tolerance; if (!aValid) - theError = "Error: Edge is already in the sketch plane."; - return aValid; + theError = "Error: Line is orthogonal to the sketch plane."; } else if (anEdge->isCircle() || anEdge->isArc()) { std::shared_ptr aCircle = anEdge->circle(); std::shared_ptr aCircNormal = aCircle->normal(); double aDot = fabs(aNormal->dot(aCircNormal)); - bool aValid = fabs(aDot - 1.0) < tolerance * tolerance; + aValid = aDot >= tolerance * tolerance; if (!aValid) - theError.arg(anEdge->isCircle() ? "Error: Cirlce is already in the sketch plane." - : "Error: Arc is already in the sketch plane."); - return aValid; + theError.arg(anEdge->isCircle() ? "Error: Circle is orthogonal to the sketch plane." + : "Error: Arc is orthogonal to the sketch plane."); + } + else if (anEdge->isEllipse()) { + std::shared_ptr anEllipse = anEdge->ellipse(); + std::shared_ptr anEllipseNormal = anEllipse->normal(); + double aDot = fabs(aNormal->dot(anEllipseNormal)); + aValid = fabs(aDot - 1.0) <= tolerance * tolerance; + if (!aValid) + theError.arg(anEdge->isClosed() ? "Error: Ellipse is orthogonal to the sketch plane." + : "Error: Elliptic Arc is orthogonal to the sketch plane."); } - theError = "Error: Selected object is not line, circle or arc."; - return false; + return aValid; } @@ -1640,3 +1794,61 @@ bool SketchPlugin_SketchFeatureValidator::isValid(const AttributePtr& theAttribu theError = "The object selected is not a sketch feature"; return false; } + +bool SketchPlugin_MultiRotationAngleValidator::isValid(const AttributePtr& theAttribute, + const std::list& 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(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; +} + +bool SketchPlugin_BSplineValidator::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + AttributePoint2DArrayPtr aPolesArray = + std::dynamic_pointer_cast(theAttribute); + if (!aPolesArray) + return false; + + if (aPolesArray->size() < 2) { + theError = "Number of B-spline poles should be 2 or more"; + return false; + } + + return true; +}