1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 #include <SketchSolver_ConstraintMirror.h>
4 #include <SketchSolver_Error.h>
6 #include <PlaneGCSSolver_Tools.h>
7 #include <PlaneGCSSolver_UpdateFeature.h>
9 #include <GeomAPI_XY.h>
10 #include <GeomDataAPI_Point2D.h>
11 #include <ModelAPI_AttributeRefList.h>
12 #include <SketchPlugin_Arc.h>
13 #include <SketchPlugin_Circle.h>
16 static void mirrorPoints(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
17 const AttributePoint2DPtr& theOriginal,
18 const AttributePoint2DPtr& theMirrored);
20 static void mirrorEntities(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
21 const FeaturePtr& theOriginal,
22 const FeaturePtr& theMirrored);
26 void SketchSolver_ConstraintMirror::getAttributes(
28 std::vector<EntityWrapperPtr>&)
30 AttributeRefAttrPtr aMirLineRefAttr =
31 myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
32 if (!aMirLineRefAttr || !aMirLineRefAttr->isInitialized() || !aMirLineRefAttr->isObject()) {
33 myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
37 FeaturePtr aMirrorLine = ModelAPI_Feature::feature(aMirLineRefAttr->object());
38 myFeatures.insert(aMirrorLine);
40 myType = TYPE(myBaseConstraint);
41 myStorage->update(aMirrorLine);
44 AttributeRefListPtr aBaseRefList =
45 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
46 AttributeRefListPtr aMirroredRefList =
47 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_C());
48 myNumberOfObjects = aMirroredRefList->size();
49 if (!aBaseRefList || !aMirroredRefList) {
50 myErrorMsg = SketchSolver_Error::INCORRECT_MIRROR_ATTRIBUTE();
54 // store only original entities because mirrored ones
55 // will be updated separately in adjustConstraint
56 std::list<ObjectPtr> aList = aBaseRefList->list();
57 std::list<ObjectPtr>::iterator anIt = aList.begin();
58 for (; anIt != aList.end(); ++anIt) {
59 FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
61 myStorage->update(aFeature);
62 myFeatures.insert(aFeature);
67 void SketchSolver_ConstraintMirror::process()
70 if (!myBaseConstraint || !myStorage) {
71 // Not enough parameters are assigned
75 EntityWrapperPtr aMirrorLine;
76 std::vector<EntityWrapperPtr> aBaseList;
77 getAttributes(aMirrorLine, aBaseList);
78 if (!myErrorMsg.empty())
82 myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateFeature::GROUP());
86 void SketchSolver_ConstraintMirror::update()
92 void SketchSolver_ConstraintMirror::adjustConstraint()
94 AttributeRefAttrPtr aMirrLineRefAttr =
95 myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
96 std::shared_ptr<GeomAPI_Lin2d> aMirrorLine =
97 PlaneGCSSolver_Tools::line(ModelAPI_Feature::feature(aMirrLineRefAttr->object()));
99 AttributeRefListPtr aBaseRefList =
100 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
101 AttributeRefListPtr aMirroredRefList =
102 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_C());
104 std::list<ObjectPtr> aBaseList = aBaseRefList->list();
105 std::list<ObjectPtr> aMirroredList = aMirroredRefList->list();
106 std::list<ObjectPtr>::iterator aBIt, aMIt;
107 for (aBIt = aBaseList.begin(), aMIt = aMirroredList.begin();
108 aBIt != aBaseList.end() && aMIt != aMirroredList.end();
110 FeaturePtr aBase = ModelAPI_Feature::feature(*aBIt);
111 FeaturePtr aMirrored = ModelAPI_Feature::feature(*aMIt);
112 mirrorEntities(aMirrorLine, aBase, aMirrored);
114 // update mirrored entity if it exists in the storage
115 if (myStorage->entity(aMirrored))
116 myStorage->update(aMirrored);
120 void SketchSolver_ConstraintMirror::notify(const FeaturePtr& theFeature,
121 PlaneGCSSolver_Update*)
123 if (myFeatures.find(theFeature) == myFeatures.end())
124 return; // the feature is not used by constraint => nothing to update
128 void SketchSolver_ConstraintMirror::blockEvents(bool isBlocked)
130 std::set<FeaturePtr>::iterator anIt = myFeatures.begin();
131 for (; anIt != myFeatures.end(); ++anIt)
132 (*anIt)->data()->blockSendAttributeUpdated(isBlocked);
134 AttributeRefListPtr aMirroredRefList =
135 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_C());
136 std::list<ObjectPtr> aMirroredList = aMirroredRefList->list();
137 std::list<ObjectPtr>::iterator aMIt = aMirroredList.begin();
138 for (; aMIt != aMirroredList.end(); ++aMIt) {
139 FeaturePtr aMirrored = ModelAPI_Feature::feature(*aMIt);
140 aMirrored->data()->blockSendAttributeUpdated(isBlocked);
144 SketchSolver_Constraint::blockEvents(isBlocked);
150 // ================= Auxiliary functions ==================================
151 void mirrorPoints(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
152 const AttributePoint2DPtr& theOriginal,
153 const AttributePoint2DPtr& theMirrored)
155 std::shared_ptr<GeomAPI_Pnt2d> anOriginal = theOriginal->pnt();
156 std::shared_ptr<GeomAPI_Pnt2d> aPtOnLine = theMirrorLine->project(anOriginal);
157 std::shared_ptr<GeomAPI_XY> aPerp = aPtOnLine->xy()->decreased(anOriginal->xy());
158 theMirrored->setValue(anOriginal->x() + aPerp->x() * 2.0, anOriginal->y() + aPerp->y() * 2.0);
161 void mirrorEntities(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
162 const FeaturePtr& theOriginal,
163 const FeaturePtr& theMirrored)
165 std::list<AttributePtr> aPoints0 =
166 theOriginal->data()->attributes(GeomDataAPI_Point2D::typeId());
167 std::list<AttributePtr> aPoints1 =
168 theMirrored->data()->attributes(GeomDataAPI_Point2D::typeId());
170 // process specific features
171 if (theOriginal->getKind() == SketchPlugin_Arc::ID()) {
172 // orientation of arc
173 theMirrored->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(
174 !theOriginal->boolean(SketchPlugin_Arc::REVERSED_ID())->value());
175 } else if (theOriginal->getKind() == SketchPlugin_Circle::ID()) {
176 // radius of the circle
177 theMirrored->real(SketchPlugin_Circle::RADIUS_ID())->setValue(
178 theOriginal->real(SketchPlugin_Circle::RADIUS_ID())->value());
181 // mirror all initialized points of features
182 std::list<AttributePtr>::iterator anIt0, anIt1;
183 for (anIt0 = aPoints0.begin(), anIt1 = aPoints1.begin();
184 anIt0 != aPoints0.end() && anIt1 != aPoints1.end(); ++anIt0, ++anIt1) {
185 AttributePoint2DPtr aPt0 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt0);
186 AttributePoint2DPtr aPt1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt1);
187 if (aPt0->isInitialized() && aPt1->isInitialized())
188 mirrorPoints(theMirrorLine, aPt0, aPt1);