1 #include <SketchSolver_ConstraintMirror.h>
2 #include <SketchSolver_Error.h>
3 #include <SketchSolver_Manager.h>
5 ////#include <ModelAPI_AttributeDouble.h>
6 ////#include <ModelAPI_AttributeRefAttr.h>
7 #include <ModelAPI_AttributeRefList.h>
8 ////#include <ModelAPI_ResultConstruction.h>
10 ////#include <GeomAPI_Dir2d.h>
11 ////#include <GeomAPI_XY.h>
15 void SketchSolver_ConstraintMirror::getAttributes(
16 EntityWrapperPtr& theMirrorLine,
17 std::vector<EntityWrapperPtr>& theBaseEntities,
18 std::vector<EntityWrapperPtr>& theMirrorEntities)
20 AttributeRefAttrPtr aMirLineAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
21 myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
22 if (!aMirLineAttr || !aMirLineAttr->isInitialized() || !aMirLineAttr->isObject()) {
23 myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
27 myType = TYPE(myBaseConstraint);
28 myStorage->update(aMirLineAttr, myGroupID);
29 theMirrorLine = myStorage->entity(aMirLineAttr);
31 // Create SolveSpace entity for all features
32 AttributeRefListPtr aBaseRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
33 myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
34 AttributeRefListPtr aMirroredRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
35 myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_C()));
36 myNumberOfObjects = aMirroredRefList->size();
37 if (!aBaseRefList || !aMirroredRefList) {
38 myErrorMsg = SketchSolver_Error::INCORRECT_MIRROR_ATTRIBUTE();
42 std::list<ObjectPtr> aBaseList = aBaseRefList->list();
43 std::list<ObjectPtr> aMirroredList = aMirroredRefList->list();
46 for (int i = 0; i < 2; i++) {
47 std::list<ObjectPtr>::iterator anIter = i == 0 ? aBaseList.begin() : aMirroredList.begin();
48 std::list<ObjectPtr>::iterator aEndIter = i == 0 ? aBaseList.end() : aMirroredList.end();
49 std::vector<EntityWrapperPtr>* aList = i == 0 ? &theBaseEntities : & theMirrorEntities;
50 for ( ; anIter != aEndIter; anIter++) {
51 aFeature = ModelAPI_Feature::feature(*anIter);
55 //// anEntity = changeEntity(aFeature, aType);
56 //// // Sort entities by their type
57 //// std::vector<Slvs_Entity>::iterator anIt = aList->begin();
58 //// for (; anIt != aList->end(); anIt++)
59 //// if (aType < anIt->type)
61 ////// aList->push_back(myStorage->getEntity(anEntity));
62 //// aList->insert(anIt, myStorage->getEntity(anEntity));
63 myStorage->update(aFeature, myGroupID);
64 aList->push_back(myStorage->entity(aFeature));
68 if (theBaseEntities.size() > theMirrorEntities.size())
69 myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
72 void SketchSolver_ConstraintMirror::process()
75 if (!myBaseConstraint || !myStorage || myGroupID == GID_UNKNOWN) {
76 // Not enough parameters are assigned
79 //// if (!mySlvsConstraints.empty()) // some data is changed, update constraint
80 //// update(myBaseConstraint);
82 EntityWrapperPtr aMirrorLine;
83 std::vector<EntityWrapperPtr> aBaseList;
84 std::vector<EntityWrapperPtr> aMirrorList;
85 getAttributes(aMirrorLine, aBaseList, aMirrorList);
86 if (!myErrorMsg.empty())
89 if (aBaseList.size() != aMirrorList.size()) {
90 myErrorMsg = SketchSolver_Error::INCORRECT_MIRROR_ATTRIBUTE();
94 std::list<ConstraintWrapperPtr> aNewConstraints;
95 SketchSolver_ConstraintType aConstrType = getType();
96 BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
97 std::list<ConstraintWrapperPtr> aMirConstrList;
99 std::vector<EntityWrapperPtr>::iterator aBIt = aBaseList.begin();
100 std::vector<EntityWrapperPtr>::iterator aMIt = aMirrorList.begin();
101 for (; aBIt != aBaseList.end(); ++aBIt, ++aMIt) {
102 if ((*aBIt)->type() == ENTITY_ARC) {
103 // add new points on arcs and mirror them
104 EntityWrapperPtr aBasePnt = myStorage->calculateMiddlePoint(*aBIt, 0.5);
105 EntityWrapperPtr aMirrPnt = myStorage->calculateMiddlePoint(*aMIt, 0.5);
107 aNewConstraints = aBuilder->createConstraint(myBaseConstraint, myGroupID, mySketchID,
108 CONSTRAINT_PT_ON_CIRCLE, 0.0, aBasePnt, EntityWrapperPtr(), *aBIt);
109 aMirConstrList.insert(aMirConstrList.end(), aNewConstraints.begin(), aNewConstraints.end());
110 // point on mirrored arc
111 aNewConstraints = aBuilder->createConstraint(myBaseConstraint, myGroupID, mySketchID,
112 CONSTRAINT_PT_ON_CIRCLE, 0.0, aMirrPnt, EntityWrapperPtr(), *aMIt);
113 aMirConstrList.insert(aMirConstrList.end(), aNewConstraints.begin(), aNewConstraints.end());
114 // mirror these points
115 aNewConstraints = aBuilder->createConstraint(myBaseConstraint, myGroupID, mySketchID,
116 aConstrType, 0.0, aBasePnt, aMirrPnt, aMirrorLine);
117 aMirConstrList.insert(aMirConstrList.end(), aNewConstraints.begin(), aNewConstraints.end());
119 aNewConstraints = aBuilder->createConstraint(
120 myBaseConstraint, myGroupID, mySketchID, aConstrType,
121 0.0, *aBIt, *aMIt, aMirrorLine);
122 aMirConstrList.insert(aMirConstrList.end(), aNewConstraints.begin(), aNewConstraints.end());
125 myStorage->addConstraint(myBaseConstraint, aMirConstrList);
129 void SketchSolver_ConstraintMirror::update()
132 AttributeRefListPtr aMirroredRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
133 myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_C()));
134 if (aMirroredRefList->size() != myNumberOfObjects) {
139 SketchSolver_Constraint::update();
142 ////bool SketchSolver_ConstraintMirror::remove(ConstraintPtr theConstraint)
144 //// cleanErrorMsg();
145 //// if (theConstraint && theConstraint != myBaseConstraint)
147 //// bool isFullyRemoved = true;
148 //// std::vector<Slvs_hEntity>::iterator aCIter = mySlvsConstraints.begin();
149 //// for (; aCIter != mySlvsConstraints.end(); aCIter++)
150 //// isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
151 //// mySlvsConstraints.clear();
153 //// std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = myFeatureMap.begin();
154 //// for (; aFeatIt != myFeatureMap.end(); aFeatIt++)
155 //// myStorage->removeEntity(aFeatIt->second);
157 //// if (isFullyRemoved) {
158 //// myFeatureMap.clear();
159 //// myAttributeMap.clear();
160 //// myValueMap.clear();
162 //// cleanRemovedEntities();
166 ////bool SketchSolver_ConstraintMirror::checkAttributesChanged(ConstraintPtr theConstraint)
168 //// // First of all, check the mirror line is changed.
169 //// // It may be changed to one of mirrored lines, which is already in this constraint
170 //// // (this case is not marked as attribute changing)
171 //// ConstraintPtr aConstraint = theConstraint ? theConstraint : myBaseConstraint;
172 //// AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
173 //// aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
174 //// if (!aRefAttr || !aRefAttr->isObject() || !aRefAttr->object())
176 //// FeaturePtr aMirrorLine = ModelAPI_Feature::feature(aRefAttr->object());
177 //// if (!aMirrorLine)
180 //// std::map<FeaturePtr, Slvs_hEntity>::iterator aMirrorIter = myFeatureMap.find(aMirrorLine);
181 //// if (aMirrorIter == myFeatureMap.end())
184 //// // Check the entity is not used as mirror line
185 //// std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
186 //// for (; aCIter != mySlvsConstraints.end(); aCIter++) {
187 //// Slvs_Constraint aMirrorConstr = myStorage->getConstraint(*aCIter);
188 //// if (aMirrorConstr.type != SLVS_C_SYMMETRIC_LINE)
190 //// if (aMirrorConstr.entityA != aMirrorIter->second)
192 //// else break; // check just one symmetric constraint
195 //// // Base verification
196 //// return SketchSolver_Constraint::checkAttributesChanged(theConstraint);
199 ////void SketchSolver_ConstraintMirror::makeMirrorEntity(
200 //// const Slvs_Entity& theBase,
201 //// const Slvs_Entity& theMirror,
202 //// const double theMirrorLine[]) const
204 //// Slvs_hEntity aBasePoint[4];
205 //// Slvs_hEntity aMirrorPoint[4];
206 //// for (int i = 0; i < 4; i++) {
207 //// aBasePoint[i] = theBase.point[i];
208 //// aMirrorPoint[i] = theMirror.point[i];
210 //// if (theBase.type == SLVS_E_ARC_OF_CIRCLE) {
211 //// Slvs_hEntity aTmp = aMirrorPoint[2];
212 //// aMirrorPoint[2] = aMirrorPoint[1];
213 //// aMirrorPoint[1] = aTmp;
214 //// adjustArcPoints(theBase);
216 //// if (theBase.type == SLVS_E_POINT_IN_2D || theBase.type == SLVS_E_POINT_IN_3D) {
217 //// aBasePoint[0] = theBase.h;
218 //// aMirrorPoint[0] = theMirror.h;
221 //// // Mirror line parameters
222 //// std::shared_ptr<GeomAPI_XY> aLinePoints[2];
223 //// for (int i = 0; i < 2; i++)
224 //// aLinePoints[i] = std::shared_ptr<GeomAPI_XY>(
225 //// new GeomAPI_XY(theMirrorLine[2*i], theMirrorLine[2*i+1]));
226 //// // direction of a mirror line
227 //// std::shared_ptr<GeomAPI_Dir2d> aDir = std::shared_ptr<GeomAPI_Dir2d>(
228 //// new GeomAPI_Dir2d(aLinePoints[1]->added(aLinePoints[0]->multiplied(-1.0))));
229 //// // orthogonal direction
230 //// aDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aDir->y(), -aDir->x()));
232 //// Slvs_hConstraint aFixed; // transient variable
233 //// for (int i = 0; i < 4; i++) {
234 //// if (aBasePoint[i] == SLVS_E_UNKNOWN || aMirrorPoint[i] == SLVS_E_UNKNOWN)
236 //// // check the mirror point is not fixed
237 //// if (myStorage->isPointFixed(aMirrorPoint[i], aFixed, true))
240 //// Slvs_Entity aPointEnt = myStorage->getEntity(aBasePoint[i]);
241 //// double aBaseX = myStorage->getParameter(aPointEnt.param[0]).val;
242 //// double aBaseY = myStorage->getParameter(aPointEnt.param[1]).val;
243 //// std::shared_ptr<GeomAPI_XY> aPoint = std::shared_ptr<GeomAPI_XY>(new GeomAPI_XY(aBaseX, aBaseY));
245 //// std::shared_ptr<GeomAPI_XY> aVec = std::shared_ptr<GeomAPI_XY>(
246 //// new GeomAPI_XY(aPoint->x() - aLinePoints[0]->x(), aPoint->y() - aLinePoints[0]->y()));
247 //// double aDist = aVec->dot(aDir->xy());
248 //// aPoint = aPoint->added(aDir->xy()->multiplied(-2.0 * aDist));
250 //// Slvs_Entity aMirrorEnt = myStorage->getEntity(aMirrorPoint[i]);
251 //// Slvs_Param aParam = Slvs_MakeParam(aMirrorEnt.param[0], myGroup->getId(), aPoint->x());
252 //// myStorage->updateParameter(aParam);
253 //// aParam = Slvs_MakeParam(aMirrorEnt.param[1], myGroup->getId(), aPoint->y());
254 //// myStorage->updateParameter(aParam);
258 ////void SketchSolver_ConstraintMirror::adjustArcPoints(const Slvs_Entity& theArc) const
260 //// Slvs_Param aParam;
261 //// Slvs_Entity aPoint;
262 //// double anArcParams[3][2];
263 //// for (int i = 0; i < 3; i++) {
264 //// aPoint = myStorage->getEntity(theArc.point[i]);
265 //// for (int j = 0; j < 2; j++) {
266 //// aParam = myStorage->getParameter(aPoint.param[j]);
267 //// anArcParams[i][j] = aParam.val;
269 //// anArcParams[i][j] -= anArcParams[0][j];
272 //// double aRad2 = anArcParams[1][0] * anArcParams[1][0] + anArcParams[1][1] * anArcParams[1][1];
273 //// double aDist2 = anArcParams[2][0] * anArcParams[2][0] + anArcParams[2][1] * anArcParams[2][1];
274 //// if (std::fabs(aRad2 - aDist2) < tolerance)
275 //// return; // nothing to update (last point already on the arc)
276 //// if (aDist2 < tolerance)
277 //// return; // unable to update
278 //// double aCoeff = std::sqrt(aRad2 / aDist2);
279 //// anArcParams[2][0] *= aCoeff;
280 //// anArcParams[2][1] *= aCoeff;
282 //// // Update last point
283 //// aPoint = myStorage->getEntity(theArc.point[2]);
284 //// for (int i = 0; i < 2; i++) {
285 //// aParam = Slvs_MakeParam(aPoint.param[i], myGroup->getId(),
286 //// anArcParams[0][i] + anArcParams[2][i]);
287 //// myStorage->updateParameter(aParam);
291 void SketchSolver_ConstraintMirror::adjustConstraint()
293 BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
295 const std::list<ConstraintWrapperPtr>& aConstraints = myStorage->constraint(myBaseConstraint);
296 std::list<ConstraintWrapperPtr>::const_iterator aCIt = aConstraints.begin();
297 for (; aCIt != aConstraints.end(); ++aCIt)
298 if ((*aCIt)->type() == CONSTRAINT_SYMMETRIC)
299 aBuilder->adjustConstraint(*aCIt);
301 //// AttributeRefAttrPtr aMirLineAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
302 //// myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
303 //// if (!aMirLineAttr || !aMirLineAttr->isInitialized() || !aMirLineAttr->isObject()) {
304 //// myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
307 //// ResultConstructionPtr aRC =
308 //// std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aMirLineAttr->object());
309 //// FeaturePtr aFeature = aRC ? aRC->document()->feature(aRC) :
310 //// std::dynamic_pointer_cast<ModelAPI_Feature>(aMirLineAttr->object());
311 //// std::map<FeaturePtr, Slvs_hEntity>::iterator aMirLineIter = myFeatureMap.find(aFeature);
312 //// if (aMirLineIter == myFeatureMap.end())
314 //// Slvs_Entity aMirrorLine = myStorage->getEntity(aMirLineIter->second);
316 //// Slvs_Constraint aMirror;
317 //// double aStartEnd[4];
318 //// for (int i = 0; i < 2; i++) {
319 //// Slvs_Entity aPoint = myStorage->getEntity(aMirrorLine.point[i]);
320 //// for (int j = 0; j < 2; j++)
321 //// aStartEnd[2*i+j] = myStorage->getParameter(aPoint.param[j]).val;
324 //// // Calculate length of the mirror line and create temporary constraint
325 //// double aLength = sqrt((aStartEnd[2] - aStartEnd[0]) * (aStartEnd[2] - aStartEnd[0]) +
326 //// (aStartEnd[3] - aStartEnd[1]) * (aStartEnd[3] - aStartEnd[1]));
327 //// if (aLength < tolerance) {
328 //// if (myMirrorLineLength < 1.0)
329 //// myMirrorLineLength = 1.0;
331 //// myMirrorLineLength = aLength;
332 //// std::list<Slvs_Constraint> aDist = myStorage->getConstraintsByType(SLVS_C_PT_PT_DISTANCE);
333 //// std::list<Slvs_Constraint>::const_iterator aDIt = aDist.begin();
334 //// for (; aDIt != aDist.end(); ++aDIt)
335 //// if ((aDIt->ptA == aMirrorLine.point[0] && aDIt->ptB == aMirrorLine.point[1]) ||
336 //// (aDIt->ptA == aMirrorLine.point[1] && aDIt->ptB == aMirrorLine.point[0]))
337 //// break; // length of mirror line is already set
338 //// if (aDIt == aDist.end()) {
339 //// // check the points of mirror line is not fixed
340 //// Slvs_hConstraint aFixed;
341 //// if (!myStorage->isPointFixed(aMirrorLine.point[0], aFixed, true) ||
342 //// !myStorage->isPointFixed(aMirrorLine.point[1], aFixed, true)) {
343 //// // Add length constraint
344 //// aMirror = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_PT_PT_DISTANCE,
345 //// myGroup->getWorkplaneId(), aLength, aMirrorLine.point[0], aMirrorLine.point[1],
346 //// SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
347 //// aMirror.h = myStorage->addConstraint(aMirror);
348 //// myStorage->addTemporaryConstraint(aMirror.h);
352 //// // Search mirror between middle points on the arcs and recompute their coordinates
353 //// std::map<Slvs_hEntity, Slvs_hEntity> aPointsOnCircles;
354 //// std::list<Slvs_Constraint> aMirrorPonCirc;
355 //// std::list<Slvs_Constraint> aPonCirc = myStorage->getConstraintsByType(SLVS_C_PT_ON_CIRCLE);
356 //// std::vector<Slvs_hConstraint>::iterator aConstrIter = mySlvsConstraints.begin();
357 //// for (; aConstrIter != mySlvsConstraints.end(); aConstrIter++) {
358 //// aMirror = myStorage->getConstraint(*aConstrIter);
359 //// if (aMirror.type != SLVS_C_SYMMETRIC_LINE)
361 //// if (aMirror.entityA != aMirrorLine.h)
362 //// continue; // don't update another Mirror constraints
363 //// Slvs_Constraint aPonCircA, aPonCircB;
364 //// aPonCircA.h = SLVS_E_UNKNOWN;
365 //// aPonCircB.h = SLVS_E_UNKNOWN;
366 //// std::list<Slvs_Constraint>::iterator aPtIter = aPonCirc.begin();
367 //// for (; aPtIter != aPonCirc.end(); aPtIter++) {
368 //// if (aMirror.ptA == aPtIter->ptA)
369 //// aPonCircA = *aPtIter;
370 //// if (aMirror.ptB == aPtIter->ptA)
371 //// aPonCircB = *aPtIter;
373 //// if (aPonCircA.h == SLVS_E_UNKNOWN || aPonCircB.h == SLVS_E_UNKNOWN)
375 //// aMirrorPonCirc.push_back(aMirror);
376 //// // Store point IDs to avoid their recalculation twice
377 //// aPointsOnCircles[aPonCircA.ptA] = aPonCircA.entityA;
378 //// aPointsOnCircles[aPonCircB.ptA] = aPonCircB.entityA;
381 //// // Recalculate positions of mirroring points
382 //// std::list<Slvs_Constraint> aMirrorList = myStorage->getConstraintsByType(SLVS_C_SYMMETRIC_LINE);
383 //// std::list<Slvs_Constraint>::iterator aMirIter = aMirrorList.begin();
384 //// for (; aMirIter != aMirrorList.end(); aMirIter++) {
385 //// if (aMirIter->entityA != aMirrorLine.h)
386 //// continue; // don't update another Mirror constraints
387 //// if (aPointsOnCircles.find(aMirIter->ptA) != aPointsOnCircles.end())
388 //// continue; // Avoid mirroring points on circles
389 //// Slvs_Entity aBase = myStorage->getEntity(aMirIter->ptA);
390 //// Slvs_Entity aMirror = myStorage->getEntity(aMirIter->ptB);
391 //// makeMirrorEntity(aBase, aMirror, aStartEnd);
394 //// bool aNeedToResolve = myStorage->isNeedToResolve();
395 //// for (aMirIter = aMirrorPonCirc.begin(); aMirIter != aMirrorPonCirc.end(); aMirIter++) {
396 //// // Make centers of arcs symmetric
397 //// Slvs_Entity aBaseArc = myStorage->getEntity(aPointsOnCircles[aMirIter->ptA]);
398 //// Slvs_Entity aBasePoint = myStorage->getEntity(aBaseArc.point[0]);
399 //// Slvs_Entity aMirrorArc = myStorage->getEntity(aPointsOnCircles[aMirIter->ptB]);
400 //// Slvs_Entity aMirrorPoint = myStorage->getEntity(aMirrorArc.point[0]);
401 //// makeMirrorEntity(aBasePoint, aMirrorPoint, aStartEnd);
402 //// // Calculate middle point for base arc and mirrored point on mirror arc
403 //// aBasePoint = myStorage->getEntity(aMirIter->ptA);
404 //// Slvs_Param aParamX = myStorage->getParameter(aBasePoint.param[0]);
405 //// Slvs_Param aParamY = myStorage->getParameter(aBasePoint.param[1]);
406 //// calculateMiddlePoint(aBaseArc, 0.5, aParamX.val, aParamY.val);
407 //// myStorage->updateParameter(aParamX);
408 //// myStorage->updateParameter(aParamY);
409 //// aMirrorPoint = myStorage->getEntity(aMirIter->ptB);
410 //// aParamX = myStorage->getParameter(aMirrorPoint.param[0]);
411 //// aParamY = myStorage->getParameter(aMirrorPoint.param[1]);
412 //// calculateMiddlePoint(aMirrorArc, 0.5, aParamX.val, aParamY.val);
413 //// myStorage->updateParameter(aParamX);
414 //// myStorage->updateParameter(aParamY);
416 //// // Restore previous value to avoid looped recalculations of sketch
417 //// myStorage->setNeedToResolve(aNeedToResolve);