]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketchSolver/SketchSolver_ConstraintMirror.cpp
Salome HOME
Issue #1848: Redesign Sketcher mirrorEntities
[modules/shaper.git] / src / SketchSolver / SketchSolver_ConstraintMirror.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 #include <SketchSolver_ConstraintMirror.h>
4 #include <SketchSolver_Error.h>
5
6 #include <PlaneGCSSolver_Tools.h>
7 #include <PlaneGCSSolver_UpdateFeature.h>
8
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>
14
15
16 static void mirrorPoints(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
17                          const AttributePoint2DPtr& theOriginal,
18                          const AttributePoint2DPtr& theMirrored);
19
20 static void mirrorEntities(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
21                            const FeaturePtr& theOriginal,
22                            const FeaturePtr& theMirrored);
23
24
25
26 void SketchSolver_ConstraintMirror::getAttributes(
27     EntityWrapperPtr&,
28     std::vector<EntityWrapperPtr>&)
29 {
30   AttributeRefAttrPtr aMirLineRefAttr =
31       myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
32   if (!aMirLineRefAttr || !aMirLineRefAttr->isInitialized() || !aMirLineRefAttr->isObject()) {
33     myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
34     return;
35   }
36
37   FeaturePtr aMirrorLine = ModelAPI_Feature::feature(aMirLineRefAttr->object());
38   myFeatures.insert(aMirrorLine);
39
40   myType = TYPE(myBaseConstraint);
41   myStorage->update(aMirrorLine);
42
43
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();
51     return;
52   }
53
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);
60     if (aFeature) {
61       myStorage->update(aFeature);
62       myFeatures.insert(aFeature);
63     }
64   }
65 }
66
67 void SketchSolver_ConstraintMirror::process()
68 {
69   cleanErrorMsg();
70   if (!myBaseConstraint || !myStorage) {
71     // Not enough parameters are assigned
72     return;
73   }
74
75   EntityWrapperPtr aMirrorLine;
76   std::vector<EntityWrapperPtr> aBaseList;
77   getAttributes(aMirrorLine, aBaseList);
78   if (!myErrorMsg.empty())
79     return;
80
81   adjustConstraint();
82   myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateFeature::GROUP());
83 }
84
85
86 void SketchSolver_ConstraintMirror::update()
87 {
88   cleanErrorMsg();
89   remove();
90   process();
91 }
92
93 void SketchSolver_ConstraintMirror::adjustConstraint()
94 {
95   AttributeRefAttrPtr aMirrLineRefAttr =
96       myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
97   std::shared_ptr<GeomAPI_Lin2d> aMirrorLine =
98       PlaneGCSSolver_Tools::line(ModelAPI_Feature::feature(aMirrLineRefAttr->object()));
99
100   AttributeRefListPtr aBaseRefList =
101       myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
102   AttributeRefListPtr aMirroredRefList =
103       myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_C());
104
105   std::list<ObjectPtr> aBaseList = aBaseRefList->list();
106   std::list<ObjectPtr> aMirroredList = aMirroredRefList->list();
107   std::list<ObjectPtr>::iterator aBIt, aMIt;
108   for (aBIt = aBaseList.begin(), aMIt = aMirroredList.begin();
109        aBIt != aBaseList.end() && aMIt != aMirroredList.end();
110        ++aBIt, ++aMIt) {
111     FeaturePtr aBase = ModelAPI_Feature::feature(*aBIt);
112     FeaturePtr aMirrored = ModelAPI_Feature::feature(*aMIt);
113     mirrorEntities(aMirrorLine, aBase, aMirrored);
114
115     // update mirrored entity if it exists in the storage
116     if (myStorage->entity(aMirrored))
117       myStorage->update(aMirrored);
118   }
119 }
120
121 void SketchSolver_ConstraintMirror::notify(const FeaturePtr& theFeature,
122                                            PlaneGCSSolver_Update*)
123 {
124   if (myFeatures.find(theFeature) == myFeatures.end())
125     return; // the feature is not used by constraint => nothing to update
126   adjustConstraint();
127 }
128
129 void SketchSolver_ConstraintMirror::blockEvents(bool isBlocked)
130 {
131   std::set<FeaturePtr>::iterator anIt = myFeatures.begin();
132   for (; anIt != myFeatures.end(); ++anIt)
133     (*anIt)->data()->blockSendAttributeUpdated(isBlocked);
134
135   SketchSolver_Constraint::blockEvents(isBlocked);
136 }
137
138
139
140
141 // =================   Auxiliary functions   ==================================
142 void mirrorPoints(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
143                   const AttributePoint2DPtr& theOriginal,
144                   const AttributePoint2DPtr& theMirrored)
145 {
146   std::shared_ptr<GeomAPI_Pnt2d> anOriginal = theOriginal->pnt();
147   std::shared_ptr<GeomAPI_Pnt2d> aPtOnLine = theMirrorLine->project(anOriginal);
148   std::shared_ptr<GeomAPI_XY> aPerp = aPtOnLine->xy()->decreased(anOriginal->xy());
149   theMirrored->setValue(anOriginal->x() + aPerp->x() * 2.0, anOriginal->y() + aPerp->y() * 2.0);
150 }
151
152 void mirrorEntities(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
153                     const FeaturePtr& theOriginal,
154                     const FeaturePtr& theMirrored)
155 {
156   std::list<AttributePtr> aPoints0 =
157       theOriginal->data()->attributes(GeomDataAPI_Point2D::typeId());
158   std::list<AttributePtr> aPoints1 =
159       theMirrored->data()->attributes(GeomDataAPI_Point2D::typeId());
160
161   // process specific features
162   if (theOriginal->getKind() == SketchPlugin_Arc::ID()) {
163     // orientation of arc
164     theMirrored->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(
165         !theOriginal->boolean(SketchPlugin_Arc::REVERSED_ID())->value());
166   } else if (theOriginal->getKind() == SketchPlugin_Circle::ID()) {
167     // radius of the circle
168     theMirrored->real(SketchPlugin_Circle::RADIUS_ID())->setValue(
169         theOriginal->real(SketchPlugin_Circle::RADIUS_ID())->value());
170   }
171
172   // mirror all initialized points of features
173   std::list<AttributePtr>::iterator anIt0, anIt1;
174   for (anIt0 = aPoints0.begin(), anIt1 = aPoints1.begin();
175        anIt0 != aPoints0.end() && anIt1 != aPoints1.end(); ++anIt0, ++anIt1) {
176     AttributePoint2DPtr aPt0 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt0);
177     AttributePoint2DPtr aPt1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt1);
178     if (aPt0->isInitialized() && aPt1->isInitialized())
179       mirrorPoints(theMirrorLine, aPt0, aPt1);
180   }
181 }