1 // Copyright (C) 2014-2019 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 "SketchPlugin_Tools.h"
22 #include "SketchPlugin_ConstraintCoincidence.h"
23 #include "SketchPlugin_ConstraintLength.h"
24 #include "SketchPlugin_ConstraintTangent.h"
25 #include "SketchPlugin_Line.h"
26 #include "SketchPlugin_Point.h"
27 #include "SketchPlugin_SketchEntity.h"
29 #include <SketcherPrs_Tools.h>
31 #include <ModelAPI_AttributeDouble.h>
33 #include <GeomAPI_Dir2d.h>
34 #include <GeomAPI_Pnt2d.h>
35 #include <GeomAPI_XY.h>
37 #include <GeomDataAPI_Point.h>
38 #include <GeomDataAPI_Point2D.h>
44 namespace SketchPlugin_Tools {
46 void clearExpressions(AttributeDoublePtr theAttribute)
48 theAttribute->setText(std::string());
51 void clearExpressions(AttributePointPtr theAttribute)
53 theAttribute->setText(std::string(), std::string(), std::string());
56 void clearExpressions(AttributePoint2DPtr theAttribute)
58 theAttribute->setText(std::string(), std::string());
61 void clearExpressions(AttributePtr theAttribute)
64 AttributeDoublePtr anAttributeDouble =
65 std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
66 if (anAttributeDouble.get())
67 clearExpressions(anAttributeDouble);
69 AttributePointPtr anAttributePoint =
70 std::dynamic_pointer_cast<GeomDataAPI_Point>(theAttribute);
71 if (anAttributePoint.get())
72 clearExpressions(anAttributePoint);
74 AttributePoint2DPtr anAttributePoint2D =
75 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
76 if (anAttributePoint2D.get())
77 clearExpressions(anAttributePoint2D);
80 void clearExpressions(FeaturePtr theFeature)
82 if (!theFeature.get())
85 std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
86 std::list<AttributePtr>::iterator anAttributeIt = anAttributes.begin();
87 for (; anAttributeIt != anAttributes.end(); ++anAttributeIt) {
88 clearExpressions(*anAttributeIt);
92 std::shared_ptr<GeomAPI_Pnt2d> getCoincidencePoint(const FeaturePtr theStartCoin)
94 std::shared_ptr<GeomAPI_Pnt2d> aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(),
95 SketchPlugin_Constraint::ENTITY_A());
96 if (aPnt.get() == NULL)
97 aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(), SketchPlugin_Constraint::ENTITY_B());
101 std::set<FeaturePtr> findCoincidentConstraints(const FeaturePtr& theFeature)
103 std::set<FeaturePtr> aCoincident;
104 const std::set<AttributePtr>& aRefsList = theFeature->data()->refsToMe();
105 std::set<AttributePtr>::const_iterator aIt;
106 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
107 FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aIt)->owner());
108 if (aConstrFeature && aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID())
109 aCoincident.insert(aConstrFeature);
114 void findCoincidences(const FeaturePtr theStartCoin,
115 const std::string& theAttr,
116 std::set<FeaturePtr>& theList,
117 const bool theIsAttrOnly)
119 AttributeRefAttrPtr aPnt = theStartCoin->refattr(theAttr);
123 FeaturePtr aObj = ModelAPI_Feature::feature(aPnt->object());
124 if(theList.find(aObj) == theList.end()) {
125 std::shared_ptr<GeomAPI_Pnt2d> aOrig = getCoincidencePoint(theStartCoin);
126 if(aOrig.get() == NULL) {
129 if(!theIsAttrOnly || !aPnt->isObject()) {
130 theList.insert(aObj);
132 std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(aObj);
133 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
134 for (; aCIt != aCoincidences.end(); ++aCIt) {
135 FeaturePtr aConstrFeature = *aCIt;
136 std::shared_ptr<GeomAPI_Pnt2d> aPnt = getCoincidencePoint(aConstrFeature);
137 if(aPnt.get() && aOrig->isEqual(aPnt)) {
138 findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A(),
139 theList, theIsAttrOnly);
140 findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B(),
141 theList, theIsAttrOnly);
147 std::set<FeaturePtr> findFeaturesCoincidentToPoint(const AttributePoint2DPtr& thePoint)
149 std::set<FeaturePtr> aCoincidentFeatures;
151 FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
152 aCoincidentFeatures.insert(anOwner);
154 std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(anOwner);
155 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
156 for (; aCIt != aCoincidences.end(); ++aCIt) {
157 bool isPointUsedInCoincidence = false;
158 AttributeRefAttrPtr anOtherCoincidentAttr;
159 for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
160 AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
163 if (!aRefAttr->isObject() && aRefAttr->attr() == thePoint)
164 isPointUsedInCoincidence = true;
166 anOtherCoincidentAttr = aRefAttr;
169 if (isPointUsedInCoincidence) {
171 if (anOtherCoincidentAttr->isObject())
172 anObj = anOtherCoincidentAttr->object();
174 anObj = anOtherCoincidentAttr->attr()->owner();
175 aCoincidentFeatures.insert(ModelAPI_Feature::feature(anObj));
179 return aCoincidentFeatures;
182 // Container for point-point coincidences.
183 // Useful to find points coincident to a given point.
184 class CoincidentPoints
187 void addCoincidence(const AttributePoint2DPtr& thePoint1,
188 const AttributePoint2DPtr& thePoint2 = AttributePoint2DPtr())
190 std::list< std::set<AttributePoint2DPtr> >::iterator aFound1 = find(thePoint1);
191 std::list< std::set<AttributePoint2DPtr> >::iterator aFound2 = find(thePoint2);
192 if (aFound1 == myCoincidentPoints.end()) {
193 if (aFound2 == myCoincidentPoints.end()) {
194 std::set<AttributePoint2DPtr> aNewSet;
195 aNewSet.insert(thePoint1);
197 aNewSet.insert(thePoint2);
198 myCoincidentPoints.push_back(aNewSet);
200 aFound2->insert(thePoint1);
201 } else if (aFound2 == myCoincidentPoints.end()) {
203 aFound1->insert(thePoint2);
205 aFound1->insert(aFound2->begin(), aFound2->end());
206 myCoincidentPoints.erase(aFound2);
210 std::set<AttributePoint2DPtr> coincidentPoints(const AttributePoint2DPtr& thePoint)
212 collectCoincidentPoints(thePoint);
214 std::list< std::set<AttributePoint2DPtr> >::iterator aFound = find(thePoint);
215 if (aFound == myCoincidentPoints.end())
216 return std::set<AttributePoint2DPtr>();
221 void coincidences(const FeaturePtr& theFeature,
222 std::set<FeaturePtr>& theCoincidences) const
224 // iterate through coincideces for the given feature
225 std::set<FeaturePtr> aCoincidences = SketchPlugin_Tools::findCoincidentConstraints(theFeature);
226 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
227 for (; aCIt != aCoincidences.end(); ++aCIt)
229 if (theCoincidences.find(*aCIt) != theCoincidences.end())
230 continue; // already processed
231 theCoincidences.insert(*aCIt);
232 // iterate on coincident attributes
233 for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
234 AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
235 if (aRefAttr && !aRefAttr->isObject())
237 FeaturePtr anOwner = ModelAPI_Feature::feature(aRefAttr->attr()->owner());
238 if (anOwner != theFeature)
239 coincidences(anOwner, theCoincidences);
245 // Iteratively search points coincident to the given point
246 // (two points may be coincident through the third point)
247 void collectCoincidentPoints(const AttributePoint2DPtr& thePoint)
249 AttributePoint2DPtr aPoints[2];
251 FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
252 std::set<FeaturePtr> aCoincidences;
253 coincidences(anOwner, aCoincidences);
255 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
256 for (; aCIt != aCoincidences.end(); ++aCIt) {
257 aPoints[0] = AttributePoint2DPtr();
258 aPoints[1] = AttributePoint2DPtr();
259 for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
260 AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
261 if (aRefAttr && !aRefAttr->isObject())
262 aPoints[aPtInd++] = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
265 if (aPoints[0] && aPoints[1])
266 addCoincidence(aPoints[0], aPoints[1]);
270 std::list< std::set<AttributePoint2DPtr> >::iterator find(const AttributePoint2DPtr& thePoint)
272 std::list< std::set<AttributePoint2DPtr> >::iterator aSeek = myCoincidentPoints.begin();
273 for (; aSeek != myCoincidentPoints.end(); ++aSeek)
274 if (aSeek->find(thePoint) != aSeek->end())
276 return myCoincidentPoints.end();
280 std::list< std::set<AttributePoint2DPtr> > myCoincidentPoints;
283 std::set<AttributePoint2DPtr> findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint)
285 CoincidentPoints aCoincidentPoints;
286 return aCoincidentPoints.coincidentPoints(thePoint);
289 void resetAttribute(SketchPlugin_Feature* theFeature,
290 const std::string& theId)
292 AttributePtr anAttr = theFeature->attribute(theId);
298 void createCoincidenceOrTangency(SketchPlugin_Feature* theFeature,
299 const std::string& theId,
300 const AttributePtr theAttr,
301 const ObjectPtr theObject,
302 const bool theIsCanBeTangent)
304 AttributeRefAttrPtr aRefAttr = theFeature->refattr(theId);
305 if(aRefAttr.get() && aRefAttr->isInitialized()) {
306 FeaturePtr aConstraint;
307 if(!theIsCanBeTangent) {
308 aConstraint = theFeature->sketch()
309 ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
311 if(aRefAttr->isObject()) {
312 ObjectPtr anObject = aRefAttr->object();
313 FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
314 if(aFeature->getKind() == SketchPlugin_Point::ID()) {
315 aConstraint = theFeature->sketch()
316 ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
318 aConstraint = theFeature->sketch()
319 ->addFeature(SketchPlugin_ConstraintTangent::ID());
322 aConstraint = theFeature->sketch()
323 ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
326 AttributeRefAttrPtr aRefAttrA = aConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
327 aRefAttr->isObject() ? aRefAttrA->setObject(aRefAttr->object())
328 : aRefAttrA->setAttr(aRefAttr->attr());
329 AttributeRefAttrPtr aRefAttrB = aConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
330 if(theObject.get()) {
331 aRefAttrB->setObject(theObject);
332 } else if(theAttr.get()) {
333 aRefAttrB->setAttr(theAttr);
338 void convertRefAttrToPointOrTangentCurve(const AttributeRefAttrPtr& theRefAttr,
339 const AttributePtr& theDefaultAttr,
340 std::shared_ptr<GeomAPI_Shape>& theTangentCurve,
341 std::shared_ptr<GeomAPI_Pnt2d>& thePassingPoint)
343 AttributePtr anAttr = theDefaultAttr;
344 if (theRefAttr->isObject()) {
345 FeaturePtr aTgFeature = ModelAPI_Feature::feature(theRefAttr->object());
347 if (aTgFeature->getKind() != SketchPlugin_Point::ID()) {
348 theTangentCurve = aTgFeature->lastResult()->shape();
351 anAttr = aTgFeature->attribute(SketchPlugin_Point::COORD_ID());
354 anAttr = theRefAttr->attr();
356 thePassingPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr)->pnt();
360 FeaturePtr createConstraintAttrAttr(SketchPlugin_Sketch* theSketch,
361 const std::string& theConstraintId,
362 const AttributePtr& theFirstAttribute,
363 const AttributePtr& theSecondAttribute)
365 FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
366 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
367 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
368 aRefAttr->setAttr(theFirstAttribute);
370 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
371 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
372 aRefAttr->setAttr(theSecondAttribute);
374 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
375 std::cout << "<createConstraint to attribute> :"
376 << " first attribute - " << theFirstAttribute->id()
377 << " second attribute - " << theSecondAttribute->id()
384 FeaturePtr createConstraintAttrObject(SketchPlugin_Sketch* theSketch,
385 const std::string& theConstraintId,
386 const AttributePtr& theFirstAttribute,
387 const ObjectPtr& theSecondObject)
389 FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
390 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
391 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
392 aRefAttr->setAttr(theFirstAttribute);
394 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
395 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
396 aRefAttr->setObject(theSecondObject);
398 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
399 std::cout << "<createConstraint to attribute> :"
400 << " first attribute - " << theFirstAttribute->id()
401 << " second object - " << ModelAPI_Feature::feature(theSecondObject)->getKind()
408 FeaturePtr createConstraintObjectObject(SketchPlugin_Sketch* theSketch,
409 const std::string& theConstraintId,
410 const ObjectPtr& theFirstObject,
411 const ObjectPtr& theSecondObject)
413 FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
414 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
415 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
416 aRefAttr->setObject(theFirstObject);
418 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
419 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
420 aRefAttr->setObject(theSecondObject);
422 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
423 std::cout << "<createConstraint to attribute> :"
424 << " first object - " << ModelAPI_Feature::feature(theFirstObject)->getKind()
425 << " second object - " << ModelAPI_Feature::feature(theSecondObject)->getKind()
432 GeomPnt2dPtr flyoutPointCoordinates(const ConstraintPtr& theConstraint)
434 // currently process Length constraints only
435 if (theConstraint->getKind() != SketchPlugin_ConstraintLength::ID())
436 return GeomPnt2dPtr();
438 AttributeRefAttrPtr aLineAttr = theConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
439 if (!aLineAttr || !aLineAttr->isObject())
440 return GeomPnt2dPtr();
441 FeaturePtr aLine = ModelAPI_Feature::feature(aLineAttr->object());
442 if (!aLine || aLine->getKind() != SketchPlugin_Line::ID())
443 return GeomPnt2dPtr();
445 std::shared_ptr<GeomAPI_XY> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
446 aLine->attribute(SketchPlugin_Line::START_ID()))->pnt()->xy();
447 std::shared_ptr<GeomAPI_XY> aEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
448 aLine->attribute(SketchPlugin_Line::END_ID()))->pnt()->xy();
450 std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr =
451 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
452 theConstraint->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
453 std::shared_ptr<GeomAPI_Pnt2d> aFltPnt = aFlyoutAttr->pnt();
455 std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
457 double X = aStartPnt->x() + aFltPnt->x() * aLineDir->x() - aFltPnt->y() * aLineDir->y();
458 double Y = aStartPnt->y() + aFltPnt->x() * aLineDir->y() + aFltPnt->y() * aLineDir->x();
460 return GeomPnt2dPtr(new GeomAPI_Pnt2d(X, Y));
463 } // namespace SketchPlugin_Tools