X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchPlugin%2FSketchPlugin_Validators.cpp;h=3c6fcc3471828c096c8eab647290c5953d7dcec4;hb=0c54e2dea1ee3052eda2e551bfb9108f97183f90;hp=bb142b319036064e27f6483f72212bc1c44fa663;hpb=10671023698288fff01b8717696d150419dc4475;p=modules%2Fshaper.git diff --git a/src/SketchPlugin/SketchPlugin_Validators.cpp b/src/SketchPlugin/SketchPlugin_Validators.cpp index bb142b319..3c6fcc347 100755 --- a/src/SketchPlugin/SketchPlugin_Validators.cpp +++ b/src/SketchPlugin/SketchPlugin_Validators.cpp @@ -1,8 +1,22 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> - -// File: SketchPlugin_Validators.cpp -// Created: 01 Aug 2014 -// Author: Vitaly SMETANNIKOV +// Copyright (C) 2014-2017 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 +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// 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 +// +// See http://www.salome-platform.org/ or +// email : webmaster.salome@opencascade.com +// #include "SketchPlugin_Validators.h" @@ -41,6 +55,7 @@ #include #include +#include #include #include @@ -486,6 +501,24 @@ static bool hasSameTangentFeature(const std::set& theRefsList, return false; } +static bool isPointPointCoincidence(const FeaturePtr& theCoincidence) +{ + AttributeRefAttrPtr aRefAttr[2] = { + theCoincidence->refattr(SketchPlugin_Constraint::ENTITY_A()), + theCoincidence->refattr(SketchPlugin_Constraint::ENTITY_B()) + }; + + bool arePoints = true; + for (int i = 0; i < 2 && arePoints; ++i) { + if (aRefAttr[i]->isObject()) { + FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr[i]->object()); + arePoints = aFeature.get() && aFeature->getKind() == SketchPlugin_Point::ID(); + } else + arePoints = aRefAttr[i]->attr().get() != NULL; + } + return arePoints; +} + bool SketchPlugin_FilletVertexValidator::isValid(const AttributePtr& theAttribute, const std::list& theArguments, Events_InfoMessage& theError) const @@ -513,23 +546,24 @@ bool SketchPlugin_FilletVertexValidator::isValid(const AttributePtr& theAttribut std::shared_ptr aAttr = (*anIt); FeaturePtr aConstrFeature = std::dynamic_pointer_cast(aAttr->owner()); if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) { + if (!isPointPointCoincidence(aConstrFeature)) + continue; + AttributeRefAttrPtr anAttrRefA = std::dynamic_pointer_cast( aConstrFeature->attribute(SketchPlugin_ConstraintCoincidence::ENTITY_A())); AttributeRefAttrPtr anAttrRefB = std::dynamic_pointer_cast( aConstrFeature->attribute(SketchPlugin_ConstraintCoincidence::ENTITY_B())); - if(anAttrRefA.get() && !anAttrRefA->isObject()) { - AttributePtr anAttrA = anAttrRefA->attr(); - if(aPointAttribute == anAttrA) { - aConstraintCoincidence = aConstrFeature; - break; - } + + AttributePtr anAttrA = anAttrRefA->attr(); + if(aPointAttribute == anAttrA) { + aConstraintCoincidence = aConstrFeature; + break; } - if(anAttrRefB.get() && !anAttrRefB->isObject()) { - AttributePtr anAttrB = anAttrRefB->attr(); - if(aPointAttribute == anAttrB) { - aConstraintCoincidence = aConstrFeature; - break; - } + + AttributePtr anAttrB = anAttrRefB->attr(); + if(aPointAttribute == anAttrB) { + aConstraintCoincidence = aConstrFeature; + break; } } } @@ -543,18 +577,20 @@ bool SketchPlugin_FilletVertexValidator::isValid(const AttributePtr& theAttribut std::set 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 aNewSetOfCoincides; for(std::set::iterator anIt = aCoinsides.begin(); anIt != aCoinsides.end(); ++anIt) { std::shared_ptr aSketchEntity = std::dynamic_pointer_cast(*anIt); - if(aSketchEntity.get() && aSketchEntity->isCopy()) { + if(aSketchEntity.get() && (aSketchEntity->isCopy() || aSketchEntity->isExternal())) { continue; } if((*anIt)->getKind() != SketchPlugin_Line::ID() && @@ -612,36 +648,51 @@ bool SketchPlugin_FilletVertexValidator::isValid(const AttributePtr& theAttribut } } - // Check that lines not collinear - if(aFirstFeature->getKind() == SketchPlugin_Line::ID() && - aSecondFeature->getKind() == SketchPlugin_Line::ID()) { - std::string aStartAttr = SketchPlugin_Line::START_ID(); - std::string anEndAttr = SketchPlugin_Line::END_ID(); - std::shared_ptr aFirstStartPnt, aFirstEndPnt, aSecondStartPnt, aSecondEndPnt; - aFirstStartPnt = - std::dynamic_pointer_cast( - aFirstFeature->attribute(aStartAttr))->pnt(); - aFirstEndPnt = - std::dynamic_pointer_cast(aFirstFeature->attribute(anEndAttr))->pnt(); - aSecondStartPnt = - std::dynamic_pointer_cast( - aSecondFeature->attribute(aStartAttr))->pnt(); - aSecondEndPnt = - std::dynamic_pointer_cast( - aSecondFeature->attribute(anEndAttr))->pnt(); - double aCheck1 = - fabs((aFirstEndPnt->x() - aFirstStartPnt->x()) * - (aSecondStartPnt->y() - aFirstStartPnt->y()) - - (aSecondStartPnt->x() - aFirstStartPnt->x()) * (aFirstEndPnt->y() - aFirstStartPnt->y())); - double aCheck2 = - fabs((aFirstEndPnt->x() - aFirstStartPnt->x()) * - (aSecondEndPnt->y() - aFirstStartPnt->y()) - - (aSecondEndPnt->x() - aFirstStartPnt->x()) * (aFirstEndPnt->y() - aFirstStartPnt->y())); - if(aCheck1 < 1.e-7 && aCheck2 < 1.e-7) { + // Check the features are not tangent + std::shared_ptr aFirstShape = aFirstFeature->lastResult()->shape(); + std::shared_ptr aSecondShape = aSecondFeature->lastResult()->shape(); + if (!aFirstShape || !aFirstShape->isEdge() || + !aSecondShape || !aSecondShape->isEdge()) { + theError = "Error: At least on of the features is not an edge"; + return false; + } + + std::shared_ptr anEdge1 = std::dynamic_pointer_cast(aFirstShape); + std::shared_ptr anEdge2 = std::dynamic_pointer_cast(aSecondShape); + + static const double TOL = 1.e-7; + if (anEdge1->isLine() && anEdge2->isLine()) { + // Check that lines not collinear + std::shared_ptr aDir1 = anEdge1->line()->direction(); + std::shared_ptr aDir2 = anEdge2->line()->direction(); + double aCross = aDir1->cross(aDir2)->squareModulus(); + if (aCross < TOL * TOL) + return false; + } else if (anEdge1->isArc() && anEdge2->isArc()) { + // check the circles are not tangent + std::shared_ptr aCirc1 = anEdge1->circle(); + std::shared_ptr aCirc2 = anEdge2->circle(); + double aDistCC = aCirc1->center()->distance(aCirc2->center()); + double aRadSum = aCirc1->radius() + aCirc2->radius(); + double aRadDiff = fabs(aCirc1->radius() - aCirc2->radius()); + if (fabs(aDistCC - aRadSum) < TOL || fabs(aDistCC - aRadDiff) < TOL) return false; + } else { + // check whether line and arc are tangent + std::shared_ptr aCirc; + std::shared_ptr aLine; + if (anEdge1->isLine()) { + aLine = anEdge1->line(); + aCirc = anEdge2->circle(); + } else { + aCirc = anEdge1->circle(); + aLine = anEdge2->line(); } - } + double aDistCL = aLine->distance(aCirc->center()); + if (fabs(aDistCL - aCirc->radius()) < TOL) + return false; + } return true; } @@ -928,18 +979,33 @@ bool SketchPlugin_ProjectionValidator::isValid(const AttributePtr& theAttribute, AttributeSelectionPtr aFeatureAttr = std::dynamic_pointer_cast(theAttribute); std::shared_ptr anEdge; + std::shared_ptr aSketchFeature; if (aFeatureAttr.get()) { GeomShapePtr aVal = aFeatureAttr->value(); ResultPtr aRes = aFeatureAttr->context(); - if(aFeatureAttr->value() && aFeatureAttr->value()->isEdge()) { + if(aVal && aVal->isEdge()) { anEdge = std::shared_ptr(new GeomAPI_Edge(aFeatureAttr->value())); - } else if(aFeatureAttr->context() && aFeatureAttr->context()->shape() && - aFeatureAttr->context()->shape()->isEdge()) { + } else if(aRes && aRes->shape() && aRes->shape()->isEdge()) { anEdge = std::shared_ptr(new GeomAPI_Edge(aFeatureAttr->context()->shape())); } + + // try to convert result to sketch feature + if (aRes) { + aSketchFeature = + std::dynamic_pointer_cast(ModelAPI_Feature::feature(aRes)); + } } if (!anEdge) { - theError = "The attribute %1 should be an edge"; + // 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; } @@ -960,6 +1026,10 @@ bool SketchPlugin_ProjectionValidator::isValid(const AttributePtr& theAttribute, theError = "There is no sketch referring to the current feature"; return false; } + if (aSketchFeature && aSketch.get() == aSketchFeature->sketch()) { + theError = "Unable to project feature from the same sketch"; + return false; + } std::shared_ptr aPlane = aSketch->plane(); std::shared_ptr aNormal = aPlane->direction(); @@ -968,11 +1038,8 @@ bool SketchPlugin_ProjectionValidator::isValid(const AttributePtr& theAttribute, if (anEdge->isLine()) { std::shared_ptr aLine = anEdge->line(); std::shared_ptr aLineDir = aLine->direction(); - std::shared_ptr aLineLoc = aLine->location(); - double aDot = aNormal->dot(aLineDir); - double aDist = aLineLoc->xyz()->decreased(anOrigin->xyz())->dot(aNormal->xyz()); - bool aValid = (fabs(aDot) >= tolerance && fabs(aDot) < 1.0 - tolerance) || - (fabs(aDot) < tolerance && fabs(aDist) > tolerance); + double aDot = fabs(aNormal->dot(aLineDir)); + bool aValid = fabs(aDot - 1.0) >= tolerance * tolerance; if (!aValid) theError = "Error: Edge is already in the sketch plane."; return aValid; @@ -980,10 +1047,8 @@ bool SketchPlugin_ProjectionValidator::isValid(const AttributePtr& theAttribute, else if (anEdge->isCircle() || anEdge->isArc()) { std::shared_ptr aCircle = anEdge->circle(); std::shared_ptr aCircNormal = aCircle->normal(); - std::shared_ptr aCircCenter = aCircle->center(); double aDot = fabs(aNormal->dot(aCircNormal)); - double aDist = aCircCenter->xyz()->decreased(anOrigin->xyz())->dot(aNormal->xyz()); - bool aValid = fabs(aDot - 1.0) < tolerance * tolerance && fabs(aDist) > tolerance; + bool aValid = fabs(aDot - 1.0) < tolerance * tolerance; if (!aValid) theError.arg(anEdge->isCircle() ? "Error: Cirlce is already in the sketch plane." : "Error: Arc is already in the sketch plane."); @@ -1068,6 +1133,39 @@ bool SketchPlugin_DifferentReferenceValidator::isValid( return isOk; } +bool SketchPlugin_DifferentPointReferenceValidator::isValid( + const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner()); + std::set aReferredCoincidentPoints; + + // find all points referred by attributes listed in theArguments + bool hasRefsToPoints = false; + std::list::const_iterator anArgIt = theArguments.begin(); + for (; anArgIt != theArguments.end(); ++anArgIt) { + AttributeRefAttrPtr aRefAttr = anOwner->refattr(*anArgIt); + if (!aRefAttr) + continue; + + if (!aRefAttr->isObject()) { + AttributePoint2DPtr aPoint = + std::dynamic_pointer_cast(aRefAttr->attr()); + if (aReferredCoincidentPoints.empty()) + aReferredCoincidentPoints = SketchPlugin_Tools::findPointsCoincidentToPoint(aPoint); + else if (aReferredCoincidentPoints.find(aPoint) == aReferredCoincidentPoints.end()) + return true; // non-coincident point has been found + else + hasRefsToPoints = true; + } + } + + if (hasRefsToPoints) + theError = "Attributes are referred to the same point"; + return !hasRefsToPoints; +} + bool SketchPlugin_CirclePassedPointValidator::isValid( const AttributePtr& theAttribute, const std::list&, @@ -1091,8 +1189,7 @@ bool SketchPlugin_CirclePassedPointValidator::isValid( return true; if (aCenterRef->isObject()) { - FeaturePtr aCenterFeature = ModelAPI_Feature::feature(aCenterRef->object()); - if (aCenterFeature == aPassedFeature) { + if (aCenterRef->object() == aPassedRef->object()) { theError = aErrorMessage; return false; } @@ -1213,8 +1310,18 @@ static bool isOnSameSide(const std::shared_ptr& theLine, static const double aTolerance = 1.e-7; std::shared_ptr aLineDir = theLine->direction(); std::shared_ptr aLineLoc = theLine->location()->xyz(); - std::shared_ptr aDirP1L(new GeomAPI_Dir(thePoint1->xyz()->decreased(aLineLoc))); - std::shared_ptr aDirP2L(new GeomAPI_Dir(thePoint2->xyz()->decreased(aLineLoc))); + + std::shared_ptr aVec1 = thePoint1->xyz()->decreased(aLineLoc); + // the first point is on the line + if (aVec1->squareModulus() < aTolerance * aTolerance) + return false; + std::shared_ptr aDirP1L(new GeomAPI_Dir(aVec1)); + std::shared_ptr aVec2 = thePoint2->xyz()->decreased(aLineLoc); + // the second point is on the line + if (aVec2->squareModulus() < aTolerance * aTolerance) + return false; + std::shared_ptr aDirP2L(new GeomAPI_Dir(aVec2)); + return aLineDir->cross(aDirP1L)->dot(aLineDir->cross(aDirP2L)) > -aTolerance; } @@ -1325,6 +1432,37 @@ bool SketchPlugin_ArcEndPointValidator::isValid( return true; } +static GeomShapePtr toInfiniteEdge(const GeomShapePtr theShape) +{ + if(!theShape.get()) { + return theShape; + } + + if(!theShape->isEdge()) { + return theShape; + } + + std::shared_ptr anEdge(new GeomAPI_Edge(theShape)); + + if(!anEdge.get()) { + return theShape; + } + + if(anEdge->isLine()) { + std::shared_ptr aLine = anEdge->line(); + GeomShapePtr aShape = GeomAlgoAPI_EdgeBuilder::line(aLine); + return aShape; + } + + if(anEdge->isCircle() || anEdge->isArc()) { + std::shared_ptr aCircle = anEdge->circle(); + GeomShapePtr aShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCircle); + return aShape; + } + + return theShape; +} + bool SketchPlugin_ArcEndPointIntersectionValidator::isValid( const AttributePtr& theAttribute, const std::list& theArguments, @@ -1338,7 +1476,7 @@ bool SketchPlugin_ArcEndPointIntersectionValidator::isValid( return true; } - GeomShapePtr anArcShape = anArcFeature->getArcShape(); + GeomShapePtr anArcShape = toInfiniteEdge(anArcFeature->getArcShape(false)); if(!anArcShape.get() || anArcShape->isNull()) { return true; @@ -1353,9 +1491,11 @@ bool SketchPlugin_ArcEndPointIntersectionValidator::isValid( ResultPtr aResult = std::dynamic_pointer_cast(anObject); if(aResult.get()) { GeomShapePtr aShape = aResult->shape(); + if (!aShape->isEdge()) + return true; + aShape = toInfiniteEdge(aShape); if(aShape.get() && !aShape->isNull()) { - GeomShapePtr anIntersection = anArcShape->intersect(aShape); - if(anIntersection.get() && !anIntersection->isNull()) { + if(anArcShape->isIntersect(aShape)) { return true; } } @@ -1369,9 +1509,11 @@ bool SketchPlugin_ArcEndPointIntersectionValidator::isValid( ++anIt) { GeomShapePtr aShape = (*anIt)->shape(); + if (!aShape->isEdge()) + return true; + aShape = toInfiniteEdge(aShape); if(aShape.get() && !aShape->isNull()) { - GeomShapePtr anIntersection = anArcShape->intersect(aShape); - if(anIntersection.get() && !anIntersection->isNull()) { + if(anArcShape->isIntersect(aShape)) { return true; } } @@ -1380,3 +1522,90 @@ bool SketchPlugin_ArcEndPointIntersectionValidator::isValid( return false; } + +bool SketchPlugin_HasNoConstraint::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + std::set aFeatureKinds; + for (std::list::const_iterator anArgIt = theArguments.begin(); + anArgIt != theArguments.end(); anArgIt++) { + aFeatureKinds.insert(*anArgIt); + } + + if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) { + theError = "The attribute with the %1 type is not processed"; + theError.arg(theAttribute->attributeType()); + return false; + } + + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast + (theAttribute); + bool isObject = aRefAttr->isObject(); + if (!isObject) { + theError = "It uses an empty object"; + return false; + } + ObjectPtr anObject = aRefAttr->object(); + FeaturePtr aFeature = ModelAPI_Feature::feature(anObject); + if (!aFeature.get()) { + theError = "The feature of the checked attribute is empty"; + return false; + } + + FeaturePtr aCurrentFeature = ModelAPI_Feature::feature(aRefAttr->owner()); + + std::set aRefsList = anObject->data()->refsToMe(); + std::set::const_iterator anIt = aRefsList.begin(); + for (; anIt != aRefsList.end(); anIt++) { + FeaturePtr aRefFeature = ModelAPI_Feature::feature((*anIt)->owner()); + if (aRefFeature.get() && aCurrentFeature != aRefFeature && + aFeatureKinds.find(aRefFeature->getKind()) != aFeatureKinds.end()) + return false; // constraint is found, that means that the check is not valid + } + return true; +} + +bool SketchPlugin_ReplicationReferenceValidator::isValid( + const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + AttributeRefAttrPtr aRefAttr = + std::dynamic_pointer_cast(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; +}