X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FSketchSolver_ConstraintMirror.cpp;h=b92a37827dae014494ccf8553649bc933091964c;hb=b3431dc6aec2a17936648af6eabd3df1a2b2affc;hp=0bccf4f0495ae3547c4d0c4d7dac714ec3d7d940;hpb=dd09fdea5a1f4a8775c48bcfc8de6650793d0cf2;p=modules%2Fshaper.git diff --git a/src/SketchSolver/SketchSolver_ConstraintMirror.cpp b/src/SketchSolver/SketchSolver_ConstraintMirror.cpp index 0bccf4f04..b92a37827 100644 --- a/src/SketchSolver/SketchSolver_ConstraintMirror.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintMirror.cpp @@ -1,137 +1,213 @@ +// Copyright (C) 2014-2022 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 #include -#include +#include +#include + +#include +#include +#include +#include #include +#include +#include +#include + + +static void mirrorPoints(const std::shared_ptr& theMirrorLine, + const AttributePoint2DPtr& theOriginal, + const AttributePoint2DPtr& theMirrored); + +static void mirrorEntities(const std::shared_ptr& theMirrorLine, + const FeaturePtr& theOriginal, + const FeaturePtr& theMirrored); + + void SketchSolver_ConstraintMirror::getAttributes( - EntityWrapperPtr& theMirrorLine, - std::vector& theBaseEntities, - std::vector& theMirrorEntities) + EntityWrapperPtr&, + std::vector&) { - AttributePtr aMirLineAttr = myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()); AttributeRefAttrPtr aMirLineRefAttr = - std::dynamic_pointer_cast(aMirLineAttr); + myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A()); if (!aMirLineRefAttr || !aMirLineRefAttr->isInitialized() || !aMirLineRefAttr->isObject()) { myErrorMsg = SketchSolver_Error::NOT_INITIALIZED(); return; } + FeaturePtr aMirrorLine = ModelAPI_Feature::feature(aMirLineRefAttr->object()); + myFeatures.insert(aMirrorLine); + myType = TYPE(myBaseConstraint); - myStorage->update(aMirLineAttr/*, myGroupID*/); - theMirrorLine = myStorage->entity(aMirLineAttr); - - // Create SolveSpace entity for all features - AttributeRefListPtr aBaseRefList = std::dynamic_pointer_cast( - myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B())); - AttributeRefListPtr aMirroredRefList = std::dynamic_pointer_cast( - myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_C())); + myStorage->update(aMirrorLine); + + + AttributeRefListPtr aBaseRefList = + myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B()); + AttributeRefListPtr aMirroredRefList = + myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_C()); myNumberOfObjects = aMirroredRefList->size(); if (!aBaseRefList || !aMirroredRefList) { myErrorMsg = SketchSolver_Error::INCORRECT_MIRROR_ATTRIBUTE(); return; } - std::list aBaseList = aBaseRefList->list(); - std::list aMirroredList = aMirroredRefList->list(); - - FeaturePtr aFeature; - for (int i = 0; i < 2; i++) { - std::list::iterator anIter = i == 0 ? aBaseList.begin() : aMirroredList.begin(); - std::list::iterator aEndIter = i == 0 ? aBaseList.end() : aMirroredList.end(); - std::vector* aList = i == 0 ? &theBaseEntities : & theMirrorEntities; - for ( ; anIter != aEndIter; anIter++) { - aFeature = ModelAPI_Feature::feature(*anIter); - if (!aFeature) - continue; - - myStorage->update(aFeature/*, myGroupID*/); - aList->push_back(myStorage->entity(aFeature)); + // store only original entities because mirrored ones + // will be updated separately in adjustConstraint + std::list aList = aBaseRefList->list(); + std::list::iterator anIt = aList.begin(); + for (; anIt != aList.end(); ++anIt) { + FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt); + if (aFeature) { + myStorage->update(aFeature); + myFeatures.insert(aFeature); } } - - if (theBaseEntities.size() > theMirrorEntities.size()) - myErrorMsg = SketchSolver_Error::NOT_INITIALIZED(); + // add mirrored features to the list + aList = aMirroredRefList->list(); + for (anIt = aList.begin(); anIt != aList.end(); ++anIt) { + FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt); + if (aFeature) + myFeatures.insert(aFeature); + } } void SketchSolver_ConstraintMirror::process() { cleanErrorMsg(); - if (!myBaseConstraint || !myStorage || myGroupID == GID_UNKNOWN) { + if (!myBaseConstraint || !myStorage) { // Not enough parameters are assigned return; } EntityWrapperPtr aMirrorLine; std::vector aBaseList; - std::vector aMirrorList; - getAttributes(aMirrorLine, aBaseList, aMirrorList); + getAttributes(aMirrorLine, aBaseList); if (!myErrorMsg.empty()) return; - if (aBaseList.size() != aMirrorList.size()) { - myErrorMsg = SketchSolver_Error::INCORRECT_MIRROR_ATTRIBUTE(); - return; - } - - std::list aNewConstraints; - SketchSolver_ConstraintType aConstrType = getType(); - BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder(); - std::list aMirConstrList; - - std::vector::iterator aBIt = aBaseList.begin(); - std::vector::iterator aMIt = aMirrorList.begin(); - for (; aBIt != aBaseList.end(); ++aBIt, ++aMIt) { - if ((*aBIt)->type() == ENTITY_ARC) { - // add new points on arcs and mirror them - EntityWrapperPtr aBasePnt = myStorage->calculateMiddlePoint(*aBIt, 0.5); - EntityWrapperPtr aMirrPnt = myStorage->calculateMiddlePoint(*aMIt, 0.5); - // point on base arc - aNewConstraints = aBuilder->createConstraint(myBaseConstraint, myGroupID, mySketchID, - CONSTRAINT_PT_ON_CIRCLE, 0.0, aBasePnt, EntityWrapperPtr(), *aBIt); - aMirConstrList.insert(aMirConstrList.end(), aNewConstraints.begin(), aNewConstraints.end()); - // point on mirrored arc - aNewConstraints = aBuilder->createConstraint(myBaseConstraint, myGroupID, mySketchID, - CONSTRAINT_PT_ON_CIRCLE, 0.0, aMirrPnt, EntityWrapperPtr(), *aMIt); - aMirConstrList.insert(aMirConstrList.end(), aNewConstraints.begin(), aNewConstraints.end()); - // mirror these points - aNewConstraints = aBuilder->createConstraint(myBaseConstraint, myGroupID, mySketchID, - aConstrType, 0.0, aBasePnt, aMirrPnt, aMirrorLine); - aMirConstrList.insert(aMirConstrList.end(), aNewConstraints.begin(), aNewConstraints.end()); - } - aNewConstraints = aBuilder->createConstraint( - myBaseConstraint, myGroupID, mySketchID, aConstrType, - 0.0, *aBIt, *aMIt, aMirrorLine); - aMirConstrList.insert(aMirConstrList.end(), aNewConstraints.begin(), aNewConstraints.end()); - } - - myStorage->addConstraint(myBaseConstraint, aMirConstrList); - // update mirrored features to be in the current group - for (aMIt = aMirrorList.begin(); aMIt != aMirrorList.end(); ++aMIt) - myStorage->update((*aMIt)->baseFeature(), myGroupID); + adjustConstraint(); + myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateFeature::GROUP()); } void SketchSolver_ConstraintMirror::update() { cleanErrorMsg(); - AttributeRefListPtr aMirroredRefList = std::dynamic_pointer_cast( - myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_C())); - if (aMirroredRefList->size() != myNumberOfObjects) { - remove(); - process(); - return; + remove(); + process(); +} + +void SketchSolver_ConstraintMirror::adjustConstraint() +{ + AttributeRefAttrPtr aMirrLineRefAttr = + myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A()); + std::shared_ptr aMirrorLine = + PlaneGCSSolver_Tools::line(ModelAPI_Feature::feature(aMirrLineRefAttr->object())); + + AttributeRefListPtr aBaseRefList = + myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B()); + AttributeRefListPtr aMirroredRefList = + myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_C()); + + std::list aBaseList = aBaseRefList->list(); + std::list aMirroredList = aMirroredRefList->list(); + std::list::iterator aBIt, aMIt; + for (aBIt = aBaseList.begin(), aMIt = aMirroredList.begin(); + aBIt != aBaseList.end() && aMIt != aMirroredList.end(); + ++aBIt, ++aMIt) { + FeaturePtr aBase = ModelAPI_Feature::feature(*aBIt); + FeaturePtr aMirrored = ModelAPI_Feature::feature(*aMIt); + mirrorEntities(aMirrorLine, aBase, aMirrored); + + // update mirrored entity if it exists in the storage + if (myStorage->entity(aMirrored)) + myStorage->update(aMirrored); } +} + +void SketchSolver_ConstraintMirror::notify(const FeaturePtr& theFeature, + PlaneGCSSolver_Update*) +{ + if (myFeatures.find(theFeature) == myFeatures.end()) + return; // the feature is not used by constraint => nothing to update adjustConstraint(); } -void SketchSolver_ConstraintMirror::adjustConstraint() +void SketchSolver_ConstraintMirror::blockEvents(bool isBlocked) { - BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder(); + std::set::iterator anIt = myFeatures.begin(); + for (; anIt != myFeatures.end(); ++anIt) + (*anIt)->data()->blockSendAttributeUpdated(isBlocked); - const std::list& aConstraints = myStorage->constraint(myBaseConstraint); - std::list::const_iterator aCIt = aConstraints.begin(); - for (; aCIt != aConstraints.end(); ++aCIt) - if ((*aCIt)->type() == CONSTRAINT_SYMMETRIC) - aBuilder->adjustConstraint(*aCIt); + SketchSolver_Constraint::blockEvents(isBlocked); +} + + + + +// ================= Auxiliary functions ================================== +void mirrorPoints(const std::shared_ptr& theMirrorLine, + const AttributePoint2DPtr& theOriginal, + const AttributePoint2DPtr& theMirrored) +{ + std::shared_ptr anOriginal = theOriginal->pnt(); + std::shared_ptr aPtOnLine = theMirrorLine->project(anOriginal); + std::shared_ptr aPerp = aPtOnLine->xy()->decreased(anOriginal->xy()); + theMirrored->setValue(anOriginal->x() + aPerp->x() * 2.0, anOriginal->y() + aPerp->y() * 2.0); +} + +void mirrorEntities(const std::shared_ptr& theMirrorLine, + const FeaturePtr& theOriginal, + const FeaturePtr& theMirrored) +{ + std::list aPoints0 = + theOriginal->data()->attributes(GeomDataAPI_Point2D::typeId()); + std::list aPoints1 = + theMirrored->data()->attributes(GeomDataAPI_Point2D::typeId()); + + // process specific features + if (theOriginal->getKind() == SketchPlugin_Arc::ID()) { + // orientation of arc + theMirrored->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue( + !theOriginal->boolean(SketchPlugin_Arc::REVERSED_ID())->value()); + } else if (theOriginal->getKind() == SketchPlugin_Circle::ID()) { + // radius of the circle + theMirrored->real(SketchPlugin_Circle::RADIUS_ID())->setValue( + theOriginal->real(SketchPlugin_Circle::RADIUS_ID())->value()); + } + else if (theOriginal->getKind() == SketchPlugin_EllipticArc::ID()) { + // orientation of arc + theMirrored->boolean(SketchPlugin_EllipticArc::REVERSED_ID())->setValue( + !theOriginal->boolean(SketchPlugin_EllipticArc::REVERSED_ID())->value()); + } + + // mirror all initialized points of features + std::list::iterator anIt0, anIt1; + for (anIt0 = aPoints0.begin(), anIt1 = aPoints1.begin(); + anIt0 != aPoints0.end() && anIt1 != aPoints1.end(); ++anIt0, ++anIt1) { + AttributePoint2DPtr aPt0 = std::dynamic_pointer_cast(*anIt0); + AttributePoint2DPtr aPt1 = std::dynamic_pointer_cast(*anIt1); + if (aPt0->isInitialized() && aPt1->isInitialized()) + mirrorPoints(theMirrorLine, aPt0, aPt1); + } }