1 // Copyright (C) 2014-2019 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include <SketchSolver_ConstraintMirror.h>
21 #include <SketchSolver_Error.h>
23 #include <PlaneGCSSolver_Tools.h>
24 #include <PlaneGCSSolver_UpdateFeature.h>
26 #include <GeomAPI_XY.h>
27 #include <GeomDataAPI_Point2D.h>
28 #include <ModelAPI_AttributeRefList.h>
29 #include <SketchPlugin_Arc.h>
30 #include <SketchPlugin_Circle.h>
33 static void mirrorPoints(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
34 const AttributePoint2DPtr& theOriginal,
35 const AttributePoint2DPtr& theMirrored);
37 static void mirrorEntities(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
38 const FeaturePtr& theOriginal,
39 const FeaturePtr& theMirrored);
43 void SketchSolver_ConstraintMirror::getAttributes(
45 std::vector<EntityWrapperPtr>&)
47 AttributeRefAttrPtr aMirLineRefAttr =
48 myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
49 if (!aMirLineRefAttr || !aMirLineRefAttr->isInitialized() || !aMirLineRefAttr->isObject()) {
50 myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
54 FeaturePtr aMirrorLine = ModelAPI_Feature::feature(aMirLineRefAttr->object());
55 myFeatures.insert(aMirrorLine);
57 myType = TYPE(myBaseConstraint);
58 myStorage->update(aMirrorLine);
61 AttributeRefListPtr aBaseRefList =
62 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
63 AttributeRefListPtr aMirroredRefList =
64 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_C());
65 myNumberOfObjects = aMirroredRefList->size();
66 if (!aBaseRefList || !aMirroredRefList) {
67 myErrorMsg = SketchSolver_Error::INCORRECT_MIRROR_ATTRIBUTE();
71 // store only original entities because mirrored ones
72 // will be updated separately in adjustConstraint
73 std::list<ObjectPtr> aList = aBaseRefList->list();
74 std::list<ObjectPtr>::iterator anIt = aList.begin();
75 for (; anIt != aList.end(); ++anIt) {
76 FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
78 myStorage->update(aFeature);
79 myFeatures.insert(aFeature);
82 // add mirrored features to the list
83 aList = aMirroredRefList->list();
84 for (anIt = aList.begin(); anIt != aList.end(); ++anIt) {
85 FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
87 myFeatures.insert(aFeature);
91 void SketchSolver_ConstraintMirror::process()
94 if (!myBaseConstraint || !myStorage) {
95 // Not enough parameters are assigned
99 EntityWrapperPtr aMirrorLine;
100 std::vector<EntityWrapperPtr> aBaseList;
101 getAttributes(aMirrorLine, aBaseList);
102 if (!myErrorMsg.empty())
106 myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateFeature::GROUP());
110 void SketchSolver_ConstraintMirror::update()
117 void SketchSolver_ConstraintMirror::adjustConstraint()
119 AttributeRefAttrPtr aMirrLineRefAttr =
120 myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
121 std::shared_ptr<GeomAPI_Lin2d> aMirrorLine =
122 PlaneGCSSolver_Tools::line(ModelAPI_Feature::feature(aMirrLineRefAttr->object()));
124 AttributeRefListPtr aBaseRefList =
125 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
126 AttributeRefListPtr aMirroredRefList =
127 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_C());
129 std::list<ObjectPtr> aBaseList = aBaseRefList->list();
130 std::list<ObjectPtr> aMirroredList = aMirroredRefList->list();
131 std::list<ObjectPtr>::iterator aBIt, aMIt;
132 for (aBIt = aBaseList.begin(), aMIt = aMirroredList.begin();
133 aBIt != aBaseList.end() && aMIt != aMirroredList.end();
135 FeaturePtr aBase = ModelAPI_Feature::feature(*aBIt);
136 FeaturePtr aMirrored = ModelAPI_Feature::feature(*aMIt);
137 mirrorEntities(aMirrorLine, aBase, aMirrored);
139 // update mirrored entity if it exists in the storage
140 if (myStorage->entity(aMirrored))
141 myStorage->update(aMirrored);
145 void SketchSolver_ConstraintMirror::notify(const FeaturePtr& theFeature,
146 PlaneGCSSolver_Update*)
148 if (myFeatures.find(theFeature) == myFeatures.end())
149 return; // the feature is not used by constraint => nothing to update
153 void SketchSolver_ConstraintMirror::blockEvents(bool isBlocked)
155 std::set<FeaturePtr>::iterator anIt = myFeatures.begin();
156 for (; anIt != myFeatures.end(); ++anIt)
157 (*anIt)->data()->blockSendAttributeUpdated(isBlocked);
159 SketchSolver_Constraint::blockEvents(isBlocked);
165 // ================= Auxiliary functions ==================================
166 void mirrorPoints(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
167 const AttributePoint2DPtr& theOriginal,
168 const AttributePoint2DPtr& theMirrored)
170 std::shared_ptr<GeomAPI_Pnt2d> anOriginal = theOriginal->pnt();
171 std::shared_ptr<GeomAPI_Pnt2d> aPtOnLine = theMirrorLine->project(anOriginal);
172 std::shared_ptr<GeomAPI_XY> aPerp = aPtOnLine->xy()->decreased(anOriginal->xy());
173 theMirrored->setValue(anOriginal->x() + aPerp->x() * 2.0, anOriginal->y() + aPerp->y() * 2.0);
176 void mirrorEntities(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
177 const FeaturePtr& theOriginal,
178 const FeaturePtr& theMirrored)
180 std::list<AttributePtr> aPoints0 =
181 theOriginal->data()->attributes(GeomDataAPI_Point2D::typeId());
182 std::list<AttributePtr> aPoints1 =
183 theMirrored->data()->attributes(GeomDataAPI_Point2D::typeId());
185 // process specific features
186 if (theOriginal->getKind() == SketchPlugin_Arc::ID()) {
187 // orientation of arc
188 theMirrored->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(
189 !theOriginal->boolean(SketchPlugin_Arc::REVERSED_ID())->value());
190 } else if (theOriginal->getKind() == SketchPlugin_Circle::ID()) {
191 // radius of the circle
192 theMirrored->real(SketchPlugin_Circle::RADIUS_ID())->setValue(
193 theOriginal->real(SketchPlugin_Circle::RADIUS_ID())->value());
196 // mirror all initialized points of features
197 std::list<AttributePtr>::iterator anIt0, anIt1;
198 for (anIt0 = aPoints0.begin(), anIt1 = aPoints1.begin();
199 anIt0 != aPoints0.end() && anIt1 != aPoints1.end(); ++anIt0, ++anIt1) {
200 AttributePoint2DPtr aPt0 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt0);
201 AttributePoint2DPtr aPt1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt1);
202 if (aPt0->isInitialized() && aPt1->isInitialized())
203 mirrorPoints(theMirrorLine, aPt0, aPt1);