1 // Copyright (C) 2014-2023 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 email : webmaster.salome@opencascade.com
20 #include <SketchSolver_ConstraintCollinear.h>
21 #include <SketchSolver_Error.h>
23 #include <PlaneGCSSolver_ConstraintWrapper.h>
24 #include <PlaneGCSSolver_EdgeWrapper.h>
25 #include <PlaneGCSSolver_PointWrapper.h>
26 #include <PlaneGCSSolver_UpdateCoincidence.h>
28 #include <SketchPlugin_Line.h>
30 static ConstraintWrapperPtr createPointsOnLine(
31 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
32 std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2,
33 std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theLine)
35 std::shared_ptr<GCS::Line> aGCSLine = std::dynamic_pointer_cast<GCS::Line>(theLine->entity());
37 std::list<GCSConstraintPtr> aConstrList;
39 aConstrList.push_back( GCSConstraintPtr(
40 new GCS::ConstraintPointOnLine(*thePoint1->point(), *aGCSLine)) );
42 aConstrList.push_back( GCSConstraintPtr(
43 new GCS::ConstraintPointOnLine(*thePoint2->point(), *aGCSLine)) );
45 return aConstrList.empty() ? ConstraintWrapperPtr() : ConstraintWrapperPtr(
46 new PlaneGCSSolver_ConstraintWrapper(aConstrList, CONSTRAINT_COLLINEAR));
50 void SketchSolver_ConstraintCollinear::process()
53 if (!myBaseConstraint || !myStorage) {
54 // Not enough parameters are assigned
58 EntityWrapperPtr aValue;
59 std::vector<EntityWrapperPtr> anAttributes;
60 getAttributes(aValue, anAttributes);
61 if (!myErrorMsg.empty())
63 if (anAttributes.empty()) {
64 myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
68 for (int i = 0; i < 2; ++i) {
69 AttributeRefAttrPtr aRefAttr = myBaseConstraint->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
70 FeaturePtr aLine = ModelAPI_Feature::feature(aRefAttr->object());
71 myPoints[2*i] = myStorage->entity(aLine->attribute(SketchPlugin_Line::START_ID()));
72 myPoints[2*i + 1] = myStorage->entity(aLine->attribute(SketchPlugin_Line::END_ID()));
75 myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateCoincidence::GROUP());
76 myStorage->notify(myBaseConstraint);
79 void SketchSolver_ConstraintCollinear::notify(const FeaturePtr& theFeature,
80 PlaneGCSSolver_Update* theUpdater)
82 if (theFeature == myBaseConstraint && myInSolver)
83 return; // the constraint is already being updated
85 PlaneGCSSolver_UpdateCoincidence* anUpdater =
86 static_cast<PlaneGCSSolver_UpdateCoincidence*>(theUpdater);
88 bool isPointOnOppositeLine[4];
89 std::list<EntityWrapperPtr>::reverse_iterator anIt = myAttributes.rbegin();
90 for (int i = 0; i < 2; ++i, ++anIt) {
91 isPointOnOppositeLine[2*i] = anUpdater->isPointOnEntity(myPoints[2*i], *anIt);
92 isPointOnOppositeLine[2*i + 1] = anUpdater->isPointOnEntity(myPoints[2*i + 1], *anIt);
95 // both points of one line is on another line => lines are already collinear,
96 // would like to show "conflicting constraints"
97 if (isPointOnOppositeLine[0] && isPointOnOppositeLine[1])
98 isPointOnOppositeLine[1] = false;
99 if (isPointOnOppositeLine[2] && isPointOnOppositeLine[3])
100 isPointOnOppositeLine[3] = false;
102 bool aConstraintToApply[4] = {false, false, false, false};
103 ConstraintWrapperPtr aNewConstraint;
104 std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoints[2];
105 std::shared_ptr<PlaneGCSSolver_EdgeWrapper> aLine;
107 if (isPointOnOppositeLine[0] || isPointOnOppositeLine[1]) {
108 // one of points of first line is already on the second line,
109 // make another point of first line to be coincident with second line
110 for (int i = 0; i < 2; ++i) {
111 if (isPointOnOppositeLine[i])
114 if (!myIsConstraintApplied[i])
115 aPoints[i] = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(myPoints[i]);
116 aConstraintToApply[i] = true;
118 aLine = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(myAttributes.back());
120 // verify second line and add necessary constraints
121 for (int i = 0; i < 2; ++i) {
122 if (isPointOnOppositeLine[i + 2])
125 if (!myIsConstraintApplied[i+2])
126 aPoints[i] = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(myPoints[i + 2]);
127 aConstraintToApply[i+2] = true;
129 aLine = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(myAttributes.front());
133 for (int i = 0; i < 4; ++i) {
134 if (aConstraintToApply[i] != myIsConstraintApplied[i])
136 myIsConstraintApplied[i] = aConstraintToApply[i];
140 mySolverConstraint = createPointsOnLine(aPoints[0], aPoints[1], aLine);
142 myStorage->removeConstraint(myBaseConstraint);
145 if (mySolverConstraint) {
146 myStorage->addConstraint(myBaseConstraint, mySolverConstraint);