X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchPlugin%2FSketchPlugin_Validators.cpp;h=3b79ad68cae45a90022ea0093a0bb4cddb89c0af;hb=868158fe6d39b25e60ac528295b1c908821e4af5;hp=674f9de12ee3be1107ddb2c399d67adb3ad86993;hpb=9fdd5bb2d329d3fc435f86a0247b6b5378c252b1;p=modules%2Fshaper.git diff --git a/src/SketchPlugin/SketchPlugin_Validators.cpp b/src/SketchPlugin/SketchPlugin_Validators.cpp old mode 100644 new mode 100755 index 674f9de12..3b79ad68c --- a/src/SketchPlugin/SketchPlugin_Validators.cpp +++ b/src/SketchPlugin/SketchPlugin_Validators.cpp @@ -5,13 +5,16 @@ // Author: Vitaly SMETANNIKOV #include "SketchPlugin_Validators.h" -#include "SketchPlugin_ConstraintDistance.h" + +#include "SketchPlugin_Arc.h" +#include "SketchPlugin_Circle.h" #include "SketchPlugin_ConstraintCoincidence.h" +#include "SketchPlugin_ConstraintDistance.h" #include "SketchPlugin_ConstraintRigid.h" #include "SketchPlugin_Line.h" -#include "SketchPlugin_Arc.h" -#include "SketchPlugin_Circle.h" #include "SketchPlugin_Point.h" +#include "SketchPlugin_Sketch.h" +#include "SketchPlugin_Tools.h" #include "SketcherPrs_Tools.h" @@ -21,25 +24,28 @@ #include #include #include +#include #include -#include - #include +const double tolerance = 1.e-7; -bool SketchPlugin_DistanceAttrValidator::isValid( - const AttributePtr& theAttribute, const std::list& theArguments ) const +bool SketchPlugin_DistanceAttrValidator::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + std::string& theError) const { + if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) { + theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed"; + return false; + } + // there is a check whether the feature contains a point and a linear edge or two point values std::string aParamA = theArguments.front(); SessionPtr aMgr = ModelAPI_Session::get(); ModelAPI_ValidatorsFactory* aFactory = aMgr->validators(); AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(theAttribute); - if (!aRefAttr) - return false; - bool isObject = aRefAttr->isObject(); if (!isObject) { // an attribute is a point. A point value is valid always for the distance @@ -48,110 +54,112 @@ bool SketchPlugin_DistanceAttrValidator::isValid( // 1. check whether the references object is a linear ObjectPtr anObject = aRefAttr->object(); - const ModelAPI_AttributeValidator* anEdgeValidator = - dynamic_cast(aFactory->validator("GeomValidators_Edge")); + const ModelAPI_AttributeValidator* aShapeValidator = + dynamic_cast(aFactory->validator("GeomValidators_ShapeType")); std::list anArguments; anArguments.push_back("circle"); - bool anEdgeValid = anEdgeValidator->isValid(aRefAttr, anArguments); + std::string aCircleError; + bool aShapeValid = aShapeValidator->isValid(aRefAttr, anArguments, aCircleError); // the circle line is not a valid case - if (anEdgeValid) + if (aShapeValid) { + theError = "Circle can not be used in distance constraint"; return false; + } anArguments.clear(); anArguments.push_back("line"); - anEdgeValid = anEdgeValidator->isValid(aRefAttr, anArguments); + std::string aLineError; + aShapeValid = aShapeValidator->isValid(aRefAttr, anArguments, aLineError); // if the attribute value is not a line, that means it is a vertex. A vertex is always valid - if (!anEdgeValid) - return true; - - FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); - // If it is a line then we have to check that first attribute id not a line - std::shared_ptr aPoint = SketcherPrs_Tools::getFeaturePoint(aFeature->data(), aParamA); - if (aPoint) - return true; + if (aShapeValid) { + FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); + // If it is a line then we have to check that first attribute id not a line + std::shared_ptr aSFeature = + std::dynamic_pointer_cast(theAttribute->owner()); + SketchPlugin_Sketch* aSketch = aSFeature->sketch(); + std::shared_ptr aPlane = SketchPlugin_Sketch::plane(aSketch); + std::shared_ptr aPoint = SketcherPrs_Tools::getFeaturePoint( + aFeature->data(), aParamA, aPlane); + if (!aPoint.get()) { + theError = "One of parameters of distance constraint should be a point"; + return false; + } + } } - return false; + return true; } -bool SketchPlugin_TangentAttrValidator::isValid( - const AttributePtr& theAttribute, const std::list& theArguments ) const + +bool SketchPlugin_TangentAttrValidator::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + std::string& theError) const { + if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) { + theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed"; + return false; + } + // there is a check whether the feature contains a point and a linear edge or two point values std::string aParamA = theArguments.front(); SessionPtr aMgr = ModelAPI_Session::get(); ModelAPI_ValidatorsFactory* aFactory = aMgr->validators(); - FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); + FeaturePtr anAttributeFeature = std::dynamic_pointer_cast(theAttribute->owner()); AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(theAttribute); - if (!aRefAttr) - return false; bool isObject = aRefAttr->isObject(); ObjectPtr anObject = aRefAttr->object(); - if (isObject && anObject) { + if (isObject && anObject.get()) { FeaturePtr aRefFea = ModelAPI_Feature::feature(anObject); - AttributeRefAttrPtr aOtherAttr = aFeature->data()->refattr(aParamA); + AttributeRefAttrPtr aOtherAttr = anAttributeFeature->data()->refattr(aParamA); ObjectPtr aOtherObject = aOtherAttr->object(); FeaturePtr aOtherFea = ModelAPI_Feature::feature(aOtherObject); if (aRefFea->getKind() == SketchPlugin_Line::ID()) { - if (aOtherFea->getKind() != SketchPlugin_Arc::ID()) + if (aOtherFea->getKind() != SketchPlugin_Arc::ID()) { + theError = "It refers to a " + SketchPlugin_Line::ID() + ", but " + aParamA + " is not an " + + SketchPlugin_Arc::ID(); return false; - } else if (aRefFea->getKind() == SketchPlugin_Arc::ID()) { + } + } + else if (aRefFea->getKind() == SketchPlugin_Arc::ID()) { if (aOtherFea->getKind() != SketchPlugin_Line::ID() && - aOtherFea->getKind() != SketchPlugin_Arc::ID()) + aOtherFea->getKind() != SketchPlugin_Arc::ID()) { + theError = "It refers to an " + SketchPlugin_Arc::ID() + ", but " + aParamA + " is not a " + + SketchPlugin_Line::ID() + " or an " + SketchPlugin_Arc::ID(); return false; - } else - return false; - - // check that both have coincidence - FeaturePtr aConstrFeature; - std::set aCoinList; - const std::set>& aRefsList = aRefFea->data()->refsToMe(); - std::set>::const_iterator aIt; - for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) { - std::shared_ptr aAttr = (*aIt); - aConstrFeature = std::dynamic_pointer_cast(aAttr->owner()); - if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) { - AttributeRefAttrPtr aRAttr = std::dynamic_pointer_cast(aAttr); - AttributePtr aAR = aRAttr->attr(); - if (aAR->id() != SketchPlugin_Arc::CENTER_ID()) // ignore constraint to center of arc - aCoinList.insert(aConstrFeature); } } - // if there is no coincidence then it is not valid - if (aCoinList.size() == 0) + else { + theError = "It refers to " + aRefFea->getKind() + "but should refer to " + SketchPlugin_Line::ID() + + " or " + SketchPlugin_Arc::ID(); return false; - - // find that coincedence is the same - const std::set>& aOtherList = aOtherFea->data()->refsToMe(); - std::set::const_iterator aCoinsIt; - for (aIt = aOtherList.cbegin(); aIt != aOtherList.cend(); ++aIt) { - std::shared_ptr aAttr = (*aIt); - aConstrFeature = std::dynamic_pointer_cast(aAttr->owner()); - aCoinsIt = aCoinList.find(aConstrFeature); - if (aCoinsIt != aCoinList.end()) { - AttributeRefAttrPtr aRAttr = std::dynamic_pointer_cast(aAttr); - AttributePtr aAR = aRAttr->attr(); - if (aAR->id() != SketchPlugin_Arc::CENTER_ID()) - return true; - } } + return true; } - return false; + else { + theError = "It uses an empty object"; + return false; + } + + return true; } -bool SketchPlugin_NotFixedValidator::isValid( - const AttributePtr& theAttribute, const std::list& theArguments) const +bool SketchPlugin_NotFixedValidator::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + std::string& theError) const { + if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) { + theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed"; + return false; + } + std::shared_ptr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); if (!aFeature) return true; AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(theAttribute); - if (!aRefAttr) - return false; SketchPlugin_Sketch* aSketch = aFeature->sketch(); int aNbFeatures = aSketch->numberOfSubs(); @@ -162,35 +170,57 @@ bool SketchPlugin_NotFixedValidator::isValid( AttributeRefAttrPtr aRAttr = std::dynamic_pointer_cast( aSubFeature->attribute(SketchPlugin_ConstraintRigid::ENTITY_A())); if (aRefAttr->isObject()) { - if (aRefAttr->object() == aRAttr->object()) + if (aRefAttr->object() == aRAttr->object()) { + ObjectPtr anObject = aRefAttr->object(); + std::string aName = anObject.get() ? anObject->data()->name() : ""; + theError = "The object " + aName + " has been already fixed."; return false; - } else if (aRefAttr->attr() == aRAttr->attr()) + } + } + else if (aRefAttr->attr() == aRAttr->attr()) { + AttributePtr anAttribute = aRefAttr->attr(); + std::string aName = anAttribute.get() ? anAttribute->id() : ""; + theError = "The attribute " + aName + " has been already fixed."; return false; + } } return true; } -bool SketchPlugin_EqualAttrValidator::isValid( - const AttributePtr& theAttribute, const std::list& theArguments ) const +bool SketchPlugin_EqualAttrValidator::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + std::string& theError) const { + if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) { + theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed"; + return false; + } + std::string aParamA = theArguments.front(); FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); AttributeRefAttrPtr aRefAttr[2]; aRefAttr[0] = std::dynamic_pointer_cast(theAttribute); - if (!aRefAttr) - return false; aRefAttr[1] = aFeature->data()->refattr(aParamA); - if (!aRefAttr[0]->isObject() || !aRefAttr[1]->isObject()) + if (!aRefAttr[0]->isObject() || !aRefAttr[1]->isObject()) { + theError = "Attributes can not be used in equal constraint"; return false; + } int aType[2] = {0, 0}; // types of attributes: 0 - incorrect, 1 - line, 2 - circle, 3 - arc 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) + if (!aFeature.get()) { + theError = "An empty feature is used."; return false; + } if (aFeature->getKind() == SketchPlugin_Line::ID()) { aType[i] = 1; @@ -204,43 +234,61 @@ bool SketchPlugin_EqualAttrValidator::isValid( aType[i] = 3; continue; } + theError = "The " + aFeature->getKind() + " feature kind of attribute is wrong. It should be " + + SketchPlugin_Line::ID() + " or " + SketchPlugin_Circle::ID() + " or " + + SketchPlugin_Arc::ID(); // wrong type of attribute return false; } if ((aType[0] == 1 && aType[1] == 2) || - (aType[0] == 2 && aType[1] == 1)) + (aType[0] == 2 && aType[1] == 1)) { + theError = "Feature with kinds " + SketchPlugin_Line::ID() + " and " + + SketchPlugin_Circle::ID() + "can not be equal."; return false; + } return true; } -bool SketchPlugin_MirrorAttrValidator::isValid( - const AttributePtr& theAttribute, const std::list& theArguments ) const +bool SketchPlugin_MirrorAttrValidator::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + std::string& theError) const { - FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); - AttributeSelectionListPtr aSelAttr = - std::dynamic_pointer_cast(theAttribute); - if (!aSelAttr) + if (theAttribute->attributeType() != ModelAPI_AttributeRefList::typeId()) { + theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed"; return false; + } + + FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); + AttributeRefListPtr aSelAttr = std::dynamic_pointer_cast(theAttribute); AttributeRefListPtr aRefListOfMirrored = std::dynamic_pointer_cast( aFeature->attribute(SketchPlugin_Constraint::ENTITY_C())); std::list aMirroredObjects = aRefListOfMirrored->list(); for(int anInd = 0; anInd < aSelAttr->size(); anInd++) { - std::shared_ptr aSelect = aSelAttr->value(anInd); + ObjectPtr aSelObject = aSelAttr->object(anInd); + std::string aName = aSelObject.get() ? aSelObject->data()->name() : ""; std::list::iterator aMirIter = aMirroredObjects.begin(); for (; aMirIter != aMirroredObjects.end(); aMirIter++) - if (aSelect->context() == *aMirIter) + if (aSelObject == *aMirIter) { + theError = "The object " + aName + " is a result of mirror"; return false; + } } return true; } -bool SketchPlugin_CoincidenceAttrValidator::isValid( - const AttributePtr& theAttribute, const std::list& theArguments ) const +bool SketchPlugin_CoincidenceAttrValidator::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + std::string& theError) const { + if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) { + theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed"; + return false; + } + // there is a check whether the feature contains a point and a linear edge or two point values std::string aParamA = theArguments.front(); SessionPtr aMgr = ModelAPI_Session::get(); @@ -248,20 +296,28 @@ bool SketchPlugin_CoincidenceAttrValidator::isValid( FeaturePtr aConstraint = std::dynamic_pointer_cast(theAttribute->owner()); AttributeRefAttrPtr aRefAttrA = aConstraint->data()->refattr(aParamA); - if (!aRefAttrA) + if (!aRefAttrA) { + theError = "The " + aParamA + " attribute " + " should be " + ModelAPI_AttributeRefAttr::typeId(); return false; + } AttributeRefAttrPtr aRefAttrB = std::dynamic_pointer_cast(theAttribute); - if (!aRefAttrB) - return false; // first attribute is a point, it may coincide with any object if (!aRefAttrA->isObject()) return true; else { + ObjectPtr anObject = aRefAttrA->object(); + if (!anObject.get()) { + theError = aParamA + " attribute has an empty object"; + return false; + } FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttrA->object()); - if (!aFeature) + if (!aFeature.get()) { + theError = aParamA + " attribute has an empty feature"; return false; + } + if (aFeature->getKind() == SketchPlugin_Point::ID()) return true; } @@ -271,12 +327,236 @@ bool SketchPlugin_CoincidenceAttrValidator::isValid( return true; else { FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttrB->object()); - if (!aFeature) + if (!aFeature) { + theError = theAttribute->id() + " attribute has an empty object"; return false; + } if (aFeature->getKind() == SketchPlugin_Point::ID()) return true; } - + theError = "There is no an attribute filled by a point"; return false; } + +bool SketchPlugin_CopyValidator::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + std::string& theError) const +{ + if (theAttribute->attributeType() != ModelAPI_AttributeRefList::typeId()) { + theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed"; + return false; + } + + FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); + AttributeRefListPtr aSelAttr = + std::dynamic_pointer_cast(theAttribute); + + AttributeRefListPtr aRefListOfInitial = std::dynamic_pointer_cast( + aFeature->attribute(SketchPlugin_Constraint::ENTITY_A())); + AttributeRefListPtr aRefListOfCopied = std::dynamic_pointer_cast( + aFeature->attribute(SketchPlugin_Constraint::ENTITY_B())); + std::list anInitialObjects = aRefListOfInitial->list(); + std::list aCopiedObjects = aRefListOfCopied->list(); + + std::list::iterator anObjIter; + for(int anInd = 0; anInd < aSelAttr->size(); anInd++) { + ObjectPtr aSelObject = aSelAttr->object(anInd); + anObjIter = anInitialObjects.begin(); + for (; anObjIter != anInitialObjects.end(); anObjIter++) + if (aSelObject == *anObjIter) + break; + if (anObjIter != anInitialObjects.end()) + continue; + anObjIter = aCopiedObjects.begin(); + for (; anObjIter != aCopiedObjects.end(); anObjIter++) + if (aSelObject == *anObjIter) { + std::string aName = aSelObject.get() ? aSelObject->data()->name() : ""; + theError = "The object " + aName + " is a result of copy"; + return false; + } + } + return true; +} + +bool SketchPlugin_SolverErrorValidator::isValid(const std::shared_ptr& theFeature, + const std::list& theArguments, + std::string& theError) const +{ + AttributeStringPtr aAttributeString = theFeature->string(SketchPlugin_Sketch::SOLVER_ERROR()); + + if (!aAttributeString->value().empty()) { + theError = aAttributeString->value(); + return false; + } + + return true; +} + +bool SketchPlugin_SolverErrorValidator::isNotObligatory(std::string theFeature, std::string theAttribute) +{ + return true; +} + +bool SketchPlugin_FilletVertexValidator::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + std::string& theError) const +{ + if(!theAttribute.get()) { + return false; + } + + AttributeRefAttrPtr aBase = std::dynamic_pointer_cast(theAttribute); + AttributePtr anAttrBase = aBase->attr(); + if(aBase->isObject()) { + return false; + } + + // If we alredy have some result then: + // - if it is the same point all ok + // - if it is point on the fillet arc then it is not valid + FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); + AttributePtr aBaseLinesAttribute = aFeature->attribute(SketchPlugin_Constraint::ENTITY_C()); + AttributeRefListPtr aRefListOfBaseLines = std::dynamic_pointer_cast(aBaseLinesAttribute); + std::list anOldFeatList = aRefListOfBaseLines->list(); + if(!aRefListOfBaseLines->list().empty()) { + FeaturePtr anOldFeatureA, anOldFeatureB; + std::list::iterator aFeatIt = anOldFeatList.begin(); + anOldFeatureA = ModelAPI_Feature::feature(*aFeatIt++); + anOldFeatureB = ModelAPI_Feature::feature(*aFeatIt); + + AttributePtr anAttrStartA = + anOldFeatureA->attribute(anOldFeatureA->getKind() == SketchPlugin_Line::ID() ? SketchPlugin_Line::START_ID() : SketchPlugin_Arc::START_ID()); + AttributePtr anAttrEndA = + anOldFeatureA->attribute(anOldFeatureA->getKind() == SketchPlugin_Line::ID() ? SketchPlugin_Line::END_ID() : SketchPlugin_Arc::END_ID()); + AttributePtr anAttrStartB = + anOldFeatureB->attribute(anOldFeatureB->getKind() == SketchPlugin_Line::ID() ? SketchPlugin_Line::START_ID() : SketchPlugin_Arc::START_ID()); + AttributePtr anAttrEndB = + anOldFeatureB->attribute(anOldFeatureB->getKind() == SketchPlugin_Line::ID() ? SketchPlugin_Line::END_ID() : SketchPlugin_Arc::END_ID()); + + std::shared_ptr aBasePnt = std::dynamic_pointer_cast(anAttrBase)->pnt(); + std::shared_ptr aStartPntA = std::dynamic_pointer_cast(anAttrStartA)->pnt(); + std::shared_ptr anEndPntA = std::dynamic_pointer_cast(anAttrEndA)->pnt(); + std::shared_ptr aStartPntB = std::dynamic_pointer_cast(anAttrStartB)->pnt(); + std::shared_ptr anEndPntB = std::dynamic_pointer_cast(anAttrEndB)->pnt(); + double aDistBaseStartA = aBasePnt->distance(aStartPntA); + double aDistBaseEndA = aBasePnt->distance(anEndPntA); + double aDistStartAStartB = aStartPntA->distance(aStartPntB); + double aDistStartAEndB = aStartPntA->distance(anEndPntB); + double aDistEndAStartB = anEndPntA->distance(aStartPntB); + double aDistEndAEndB = anEndPntA->distance(anEndPntB); + + if((aDistBaseStartA < tolerance && (aDistStartAStartB < tolerance || aDistStartAEndB < tolerance)) || + (aDistBaseEndA < tolerance && (aDistEndAStartB < tolerance || aDistEndAStartB < tolerance))) { + return true; + } + + // Check that point not on fillet arc + AttributeRefListPtr aRefListOfFillet = std::dynamic_pointer_cast( + aFeature->attribute(SketchPlugin_Constraint::ENTITY_B())); + std::list aNewFeatList = aRefListOfFillet->list(); + if(!aNewFeatList.empty()) { + aFeatIt = aNewFeatList.begin(); + FeaturePtr aNewArc; + //aNewFeatureA = ModelAPI_Feature::feature(*aFeatIt++); + //aNewFeatureB = ModelAPI_Feature::feature(*aFeatIt++); + aFeatIt++; aFeatIt++; + aNewArc = ModelAPI_Feature::feature(*aFeatIt); + AttributePtr anArcStart = aNewArc->attribute(SketchPlugin_Arc::START_ID()); + AttributePtr anArcEnd = aNewArc->attribute(SketchPlugin_Arc::END_ID()); + std::shared_ptr anArcStartPnt = std::dynamic_pointer_cast(anArcStart)->pnt(); + std::shared_ptr anArcEndPnt = std::dynamic_pointer_cast(anArcEnd)->pnt(); + double aDistBaseArcStart = aBasePnt->distance(anArcStartPnt); + double aDistBaseArcEnd = aBasePnt->distance(anArcEndPnt); + if(aDistBaseArcStart < tolerance || aDistBaseArcEnd < tolerance) { + return false; + } + } + } + + const std::set& aRefsList = anAttrBase->owner()->data()->refsToMe(); + std::set::const_iterator aIt; + FeaturePtr aCoincident; + for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) { + std::shared_ptr aAttr = (*aIt); + FeaturePtr aConstrFeature = std::dynamic_pointer_cast(aAttr->owner()); + if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) { + 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(anAttrBase == anAttrA) { + aCoincident = aConstrFeature; + break; + } + } + if(anAttrRefA.get() && !anAttrRefB->isObject()) { + AttributePtr anAttrB = anAttrRefB->attr(); + if(anAttrBase == anAttrB) { + aCoincident = aConstrFeature; + break; + } + } + } + } + + if(!aCoincident.get()) { + return false; + } + + std::set aCoinsides; + SketchPlugin_Tools::findCoincidences(aCoincident, + SketchPlugin_ConstraintCoincidence::ENTITY_A(), + aCoinsides); + SketchPlugin_Tools::findCoincidences(aCoincident, + SketchPlugin_ConstraintCoincidence::ENTITY_B(), + aCoinsides); + // Remove points + std::set aNewLines; + for(std::set::iterator anIt = aCoinsides.begin(); anIt != aCoinsides.end(); ++anIt) { + if((*anIt)->getKind() != SketchPlugin_Point::ID()) { + aNewLines.insert(*anIt); + } + } + aCoinsides = aNewLines; + + // Remove auxilary lines + if(aCoinsides.size() > 2) { + aNewLines.clear(); + for(std::set::iterator anIt = aCoinsides.begin(); anIt != aCoinsides.end(); ++anIt) { + if(!(*anIt)->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value()) { + aNewLines.insert(*anIt); + } + } + aCoinsides = aNewLines; + } + + if(aCoinsides.size() != 2) { + return false; + } + + // Check that lines not collinear + std::set::iterator anIt = aCoinsides.begin(); + FeaturePtr aFirstFeature = *anIt++; + FeaturePtr aSecondFeature = *anIt; + 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 = abs((aFirstEndPnt->x() - aFirstStartPnt->x()) * (aSecondStartPnt->y() - aFirstStartPnt->y()) - + (aSecondStartPnt->x() - aFirstStartPnt->x()) * (aFirstEndPnt->y() - aFirstStartPnt->y())); + double aCheck2 = abs((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) { + return false; + } + } + + return true; +}