Salome HOME
6381b2bd3dc8f85750cab74f798213a6d37bfb40
[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 #include <SketchSolver_Manager.h>
6
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   // add mirrored features to the list
66   aList = aMirroredRefList->list();
67   for (anIt = aList.begin(); anIt != aList.end(); ++anIt) {
68     FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
69     if (aFeature)
70       myFeatures.insert(aFeature);
71   }
72 }
73
74 void SketchSolver_ConstraintMirror::process()
75 {
76   cleanErrorMsg();
77   if (!myBaseConstraint || !myStorage) {
78     // Not enough parameters are assigned
79     return;
80   }
81
82   EntityWrapperPtr aMirrorLine;
83   std::vector<EntityWrapperPtr> aBaseList;
84   getAttributes(aMirrorLine, aBaseList);
85   if (!myErrorMsg.empty())
86     return;
87
88   adjustConstraint();
89   myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateFeature::GROUP());
90 }
91
92
93 void SketchSolver_ConstraintMirror::update()
94 {
95   cleanErrorMsg();
96   remove();
97   process();
98 }
99
100 void SketchSolver_ConstraintMirror::adjustConstraint()
101 {
102   BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
103
104   AttributeRefAttrPtr aMirrLineRefAttr =
105       myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
106   std::shared_ptr<GeomAPI_Lin2d> aMirrorLine =
107       aBuilder->line(ModelAPI_Feature::feature(aMirrLineRefAttr->object()));
108
109   AttributeRefListPtr aBaseRefList =
110       myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
111   AttributeRefListPtr aMirroredRefList =
112       myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_C());
113
114   std::list<ObjectPtr> aBaseList = aBaseRefList->list();
115   std::list<ObjectPtr> aMirroredList = aMirroredRefList->list();
116   std::list<ObjectPtr>::iterator aBIt, aMIt;
117   for (aBIt = aBaseList.begin(), aMIt = aMirroredList.begin();
118        aBIt != aBaseList.end() && aMIt != aMirroredList.end();
119        ++aBIt, ++aMIt) {
120     FeaturePtr aBase = ModelAPI_Feature::feature(*aBIt);
121     FeaturePtr aMirrored = ModelAPI_Feature::feature(*aMIt);
122     mirrorEntities(aMirrorLine, aBase, aMirrored);
123   }
124 }
125
126 void SketchSolver_ConstraintMirror::notify(const FeaturePtr& theFeature,
127                                            PlaneGCSSolver_Update*)
128 {
129   if (myFeatures.find(theFeature) == myFeatures.end())
130     return; // the feature is not used by constraint => nothing to update
131   adjustConstraint();
132 }
133
134 void SketchSolver_ConstraintMirror::blockEvents(bool isBlocked)
135 {
136   std::set<FeaturePtr>::iterator anIt = myFeatures.begin();
137   for (; anIt != myFeatures.end(); ++anIt)
138     (*anIt)->data()->blockSendAttributeUpdated(isBlocked);
139
140   SketchSolver_Constraint::blockEvents(isBlocked);
141 }
142
143
144
145
146 // =================   Auxiliary functions   ==================================
147 void mirrorPoints(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
148                   const AttributePoint2DPtr& theOriginal,
149                   const AttributePoint2DPtr& theMirrored)
150 {
151   std::shared_ptr<GeomAPI_Pnt2d> anOriginal = theOriginal->pnt();
152   std::shared_ptr<GeomAPI_Pnt2d> aPtOnLine = theMirrorLine->project(anOriginal);
153   std::shared_ptr<GeomAPI_XY> aPerp = aPtOnLine->xy()->decreased(anOriginal->xy());
154   theMirrored->setValue(anOriginal->x() + aPerp->x() * 2.0, anOriginal->y() + aPerp->y() * 2.0);
155 }
156
157 void mirrorEntities(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
158                     const FeaturePtr& theOriginal,
159                     const FeaturePtr& theMirrored)
160 {
161   std::list<AttributePtr> aPoints0 =
162       theOriginal->data()->attributes(GeomDataAPI_Point2D::typeId());
163   std::list<AttributePtr> aPoints1 =
164       theMirrored->data()->attributes(GeomDataAPI_Point2D::typeId());
165
166   // process specific features
167   if (theOriginal->getKind() == SketchPlugin_Arc::ID()) {
168     // orientation of arc
169     theMirrored->boolean(SketchPlugin_Arc::INVERSED_ID())->setValue(
170         !theOriginal->boolean(SketchPlugin_Arc::INVERSED_ID())->value());
171   } else if (theOriginal->getKind() == SketchPlugin_Circle::ID()) {
172     // radius of the circle
173     theMirrored->real(SketchPlugin_Circle::RADIUS_ID())->setValue(
174         theOriginal->real(SketchPlugin_Circle::RADIUS_ID())->value());
175   }
176
177   // mirror all initialized points of features
178   std::list<AttributePtr>::iterator anIt0, anIt1;
179   for (anIt0 = aPoints0.begin(), anIt1 = aPoints1.begin();
180        anIt0 != aPoints0.end() && anIt1 != aPoints1.end(); ++anIt0, ++anIt1) {
181     AttributePoint2DPtr aPt0 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt0);
182     AttributePoint2DPtr aPt1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt1);
183     if (aPt0->isInitialized() && aPt1->isInitialized())
184       mirrorPoints(theMirrorLine, aPt0, aPt1);
185   }
186 }