+// Copyright (C) 2014-2023 CEA, EDF
+//
+// 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 <SketchSolver_ConstraintMirror.h>
-#include <SketchSolver_Group.h>
#include <SketchSolver_Error.h>
-#include <ModelAPI_AttributeDouble.h>
-#include <ModelAPI_AttributeRefAttr.h>
-#include <ModelAPI_AttributeRefList.h>
-#include <ModelAPI_ResultConstruction.h>
+#include <PlaneGCSSolver_Tools.h>
+#include <PlaneGCSSolver_UpdateFeature.h>
-#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_Lin2d.h>
+#include <GeomAPI_Pnt2d.h>
#include <GeomAPI_XY.h>
+#include <GeomDataAPI_Point2D.h>
+#include <ModelAPI_AttributeRefList.h>
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_EllipticArc.h>
+
+
+static void mirrorPoints(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
+ const AttributePoint2DPtr& theOriginal,
+ const AttributePoint2DPtr& theMirrored);
+
+static void mirrorEntities(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
+ const FeaturePtr& theOriginal,
+ const FeaturePtr& theMirrored);
+
-#include <cmath>
void SketchSolver_ConstraintMirror::getAttributes(
- Slvs_Entity& theMirrorLine,
- std::vector<Slvs_Entity>& theBaseEntities,
- std::vector<Slvs_Entity>& theMirrorEntities)
+ EntityWrapperPtr&,
+ std::vector<EntityWrapperPtr>&)
{
- DataPtr aData = myBaseConstraint->data();
- AttributeRefAttrPtr aMirLineAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
- if (!aMirLineAttr || !aMirLineAttr->isInitialized() || !aMirLineAttr->isObject()) {
+ AttributeRefAttrPtr aMirLineRefAttr =
+ myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
+ if (!aMirLineRefAttr || !aMirLineRefAttr->isInitialized() || !aMirLineRefAttr->isObject()) {
myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
return;
}
- int aType = SLVS_E_UNKNOWN; // type of created entity
- Slvs_hEntity anEntity = myGroup->getAttributeId(aMirLineAttr);
- if (anEntity == SLVS_E_UNKNOWN)
- anEntity = changeEntity(aMirLineAttr, aType);
- theMirrorLine = myStorage->getEntity(anEntity);
-
- // Create SolveSpace entity for all features
- AttributeRefListPtr aBaseRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
- myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
- AttributeRefListPtr aMirroredRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
- myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_C()));
+
+ FeaturePtr aMirrorLine = ModelAPI_Feature::feature(aMirLineRefAttr->object());
+ myFeatures.insert(aMirrorLine);
+
+ myType = TYPE(myBaseConstraint);
+ 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<ObjectPtr> aBaseList = aBaseRefList->list();
- std::list<ObjectPtr> aMirroredList = aMirroredRefList->list();
-
- FeaturePtr aFeature;
- ResultConstructionPtr aRC;
- for (int i = 0; i < 2; i++) {
- std::list<ObjectPtr>::iterator anIter = i == 0 ? aBaseList.begin() : aMirroredList.begin();
- std::list<ObjectPtr>::iterator aEndIter = i == 0 ? aBaseList.end() : aMirroredList.end();
- std::vector<Slvs_Entity>* aList = i == 0 ? &theBaseEntities : & theMirrorEntities;
- for ( ; anIter != aEndIter; anIter++) {
- aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anIter);
- aFeature = aRC ? aRC->document()->feature(aRC) :
- std::dynamic_pointer_cast<ModelAPI_Feature>(*anIter);
- if (!aFeature)
- continue;
-
- anEntity = changeEntity(aFeature, aType);
- // Sort entities by their type
- std::vector<Slvs_Entity>::iterator anIt = aList->begin();
- for (; anIt != aList->end(); anIt++)
- if (aType < anIt->type)
- break;
-// aList->push_back(myStorage->getEntity(anEntity));
- aList->insert(anIt, myStorage->getEntity(anEntity));
+ // store only original entities because mirrored ones
+ // will be updated separately in adjustConstraint
+ std::list<ObjectPtr> aList = aBaseRefList->list();
+ std::list<ObjectPtr>::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 || myGroup == 0) {
- /// TODO: Put error message here
+ if (!myBaseConstraint || !myStorage) {
+ // Not enough parameters are assigned
return;
}
- if (!mySlvsConstraints.empty()) // some data is changed, update constraint
- update(myBaseConstraint);
- Slvs_Entity aMirrorLine;
- std::vector<Slvs_Entity> aBaseList;
- std::vector<Slvs_Entity> aMirrorList;
- getAttributes(aMirrorLine, aBaseList, aMirrorList);
+ EntityWrapperPtr aMirrorLine;
+ std::vector<EntityWrapperPtr> aBaseList;
+ getAttributes(aMirrorLine, aBaseList);
if (!myErrorMsg.empty())
return;
- if (aBaseList.size() != aMirrorList.size()) {
- myErrorMsg = SketchSolver_Error::INCORRECT_MIRROR_ATTRIBUTE();
- return;
- }
-
- Slvs_Constraint aConstraint;
- // Get coordinates of mirror line points for speed up
- double aStartEnd[4];
- for (int i = 0; i < 2; i++) {
- Slvs_Entity aPoint = myStorage->getEntity(aMirrorLine.point[i]);
- for (int j = 0; j < 2; j++)
- aStartEnd[2*i+j] = myStorage->getParameter(aPoint.param[j]).val;
- }
-
- std::vector<Slvs_Entity>::iterator aBaseIter = aBaseList.begin();
- std::vector<Slvs_Entity>::iterator aMirrorIter = aMirrorList.begin();
- for (; aBaseIter != aBaseList.end(); aBaseIter++, aMirrorIter++) {
- // Make aMirrorEnt parameters to be symmetric with aBaseEnt
- makeMirrorEntity(*aBaseIter, *aMirrorIter, aStartEnd);
-
- if (aBaseIter->type == SLVS_E_POINT_IN_2D) {
- aConstraint = Slvs_MakeConstraint(
- SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(),
- 0.0, aBaseIter->h, aMirrorIter->h, aMirrorLine.h, SLVS_E_UNKNOWN);
- aConstraint.h = myStorage->addConstraint(aConstraint);
- mySlvsConstraints.push_back(aConstraint.h);
- } else if (aBaseIter->type == SLVS_E_LINE_SEGMENT) {
- for (int i = 0; i < 2; i++) {
- aConstraint = Slvs_MakeConstraint(
- SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(), 0.0,
- aBaseIter->point[i], aMirrorIter->point[i], aMirrorLine.h, SLVS_E_UNKNOWN);
- aConstraint.h = myStorage->addConstraint(aConstraint);
- mySlvsConstraints.push_back(aConstraint.h);
- }
- } else if (aBaseIter->type == SLVS_E_CIRCLE) {
- aConstraint = Slvs_MakeConstraint(
- SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(), 0.0,
- aBaseIter->point[0], aMirrorIter->point[0], aMirrorLine.h, SLVS_E_UNKNOWN);
- aConstraint.h = myStorage->addConstraint(aConstraint);
- mySlvsConstraints.push_back(aConstraint.h);
- // Additional constraint for equal radii
- Slvs_Constraint anEqRadConstr = Slvs_MakeConstraint(
- SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_EQUAL_RADIUS, myGroup->getWorkplaneId(),
- 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aBaseIter->h, aMirrorIter->h);
- anEqRadConstr.h = myStorage->addConstraint(anEqRadConstr);
- mySlvsConstraints.push_back(anEqRadConstr.h);
- } else if (aBaseIter->type == SLVS_E_ARC_OF_CIRCLE) {
- // Workaround to avoid problems in SolveSpace.
- // The symmetry of two arcs will be done using symmetry of three points on these arcs:
- // start point, end point, and any other point on the arc
- Slvs_hEntity aBaseArcPoints[3] = {
- aBaseIter->point[1],
- aBaseIter->point[2],
- SLVS_E_UNKNOWN};
- Slvs_hEntity aMirrorArcPoints[3] = { // indices of points of arc, center corresponds center, first point corresponds last point
- aMirrorIter->point[2],
- aMirrorIter->point[1],
- SLVS_E_UNKNOWN};
-
- Slvs_Entity aBothArcs[2] = {*aBaseIter, *aMirrorIter};
- Slvs_hEntity aBothMiddlePoints[2];
- for (int i = 0; i < 2; i++) {
- double x, y;
- calculateMiddlePoint(aBothArcs[i], 0.5, x, y);
- Slvs_Param aParamX = Slvs_MakeParam(SLVS_E_UNKNOWN, myGroup->getId(), x);
- Slvs_Param aParamY = Slvs_MakeParam(SLVS_E_UNKNOWN, myGroup->getId(), y);
- aParamX.h = myStorage->addParameter(aParamX);
- aParamY.h = myStorage->addParameter(aParamY);
- Slvs_Entity aPoint = Slvs_MakePoint2d(SLVS_E_UNKNOWN, myGroup->getId(),
- myGroup->getWorkplaneId(), aParamX.h, aParamY.h);
- aBothMiddlePoints[i] = myStorage->addEntity(aPoint);
- // additional constraint point-on-curve
- Slvs_Constraint aPonCircConstr = Slvs_MakeConstraint(
- SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_PT_ON_CIRCLE, myGroup->getWorkplaneId(),
- 0.0, aBothMiddlePoints[i], SLVS_E_UNKNOWN, aBothArcs[i].h, SLVS_E_UNKNOWN);
- aPonCircConstr.h = myStorage->addConstraint(aPonCircConstr);
- mySlvsConstraints.push_back(aPonCircConstr.h);
- if (i == 0) {
- // additional constraint for the point to be in the middle of a base arc
- Slvs_Entity aLine1 = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
- myGroup->getWorkplaneId(), aBothArcs[i].point[1], aBothMiddlePoints[i]);
- aLine1.h = myStorage->addEntity(aLine1);
- Slvs_Entity aLine2 = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
- myGroup->getWorkplaneId(), aBothArcs[i].point[2], aBothMiddlePoints[i]);
- aLine2.h = myStorage->addEntity(aLine2);
- Slvs_Constraint aMiddleConstr = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
- SLVS_C_EQUAL_LENGTH_LINES, myGroup->getWorkplaneId(),
- 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aLine1.h, aLine2.h);
- aMiddleConstr.h = myStorage->addConstraint(aMiddleConstr);
- mySlvsConstraints.push_back(aMiddleConstr.h);
- }
- }
-
- aBaseArcPoints[2] = aBothMiddlePoints[0];
- aMirrorArcPoints[2] = aBothMiddlePoints[1];
- for (int ind = 0; ind < 3; ind++) {
- Slvs_Constraint aConstraint = Slvs_MakeConstraint(
- SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(), 0.0,
- aBaseArcPoints[ind], aMirrorArcPoints[ind], aMirrorLine.h, SLVS_E_UNKNOWN);
- aConstraint.h = myStorage->addConstraint(aConstraint);
- mySlvsConstraints.push_back(aConstraint.h);
- }
- }
- }
+ adjustConstraint();
+ myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateFeature::GROUP());
}
-void SketchSolver_ConstraintMirror::update(ConstraintPtr theConstraint)
+void SketchSolver_ConstraintMirror::update()
{
cleanErrorMsg();
- if (!theConstraint || theConstraint == myBaseConstraint) {
- AttributeRefListPtr aMirroredRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
- myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_C()));
- if (aMirroredRefList->size() != myNumberOfObjects) {
- remove(myBaseConstraint);
- process();
- return;
- }
- }
- SketchSolver_Constraint::update();
+ remove();
+ process();
}
-bool SketchSolver_ConstraintMirror::remove(ConstraintPtr theConstraint)
+void SketchSolver_ConstraintMirror::adjustConstraint()
{
- cleanErrorMsg();
- if (theConstraint && theConstraint != myBaseConstraint)
- return false;
- bool isFullyRemoved = true;
- std::vector<Slvs_hEntity>::iterator aCIter = mySlvsConstraints.begin();
- for (; aCIter != mySlvsConstraints.end(); aCIter++)
- isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
- mySlvsConstraints.clear();
-
- std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = myFeatureMap.begin();
- for (; aFeatIt != myFeatureMap.end(); aFeatIt++)
- myStorage->removeEntity(aFeatIt->second);
-
- if (isFullyRemoved) {
- myFeatureMap.clear();
- myAttributeMap.clear();
- myValueMap.clear();
- } else
- cleanRemovedEntities();
- return true;
-}
+ AttributeRefAttrPtr aMirrLineRefAttr =
+ myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
+ std::shared_ptr<GeomAPI_Lin2d> aMirrorLine =
+ PlaneGCSSolver_Tools::line(ModelAPI_Feature::feature(aMirrLineRefAttr->object()));
-bool SketchSolver_ConstraintMirror::checkAttributesChanged(ConstraintPtr theConstraint)
-{
- // First of all, check the mirror line is changed.
- // It may be changed to one of mirrored lines, which is already in this constraint
- // (this case is not marked as attribute changing)
- ConstraintPtr aConstraint = theConstraint ? theConstraint : myBaseConstraint;
- AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
- if (!aRefAttr || !aRefAttr->isObject() || !aRefAttr->object())
- return true;
- FeaturePtr aMirrorLine = ModelAPI_Feature::feature(aRefAttr->object());
- if (!aMirrorLine)
- return true;
-
- std::map<FeaturePtr, Slvs_hEntity>::iterator aMirrorIter = myFeatureMap.find(aMirrorLine);
- if (aMirrorIter == myFeatureMap.end())
- return true;
-
- // Check the entity is not used as mirror line
- std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
- for (; aCIter != mySlvsConstraints.end(); aCIter++) {
- Slvs_Constraint aMirrorConstr = myStorage->getConstraint(*aCIter);
- if (aMirrorConstr.type != SLVS_C_SYMMETRIC_LINE)
- continue;
- if (aMirrorConstr.entityA != aMirrorIter->second)
- return true;
- else break; // check just one symmetric constraint
- }
+ AttributeRefListPtr aBaseRefList =
+ myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
+ AttributeRefListPtr aMirroredRefList =
+ myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_C());
- // Base verification
- return SketchSolver_Constraint::checkAttributesChanged(theConstraint);
+ std::list<ObjectPtr> aBaseList = aBaseRefList->list();
+ std::list<ObjectPtr> aMirroredList = aMirroredRefList->list();
+ std::list<ObjectPtr>::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::makeMirrorEntity(
- const Slvs_Entity& theBase,
- const Slvs_Entity& theMirror,
- const double theMirrorLine[]) const
+void SketchSolver_ConstraintMirror::notify(const FeaturePtr& theFeature,
+ PlaneGCSSolver_Update*)
{
- Slvs_hEntity aBasePoint[4];
- Slvs_hEntity aMirrorPoint[4];
- for (int i = 0; i < 4; i++) {
- aBasePoint[i] = theBase.point[i];
- aMirrorPoint[i] = theMirror.point[i];
- }
- if (theBase.type == SLVS_E_ARC_OF_CIRCLE) {
- Slvs_hEntity aTmp = aMirrorPoint[2];
- aMirrorPoint[2] = aMirrorPoint[1];
- aMirrorPoint[1] = aTmp;
- adjustArcPoints(theBase);
- }
- if (theBase.type == SLVS_E_POINT_IN_2D || theBase.type == SLVS_E_POINT_IN_3D) {
- aBasePoint[0] = theBase.h;
- aMirrorPoint[0] = theMirror.h;
- }
-
- // Mirror line parameters
- std::shared_ptr<GeomAPI_XY> aLinePoints[2];
- for (int i = 0; i < 2; i++)
- aLinePoints[i] = std::shared_ptr<GeomAPI_XY>(
- new GeomAPI_XY(theMirrorLine[2*i], theMirrorLine[2*i+1]));
- // direction of a mirror line
- std::shared_ptr<GeomAPI_Dir2d> aDir = std::shared_ptr<GeomAPI_Dir2d>(
- new GeomAPI_Dir2d(aLinePoints[1]->added(aLinePoints[0]->multiplied(-1.0))));
- // orthogonal direction
- aDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aDir->y(), -aDir->x()));
-
- Slvs_hConstraint aFixed; // transient variable
- for (int i = 0; i < 4; i++) {
- if (aBasePoint[i] == SLVS_E_UNKNOWN || aMirrorPoint[i] == SLVS_E_UNKNOWN)
- continue;
- // check the mirror point is not fixed
- if (myStorage->isPointFixed(aMirrorPoint[i], aFixed, true))
- continue;
-
- Slvs_Entity aPointEnt = myStorage->getEntity(aBasePoint[i]);
- double aBaseX = myStorage->getParameter(aPointEnt.param[0]).val;
- double aBaseY = myStorage->getParameter(aPointEnt.param[1]).val;
- std::shared_ptr<GeomAPI_XY> aPoint = std::shared_ptr<GeomAPI_XY>(new GeomAPI_XY(aBaseX, aBaseY));
-
- std::shared_ptr<GeomAPI_XY> aVec = std::shared_ptr<GeomAPI_XY>(
- new GeomAPI_XY(aPoint->x() - aLinePoints[0]->x(), aPoint->y() - aLinePoints[0]->y()));
- double aDist = aVec->dot(aDir->xy());
- aPoint = aPoint->added(aDir->xy()->multiplied(-2.0 * aDist));
-
- Slvs_Entity aMirrorEnt = myStorage->getEntity(aMirrorPoint[i]);
- Slvs_Param aParam = Slvs_MakeParam(aMirrorEnt.param[0], myGroup->getId(), aPoint->x());
- myStorage->updateParameter(aParam);
- aParam = Slvs_MakeParam(aMirrorEnt.param[1], myGroup->getId(), aPoint->y());
- myStorage->updateParameter(aParam);
- }
+ if (myFeatures.find(theFeature) == myFeatures.end())
+ return; // the feature is not used by constraint => nothing to update
+ adjustConstraint();
}
-void SketchSolver_ConstraintMirror::adjustArcPoints(const Slvs_Entity& theArc) const
+void SketchSolver_ConstraintMirror::blockEvents(bool isBlocked)
{
- Slvs_Param aParam;
- Slvs_Entity aPoint;
- double anArcParams[3][2];
- for (int i = 0; i < 3; i++) {
- aPoint = myStorage->getEntity(theArc.point[i]);
- for (int j = 0; j < 2; j++) {
- aParam = myStorage->getParameter(aPoint.param[j]);
- anArcParams[i][j] = aParam.val;
- if (i > 0)
- anArcParams[i][j] -= anArcParams[0][j];
- }
- }
- double aRad2 = anArcParams[1][0] * anArcParams[1][0] + anArcParams[1][1] * anArcParams[1][1];
- double aDist2 = anArcParams[2][0] * anArcParams[2][0] + anArcParams[2][1] * anArcParams[2][1];
- if (std::fabs(aRad2 - aDist2) < tolerance)
- return; // nothing to update (last point already on the arc)
- if (aDist2 < tolerance)
- return; // unable to update
- double aCoeff = std::sqrt(aRad2 / aDist2);
- anArcParams[2][0] *= aCoeff;
- anArcParams[2][1] *= aCoeff;
-
- // Update last point
- aPoint = myStorage->getEntity(theArc.point[2]);
- for (int i = 0; i < 2; i++) {
- aParam = Slvs_MakeParam(aPoint.param[i], myGroup->getId(),
- anArcParams[0][i] + anArcParams[2][i]);
- myStorage->updateParameter(aParam);
- }
+ std::set<FeaturePtr>::iterator anIt = myFeatures.begin();
+ for (; anIt != myFeatures.end(); ++anIt)
+ (*anIt)->data()->blockSendAttributeUpdated(isBlocked);
+
+ SketchSolver_Constraint::blockEvents(isBlocked);
}
-void SketchSolver_ConstraintMirror::adjustConstraint()
-{
- AttributeRefAttrPtr aMirLineAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
- if (!aMirLineAttr || !aMirLineAttr->isInitialized() || !aMirLineAttr->isObject()) {
- myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
- return;
- }
- ResultConstructionPtr aRC =
- std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aMirLineAttr->object());
- FeaturePtr aFeature = aRC ? aRC->document()->feature(aRC) :
- std::dynamic_pointer_cast<ModelAPI_Feature>(aMirLineAttr->object());
- std::map<FeaturePtr, Slvs_hEntity>::iterator aMirLineIter = myFeatureMap.find(aFeature);
- if (aMirLineIter == myFeatureMap.end())
- return;
- Slvs_Entity aMirrorLine = myStorage->getEntity(aMirLineIter->second);
-
- Slvs_Constraint aMirror;
- double aStartEnd[4];
- for (int i = 0; i < 2; i++) {
- Slvs_Entity aPoint = myStorage->getEntity(aMirrorLine.point[i]);
- for (int j = 0; j < 2; j++)
- aStartEnd[2*i+j] = myStorage->getParameter(aPoint.param[j]).val;
- }
- // Search mirror between middle points on the arcs and recompute their coordinates
- std::map<Slvs_hEntity, Slvs_hEntity> aPointsOnCircles;
- std::list<Slvs_Constraint> aMirrorPonCirc;
- std::list<Slvs_Constraint> aPonCirc = myStorage->getConstraintsByType(SLVS_C_PT_ON_CIRCLE);
- std::vector<Slvs_hConstraint>::iterator aConstrIter = mySlvsConstraints.begin();
- for (; aConstrIter != mySlvsConstraints.end(); aConstrIter++) {
- aMirror = myStorage->getConstraint(*aConstrIter);
- if (aMirror.type != SLVS_C_SYMMETRIC_LINE)
- continue;
- Slvs_Constraint aPonCircA, aPonCircB;
- aPonCircA.h = SLVS_E_UNKNOWN;
- aPonCircB.h = SLVS_E_UNKNOWN;
- std::list<Slvs_Constraint>::iterator aPtIter = aPonCirc.begin();
- for (; aPtIter != aPonCirc.end(); aPtIter++) {
- if (aMirror.ptA == aPtIter->ptA)
- aPonCircA = *aPtIter;
- if (aMirror.ptB == aPtIter->ptA)
- aPonCircB = *aPtIter;
- }
- if (aPonCircA.h == SLVS_E_UNKNOWN || aPonCircB.h == SLVS_E_UNKNOWN)
- continue;
- aMirrorPonCirc.push_back(aMirror);
- // Store point IDs to avoid their recalculation twice
- aPointsOnCircles[aPonCircA.ptA] = aPonCircA.entityA;
- aPointsOnCircles[aPonCircB.ptA] = aPonCircB.entityA;
- }
- // Recalculate positions of mirroring points
- std::list<Slvs_Constraint> aMirrorList = myStorage->getConstraintsByType(SLVS_C_SYMMETRIC_LINE);
- std::list<Slvs_Constraint>::iterator aMirIter = aMirrorList.begin();
- for (; aMirIter != aMirrorList.end(); aMirIter++) {
- if (aPointsOnCircles.find(aMirIter->ptA) != aPointsOnCircles.end())
- continue; // Avoid mirroring points on circles
- Slvs_Entity aBase = myStorage->getEntity(aMirIter->ptA);
- Slvs_Entity aMirror = myStorage->getEntity(aMirIter->ptB);
- makeMirrorEntity(aBase, aMirror, aStartEnd);
- }
- bool aNeedToResolve = myStorage->isNeedToResolve();
- for (aMirIter = aMirrorPonCirc.begin(); aMirIter != aMirrorPonCirc.end(); aMirIter++) {
- // Calculate middle point for base arc and mirrored point on mirror arc
- Slvs_Entity aBaseArc = myStorage->getEntity(aPointsOnCircles[aMirIter->ptA]);
- Slvs_Entity aBasePoint = myStorage->getEntity(aMirIter->ptA);
- Slvs_Param aParamX = myStorage->getParameter(aBasePoint.param[0]);
- Slvs_Param aParamY = myStorage->getParameter(aBasePoint.param[1]);
- calculateMiddlePoint(aBaseArc, 0.5, aParamX.val, aParamY.val);
- myStorage->updateParameter(aParamX);
- myStorage->updateParameter(aParamY);
- Slvs_Entity aMirrorArc = myStorage->getEntity(aPointsOnCircles[aMirIter->ptB]);
- Slvs_Entity aMirrorPoint = myStorage->getEntity(aMirIter->ptB);
- aParamX = myStorage->getParameter(aMirrorPoint.param[0]);
- aParamY = myStorage->getParameter(aMirrorPoint.param[1]);
- calculateMiddlePoint(aMirrorArc, 0.5, aParamX.val, aParamY.val);
- myStorage->updateParameter(aParamX);
- myStorage->updateParameter(aParamY);
- // make centers of arcs symmetric
- aBasePoint = myStorage->getEntity(aBaseArc.point[0]);
- aMirrorPoint = myStorage->getEntity(aMirrorArc.point[0]);
- makeMirrorEntity(aBasePoint, aMirrorPoint, aStartEnd);
+// ================= Auxiliary functions ==================================
+void mirrorPoints(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
+ const AttributePoint2DPtr& theOriginal,
+ const AttributePoint2DPtr& theMirrored)
+{
+ std::shared_ptr<GeomAPI_Pnt2d> anOriginal = theOriginal->pnt();
+ std::shared_ptr<GeomAPI_Pnt2d> aPtOnLine = theMirrorLine->project(anOriginal);
+ std::shared_ptr<GeomAPI_XY> 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<GeomAPI_Lin2d>& theMirrorLine,
+ const FeaturePtr& theOriginal,
+ const FeaturePtr& theMirrored)
+{
+ std::list<AttributePtr> aPoints0 =
+ theOriginal->data()->attributes(GeomDataAPI_Point2D::typeId());
+ std::list<AttributePtr> 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<AttributePtr>::iterator anIt0, anIt1;
+ for (anIt0 = aPoints0.begin(), anIt1 = aPoints1.begin();
+ anIt0 != aPoints0.end() && anIt1 != aPoints1.end(); ++anIt0, ++anIt1) {
+ AttributePoint2DPtr aPt0 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt0);
+ AttributePoint2DPtr aPt1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt1);
+ if (aPt0->isInitialized() && aPt1->isInitialized())
+ mirrorPoints(theMirrorLine, aPt0, aPt1);
}
- // Restore previous value to avoid looped recalculations of sketch
- myStorage->setNeedToResolve(aNeedToResolve);
}