- // 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
- }
-
- // Base verification
- return SketchSolver_Constraint::checkAttributesChanged(theConstraint);
-}
-
-void SketchSolver_ConstraintMirror::makeMirrorEntity(
- const Slvs_Entity& theBase,
- const Slvs_Entity& theMirror,
- const double theMirrorLine[]) const
-{
- 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);
- }
-}
-
-void SketchSolver_ConstraintMirror::adjustArcPoints(const Slvs_Entity& theArc) const
-{
- 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);
- }