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_ConstraintCoincidenceInternal.h"
24 #include "SketchPlugin_ConstraintLength.h"
25 #include "SketchPlugin_ConstraintTangent.h"
26 #include "SketchPlugin_Ellipse.h"
27 #include "SketchPlugin_Line.h"
28 #include "SketchPlugin_Point.h"
29 #include "SketchPlugin_SketchEntity.h"
31 #include <SketcherPrs_Tools.h>
33 #include <ModelAPI_AttributeDouble.h>
35 #include <GeomAPI_Dir2d.h>
36 #include <GeomAPI_Pnt2d.h>
37 #include <GeomAPI_XY.h>
39 #include <GeomDataAPI_Point.h>
40 #include <GeomDataAPI_Point2D.h>
46 namespace SketchPlugin_Tools {
48 void clearExpressions(AttributeDoublePtr theAttribute)
50 theAttribute->setText(std::string());
53 void clearExpressions(AttributePointPtr theAttribute)
55 theAttribute->setText(std::string(), std::string(), std::string());
58 void clearExpressions(AttributePoint2DPtr theAttribute)
60 theAttribute->setText(std::string(), std::string());
63 void clearExpressions(AttributePtr theAttribute)
66 AttributeDoublePtr anAttributeDouble =
67 std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
68 if (anAttributeDouble.get())
69 clearExpressions(anAttributeDouble);
71 AttributePointPtr anAttributePoint =
72 std::dynamic_pointer_cast<GeomDataAPI_Point>(theAttribute);
73 if (anAttributePoint.get())
74 clearExpressions(anAttributePoint);
76 AttributePoint2DPtr anAttributePoint2D =
77 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
78 if (anAttributePoint2D.get())
79 clearExpressions(anAttributePoint2D);
82 void clearExpressions(FeaturePtr theFeature)
84 if (!theFeature.get())
87 std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
88 std::list<AttributePtr>::iterator anAttributeIt = anAttributes.begin();
89 for (; anAttributeIt != anAttributes.end(); ++anAttributeIt) {
90 clearExpressions(*anAttributeIt);
94 std::shared_ptr<GeomAPI_Pnt2d> getCoincidencePoint(const FeaturePtr theStartCoin)
96 std::shared_ptr<GeomAPI_Pnt2d> aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(),
97 SketchPlugin_Constraint::ENTITY_A());
98 if (aPnt.get() == NULL)
99 aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(), SketchPlugin_Constraint::ENTITY_B());
103 std::set<FeaturePtr> findCoincidentConstraints(const FeaturePtr& theFeature)
105 std::set<FeaturePtr> aCoincident;
106 const std::set<AttributePtr>& aRefsList = theFeature->data()->refsToMe();
107 std::set<AttributePtr>::const_iterator aIt;
108 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
109 FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aIt)->owner());
110 if (aConstrFeature && aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID())
111 aCoincident.insert(aConstrFeature);
116 void findCoincidences(const FeaturePtr theStartCoin,
117 const std::string& theAttr,
118 std::set<FeaturePtr>& theList,
119 const bool theIsAttrOnly)
121 AttributeRefAttrPtr aPnt = theStartCoin->refattr(theAttr);
125 FeaturePtr aObj = ModelAPI_Feature::feature(aPnt->object());
126 if(theList.find(aObj) == theList.end()) {
127 std::shared_ptr<GeomAPI_Pnt2d> aOrig = getCoincidencePoint(theStartCoin);
128 if(aOrig.get() == NULL) {
131 if(!theIsAttrOnly || !aPnt->isObject()) {
132 theList.insert(aObj);
134 std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(aObj);
135 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
136 for (; aCIt != aCoincidences.end(); ++aCIt) {
137 FeaturePtr aConstrFeature = *aCIt;
138 std::shared_ptr<GeomAPI_Pnt2d> aPnt = getCoincidencePoint(aConstrFeature);
139 if(aPnt.get() && aOrig->isEqual(aPnt)) {
140 findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A(),
141 theList, theIsAttrOnly);
142 findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B(),
143 theList, theIsAttrOnly);
149 std::set<FeaturePtr> findFeaturesCoincidentToPoint(const AttributePoint2DPtr& thePoint)
151 std::set<FeaturePtr> aCoincidentFeatures;
153 FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
154 aCoincidentFeatures.insert(anOwner);
156 std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(anOwner);
157 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
158 for (; aCIt != aCoincidences.end(); ++aCIt) {
159 bool isPointUsedInCoincidence = false;
160 AttributeRefAttrPtr anOtherCoincidentAttr;
161 for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
162 AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
165 if (!aRefAttr->isObject() && aRefAttr->attr() == thePoint)
166 isPointUsedInCoincidence = true;
168 anOtherCoincidentAttr = aRefAttr;
171 if (isPointUsedInCoincidence) {
173 if (anOtherCoincidentAttr->isObject())
174 anObj = anOtherCoincidentAttr->object();
176 anObj = anOtherCoincidentAttr->attr()->owner();
177 aCoincidentFeatures.insert(ModelAPI_Feature::feature(anObj));
181 return aCoincidentFeatures;
184 // Container for point-point coincidences.
185 // Useful to find points coincident to a given point.
186 class CoincidentPoints
189 void addCoincidence(const AttributePoint2DPtr& thePoint1,
190 const AttributePoint2DPtr& thePoint2 = AttributePoint2DPtr())
192 std::list< std::set<AttributePoint2DPtr> >::iterator aFound1 = find(thePoint1);
193 std::list< std::set<AttributePoint2DPtr> >::iterator aFound2 = find(thePoint2);
194 if (aFound1 == myCoincidentPoints.end()) {
195 if (aFound2 == myCoincidentPoints.end()) {
196 std::set<AttributePoint2DPtr> aNewSet;
197 aNewSet.insert(thePoint1);
199 aNewSet.insert(thePoint2);
200 myCoincidentPoints.push_back(aNewSet);
202 aFound2->insert(thePoint1);
203 } else if (aFound2 == myCoincidentPoints.end()) {
205 aFound1->insert(thePoint2);
207 aFound1->insert(aFound2->begin(), aFound2->end());
208 myCoincidentPoints.erase(aFound2);
212 std::set<AttributePoint2DPtr> coincidentPoints(const AttributePoint2DPtr& thePoint)
214 collectCoincidentPoints(thePoint);
216 std::list< std::set<AttributePoint2DPtr> >::iterator aFound = find(thePoint);
217 if (aFound == myCoincidentPoints.end())
218 return std::set<AttributePoint2DPtr>();
223 void coincidences(const FeaturePtr& theFeature,
224 std::set<FeaturePtr>& theCoincidences) const
226 // iterate through coincideces for the given feature
227 std::set<FeaturePtr> aCoincidences = SketchPlugin_Tools::findCoincidentConstraints(theFeature);
228 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
229 for (; aCIt != aCoincidences.end(); ++aCIt)
231 if (theCoincidences.find(*aCIt) != theCoincidences.end())
232 continue; // already processed
233 theCoincidences.insert(*aCIt);
234 // iterate on coincident attributes
235 for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
236 AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
237 if (aRefAttr && !aRefAttr->isObject())
239 FeaturePtr anOwner = ModelAPI_Feature::feature(aRefAttr->attr()->owner());
240 if (anOwner != theFeature)
241 coincidences(anOwner, theCoincidences);
247 // Iteratively search points coincident to the given point
248 // (two points may be coincident through the third point)
249 void collectCoincidentPoints(const AttributePoint2DPtr& thePoint)
251 AttributePoint2DPtr aPoints[2];
253 FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
254 std::set<FeaturePtr> aCoincidences;
255 coincidences(anOwner, aCoincidences);
257 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
258 for (; aCIt != aCoincidences.end(); ++aCIt) {
259 aPoints[0] = AttributePoint2DPtr();
260 aPoints[1] = AttributePoint2DPtr();
261 for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
262 AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
263 if (aRefAttr && !aRefAttr->isObject())
264 aPoints[aPtInd++] = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
267 if (aPoints[0] && aPoints[1])
268 addCoincidence(aPoints[0], aPoints[1]);
272 std::list< std::set<AttributePoint2DPtr> >::iterator find(const AttributePoint2DPtr& thePoint)
274 std::list< std::set<AttributePoint2DPtr> >::iterator aSeek = myCoincidentPoints.begin();
275 for (; aSeek != myCoincidentPoints.end(); ++aSeek)
276 if (aSeek->find(thePoint) != aSeek->end())
278 return myCoincidentPoints.end();
282 std::list< std::set<AttributePoint2DPtr> > myCoincidentPoints;
285 std::set<AttributePoint2DPtr> findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint)
287 CoincidentPoints aCoincidentPoints;
288 return aCoincidentPoints.coincidentPoints(thePoint);
291 void resetAttribute(SketchPlugin_Feature* theFeature,
292 const std::string& theId)
294 AttributePtr anAttr = theFeature->attribute(theId);
300 void createCoincidenceOrTangency(SketchPlugin_Feature* theFeature,
301 const std::string& theId,
302 const AttributePtr theAttr,
303 const ObjectPtr theObject,
304 const bool theIsCanBeTangent)
306 AttributeRefAttrPtr aRefAttr = theFeature->refattr(theId);
307 if(aRefAttr.get() && aRefAttr->isInitialized()) {
308 FeaturePtr aConstraint;
309 if(!theIsCanBeTangent) {
310 aConstraint = theFeature->sketch()
311 ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
313 if(aRefAttr->isObject()) {
314 ObjectPtr anObject = aRefAttr->object();
315 FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
316 if(aFeature->getKind() == SketchPlugin_Point::ID()) {
317 aConstraint = theFeature->sketch()
318 ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
320 aConstraint = theFeature->sketch()
321 ->addFeature(SketchPlugin_ConstraintTangent::ID());
324 aConstraint = theFeature->sketch()
325 ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
328 AttributeRefAttrPtr aRefAttrA = aConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
329 aRefAttr->isObject() ? aRefAttrA->setObject(aRefAttr->object())
330 : aRefAttrA->setAttr(aRefAttr->attr());
331 AttributeRefAttrPtr aRefAttrB = aConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
332 if(theObject.get()) {
333 aRefAttrB->setObject(theObject);
334 } else if(theAttr.get()) {
335 aRefAttrB->setAttr(theAttr);
340 void convertRefAttrToPointOrTangentCurve(const AttributeRefAttrPtr& theRefAttr,
341 const AttributePtr& theDefaultAttr,
342 std::shared_ptr<GeomAPI_Shape>& theTangentCurve,
343 std::shared_ptr<GeomAPI_Pnt2d>& thePassingPoint)
345 AttributePtr anAttr = theDefaultAttr;
346 if (theRefAttr->isObject()) {
347 FeaturePtr aTgFeature = ModelAPI_Feature::feature(theRefAttr->object());
349 if (aTgFeature->getKind() != SketchPlugin_Point::ID()) {
350 theTangentCurve = aTgFeature->lastResult()->shape();
353 anAttr = aTgFeature->attribute(SketchPlugin_Point::COORD_ID());
356 anAttr = theRefAttr->attr();
358 thePassingPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr)->pnt();
362 FeaturePtr createConstraintAttrAttr(SketchPlugin_Sketch* theSketch,
363 const std::string& theConstraintId,
364 const AttributePtr& theFirstAttribute,
365 const AttributePtr& theSecondAttribute)
367 FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
368 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
369 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
370 aRefAttr->setAttr(theFirstAttribute);
372 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
373 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
374 aRefAttr->setAttr(theSecondAttribute);
376 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
377 std::cout << "<createConstraint to attribute> :"
378 << " first attribute - " << theFirstAttribute->id()
379 << " second attribute - " << theSecondAttribute->id()
386 FeaturePtr createConstraintAttrObject(SketchPlugin_Sketch* theSketch,
387 const std::string& theConstraintId,
388 const AttributePtr& theFirstAttribute,
389 const ObjectPtr& theSecondObject)
391 FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
392 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
393 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
394 aRefAttr->setAttr(theFirstAttribute);
396 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
397 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
398 aRefAttr->setObject(theSecondObject);
400 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
401 std::cout << "<createConstraint to attribute> :"
402 << " first attribute - " << theFirstAttribute->id()
403 << " second object - " << ModelAPI_Feature::feature(theSecondObject)->getKind()
410 FeaturePtr createConstraintObjectObject(SketchPlugin_Sketch* theSketch,
411 const std::string& theConstraintId,
412 const ObjectPtr& theFirstObject,
413 const ObjectPtr& theSecondObject)
415 FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
416 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
417 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
418 aRefAttr->setObject(theFirstObject);
420 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
421 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
422 aRefAttr->setObject(theSecondObject);
424 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
425 std::cout << "<createConstraint to attribute> :"
426 << " first object - " << ModelAPI_Feature::feature(theFirstObject)->getKind()
427 << " second object - " << ModelAPI_Feature::feature(theSecondObject)->getKind()
434 void createAuxiliaryPointOnEllipse(const FeaturePtr& theEllipseFeature,
435 const std::string& theEllipsePoint)
437 SketchPlugin_Sketch* aSketch =
438 std::dynamic_pointer_cast<SketchPlugin_Feature>(theEllipseFeature)->sketch();
440 FeaturePtr aPointFeature = aSketch->addFeature(SketchPlugin_Point::ID());
441 aPointFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
442 aPointFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipseFeature);
444 AttributePoint2DPtr anElPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
445 theEllipseFeature->attribute(theEllipsePoint));
447 AttributePoint2DPtr aCoord = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
448 aPointFeature->attribute(SketchPlugin_Point::COORD_ID()));
449 aCoord->setValue(anElPoint->x(), anElPoint->y());
451 aPointFeature->execute();
452 std::string aName = theEllipseFeature->name() + "_" + theEllipsePoint;
453 aPointFeature->data()->setName(aName);
454 aPointFeature->lastResult()->data()->setName(aName);
456 createConstraintAttrAttr(aSketch,
457 SketchPlugin_ConstraintCoincidenceInternal::ID(), anElPoint, aCoord);
460 void createAuxiliaryAxisOfEllipse(const FeaturePtr& theEllipseFeature,
461 const std::string& theStartPoint,
462 const std::string& theEndPoint)
464 SketchPlugin_Sketch* aSketch =
465 std::dynamic_pointer_cast<SketchPlugin_Feature>(theEllipseFeature)->sketch();
467 FeaturePtr aLineFeature = aSketch->addFeature(SketchPlugin_Line::ID());
468 aLineFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
469 aLineFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipseFeature);
471 AttributePoint2DPtr aStartPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
472 theEllipseFeature->attribute(theStartPoint));
473 AttributePoint2DPtr aEndPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
474 theEllipseFeature->attribute(theEndPoint));
476 AttributePoint2DPtr aLineStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
477 aLineFeature->attribute(SketchPlugin_Line::START_ID()));
478 aLineStart->setValue(aStartPoint->x(), aStartPoint->y());
480 AttributePoint2DPtr aLineEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
481 aLineFeature->attribute(SketchPlugin_Line::END_ID()));
482 aLineEnd->setValue(aEndPoint->x(), aEndPoint->y());
484 aLineFeature->execute();
485 std::string aName = theEllipseFeature->name() + "_" +
486 (theStartPoint == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() ? "major_axis" : "minor_axis");
487 aLineFeature->data()->setName(aName);
488 aLineFeature->lastResult()->data()->setName(aName);
490 createConstraintAttrAttr(aSketch,
491 SketchPlugin_ConstraintCoincidenceInternal::ID(), aStartPoint, aLineStart);
492 createConstraintAttrAttr(aSketch,
493 SketchPlugin_ConstraintCoincidenceInternal::ID(), aEndPoint, aLineEnd);
496 GeomPnt2dPtr flyoutPointCoordinates(const ConstraintPtr& theConstraint)
498 // currently process Length constraints only
499 if (theConstraint->getKind() != SketchPlugin_ConstraintLength::ID())
500 return GeomPnt2dPtr();
502 AttributeRefAttrPtr aLineAttr = theConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
503 if (!aLineAttr || !aLineAttr->isObject())
504 return GeomPnt2dPtr();
505 FeaturePtr aLine = ModelAPI_Feature::feature(aLineAttr->object());
506 if (!aLine || aLine->getKind() != SketchPlugin_Line::ID())
507 return GeomPnt2dPtr();
509 std::shared_ptr<GeomAPI_XY> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
510 aLine->attribute(SketchPlugin_Line::START_ID()))->pnt()->xy();
511 std::shared_ptr<GeomAPI_XY> aEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
512 aLine->attribute(SketchPlugin_Line::END_ID()))->pnt()->xy();
514 std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr =
515 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
516 theConstraint->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
517 std::shared_ptr<GeomAPI_Pnt2d> aFltPnt = aFlyoutAttr->pnt();
519 std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
521 double X = aStartPnt->x() + aFltPnt->x() * aLineDir->x() - aFltPnt->y() * aLineDir->y();
522 double Y = aStartPnt->y() + aFltPnt->x() * aLineDir->y() + aFltPnt->y() * aLineDir->x();
524 return GeomPnt2dPtr(new GeomAPI_Pnt2d(X, Y));
527 } // namespace SketchPlugin_Tools