1 // Copyright (C) 2014-2017 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
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
21 #include <SketchSolver_ConstraintCollinear.h>
22 #include <SketchSolver_Error.h>
24 #include <PlaneGCSSolver_ConstraintWrapper.h>
25 #include <PlaneGCSSolver_EdgeWrapper.h>
26 #include <PlaneGCSSolver_PointWrapper.h>
27 #include <PlaneGCSSolver_UpdateCoincidence.h>
29 #include <SketchPlugin_Line.h>
31 static ConstraintWrapperPtr createPointsOnLine(
32 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
33 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2,
34 std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theLine)
36 std::shared_ptr<GCS::Line> aGCSLine = std::dynamic_pointer_cast<GCS::Line>(theLine->entity());
38 std::list<GCSConstraintPtr> aConstrList;
40 aConstrList.push_back( GCSConstraintPtr(
41 new GCS::ConstraintPointOnLine(*thePoint1->point(), *aGCSLine)) );
43 aConstrList.push_back( GCSConstraintPtr(
44 new GCS::ConstraintPointOnLine(*thePoint2->point(), *aGCSLine)) );
46 return aConstrList.empty() ? ConstraintWrapperPtr() : ConstraintWrapperPtr(
47 new PlaneGCSSolver_ConstraintWrapper(aConstrList, CONSTRAINT_COLLINEAR));
51 void SketchSolver_ConstraintCollinear::process()
54 if (!myBaseConstraint || !myStorage) {
55 // Not enough parameters are assigned
59 EntityWrapperPtr aValue;
60 std::vector<EntityWrapperPtr> anAttributes;
61 getAttributes(aValue, anAttributes);
62 if (!myErrorMsg.empty())
64 if (anAttributes.empty()) {
65 myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
69 for (int i = 0; i < 2; ++i) {
70 AttributeRefAttrPtr aRefAttr = myBaseConstraint->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
71 FeaturePtr aLine = ModelAPI_Feature::feature(aRefAttr->object());
72 myPoints[2*i] = myStorage->entity(aLine->attribute(SketchPlugin_Line::START_ID()));
73 myPoints[2*i + 1] = myStorage->entity(aLine->attribute(SketchPlugin_Line::END_ID()));
76 myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateCoincidence::GROUP());
77 myStorage->notify(myBaseConstraint);
80 void SketchSolver_ConstraintCollinear::notify(const FeaturePtr& theFeature,
81 PlaneGCSSolver_Update* theUpdater)
83 if (theFeature == myBaseConstraint && myInSolver)
84 return; // the constraint is already being updated
86 PlaneGCSSolver_UpdateCoincidence* anUpdater =
87 static_cast<PlaneGCSSolver_UpdateCoincidence*>(theUpdater);
89 bool isPointOnOppositeLine[4];
90 std::list<EntityWrapperPtr>::reverse_iterator anIt = myAttributes.rbegin();
91 for (int i = 0; i < 2; ++i, ++anIt) {
92 isPointOnOppositeLine[2*i] = anUpdater->isPointOnEntity(myPoints[2*i], *anIt);
93 isPointOnOppositeLine[2*i + 1] = anUpdater->isPointOnEntity(myPoints[2*i + 1], *anIt);
96 // both points of one line is on another line => lines are already collinear,
97 // would like to show "conflicting constraints"
98 if (isPointOnOppositeLine[0] && isPointOnOppositeLine[1])
99 isPointOnOppositeLine[1] = false;
100 if (isPointOnOppositeLine[2] && isPointOnOppositeLine[3])
101 isPointOnOppositeLine[3] = false;
103 bool aConstraintToApply[4] = {false, false, false, false};
104 ConstraintWrapperPtr aNewConstraint;
105 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoints[2];
106 std::shared_ptr<PlaneGCSSolver_EdgeWrapper> aLine;
108 if (isPointOnOppositeLine[0] || isPointOnOppositeLine[1]) {
109 // one of points of first line is already on the second line,
110 // make another point of first line to be coincident with second line
111 for (int i = 0; i < 2; ++i) {
112 if (isPointOnOppositeLine[i])
115 if (!myIsConstraintApplied[i])
116 aPoints[i] = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(myPoints[i]);
117 aConstraintToApply[i] = true;
119 aLine = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(myAttributes.back());
121 // verify second line and add necessary constraints
122 for (int i = 0; i < 2; ++i) {
123 if (isPointOnOppositeLine[i + 2])
126 if (!myIsConstraintApplied[i+2])
127 aPoints[i] = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(myPoints[i + 2]);
128 aConstraintToApply[i+2] = true;
130 aLine = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(myAttributes.front());
134 for (int i = 0; i < 4; ++i) {
135 if (aConstraintToApply[i] != myIsConstraintApplied[i])
137 myIsConstraintApplied[i] = aConstraintToApply[i];
141 mySolverConstraint = createPointsOnLine(aPoints[0], aPoints[1], aLine);
143 myStorage->removeConstraint(myBaseConstraint);
146 if (mySolverConstraint) {
147 myStorage->addConstraint(myBaseConstraint, mySolverConstraint);