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 "SketchPlugin_Tools.h"
23 #include "SketchPlugin_ConstraintCoincidence.h"
24 #include "SketchPlugin_ConstraintLength.h"
25 #include "SketchPlugin_ConstraintTangent.h"
26 #include "SketchPlugin_Line.h"
27 #include "SketchPlugin_Point.h"
28 #include "SketchPlugin_SketchEntity.h"
30 #include <SketcherPrs_Tools.h>
32 #include <ModelAPI_AttributeDouble.h>
34 #include <GeomAPI_Dir2d.h>
35 #include <GeomAPI_Pnt2d.h>
36 #include <GeomAPI_XY.h>
38 #include <GeomDataAPI_Point.h>
39 #include <GeomDataAPI_Point2D.h>
45 namespace SketchPlugin_Tools {
47 void clearExpressions(AttributeDoublePtr theAttribute)
49 theAttribute->setText(std::string());
52 void clearExpressions(AttributePointPtr theAttribute)
54 theAttribute->setText(std::string(), std::string(), std::string());
57 void clearExpressions(AttributePoint2DPtr theAttribute)
59 theAttribute->setText(std::string(), std::string());
62 void clearExpressions(AttributePtr theAttribute)
65 AttributeDoublePtr anAttributeDouble =
66 std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
67 if (anAttributeDouble.get())
68 clearExpressions(anAttributeDouble);
70 AttributePointPtr anAttributePoint =
71 std::dynamic_pointer_cast<GeomDataAPI_Point>(theAttribute);
72 if (anAttributePoint.get())
73 clearExpressions(anAttributePoint);
75 AttributePoint2DPtr anAttributePoint2D =
76 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
77 if (anAttributePoint2D.get())
78 clearExpressions(anAttributePoint2D);
81 void clearExpressions(FeaturePtr theFeature)
83 if (!theFeature.get())
86 std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
87 std::list<AttributePtr>::iterator anAttributeIt = anAttributes.begin();
88 for (; anAttributeIt != anAttributes.end(); ++anAttributeIt) {
89 clearExpressions(*anAttributeIt);
93 std::shared_ptr<GeomAPI_Pnt2d> getCoincidencePoint(const FeaturePtr theStartCoin)
95 std::shared_ptr<GeomAPI_Pnt2d> aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(),
96 SketchPlugin_Constraint::ENTITY_A());
97 if (aPnt.get() == NULL)
98 aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(), SketchPlugin_Constraint::ENTITY_B());
102 std::set<FeaturePtr> findCoincidentConstraints(const FeaturePtr& theFeature)
104 std::set<FeaturePtr> aCoincident;
105 const std::set<AttributePtr>& aRefsList = theFeature->data()->refsToMe();
106 std::set<AttributePtr>::const_iterator aIt;
107 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
108 FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aIt)->owner());
109 if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID())
110 aCoincident.insert(aConstrFeature);
115 void findCoincidences(const FeaturePtr theStartCoin,
116 const std::string& theAttr,
117 std::set<FeaturePtr>& theList,
118 const bool theIsAttrOnly)
120 AttributeRefAttrPtr aPnt = theStartCoin->refattr(theAttr);
124 FeaturePtr aObj = ModelAPI_Feature::feature(aPnt->object());
125 if(theList.find(aObj) == theList.end()) {
126 std::shared_ptr<GeomAPI_Pnt2d> aOrig = getCoincidencePoint(theStartCoin);
127 if(aOrig.get() == NULL) {
130 if(!theIsAttrOnly || !aPnt->isObject()) {
131 theList.insert(aObj);
133 std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(aObj);
134 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
135 for (; aCIt != aCoincidences.end(); ++aCIt) {
136 FeaturePtr aConstrFeature = *aCIt;
137 std::shared_ptr<GeomAPI_Pnt2d> aPnt = getCoincidencePoint(aConstrFeature);
138 if(aPnt.get() && aOrig->isEqual(aPnt)) {
139 findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A(),
140 theList, theIsAttrOnly);
141 findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B(),
142 theList, theIsAttrOnly);
148 std::set<FeaturePtr> findFeaturesCoincidentToPoint(const AttributePoint2DPtr& thePoint)
150 std::set<FeaturePtr> aCoincidentFeatures;
152 FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
153 aCoincidentFeatures.insert(anOwner);
155 std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(anOwner);
156 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
157 for (; aCIt != aCoincidences.end(); ++aCIt) {
158 bool isPointUsedInCoincidence = false;
159 AttributeRefAttrPtr anOtherCoincidentAttr;
160 for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
161 AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
164 if (!aRefAttr->isObject() && aRefAttr->attr() == thePoint)
165 isPointUsedInCoincidence = true;
167 anOtherCoincidentAttr = aRefAttr;
170 if (isPointUsedInCoincidence) {
172 if (anOtherCoincidentAttr->isObject())
173 anObj = anOtherCoincidentAttr->object();
175 anObj = anOtherCoincidentAttr->attr()->owner();
176 aCoincidentFeatures.insert(ModelAPI_Feature::feature(anObj));
180 return aCoincidentFeatures;
183 // Container for point-point coincidences.
184 // Useful to find points coincident to a given point.
185 class CoincidentPoints
188 void addCoincidence(const AttributePoint2DPtr& thePoint1,
189 const AttributePoint2DPtr& thePoint2 = AttributePoint2DPtr())
191 std::list< std::set<AttributePoint2DPtr> >::iterator aFound1 = find(thePoint1);
192 std::list< std::set<AttributePoint2DPtr> >::iterator aFound2 = find(thePoint2);
193 if (aFound1 == myCoincidentPoints.end()) {
194 if (aFound2 == myCoincidentPoints.end()) {
195 std::set<AttributePoint2DPtr> aNewSet;
196 aNewSet.insert(thePoint1);
198 aNewSet.insert(thePoint2);
199 myCoincidentPoints.push_back(aNewSet);
201 aFound2->insert(thePoint1);
202 } else if (aFound2 == myCoincidentPoints.end()) {
204 aFound1->insert(thePoint2);
206 aFound1->insert(aFound2->begin(), aFound2->end());
207 myCoincidentPoints.erase(aFound2);
211 std::set<AttributePoint2DPtr> coincidentPoints(const AttributePoint2DPtr& thePoint)
213 collectCoincidentPoints(thePoint);
215 std::list< std::set<AttributePoint2DPtr> >::iterator aFound = find(thePoint);
216 if (aFound == myCoincidentPoints.end())
217 return std::set<AttributePoint2DPtr>();
222 void coincidences(const FeaturePtr& theFeature,
223 std::set<FeaturePtr>& theCoincidences) const
225 // iterate through coincideces for the given feature
226 std::set<FeaturePtr> aCoincidences = SketchPlugin_Tools::findCoincidentConstraints(theFeature);
227 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
228 for (; aCIt != aCoincidences.end(); ++aCIt)
230 if (theCoincidences.find(*aCIt) != theCoincidences.end())
231 continue; // already processed
232 theCoincidences.insert(*aCIt);
233 // iterate on coincident attributes
234 for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
235 AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
236 if (aRefAttr && !aRefAttr->isObject())
238 FeaturePtr anOwner = ModelAPI_Feature::feature(aRefAttr->attr()->owner());
239 if (anOwner != theFeature)
240 coincidences(anOwner, theCoincidences);
246 // Iteratively search points coincident to the given point
247 // (two points may be coincident through the third point)
248 void collectCoincidentPoints(const AttributePoint2DPtr& thePoint)
250 AttributePoint2DPtr aPoints[2];
252 FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
253 std::set<FeaturePtr> aCoincidences;
254 coincidences(anOwner, aCoincidences);
256 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
257 for (; aCIt != aCoincidences.end(); ++aCIt) {
258 aPoints[0] = AttributePoint2DPtr();
259 aPoints[1] = AttributePoint2DPtr();
260 for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
261 AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
262 if (aRefAttr && !aRefAttr->isObject())
263 aPoints[aPtInd++] = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
266 if (aPoints[0] && aPoints[1])
267 addCoincidence(aPoints[0], aPoints[1]);
271 std::list< std::set<AttributePoint2DPtr> >::iterator find(const AttributePoint2DPtr& thePoint)
273 std::list< std::set<AttributePoint2DPtr> >::iterator aSeek = myCoincidentPoints.begin();
274 for (; aSeek != myCoincidentPoints.end(); ++aSeek)
275 if (aSeek->find(thePoint) != aSeek->end())
277 return myCoincidentPoints.end();
281 std::list< std::set<AttributePoint2DPtr> > myCoincidentPoints;
284 std::set<AttributePoint2DPtr> findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint)
286 CoincidentPoints aCoincidentPoints;
287 return aCoincidentPoints.coincidentPoints(thePoint);
290 void resetAttribute(SketchPlugin_Feature* theFeature,
291 const std::string& theId)
293 AttributePtr anAttr = theFeature->attribute(theId);
299 void createCoincidenceOrTangency(SketchPlugin_Feature* theFeature,
300 const std::string& theId,
301 const AttributePtr theAttr,
302 const ObjectPtr theObject,
303 const bool theIsCanBeTangent)
305 AttributeRefAttrPtr aRefAttr = theFeature->refattr(theId);
306 if(aRefAttr.get() && aRefAttr->isInitialized()) {
307 FeaturePtr aConstraint;
308 if(!theIsCanBeTangent) {
309 aConstraint = theFeature->sketch()
310 ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
312 if(aRefAttr->isObject()) {
313 ObjectPtr anObject = aRefAttr->object();
314 FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
315 if(aFeature->getKind() == SketchPlugin_Point::ID()) {
316 aConstraint = theFeature->sketch()
317 ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
319 aConstraint = theFeature->sketch()
320 ->addFeature(SketchPlugin_ConstraintTangent::ID());
323 aConstraint = theFeature->sketch()
324 ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
327 AttributeRefAttrPtr aRefAttrA = aConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
328 aRefAttr->isObject() ? aRefAttrA->setObject(aRefAttr->object())
329 : aRefAttrA->setAttr(aRefAttr->attr());
330 AttributeRefAttrPtr aRefAttrB = aConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
331 if(theObject.get()) {
332 aRefAttrB->setObject(theObject);
333 } else if(theAttr.get()) {
334 aRefAttrB->setAttr(theAttr);
339 void convertRefAttrToPointOrTangentCurve(const AttributeRefAttrPtr& theRefAttr,
340 const AttributePtr& theDefaultAttr,
341 std::shared_ptr<GeomAPI_Shape>& theTangentCurve,
342 std::shared_ptr<GeomAPI_Pnt2d>& thePassingPoint)
344 AttributePtr anAttr = theDefaultAttr;
345 if (theRefAttr->isObject()) {
346 FeaturePtr aTgFeature = ModelAPI_Feature::feature(theRefAttr->object());
348 if (aTgFeature->getKind() != SketchPlugin_Point::ID()) {
349 theTangentCurve = aTgFeature->lastResult()->shape();
352 anAttr = aTgFeature->attribute(SketchPlugin_Point::COORD_ID());
355 anAttr = theRefAttr->attr();
357 thePassingPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr)->pnt();
361 FeaturePtr createConstraintAttrAttr(SketchPlugin_Sketch* theSketch,
362 const std::string& theConstraintId,
363 const AttributePtr& theFirstAttribute,
364 const AttributePtr& theSecondAttribute)
366 FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
367 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
368 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
369 aRefAttr->setAttr(theFirstAttribute);
371 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
372 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
373 aRefAttr->setAttr(theSecondAttribute);
375 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
376 std::cout << "<createConstraint to attribute> :"
377 << " first attribute - " << theFirstAttribute->id()
378 << " second attribute - " << theSecondAttribute->id()
385 FeaturePtr createConstraintAttrObject(SketchPlugin_Sketch* theSketch,
386 const std::string& theConstraintId,
387 const AttributePtr& theFirstAttribute,
388 const ObjectPtr& theSecondObject)
390 FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
391 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
392 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
393 aRefAttr->setAttr(theFirstAttribute);
395 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
396 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
397 aRefAttr->setObject(theSecondObject);
399 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
400 std::cout << "<createConstraint to attribute> :"
401 << " first attribute - " << theFirstAttribute->id()
402 << " second object - " << ModelAPI_Feature::feature(theSecondObject)->getKind()
409 FeaturePtr createConstraintObjectObject(SketchPlugin_Sketch* theSketch,
410 const std::string& theConstraintId,
411 const ObjectPtr& theFirstObject,
412 const ObjectPtr& theSecondObject)
414 FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
415 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
416 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
417 aRefAttr->setObject(theFirstObject);
419 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
420 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
421 aRefAttr->setObject(theSecondObject);
423 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
424 std::cout << "<createConstraint to attribute> :"
425 << " first object - " << ModelAPI_Feature::feature(theFirstObject)->getKind()
426 << " second object - " << ModelAPI_Feature::feature(theSecondObject)->getKind()
433 GeomPnt2dPtr flyoutPointCoordinates(const ConstraintPtr& theConstraint)
435 // currently process Length constraints only
436 if (theConstraint->getKind() != SketchPlugin_ConstraintLength::ID())
437 return GeomPnt2dPtr();
439 AttributeRefAttrPtr aLineAttr = theConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
440 if (!aLineAttr || !aLineAttr->isObject())
441 return GeomPnt2dPtr();
442 FeaturePtr aLine = ModelAPI_Feature::feature(aLineAttr->object());
443 if (!aLine || aLine->getKind() != SketchPlugin_Line::ID())
444 return GeomPnt2dPtr();
446 std::shared_ptr<GeomAPI_XY> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
447 aLine->attribute(SketchPlugin_Line::START_ID()))->pnt()->xy();
448 std::shared_ptr<GeomAPI_XY> aEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
449 aLine->attribute(SketchPlugin_Line::END_ID()))->pnt()->xy();
451 std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr =
452 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
453 theConstraint->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
454 std::shared_ptr<GeomAPI_Pnt2d> aFltPnt = aFlyoutAttr->pnt();
456 std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
458 double X = aStartPnt->x() + aFltPnt->x() * aLineDir->x() - aFltPnt->y() * aLineDir->y();
459 double Y = aStartPnt->y() + aFltPnt->x() * aLineDir->y() + aFltPnt->y() * aLineDir->x();
461 return GeomPnt2dPtr(new GeomAPI_Pnt2d(X, Y));
464 } // namespace SketchPlugin_Tools