1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 #include <SketchSolver_ConstraintCollinear.h>
4 #include <SketchSolver_Error.h>
6 #include <PlaneGCSSolver_ConstraintWrapper.h>
7 #include <PlaneGCSSolver_EdgeWrapper.h>
8 #include <PlaneGCSSolver_PointWrapper.h>
9 #include <PlaneGCSSolver_UpdateCoincidence.h>
11 #include <SketchPlugin_Line.h>
13 static ConstraintWrapperPtr createPointsOnLine(
14 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
15 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2,
16 std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theLine)
18 std::shared_ptr<GCS::Line> aGCSLine = std::dynamic_pointer_cast<GCS::Line>(theLine->entity());
20 std::list<GCSConstraintPtr> aConstrList;
22 aConstrList.push_back( GCSConstraintPtr(
23 new GCS::ConstraintPointOnLine(*thePoint1->point(), *aGCSLine)) );
25 aConstrList.push_back( GCSConstraintPtr(
26 new GCS::ConstraintPointOnLine(*thePoint2->point(), *aGCSLine)) );
28 return aConstrList.empty() ? ConstraintWrapperPtr() : ConstraintWrapperPtr(
29 new PlaneGCSSolver_ConstraintWrapper(aConstrList, CONSTRAINT_COLLINEAR));
33 void SketchSolver_ConstraintCollinear::process()
36 if (!myBaseConstraint || !myStorage) {
37 // Not enough parameters are assigned
41 EntityWrapperPtr aValue;
42 std::vector<EntityWrapperPtr> anAttributes;
43 getAttributes(aValue, anAttributes);
44 if (!myErrorMsg.empty())
46 if (anAttributes.empty()) {
47 myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
51 for (int i = 0; i < 2; ++i) {
52 AttributeRefAttrPtr aRefAttr = myBaseConstraint->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
53 FeaturePtr aLine = ModelAPI_Feature::feature(aRefAttr->object());
54 myPoints[2*i] = myStorage->entity(aLine->attribute(SketchPlugin_Line::START_ID()));
55 myPoints[2*i + 1] = myStorage->entity(aLine->attribute(SketchPlugin_Line::END_ID()));
58 myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateCoincidence::GROUP());
59 myStorage->notify(myBaseConstraint);
62 void SketchSolver_ConstraintCollinear::notify(const FeaturePtr& theFeature,
63 PlaneGCSSolver_Update* theUpdater)
65 PlaneGCSSolver_UpdateCoincidence* anUpdater =
66 static_cast<PlaneGCSSolver_UpdateCoincidence*>(theUpdater);
68 bool isPointOnOppositeLine[4];
69 std::list<EntityWrapperPtr>::reverse_iterator anIt = myAttributes.rbegin();
70 for (int i = 0; i < 2; ++i, ++anIt) {
71 isPointOnOppositeLine[2*i] = anUpdater->isPointOnEntity(myPoints[2*i], *anIt);
72 isPointOnOppositeLine[2*i + 1] = anUpdater->isPointOnEntity(myPoints[2*i + 1], *anIt);
75 // both points of one line is on another line => lines are already collinear,
76 // would like to show "conflicting constraints"
77 if (isPointOnOppositeLine[0] && isPointOnOppositeLine[1])
78 isPointOnOppositeLine[1] = false;
79 if (isPointOnOppositeLine[2] && isPointOnOppositeLine[3])
80 isPointOnOppositeLine[3] = false;
82 bool aConstraintToApply[4] = {false, false, false, false};
83 ConstraintWrapperPtr aNewConstraint;
84 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoints[2];
85 std::shared_ptr<PlaneGCSSolver_EdgeWrapper> aLine;
87 if (isPointOnOppositeLine[0] || isPointOnOppositeLine[1]) {
88 // one of points of first line is already on the second line,
89 // make another point of first line to be coincident with second line
90 for (int i = 0; i < 2; ++i) {
91 if (isPointOnOppositeLine[i])
94 if (!myIsConstraintApplied[i])
95 aPoints[i] = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(myPoints[i]);
96 aConstraintToApply[i] = true;
98 aLine = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(myAttributes.back());
100 // verify second line and add necessary constraints
101 for (int i = 0; i < 2; ++i) {
102 if (isPointOnOppositeLine[i + 2])
105 if (!myIsConstraintApplied[i+2])
106 aPoints[i] = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(myPoints[i + 2]);
107 aConstraintToApply[i+2] = true;
109 aLine = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(myAttributes.front());
113 for (int i = 0; i < 4 && !isNew; ++i)
114 if (aConstraintToApply[i] != myIsConstraintApplied[i])
117 mySolverConstraint = createPointsOnLine(aPoints[0], aPoints[1], aLine);
119 myStorage->removeConstraint(myBaseConstraint);
122 if (mySolverConstraint) {
123 myStorage->addConstraint(myBaseConstraint, mySolverConstraint);
127 for (int i = 0; i < 4; ++i)
128 myIsConstraintApplied[i] = aConstraintToApply[i];