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 if (theFeature == myBaseConstraint)
66 return; // the constraint is already being updated
68 PlaneGCSSolver_UpdateCoincidence* anUpdater =
69 static_cast<PlaneGCSSolver_UpdateCoincidence*>(theUpdater);
71 bool isPointOnOppositeLine[4];
72 std::list<EntityWrapperPtr>::reverse_iterator anIt = myAttributes.rbegin();
73 for (int i = 0; i < 2; ++i, ++anIt) {
74 isPointOnOppositeLine[2*i] = anUpdater->isPointOnEntity(myPoints[2*i], *anIt);
75 isPointOnOppositeLine[2*i + 1] = anUpdater->isPointOnEntity(myPoints[2*i + 1], *anIt);
78 // both points of one line is on another line => lines are already collinear,
79 // would like to show "conflicting constraints"
80 if (isPointOnOppositeLine[0] && isPointOnOppositeLine[1])
81 isPointOnOppositeLine[1] = false;
82 if (isPointOnOppositeLine[2] && isPointOnOppositeLine[3])
83 isPointOnOppositeLine[3] = false;
85 bool aConstraintToApply[4] = {false, false, false, false};
86 ConstraintWrapperPtr aNewConstraint;
87 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoints[2];
88 std::shared_ptr<PlaneGCSSolver_EdgeWrapper> aLine;
90 if (isPointOnOppositeLine[0] || isPointOnOppositeLine[1]) {
91 // one of points of first line is already on the second line,
92 // make another point of first line to be coincident with second line
93 for (int i = 0; i < 2; ++i) {
94 if (isPointOnOppositeLine[i])
97 if (!myIsConstraintApplied[i])
98 aPoints[i] = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(myPoints[i]);
99 aConstraintToApply[i] = true;
101 aLine = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(myAttributes.back());
103 // verify second line and add necessary constraints
104 for (int i = 0; i < 2; ++i) {
105 if (isPointOnOppositeLine[i + 2])
108 if (!myIsConstraintApplied[i+2])
109 aPoints[i] = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(myPoints[i + 2]);
110 aConstraintToApply[i+2] = true;
112 aLine = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(myAttributes.front());
116 for (int i = 0; i < 4; ++i) {
117 if (aConstraintToApply[i] != myIsConstraintApplied[i])
119 myIsConstraintApplied[i] = aConstraintToApply[i];
123 mySolverConstraint = createPointsOnLine(aPoints[0], aPoints[1], aLine);
125 myStorage->removeConstraint(myBaseConstraint);
128 if (mySolverConstraint) {
129 myStorage->addConstraint(myBaseConstraint, mySolverConstraint);