1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 #include <SketchSolver_ConstraintFixed.h>
4 #include <SketchSolver_Error.h>
6 #include <PlaneGCSSolver_ConstraintWrapper.h>
7 #include <PlaneGCSSolver_EdgeWrapper.h>
8 #include <PlaneGCSSolver_EntityDestroyer.h>
9 #include <PlaneGCSSolver_FeatureBuilder.h>
10 #include <PlaneGCSSolver_PointWrapper.h>
12 #include <GeomDataAPI_Point2D.h>
13 #include <SketchPlugin_Feature.h>
17 // Verify the points are equal
18 static bool isEqual(const GCS::Point& thePoint1, const GCS::Point& thePoint2);
19 // Verify the entities are equal
20 static bool isEqual(const EntityWrapperPtr& theEntity1, const EntityWrapperPtr& theEntity2);
21 // Convert entity to the list of parameters
22 static GCS::VEC_pD toParameters(const EntityWrapperPtr& theEntity);
25 SketchSolver_ConstraintFixed::SketchSolver_ConstraintFixed(ConstraintPtr theConstraint)
26 : SketchSolver_Constraint(theConstraint)
28 myType = CONSTRAINT_FIXED;
31 SketchSolver_ConstraintFixed::SketchSolver_ConstraintFixed(FeaturePtr theFeature)
32 : SketchSolver_Constraint(),
33 myBaseFeature(theFeature)
35 myType = CONSTRAINT_FIXED;
38 void SketchSolver_ConstraintFixed::blockEvents(bool isBlocked)
41 myBaseFeature->data()->blockSendAttributeUpdated(isBlocked);
43 SketchSolver_Constraint::blockEvents(isBlocked);
46 void SketchSolver_ConstraintFixed::process()
49 if ((!myBaseConstraint && !myBaseFeature) || !myStorage) {
50 // Not enough parameters are assigned
54 EntityWrapperPtr aBaseEntity;
55 getAttributes(aBaseEntity, myFixedEntity);
57 moveFeature(); // remove myFixed entity
58 myErrorMsg = SketchSolver_Error::ALREADY_FIXED();
60 if (!myErrorMsg.empty())
63 fixFeature(aBaseEntity);
66 void SketchSolver_ConstraintFixed::fixFeature(EntityWrapperPtr theFeature)
68 GCS::VEC_pD aParameters = toParameters(theFeature);
70 // Fix given list of parameters
71 std::list<GCSConstraintPtr> aConstraints;
72 myFixedValues.reserve(aParameters.size());
73 GCS::VEC_pD::const_iterator anIt = aParameters.begin();
74 for (int i = 0; anIt != aParameters.end(); ++anIt, ++i) {
75 myFixedValues.push_back(**anIt);
76 aConstraints.push_back(
77 GCSConstraintPtr(new GCS::ConstraintEqual(&myFixedValues[i], *anIt)));
80 myConstraint = ConstraintWrapperPtr(
81 new PlaneGCSSolver_ConstraintWrapper(aConstraints, getType()));
84 myStorage->addConstraint(myBaseConstraint, myConstraint);
86 myStorage->addTemporaryConstraint(myConstraint);
89 void SketchSolver_ConstraintFixed::getAttributes(EntityWrapperPtr& theBaseEntity,
90 EntityWrapperPtr& theFixedEntity)
93 // if the feature is copy, do not move it
94 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
95 std::dynamic_pointer_cast<SketchPlugin_Feature>(myBaseFeature);
96 if (aSketchFeature && aSketchFeature->isCopy()) {
97 myStorage->setNeedToResolve(true);
101 bool fixFullFeature = false;
102 theBaseEntity = EntityWrapperPtr();
103 theFixedEntity = EntityWrapperPtr();
105 // The feature is fixed.
106 PlaneGCSSolver_FeatureBuilder aBuilder;
107 std::list<AttributePtr> aBaseAttr = myBaseFeature->data()->attributes(std::string());
108 std::list<AttributePtr>::const_iterator anIt = aBaseAttr.begin();
109 for (; anIt != aBaseAttr.end(); ++anIt) {
110 EntityWrapperPtr anEntity = aBuilder.createAttribute(*anIt);
111 EntityWrapperPtr aBaseEntity = myStorage->entity(*anIt);
112 if (!anEntity || !aBaseEntity)
115 if (!fixFullFeature && anEntity->type() == ENTITY_POINT &&
116 !isEqual(anEntity, aBaseEntity)) {
118 fixFullFeature = true;
119 theFixedEntity = anEntity;
120 theBaseEntity = aBaseEntity;
124 if (fixFullFeature) {
125 theFixedEntity = aBuilder.createFeature(myBaseFeature);
126 theBaseEntity = myStorage->entity(myBaseFeature);
127 if (isEqual(theBaseEntity, theFixedEntity))
128 theBaseEntity = EntityWrapperPtr(); // do not want to fix already fixed entity
131 } else if (myBaseConstraint) {
132 // Constraint Fixed is added by user.
133 // Get the attribute of constraint (it should be alone in the list of constraints).
134 EntityWrapperPtr aValue;
135 std::vector<EntityWrapperPtr> anAttributes;
136 SketchSolver_Constraint::getAttributes(aValue, anAttributes);
137 std::vector<EntityWrapperPtr>::const_iterator anIt = anAttributes.begin();
138 for (; anIt != anAttributes.end(); ++anIt)
140 theBaseEntity = *anIt;
142 myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
145 void SketchSolver_ConstraintFixed::moveFeature()
150 GCS::VEC_pD aFixedParams = toParameters(myFixedEntity);
151 for (int i = 0; i < aFixedParams.size() && i < myFixedValues.size(); ++i)
152 myFixedValues[i] = *(aFixedParams[i]);
154 // Remove fixed entity due to its parameters already copied into the constraint
155 PlaneGCSSolver_EntityDestroyer aDestroyer;
156 aDestroyer.remove(myFixedEntity);
157 std::dynamic_pointer_cast<PlaneGCSSolver_Storage>(myStorage)->removeParameters(
158 aDestroyer.parametersToRemove());
160 myFixedEntity = EntityWrapperPtr();
166 // ==================== Auxiliary functions ===============================
167 GCS::VEC_pD toParameters(const EntityWrapperPtr& theEntity)
169 GCS::VEC_pD aParameters;
173 std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEntity =
174 std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEntity);
176 // Collect parameters for each type of entity
177 switch (theEntity->type()) {
179 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
180 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity);
181 aParameters.push_back(aPoint->point()->x);
182 aParameters.push_back(aPoint->point()->y);
186 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(anEntity->entity());
187 aParameters.push_back(aLine->p1.x);
188 aParameters.push_back(aLine->p1.y);
189 aParameters.push_back(aLine->p2.x);
190 aParameters.push_back(aLine->p2.y);
193 case ENTITY_CIRCLE: {
194 std::shared_ptr<GCS::Circle> aCircle =
195 std::dynamic_pointer_cast<GCS::Circle>(anEntity->entity());
196 aParameters.push_back(aCircle->center.x);
197 aParameters.push_back(aCircle->center.y);
198 aParameters.push_back(aCircle->rad);
202 std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEntity->entity());
203 aParameters.push_back(anArc->center.x);
204 aParameters.push_back(anArc->center.y);
205 aParameters.push_back(anArc->rad);
206 aParameters.push_back(anArc->startAngle);
207 aParameters.push_back(anArc->endAngle);
217 bool isEqual(const GCS::Point& thePoint1, const GCS::Point& thePoint2)
219 return fabs((*thePoint1.x) - (*thePoint2.x)) <= tolerance &&
220 fabs((*thePoint1.y) - (*thePoint2.y)) <= tolerance;
223 bool isEqual(const EntityWrapperPtr& theEntity1, const EntityWrapperPtr& theEntity2)
225 GCS::VEC_pD aParamList1 = toParameters(theEntity1);
226 GCS::VEC_pD aParamList2 = toParameters(theEntity2);
228 GCS::VEC_pD::const_iterator anIt1 = aParamList1.begin();
229 GCS::VEC_pD::const_iterator anIt2 = aParamList2.begin();
230 for (; anIt1 != aParamList1.end() && anIt2 != aParamList2.end(); ++anIt1, ++anIt2)
231 if (fabs((**anIt1) - (**anIt2)) > tolerance)
234 return anIt1 == aParamList1.end() && anIt2 == aParamList2.end();