1 #include <SketchSolver_ConstraintFillet.h>
2 #include <SketchSolver_Group.h>
3 #include <SketchSolver_Error.h>
5 #include <ModelAPI_AttributeDouble.h>
6 #include <ModelAPI_AttributeRefAttr.h>
7 #include <ModelAPI_AttributeRefList.h>
8 #include <ModelAPI_ResultConstruction.h>
11 void SketchSolver_ConstraintFillet::getAttributes(
12 double& theValue, std::vector<Slvs_hEntity>& theAttributes)
14 theAttributes.clear();
16 DataPtr aData = myBaseConstraint->data();
17 AttributeDoublePtr aValueAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
18 aData->attribute(SketchPlugin_Constraint::VALUE()));
19 theValue = aValueAttr ? aValueAttr->value() : 0.0;
21 std::list<AttributePtr> aBaseAttrs = aData->attributes(ModelAPI_AttributeRefAttr::typeId());
22 std::list<AttributePtr>::iterator anIter = aBaseAttrs.begin();
23 for (; anIter != aBaseAttrs.end(); anIter++) {
24 AttributeRefAttrPtr aRefAttr =
25 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
26 if (!aRefAttr || !aRefAttr->isInitialized()) {
27 myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
31 int aType = SLVS_E_UNKNOWN; // type of created entity
32 Slvs_hEntity anEntity = myGroup->getAttributeId(aRefAttr);
33 if (anEntity == SLVS_E_UNKNOWN)
34 anEntity = changeEntity(aRefAttr, aType);
36 if (aType == SLVS_E_UNKNOWN)
38 theAttributes.push_back(anEntity);
42 AttributeRefListPtr aFilletRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
43 aData->attribute(SketchPlugin_Constraint::ENTITY_C()));
44 if (!aFilletRefList || !aFilletRefList->isInitialized()) {
45 myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
48 std::list<ObjectPtr> aFilletList = aFilletRefList->list();
49 if (aFilletList.size() < theAttributes.size() + 1) {
50 myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
53 FeaturePtr aFilletFeature;
54 ResultConstructionPtr aRC;
56 std::list<ObjectPtr>::iterator aFilIter = aFilletList.begin();
57 for (int indEnt = 0; aFilIter != aFilletList.end(); aFilIter++, indEnt++) {
58 aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aFilIter);
59 aFilletFeature = aRC ? aRC->document()->feature(aRC) :
60 std::dynamic_pointer_cast<ModelAPI_Feature>(*aFilIter);
61 if (!aFilletFeature) {
62 myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
65 Slvs_hEntity anEntity = changeEntity(aFilletFeature, aType);
66 theAttributes.push_back(anEntity);
70 void SketchSolver_ConstraintFillet::process()
73 if (!myBaseConstraint || !myStorage || myGroup == 0) {
74 /// TODO: Put error message here
77 if (!mySlvsConstraints.empty()) // some data is changed, update constraint
78 update(myBaseConstraint);
81 std::vector<Slvs_hEntity> anEntID;
82 getAttributes(aValue, anEntID);
83 if (!myErrorMsg.empty())
86 // Obtain the entities itself:
87 // First two are base entities
88 // Second two are trimmed them
89 // Last one is a fillet arc
90 std::vector<Slvs_Entity> anEntities;
91 std::vector<Slvs_hEntity>::iterator anIt = anEntID.begin();
92 for (; anIt != anEntID.end(); anIt++)
93 anEntities.push_back(myStorage->getEntity(*anIt));
95 // Check the base entities have a coincident point
96 Slvs_hEntity aPointsToFind[4];
97 for (int i = 0; i < 2; i++) {
98 int aShift = anEntities[i].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0;
99 aPointsToFind[2*i] = anEntities[i].point[aShift];
100 aPointsToFind[2*i+1]= anEntities[i].point[aShift+1];
102 // Search coincident points
103 int aCoincInd[2]; // indices of coincident points on each entity (0 - first, 1 - last)
104 bool isPointFound = false;
105 for (int i = 0; i < 2 && !isPointFound; i++)
106 for (int j = 2; j < 4 && !isPointFound; j++)
107 if (myStorage->isCoincident(aPointsToFind[i], aPointsToFind[j])) {
109 aCoincInd[1] = j - 2;
113 // There is no coincident points between tangential objects. Generate error message
114 myErrorMsg = SketchSolver_Error::NO_COINCIDENT_POINTS();
118 // For correct result, move floating points of fillet on the middle points of base objects
121 double anArcPoints[3][2];
122 for (int i = 0; i < 2; i++) {
123 calculateMiddlePoint(anEntities[i], 0.1 + 0.8 * aCoincInd[i], anArcPoints[i+1][0], anArcPoints[i+1][1]);
124 aPoint = myStorage->getEntity(anEntities[i+2].point[aCoincInd[i]]);
125 for (int j = 0; j < 2; j++) {
126 aParam = myStorage->getParameter(aPoint.param[j]);
127 aParam.val = anArcPoints[i+1][j];
128 aPoint.param[j] = myStorage->updateParameter(aParam);
131 anArcPoints[0][0] = 0.5 * (anArcPoints[1][0] + anArcPoints[2][0]);
132 anArcPoints[0][1] = 0.5 * (anArcPoints[1][1] + anArcPoints[2][1]);
133 // Check the arc is need to be reversed
134 double aSharedPoint[2];
135 aPoint = myStorage->getEntity(aPointsToFind[aCoincInd[0]]);
136 for (int j = 0; j < 2; j++)
137 aSharedPoint[j] = myStorage->getParameter(aPoint.param[j]).val;
138 double aCross = (anArcPoints[1][0] - anArcPoints[0][0]) * (aSharedPoint[1] - anArcPoints[0][1]) -
139 (anArcPoints[1][1] - anArcPoints[0][1]) * (aSharedPoint[0] - anArcPoints[0][0]);
140 if (aCross < 0.0) { // reverse fillet arc
142 for (int j = 0; j < 2; j++) {
143 aTmp = anArcPoints[1][j];
144 anArcPoints[1][j] = anArcPoints[2][j];
145 anArcPoints[2][j] = aTmp;
148 // update fillet arc coordinates
149 for (int indArcPt = 0; indArcPt < 3; indArcPt++) {
150 aPoint = myStorage->getEntity(anEntities.back().point[indArcPt]);
151 for (int j = 0; j < 2; j++) {
152 aParam = myStorage->getParameter(aPoint.param[j]);
153 aParam.val = anArcPoints[indArcPt][j];
154 aPoint.param[j] = myStorage->updateParameter(aParam);
158 for (int indEnt = 0; indEnt < 2; indEnt++) {
159 int aShift = anEntities[indEnt].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0;
160 // one point of fillet object should be coincident with the point on base, non-coincident with another base object
161 Slvs_hEntity aBaseID = anEntities[indEnt].point[1 - aCoincInd[indEnt] + aShift];
162 Slvs_hEntity aFilletID = anEntities[2 + indEnt].point[1 - aCoincInd[indEnt] + aShift];
163 Slvs_Constraint aCoincConstr = Slvs_MakeConstraint(
164 SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(),
165 0.0, aBaseID, aFilletID, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
166 aCoincConstr.h = myStorage->addConstraint(aCoincConstr);
167 mySlvsConstraints.push_back(aCoincConstr.h);
169 // another point of fillet object should be placed on the base object
170 Slvs_Constraint aPonCurveConstr;
171 if (anEntities[indEnt].type == SLVS_E_ARC_OF_CIRCLE) {
172 // centers of arcs should be coincident
173 aBaseID = anEntities[indEnt].point[0];
174 aFilletID = anEntities[2 + indEnt].point[0];
175 aPonCurveConstr = Slvs_MakeConstraint(
176 SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(),
177 0.0, aBaseID, aFilletID, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
179 aFilletID = anEntities[2 + indEnt].point[aCoincInd[indEnt]];
180 aPonCurveConstr = Slvs_MakeConstraint(
181 SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_PT_ON_LINE, myGroup->getWorkplaneId(),
182 0.0, aFilletID, SLVS_E_UNKNOWN, anEntities[indEnt].h, SLVS_E_UNKNOWN);
184 aPonCurveConstr.h = myStorage->addConstraint(aPonCurveConstr);
185 mySlvsConstraints.push_back(aPonCurveConstr.h);
189 bool SketchSolver_ConstraintFillet::remove(ConstraintPtr theConstraint)
192 if (theConstraint && theConstraint != myBaseConstraint)
194 bool isFullyRemoved = true;
195 std::vector<Slvs_hEntity>::iterator aCIter = mySlvsConstraints.begin();
196 for (; aCIter != mySlvsConstraints.end(); aCIter++)
197 isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
198 mySlvsConstraints.clear();
200 if (isFullyRemoved) {
201 myFeatureMap.clear();
202 myAttributeMap.clear();
205 cleanRemovedEntities();