Salome HOME
Add copyright header according to request of CEA from 06.06.2017
[modules/shaper.git] / src / SketchSolver / SketchSolver_ConstraintMirror.cpp
1 // Copyright (C) 2014-2017  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include <SketchSolver_ConstraintMirror.h>
22 #include <SketchSolver_Error.h>
23
24 #include <PlaneGCSSolver_Tools.h>
25 #include <PlaneGCSSolver_UpdateFeature.h>
26
27 #include <GeomAPI_XY.h>
28 #include <GeomDataAPI_Point2D.h>
29 #include <ModelAPI_AttributeRefList.h>
30 #include <SketchPlugin_Arc.h>
31 #include <SketchPlugin_Circle.h>
32
33
34 static void mirrorPoints(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
35                          const AttributePoint2DPtr& theOriginal,
36                          const AttributePoint2DPtr& theMirrored);
37
38 static void mirrorEntities(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
39                            const FeaturePtr& theOriginal,
40                            const FeaturePtr& theMirrored);
41
42
43
44 void SketchSolver_ConstraintMirror::getAttributes(
45     EntityWrapperPtr&,
46     std::vector<EntityWrapperPtr>&)
47 {
48   AttributeRefAttrPtr aMirLineRefAttr =
49       myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
50   if (!aMirLineRefAttr || !aMirLineRefAttr->isInitialized() || !aMirLineRefAttr->isObject()) {
51     myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
52     return;
53   }
54
55   FeaturePtr aMirrorLine = ModelAPI_Feature::feature(aMirLineRefAttr->object());
56   myFeatures.insert(aMirrorLine);
57
58   myType = TYPE(myBaseConstraint);
59   myStorage->update(aMirrorLine);
60
61
62   AttributeRefListPtr aBaseRefList =
63       myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
64   AttributeRefListPtr aMirroredRefList =
65       myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_C());
66   myNumberOfObjects = aMirroredRefList->size();
67   if (!aBaseRefList || !aMirroredRefList) {
68     myErrorMsg = SketchSolver_Error::INCORRECT_MIRROR_ATTRIBUTE();
69     return;
70   }
71
72   // store only original entities because mirrored ones
73   // will be updated separately in adjustConstraint
74   std::list<ObjectPtr> aList = aBaseRefList->list();
75   std::list<ObjectPtr>::iterator anIt = aList.begin();
76   for (; anIt != aList.end(); ++anIt) {
77     FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
78     if (aFeature) {
79       myStorage->update(aFeature);
80       myFeatures.insert(aFeature);
81     }
82   }
83   // add mirrored features to the list
84   aList = aMirroredRefList->list();
85   for (anIt = aList.begin(); anIt != aList.end(); ++anIt) {
86     FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
87     if (aFeature)
88       myFeatures.insert(aFeature);
89   }
90 }
91
92 void SketchSolver_ConstraintMirror::process()
93 {
94   cleanErrorMsg();
95   if (!myBaseConstraint || !myStorage) {
96     // Not enough parameters are assigned
97     return;
98   }
99
100   EntityWrapperPtr aMirrorLine;
101   std::vector<EntityWrapperPtr> aBaseList;
102   getAttributes(aMirrorLine, aBaseList);
103   if (!myErrorMsg.empty())
104     return;
105
106   adjustConstraint();
107   myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateFeature::GROUP());
108 }
109
110
111 void SketchSolver_ConstraintMirror::update()
112 {
113   cleanErrorMsg();
114   remove();
115   process();
116 }
117
118 void SketchSolver_ConstraintMirror::adjustConstraint()
119 {
120   AttributeRefAttrPtr aMirrLineRefAttr =
121       myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
122   std::shared_ptr<GeomAPI_Lin2d> aMirrorLine =
123       PlaneGCSSolver_Tools::line(ModelAPI_Feature::feature(aMirrLineRefAttr->object()));
124
125   AttributeRefListPtr aBaseRefList =
126       myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
127   AttributeRefListPtr aMirroredRefList =
128       myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_C());
129
130   std::list<ObjectPtr> aBaseList = aBaseRefList->list();
131   std::list<ObjectPtr> aMirroredList = aMirroredRefList->list();
132   std::list<ObjectPtr>::iterator aBIt, aMIt;
133   for (aBIt = aBaseList.begin(), aMIt = aMirroredList.begin();
134        aBIt != aBaseList.end() && aMIt != aMirroredList.end();
135        ++aBIt, ++aMIt) {
136     FeaturePtr aBase = ModelAPI_Feature::feature(*aBIt);
137     FeaturePtr aMirrored = ModelAPI_Feature::feature(*aMIt);
138     mirrorEntities(aMirrorLine, aBase, aMirrored);
139
140     // update mirrored entity if it exists in the storage
141     if (myStorage->entity(aMirrored))
142       myStorage->update(aMirrored);
143   }
144 }
145
146 void SketchSolver_ConstraintMirror::notify(const FeaturePtr& theFeature,
147                                            PlaneGCSSolver_Update*)
148 {
149   if (myFeatures.find(theFeature) == myFeatures.end())
150     return; // the feature is not used by constraint => nothing to update
151   adjustConstraint();
152 }
153
154 void SketchSolver_ConstraintMirror::blockEvents(bool isBlocked)
155 {
156   std::set<FeaturePtr>::iterator anIt = myFeatures.begin();
157   for (; anIt != myFeatures.end(); ++anIt)
158     (*anIt)->data()->blockSendAttributeUpdated(isBlocked);
159
160   SketchSolver_Constraint::blockEvents(isBlocked);
161 }
162
163
164
165
166 // =================   Auxiliary functions   ==================================
167 void mirrorPoints(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
168                   const AttributePoint2DPtr& theOriginal,
169                   const AttributePoint2DPtr& theMirrored)
170 {
171   std::shared_ptr<GeomAPI_Pnt2d> anOriginal = theOriginal->pnt();
172   std::shared_ptr<GeomAPI_Pnt2d> aPtOnLine = theMirrorLine->project(anOriginal);
173   std::shared_ptr<GeomAPI_XY> aPerp = aPtOnLine->xy()->decreased(anOriginal->xy());
174   theMirrored->setValue(anOriginal->x() + aPerp->x() * 2.0, anOriginal->y() + aPerp->y() * 2.0);
175 }
176
177 void mirrorEntities(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
178                     const FeaturePtr& theOriginal,
179                     const FeaturePtr& theMirrored)
180 {
181   std::list<AttributePtr> aPoints0 =
182       theOriginal->data()->attributes(GeomDataAPI_Point2D::typeId());
183   std::list<AttributePtr> aPoints1 =
184       theMirrored->data()->attributes(GeomDataAPI_Point2D::typeId());
185
186   // process specific features
187   if (theOriginal->getKind() == SketchPlugin_Arc::ID()) {
188     // orientation of arc
189     theMirrored->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(
190         !theOriginal->boolean(SketchPlugin_Arc::REVERSED_ID())->value());
191   } else if (theOriginal->getKind() == SketchPlugin_Circle::ID()) {
192     // radius of the circle
193     theMirrored->real(SketchPlugin_Circle::RADIUS_ID())->setValue(
194         theOriginal->real(SketchPlugin_Circle::RADIUS_ID())->value());
195   }
196
197   // mirror all initialized points of features
198   std::list<AttributePtr>::iterator anIt0, anIt1;
199   for (anIt0 = aPoints0.begin(), anIt1 = aPoints1.begin();
200        anIt0 != aPoints0.end() && anIt1 != aPoints1.end(); ++anIt0, ++anIt1) {
201     AttributePoint2DPtr aPt0 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt0);
202     AttributePoint2DPtr aPt1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt1);
203     if (aPt0->isInitialized() && aPt1->isInitialized())
204       mirrorPoints(theMirrorLine, aPt0, aPt1);
205   }
206 }