X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchPlugin%2FSketchPlugin_Fillet.cpp;h=3916cfb35e1a343b4171f63302a320a779c7d957;hb=faaea2f382805c9a5eb6d1e98a9e10354f62be5d;hp=cb856fdc8bc03e6dde57bf87f887cf754ca6a2f6;hpb=efaccbcdeef7f5da06bbddbd6ffb2209fb78153f;p=modules%2Fshaper.git diff --git a/src/SketchPlugin/SketchPlugin_Fillet.cpp b/src/SketchPlugin/SketchPlugin_Fillet.cpp index cb856fdc8..3916cfb35 100644 --- a/src/SketchPlugin/SketchPlugin_Fillet.cpp +++ b/src/SketchPlugin/SketchPlugin_Fillet.cpp @@ -1,8 +1,22 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> - -// File: SketchPlugin_Fillet.cpp -// Created: 19 Mar 2015 -// Author: Artem ZHIDKOV +// 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_Fillet.h" @@ -10,6 +24,7 @@ #include "SketchPlugin_Line.h" #include "SketchPlugin_Point.h" #include "SketchPlugin_Sketch.h" +#include "SketchPlugin_ConstraintDistance.h" #include "SketchPlugin_ConstraintEqual.h" #include "SketchPlugin_ConstraintCoincidence.h" #include "SketchPlugin_ConstraintLength.h" @@ -18,6 +33,8 @@ #include "SketchPlugin_ConstraintRadius.h" #include "SketchPlugin_Tools.h" +#include +#include #include #include #include @@ -61,9 +78,6 @@ static void calculateFilletCenter(FeaturePtr theFilletFeatures[2], std::shared_ptr& theTangentA, std::shared_ptr& theTangentB); -/// Get coincide edges for fillet -static std::set getCoincides(const FeaturePtr& theConstraintCoincidence); - static std::set findFeaturesToRemove(const FeaturePtr theFeature, const AttributePtr theAttribute); @@ -88,100 +102,61 @@ void SketchPlugin_Fillet::execute() // set flag here to avoid building Fillet presentation if "Redisplay" event appears myFilletCreated = true; - // Calculate Fillet parameters if does not yet - if (!myBaseFeatures[0] || !myBaseFeatures[1]) - calculateFilletParameters(); + // create feature for fillet arc + FeaturePtr aFilletArc = createFilletArc(); - // Create arc feature. - FeaturePtr aFilletArc = sketch()->addFeature(SketchPlugin_Arc::ID()); - - // Set arc attributes. - bool aWasBlocked = aFilletArc->data()->blockSendAttributeUpdated(true); - std::dynamic_pointer_cast( - aFilletArc->attribute(SketchPlugin_Arc::CENTER_ID()))->setValue(myCenterXY->x(), - myCenterXY->y()); - std::shared_ptr aStartPoint = - std::dynamic_pointer_cast( - aFilletArc->attribute(SketchPlugin_Arc::START_ID())); - std::shared_ptr aEndPoint = - std::dynamic_pointer_cast( - aFilletArc->attribute(SketchPlugin_Arc::END_ID())); - if(aStartPoint->isInitialized() && aEndPoint->isInitialized() - && (aStartPoint->pnt()->xy()->distance(myTangentXY1) > tolerance - || aEndPoint->pnt()->xy()->distance(myTangentXY2) > tolerance)) { - std::dynamic_pointer_cast(aFilletArc)->setReversed(false); + // collect features referred to the edges participating in fillet + AttributePoint2DPtr aFilletPoints[2]; + int aFeatInd[2]; + int anAttrInd[2]; + std::set aFeaturesToBeRemoved; + for (int i = 0; i < 2; ++i) { + bool isFirstIndex = (i == 0); + aFeatInd[i] = myIsReversed == isFirstIndex ? 1 : 0; + anAttrInd[i] = (myIsReversed == isFirstIndex ? 2 : 0) + (myIsNotInversed[aFeatInd[i]] ? 0 : 1); + aFilletPoints[i] = std::dynamic_pointer_cast( + myBaseFeatures[aFeatInd[i]]->attribute(myFeatAttributes[anAttrInd[i]])); + std::set aRemove = + findFeaturesToRemove(myBaseFeatures[aFeatInd[i]], aFilletPoints[i]); + aFeaturesToBeRemoved.insert(aRemove.begin(), aRemove.end()); } - aStartPoint->setValue(myTangentXY1->x(), myTangentXY1->y()); - aEndPoint->setValue(myTangentXY2->x(), myTangentXY2->y()); - aFilletArc->data()->blockSendAttributeUpdated(aWasBlocked); - aFilletArc->execute(); - // Delete features with refs to points of edges. - std::shared_ptr aStartPoint1; - int aFeatInd1 = myIsReversed ? 1 : 0; - int anAttrInd1 = (myIsReversed ? 2 : 0) + (myIsNotInversed[aFeatInd1] ? 0 : 1); - aStartPoint1 = std::dynamic_pointer_cast( - myBaseFeatures[aFeatInd1]->attribute(myFeatAttributes[anAttrInd1])); - std::set aFeaturesToBeRemoved1 = - findFeaturesToRemove(myBaseFeatures[aFeatInd1], aStartPoint1); - - std::shared_ptr aStartPoint2; - int aFeatInd2 = myIsReversed ? 0 : 1; - int anAttrInd2 = (myIsReversed ? 0 : 2) + (myIsNotInversed[aFeatInd2] ? 0 : 1); - aStartPoint2 = std::dynamic_pointer_cast( - myBaseFeatures[aFeatInd2]->attribute(myFeatAttributes[anAttrInd2])); - std::set aFeaturesToBeRemoved2 = - findFeaturesToRemove(myBaseFeatures[aFeatInd2], aStartPoint2); - - aFeaturesToBeRemoved1.insert(aFeaturesToBeRemoved2.begin(), aFeaturesToBeRemoved2.end()); - ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToBeRemoved1); - Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED)); + // keep "distance" constraints and remove all other references + removeReferencesButKeepDistances(aFeaturesToBeRemoved, aFilletPoints); // Update fillet edges. recalculateAttributes(aFilletArc, SketchPlugin_Arc::START_ID(), - myBaseFeatures[aFeatInd1], myFeatAttributes[anAttrInd1]); + myBaseFeatures[aFeatInd[0]], myFeatAttributes[anAttrInd[0]]); recalculateAttributes(aFilletArc, SketchPlugin_Arc::END_ID(), - myBaseFeatures[aFeatInd2], myFeatAttributes[anAttrInd2]); + myBaseFeatures[aFeatInd[1]], myFeatAttributes[anAttrInd[1]]); + + FeaturePtr aConstraint; // Create coincidence features. - FeaturePtr aConstraint = sketch()->addFeature(SketchPlugin_ConstraintCoincidence::ID()); - AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( - aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A())); - aRefAttr->setAttr(aFilletArc->attribute(SketchPlugin_Arc::START_ID())); - aRefAttr = std::dynamic_pointer_cast( - aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B())); - aRefAttr->setAttr(myBaseFeatures[aFeatInd1]->attribute(myFeatAttributes[anAttrInd1])); - aConstraint->execute(); + aConstraint = SketchPlugin_Tools::createConstraint(sketch(), + SketchPlugin_ConstraintCoincidence::ID(), + aFilletArc->attribute(SketchPlugin_Arc::START_ID()), + myBaseFeatures[aFeatInd[0]]->attribute(myFeatAttributes[anAttrInd[0]])); ModelAPI_EventCreator::get()->sendUpdated(aConstraint, anUpdateEvent); - aConstraint = sketch()->addFeature(SketchPlugin_ConstraintCoincidence::ID()); - aRefAttr = std::dynamic_pointer_cast( - aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A())); - aRefAttr->setAttr(aFilletArc->attribute(SketchPlugin_Arc::END_ID())); - aRefAttr = std::dynamic_pointer_cast( - aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B())); - aRefAttr->setAttr(myBaseFeatures[aFeatInd2]->attribute(myFeatAttributes[anAttrInd2])); - aConstraint->execute(); + aConstraint = SketchPlugin_Tools::createConstraint(sketch(), + SketchPlugin_ConstraintCoincidence::ID(), + aFilletArc->attribute(SketchPlugin_Arc::END_ID()), + myBaseFeatures[aFeatInd[1]]->attribute(myFeatAttributes[anAttrInd[1]])); ModelAPI_EventCreator::get()->sendUpdated(aConstraint, anUpdateEvent); // Create tangent features. for (int i = 0; i < 2; i++) { - aConstraint = sketch()->addFeature(SketchPlugin_ConstraintTangent::ID()); - aRefAttr = std::dynamic_pointer_cast( - aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A())); - aRefAttr->setObject(aFilletArc->lastResult()); - aRefAttr = std::dynamic_pointer_cast( - aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B())); - bool isArc = myBaseFeatures[i]->getKind() == SketchPlugin_Arc::ID(); - aRefAttr->setObject(isArc ? myBaseFeatures[i]->lastResult() : - myBaseFeatures[i]->firstResult()); + aConstraint = SketchPlugin_Tools::createConstraint(sketch(), + SketchPlugin_ConstraintTangent::ID(), + aFilletArc->lastResult(), + myBaseFeatures[i]->lastResult()); aConstraint->execute(); ModelAPI_EventCreator::get()->sendUpdated(aConstraint, anUpdateEvent); } // Send events to update the sub-features by the solver. - if(isUpdateFlushed) { + if (isUpdateFlushed) Events_Loop::loop()->setFlushed(anUpdateEvent, true); - } } AISObjectPtr SketchPlugin_Fillet::getAISObject(AISObjectPtr thePrevious) @@ -228,11 +203,17 @@ bool SketchPlugin_Fillet::calculateFilletParameters() if (!aFilletPoint2D.get()) return false; - if (!findFeaturesContainingFilletPoint(aFilletPoint2D)) { + std::set aFilletFeatures = + SketchPlugin_Tools::findFeaturesCoincidentToPoint(aFilletPoint2D); + if (aFilletFeatures.size() != 2) { setError("Error: Selected point does not have two suitable edges for fillet."); return false; } + std::set::iterator aFIt = aFilletFeatures.begin(); + myBaseFeatures[0] = *aFIt; + myBaseFeatures[1] = *(++aFIt); + std::shared_ptr aFilletPnt2d = aFilletPoint2D->pnt(); double aRadius = calculateFilletRadius(myBaseFeatures); @@ -312,49 +293,174 @@ bool SketchPlugin_Fillet::calculateFilletParameters() return true; } -bool SketchPlugin_Fillet::findFeaturesContainingFilletPoint( - std::shared_ptr theFilletPoint) +FeaturePtr SketchPlugin_Fillet::createFilletArc() { - // Obtain constraint coincidence for the fillet point. - FeaturePtr aConstraintCoincidence; - const std::set& aRefsList = theFilletPoint->owner()->data()->refsToMe(); - for(std::set::const_iterator anIt = aRefsList.cbegin(); - anIt != aRefsList.cend(); - ++anIt) { - std::shared_ptr anAttr = (*anIt); - FeaturePtr aFeature = std::dynamic_pointer_cast(anAttr->owner()); - if(aFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) { - AttributeRefAttrPtr anAttrRefA = - aFeature->refattr(SketchPlugin_ConstraintCoincidence::ENTITY_A()); - AttributeRefAttrPtr anAttrRefB = - aFeature->refattr(SketchPlugin_ConstraintCoincidence::ENTITY_B()); - if(anAttrRefA.get() && !anAttrRefA->isObject()) { - AttributePtr anAttrA = anAttrRefA->attr(); - if(theFilletPoint == anAttrA) { - aConstraintCoincidence = aFeature; - break; + // Calculate Fillet parameters if does not yet + if (!myBaseFeatures[0] || !myBaseFeatures[1]) + calculateFilletParameters(); + + // Create arc feature. + FeaturePtr aFilletArc = sketch()->addFeature(SketchPlugin_Arc::ID()); + + // Set arc attributes. + bool aWasBlocked = aFilletArc->data()->blockSendAttributeUpdated(true); + std::dynamic_pointer_cast( + aFilletArc->attribute(SketchPlugin_Arc::CENTER_ID()))->setValue(myCenterXY->x(), + myCenterXY->y()); + std::shared_ptr aStartPoint = + std::dynamic_pointer_cast( + aFilletArc->attribute(SketchPlugin_Arc::START_ID())); + std::shared_ptr aEndPoint = + std::dynamic_pointer_cast( + aFilletArc->attribute(SketchPlugin_Arc::END_ID())); + if(aStartPoint->isInitialized() && aEndPoint->isInitialized() + && (aStartPoint->pnt()->xy()->distance(myTangentXY1) > tolerance + || aEndPoint->pnt()->xy()->distance(myTangentXY2) > tolerance)) { + std::dynamic_pointer_cast(aFilletArc)->setReversed(false); + } + aStartPoint->setValue(myTangentXY1->x(), myTangentXY1->y()); + aEndPoint->setValue(myTangentXY2->x(), myTangentXY2->y()); + aFilletArc->data()->blockSendAttributeUpdated(aWasBlocked); + aFilletArc->execute(); + + return aFilletArc; +} + +FeaturePtr SketchPlugin_Fillet::createFilletApex(const GeomPnt2dPtr& theCoordinates) +{ + FeaturePtr anApex = sketch()->addFeature(SketchPlugin_Point::ID()); + AttributePoint2DPtr aCoord = std::dynamic_pointer_cast( + anApex->attribute(SketchPlugin_Point::COORD_ID())); + aCoord->setValue(theCoordinates); + + // additional coincidence constraints + static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); + FeaturePtr aConstraint; + for (int i = 0; i < 2; i++) { + aConstraint = SketchPlugin_Tools::createConstraint(sketch(), + SketchPlugin_ConstraintCoincidence::ID(), + aCoord, + myBaseFeatures[i]->lastResult()); + aConstraint->execute(); + ModelAPI_EventCreator::get()->sendUpdated(aConstraint, anUpdateEvent); + } + + return anApex; +} + +void SketchPlugin_Fillet::removeReferencesButKeepDistances( + std::set& theFeaturesToRemove, + const AttributePoint2DPtr theFilletPoints[2]) +{ + FeaturePtr aFilletApex; + struct Length { + AttributePtr myPoints[2]; + std::string myValueText; + double myValueDouble; + GeomPnt2dPtr myFlyoutPoint; + int myLocationType; + }; + std::list aLengthToDistance; + + std::set::iterator aFeat = theFeaturesToRemove.begin(); + while (aFeat != theFeaturesToRemove.end()) { + std::shared_ptr aDistance = + std::dynamic_pointer_cast(*aFeat); + if (aDistance) { + if (!aFilletApex) + aFilletApex = createFilletApex(theFilletPoints[0]->pnt()); + // update attributes of distance constraints + bool isUpdated = false; + for (int attrInd = 0; attrInd < CONSTRAINT_ATTR_SIZE && !isUpdated; ++attrInd) { + AttributeRefAttrPtr aRefAttr = + aDistance->refattr(SketchPlugin_Constraint::ATTRIBUTE(attrInd)); + if (aRefAttr && !aRefAttr->isObject() && + (aRefAttr->attr() == theFilletPoints[0] || aRefAttr->attr() == theFilletPoints[1])) { + aRefAttr->setAttr(aFilletApex->attribute(SketchPlugin_Point::COORD_ID())); + isUpdated = true; } } - if(anAttrRefB.get() && !anAttrRefB->isObject()) { - AttributePtr anAttrB = anAttrRefB->attr(); - if(theFilletPoint == anAttrB) { - aConstraintCoincidence = aFeature; - break; + // avoid distance from removing if it is updated + std::set::iterator aKeepIt = aFeat++; + if (isUpdated) + theFeaturesToRemove.erase(aKeepIt); + + } else { + std::shared_ptr aLength = + std::dynamic_pointer_cast(*aFeat); + if (aLength) { + if (!aFilletApex) + aFilletApex = createFilletApex(theFilletPoints[0]->pnt()); + // remove Length, but create new distance constraint + AttributeRefAttrPtr aRefAttr = + aLength->refattr(SketchPlugin_Constraint::ENTITY_A()); + FeaturePtr aLine = ModelAPI_Feature::feature(aRefAttr->object()); + if (aLine) { + aLengthToDistance.push_back(Length()); + Length& aNewLength = aLengthToDistance.back(); + // main attrbutes + for (int i = 0; i < 2; ++i) { + AttributePtr anAttr = aLine->attribute( + i == 0 ? SketchPlugin_Line::START_ID() : SketchPlugin_Line::END_ID()); + if (anAttr == theFilletPoints[0] || anAttr == theFilletPoints[1]) + aNewLength.myPoints[i] = aFilletApex->attribute(SketchPlugin_Point::COORD_ID()); + else + aNewLength.myPoints[i] = anAttr; + } + // value + AttributeDoublePtr aValue = aLength->real(SketchPlugin_Constraint::VALUE()); + aNewLength.myValueDouble = aValue->value(); + aNewLength.myValueText = aValue->text(); + // auxiliary attributes + AttributePoint2DPtr aFlyoutAttr = std::dynamic_pointer_cast( + aLength->attribute(SketchPlugin_ConstraintLength::FLYOUT_VALUE_PNT())); + if (aFlyoutAttr && aFlyoutAttr->isInitialized()) + aNewLength.myFlyoutPoint = aFlyoutAttr->pnt(); + AttributeIntegerPtr aLocationAttr = + aLength->integer(SketchPlugin_ConstraintLength::LOCATION_TYPE_ID()); + if (aLocationAttr && aLocationAttr->isInitialized()) + aNewLength.myLocationType = aLocationAttr->value(); + else + aNewLength.myLocationType = -1; } } + + ++aFeat; } } - if(!aConstraintCoincidence.get()) - return false; - - // Get coincide edges. - std::set anEdgeFeatures = getCoincides(aConstraintCoincidence); - std::set::iterator aLinesIt = anEdgeFeatures.begin(); - for (int i = 0; aLinesIt != anEdgeFeatures.end() && i < 2; ++aLinesIt, ++i) - myBaseFeatures[i] = *aLinesIt; + // remove references + ModelAPI_Tools::removeFeaturesAndReferences(theFeaturesToRemove); + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED)); - return myBaseFeatures[0] && myBaseFeatures[1]; + // restore Length constraints as point-point distances + FeaturePtr aConstraint; + std::list::iterator anIt = aLengthToDistance.begin(); + for (; anIt != aLengthToDistance.end(); ++anIt) { + aConstraint = SketchPlugin_Tools::createConstraint(sketch(), + SketchPlugin_ConstraintDistance::ID(), anIt->myPoints[0], anIt->myPoints[1]); + // set value + AttributeDoublePtr aValue = aConstraint->real(SketchPlugin_Constraint::VALUE()); + if (anIt->myValueText.empty()) + aValue->setValue(anIt->myValueDouble); + else + aValue->setText(anIt->myValueText); + // set flyout point if exists + if (anIt->myFlyoutPoint) { + AttributePoint2DPtr aFlyoutAttr = std::dynamic_pointer_cast( + aConstraint->attribute(SketchPlugin_ConstraintDistance::FLYOUT_VALUE_PNT())); + aFlyoutAttr->setValue(anIt->myFlyoutPoint); + } + // set location type if initialized + if (anIt->myLocationType >= 0) { + AttributeIntegerPtr aLocationType = + aConstraint->integer(SketchPlugin_ConstraintDistance::LOCATION_TYPE_ID()); + aLocationType->setValue(anIt->myLocationType); + } + aConstraint->execute(); + ModelAPI_EventCreator::get()->sendUpdated(aConstraint, + Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); + } } // ========= Auxiliary functions ================= @@ -451,57 +557,6 @@ double calculateFilletRadius(FeaturePtr theFilletFeatures[2]) return std::min(aLengths[0], aLengths[1]) / 6.0; } -std::set getCoincides(const FeaturePtr& theConstraintCoincidence) -{ - std::set aCoincides; - - std::shared_ptr aFilletPnt = - SketchPlugin_Tools::getCoincidencePoint(theConstraintCoincidence); - - SketchPlugin_Tools::findCoincidences(theConstraintCoincidence, - SketchPlugin_ConstraintCoincidence::ENTITY_A(), - aCoincides); - SketchPlugin_Tools::findCoincidences(theConstraintCoincidence, - SketchPlugin_ConstraintCoincidence::ENTITY_B(), - aCoincides); - - // Remove points from set of coincides. - std::set aNewSetOfCoincides; - for(std::set::iterator anIt = aCoincides.begin(); anIt != aCoincides.end(); ++anIt) { - std::shared_ptr aSketchEntity = - std::dynamic_pointer_cast(*anIt); - if(aSketchEntity.get() && aSketchEntity->isCopy()) { - continue; - } - if((*anIt)->getKind() == SketchPlugin_Line::ID()) { - aNewSetOfCoincides.insert(*anIt); - } else if((*anIt)->getKind() == SketchPlugin_Arc::ID()) { - AttributePtr anAttrCenter = (*anIt)->attribute(SketchPlugin_Arc::CENTER_ID()); - std::shared_ptr aPointCenter2D = - std::dynamic_pointer_cast(anAttrCenter); - if(aPointCenter2D.get() && aFilletPnt->isEqual(aPointCenter2D->pnt())) { - continue; - } - aNewSetOfCoincides.insert(*anIt); - } - } - aCoincides = aNewSetOfCoincides; - - // If we still have more than two coincides remove auxilary entities from set of coincides. - if(aCoincides.size() > 2) { - aNewSetOfCoincides.clear(); - for(std::set::iterator - anIt = aCoincides.begin(); anIt != aCoincides.end(); ++anIt) { - if(!(*anIt)->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value()) { - aNewSetOfCoincides.insert(*anIt); - } - } - aCoincides = aNewSetOfCoincides; - } - - return aCoincides; -} - std::set findFeaturesToRemove(const FeaturePtr theFeature, const AttributePtr theAttribute) { std::set aFeaturesToBeRemoved;