From 75ef657b4bf17c7805df0b0bc3aab14611f4268c Mon Sep 17 00:00:00 2001 From: dbv Date: Mon, 2 Nov 2015 15:43:52 +0300 Subject: [PATCH] Fillet creation by point --- .../SketchPlugin_ConstraintFillet.cpp | 132 ++++++++++++------ src/SketchPlugin/SketchPlugin_Plugin.cpp | 2 + src/SketchPlugin/SketchPlugin_Sketch.cpp | 2 +- src/SketchPlugin/SketchPlugin_Tools.cpp | 43 ++++++ src/SketchPlugin/SketchPlugin_Tools.h | 18 +++ src/SketchPlugin/SketchPlugin_Validators.cpp | 60 ++++++++ src/SketchPlugin/SketchPlugin_Validators.h | 18 +++ src/SketchPlugin/plugin-Sketch.xml | 30 ++-- 8 files changed, 243 insertions(+), 62 deletions(-) diff --git a/src/SketchPlugin/SketchPlugin_ConstraintFillet.cpp b/src/SketchPlugin/SketchPlugin_ConstraintFillet.cpp index a9f00c9f4..25d2daf2a 100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintFillet.cpp +++ b/src/SketchPlugin/SketchPlugin_ConstraintFillet.cpp @@ -25,8 +25,10 @@ #include #include #include +#include #include +#include #include #include @@ -46,7 +48,6 @@ static void calculateFilletCenter(FeaturePtr theFeatureA, FeaturePtr theFeatureB std::shared_ptr& theTangentA, std::shared_ptr& theTangentB); - SketchPlugin_ConstraintFillet::SketchPlugin_ConstraintFillet() { } @@ -55,11 +56,10 @@ void SketchPlugin_ConstraintFillet::initAttributes() { data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeDouble::typeId()); data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId()); - data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId()); - data()->addAttribute(SketchPlugin_Constraint::ENTITY_C(), ModelAPI_AttributeRefList::typeId()); + data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefList::typeId()); data()->addAttribute(PREVIOUS_VALUE, ModelAPI_AttributeDouble::typeId()); // initialize attribute not applicable for user - ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_C()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_B()); data()->attribute(PREVIOUS_VALUE)->setInitialized(); std::dynamic_pointer_cast(data()->attribute(PREVIOUS_VALUE))->setValue(0.0); } @@ -79,32 +79,83 @@ void SketchPlugin_ConstraintFillet::execute() aData->attribute(SketchPlugin_Constraint::VALUE()))->value(); AttributeRefAttrPtr aBaseA = std::dynamic_pointer_cast( aData->attribute(SketchPlugin_Constraint::ENTITY_A())); - AttributeRefAttrPtr aBaseB = std::dynamic_pointer_cast( - aData->attribute(SketchPlugin_Constraint::ENTITY_B())); - if (!aBaseA->isInitialized() || !aBaseB->isInitialized() || - !aBaseA->isObject() || !aBaseB->isObject()) + if (!aBaseA->isInitialized() || aBaseA->isObject()) { + setError("Bad vertex selected"); return; + } + // Check the fillet shapes is not initialized yet AttributeRefListPtr aRefListOfFillet = std::dynamic_pointer_cast( - aData->attribute(SketchPlugin_Constraint::ENTITY_C())); + aData->attribute(SketchPlugin_Constraint::ENTITY_B())); bool needNewObjects = aRefListOfFillet->size() == 0; - // Obtain features for the base objects - FeaturePtr aFeatureA, aFeatureB; - aRC = std::dynamic_pointer_cast(aBaseA->object()); - if (aRC) aFeatureA = aRC->document()->feature(aRC); - aRC = std::dynamic_pointer_cast(aBaseB->object()); - if (aRC) aFeatureB = aRC->document()->feature(aRC); - if (!aFeatureA || !aFeatureB) + // Obtain base features + AttributePtr anAttrBase = aBaseA->attr(); + 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()) { + setError("No coincident edges at selected vertex"); + return; + } + + std::set aCoinsideLines; + SketchPlugin_Tools::findCoincidences(aCoincident, + SketchPlugin_ConstraintCoincidence::ENTITY_A(), + aCoinsideLines); + SketchPlugin_Tools::findCoincidences(aCoincident, + SketchPlugin_ConstraintCoincidence::ENTITY_B(), + aCoinsideLines); + if(aCoinsideLines.size() != 2) { + setError("At selected vertex should be two coincident lines"); + return; + } + + std::set::iterator aLinesIt = aCoinsideLines.begin(); + FeaturePtr anOldFeatureA = *aLinesIt; + if(!anOldFeatureA) { + setError("One of the edges is empty"); + return; + } + aLinesIt++; + FeaturePtr anOldFeatureB = *aLinesIt; + if(!anOldFeatureB) { + setError("One of the edges is empty"); return; + } FeaturePtr aNewFeatureA, aNewFeatureB, aNewArc; if (needNewObjects) { // Create list of objects composing a fillet // copy aFeatureA - aNewFeatureA = SketchPlugin_Sketch::addUniqueNamedCopiedFeature(aFeatureA, sketch()); + aNewFeatureA = SketchPlugin_Sketch::addUniqueNamedCopiedFeature(anOldFeatureB, sketch()); // copy aFeatureB - aNewFeatureB = SketchPlugin_Sketch::addUniqueNamedCopiedFeature(aFeatureB, sketch()); + aNewFeatureB = SketchPlugin_Sketch::addUniqueNamedCopiedFeature(anOldFeatureB, sketch()); // create filleting arc (it will be attached to the list later) aNewArc = sketch()->addFeature(SketchPlugin_Arc::ID()); } else { @@ -118,7 +169,7 @@ void SketchPlugin_ConstraintFillet::execute() // Calculate arc attributes static const int aNbFeatures = 2; - FeaturePtr aFeature[aNbFeatures] = {aFeatureA, aFeatureB}; + FeaturePtr aFeature[aNbFeatures] = {anOldFeatureA, anOldFeatureB}; FeaturePtr aNewFeature[aNbFeatures] = {aNewFeatureA, aNewFeatureB}; std::shared_ptr aTangentDir[aNbFeatures]; // tangent directions of the features in coincident point bool isStart[aNbFeatures]; // indicates which point the features share @@ -194,7 +245,7 @@ void SketchPlugin_ConstraintFillet::execute() // Calculate fillet arc parameters std::shared_ptr aCenter, aTangentPntA, aTangentPntB; - calculateFilletCenter(aFeatureA, aFeatureB, aFilletRadius, isStart, aCenter, aTangentPntA, aTangentPntB); + calculateFilletCenter(anOldFeatureA, anOldFeatureB, aFilletRadius, isStart, aCenter, aTangentPntA, aTangentPntB); // update features std::dynamic_pointer_cast( aNewFeatureA->attribute(aFeatAttributes[isStart[0] ? 0 : 1]))->setValue( @@ -260,18 +311,18 @@ void SketchPlugin_ConstraintFillet::execute() myProducedFeatures.push_back(aConstraint); ModelAPI_EventCreator::get()->sendUpdated(aConstraint, anUpdateEvent); // 2. Fillet arc radius - aConstraint = sketch()->addFeature(SketchPlugin_ConstraintRadius::ID()); - aRefAttr = std::dynamic_pointer_cast( - aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A())); - aRefAttr->setObject(aNewArc->lastResult()); - std::dynamic_pointer_cast( - aConstraint->attribute(SketchPlugin_Constraint::VALUE()))->setValue(aFilletRadius); - std::dynamic_pointer_cast( - aConstraint->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()))->setValue( - isStart[0] ? aStartEndPnt[0] : aStartEndPnt[1]); - aConstraint->execute(); - myProducedFeatures.push_back(aConstraint); - ModelAPI_EventCreator::get()->sendUpdated(aConstraint, anUpdateEvent); + //aConstraint = sketch()->addFeature(SketchPlugin_ConstraintRadius::ID()); + //aRefAttr = std::dynamic_pointer_cast( + // aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A())); + //aRefAttr->setObject(aNewArc->lastResult()); + //std::dynamic_pointer_cast( + // aConstraint->attribute(SketchPlugin_Constraint::VALUE()))->setValue(aFilletRadius); + //std::dynamic_pointer_cast( + // aConstraint->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()))->setValue( + // isStart[0] ? aStartEndPnt[0] : aStartEndPnt[1]); + //aConstraint->execute(); + //myProducedFeatures.push_back(aConstraint); + //ModelAPI_EventCreator::get()->sendUpdated(aConstraint, anUpdateEvent); // 3. Tangency of fillet arc and features for (int i = 0; i < aNbFeatures; i++) { aConstraint = sketch()->addFeature(SketchPlugin_ConstraintTangent::ID()); @@ -311,14 +362,14 @@ void SketchPlugin_ConstraintFillet::execute() myProducedFeatures.push_back(aConstraint); } // make base features auxiliary - aFeatureA->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(true); - aFeatureB->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(true); + anOldFeatureA->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(true); + anOldFeatureB->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(true); myBaseObjects.clear(); - myBaseObjects.push_back(aFeatureA); - myBaseObjects.push_back(aFeatureB); + myBaseObjects.push_back(anOldFeatureA); + myBaseObjects.push_back(anOldFeatureB); // exchange the naming IDs of newly created and old line that become auxiliary - sketch()->exchangeIDs(aFeatureA, aNewFeatureA); - sketch()->exchangeIDs(aFeatureB, aNewFeatureB); + sketch()->exchangeIDs(anOldFeatureA, aNewFeatureA); + sketch()->exchangeIDs(anOldFeatureB, aNewFeatureB); } else { // Update radius value int aNbSubs = sketch()->numberOfSubs(); @@ -354,11 +405,10 @@ void SketchPlugin_ConstraintFillet::execute() void SketchPlugin_ConstraintFillet::attributeChanged(const std::string& theID) { - if (theID == SketchPlugin_Constraint::ENTITY_A() || - theID == SketchPlugin_Constraint::ENTITY_B()) { + if (theID == SketchPlugin_Constraint::ENTITY_A()) { // clear the list of fillet entities AttributeRefListPtr aRefListOfFillet = std::dynamic_pointer_cast( - data()->attribute(SketchPlugin_Constraint::ENTITY_C())); + data()->attribute(SketchPlugin_Constraint::ENTITY_B())); aRefListOfFillet->clear(); // remove all produced objects and constraints diff --git a/src/SketchPlugin/SketchPlugin_Plugin.cpp b/src/SketchPlugin/SketchPlugin_Plugin.cpp index cfa5e8a09..a40e77722 100644 --- a/src/SketchPlugin/SketchPlugin_Plugin.cpp +++ b/src/SketchPlugin/SketchPlugin_Plugin.cpp @@ -70,6 +70,8 @@ SketchPlugin_Plugin::SketchPlugin_Plugin() new SketchPlugin_CopyValidator); aFactory->registerValidator("SketchPlugin_SolverErrorValidator", new SketchPlugin_SolverErrorValidator); + aFactory->registerValidator("SketchPlugin_FilletVertexValidator", + new SketchPlugin_FilletVertexValidator); // register this plugin ModelAPI_Session::get()->registerPlugin(this); diff --git a/src/SketchPlugin/SketchPlugin_Sketch.cpp b/src/SketchPlugin/SketchPlugin_Sketch.cpp index 21247d13a..3f6c91b59 100644 --- a/src/SketchPlugin/SketchPlugin_Sketch.cpp +++ b/src/SketchPlugin/SketchPlugin_Sketch.cpp @@ -301,7 +301,7 @@ FeaturePtr SketchPlugin_Sketch::addUniqueNamedCopiedFeature(FeaturePtr theFeatur // as a name for the feature, the generated unique name is set aNewFeature->data()->setName(aUniqueFeatureName); // text expressions could block setValue of some attributes - clearExpressions(aNewFeature); + SketchPlugin_Tools::clearExpressions(aNewFeature); return aNewFeature; } diff --git a/src/SketchPlugin/SketchPlugin_Tools.cpp b/src/SketchPlugin/SketchPlugin_Tools.cpp index 134e00ddf..297649e62 100644 --- a/src/SketchPlugin/SketchPlugin_Tools.cpp +++ b/src/SketchPlugin/SketchPlugin_Tools.cpp @@ -9,6 +9,10 @@ #include #include #include +#include +#include + +namespace SketchPlugin_Tools { void clearExpressions(AttributeDoublePtr theAttribute) { @@ -55,3 +59,42 @@ void clearExpressions(FeaturePtr theFeature) clearExpressions(*anAttributeIt); } } + +std::shared_ptr getCoincidencePoint(FeaturePtr theStartCoin) +{ + std::shared_ptr aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(), + SketchPlugin_Constraint::ENTITY_A()); + if (aPnt.get() == NULL) + aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(), SketchPlugin_Constraint::ENTITY_B()); + return aPnt; +} + +void findCoincidences(FeaturePtr theStartCoin, + std::string theAttr, + std::set& theList) +{ + AttributeRefAttrPtr aPnt = theStartCoin->refattr(theAttr); + if (!aPnt) return; + FeaturePtr aObj = ModelAPI_Feature::feature(aPnt->object()); + if (theList.find(aObj) == theList.end()) { + std::shared_ptr aOrig = getCoincidencePoint(theStartCoin); + if (aOrig.get() == NULL) + return; + theList.insert(aObj); + const std::set& aRefsList = aObj->data()->refsToMe(); + std::set::const_iterator aIt; + 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()) { + std::shared_ptr aPnt = getCoincidencePoint(aConstrFeature); + if (aPnt.get() && aOrig->isEqual(aPnt)) { + findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A(), theList); + findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B(), theList); + } + } + } + } +} + +} // namespace SketchPlugin_Tools diff --git a/src/SketchPlugin/SketchPlugin_Tools.h b/src/SketchPlugin/SketchPlugin_Tools.h index a574db78a..9123cab7a 100644 --- a/src/SketchPlugin/SketchPlugin_Tools.h +++ b/src/SketchPlugin/SketchPlugin_Tools.h @@ -7,9 +7,27 @@ #ifndef SKETCHPLUGIN_TOOLS_H_ #define SKETCHPLUGIN_TOOLS_H_ +#include + #include +namespace SketchPlugin_Tools { + /// Clears text expressions for all attributes of the feature void clearExpressions(FeaturePtr theFeature); +/// \return coincidence point +/// \param[in] theStartCoin coincidence feature +std::shared_ptr getCoincidencePoint(FeaturePtr theStartCoin); + +/// Finds lines coincident at point +/// \param[in] theStartCoin coincidence feature +/// \param[in] theAttr attribute name +/// \param[out] theList list of lines +void findCoincidences(FeaturePtr theStartCoin, + std::string theAttr, + std::set& theList); + +}; // namespace SketchPlugin_Tools + #endif // SKETCHPLUGIN_TOOLS_H_ \ No newline at end of file diff --git a/src/SketchPlugin/SketchPlugin_Validators.cpp b/src/SketchPlugin/SketchPlugin_Validators.cpp index be53bdcf7..9c8dd5809 100755 --- a/src/SketchPlugin/SketchPlugin_Validators.cpp +++ b/src/SketchPlugin/SketchPlugin_Validators.cpp @@ -14,6 +14,7 @@ #include "SketchPlugin_Line.h" #include "SketchPlugin_Point.h" #include "SketchPlugin_Sketch.h" +#include "SketchPlugin_Tools.h" #include "SketcherPrs_Tools.h" @@ -398,3 +399,62 @@ bool SketchPlugin_SolverErrorValidator::isNotObligatory(std::string theFeature, 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); + if (aBase->isObject()) { + return false; + } + + AttributePtr anAttrBase = aBase->attr(); + 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 aCoinsideLines; + SketchPlugin_Tools::findCoincidences(aCoincident, + SketchPlugin_ConstraintCoincidence::ENTITY_A(), + aCoinsideLines); + SketchPlugin_Tools::findCoincidences(aCoincident, + SketchPlugin_ConstraintCoincidence::ENTITY_B(), + aCoinsideLines); + if(aCoinsideLines.size() != 2) { + return false; + } + + return true; +} diff --git a/src/SketchPlugin/SketchPlugin_Validators.h b/src/SketchPlugin/SketchPlugin_Validators.h index da003f8b0..966f33be1 100644 --- a/src/SketchPlugin/SketchPlugin_Validators.h +++ b/src/SketchPlugin/SketchPlugin_Validators.h @@ -162,4 +162,22 @@ class SketchPlugin_SolverErrorValidator : public ModelAPI_FeatureValidator virtual bool isNotObligatory(std::string theFeature, std::string theAttribute); }; +/**\class SketchPlugin_FilletVertexValidator + * \ingroup Validators + * \brief Validator for the point for fillet creation. + * + * Checks that selected point have exactly two coincident lines. + */ +class SketchPlugin_FilletVertexValidator : public ModelAPI_AttributeValidator +{ + public: + //! returns true if attribute is valid + //! \param theAttribute the checked attribute + //! \param theArguments arguments of the attribute (not used) + //! \param theError error message + virtual bool isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + std::string& theError) const; +}; + #endif diff --git a/src/SketchPlugin/plugin-Sketch.xml b/src/SketchPlugin/plugin-Sketch.xml index 546a445cc..3891315ef 100644 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@ -41,6 +41,16 @@ + + + + + + + + + @@ -245,26 +255,6 @@ - - - - - - - - - - - - - - - - - -