1 // Copyright (C) 2014-2020 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_Arc.h"
23 #include "SketchPlugin_Circle.h"
24 #include "SketchPlugin_ConstraintCoincidence.h"
25 #include "SketchPlugin_ConstraintCoincidenceInternal.h"
26 #include "SketchPlugin_ConstraintLength.h"
27 #include "SketchPlugin_ConstraintTangent.h"
28 #include "SketchPlugin_Ellipse.h"
29 #include "SketchPlugin_EllipticArc.h"
30 #include "SketchPlugin_Line.h"
31 #include "SketchPlugin_Point.h"
32 #include "SketchPlugin_Projection.h"
33 #include "SketchPlugin_SketchEntity.h"
34 #include "SketchPlugin_Split.h"
35 #include "SketchPlugin_Trim.h"
37 #include <SketcherPrs_Tools.h>
39 #include <ModelAPI_AttributeDouble.h>
41 #include <ModelGeomAlgo_Point2D.h>
42 #include <ModelGeomAlgo_Shape.h>
44 #include <GeomAPI_Dir2d.h>
45 #include <GeomAPI_Edge.h>
46 #include <GeomAPI_Pnt2d.h>
47 #include <GeomAPI_XY.h>
49 #include <GeomAlgoAPI_CompoundBuilder.h>
50 #include <GeomAlgoAPI_ShapeTools.h>
52 #include <GeomDataAPI_Point.h>
53 #include <GeomDataAPI_Point2D.h>
59 namespace SketchPlugin_Tools {
61 void clearExpressions(AttributeDoublePtr theAttribute)
63 theAttribute->setText(std::string());
66 void clearExpressions(AttributePointPtr theAttribute)
68 theAttribute->setText(std::string(), std::string(), std::string());
71 void clearExpressions(AttributePoint2DPtr theAttribute)
73 theAttribute->setText(std::string(), std::string());
76 void clearExpressions(AttributePtr theAttribute)
79 AttributeDoublePtr anAttributeDouble =
80 std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
81 if (anAttributeDouble.get())
82 clearExpressions(anAttributeDouble);
84 AttributePointPtr anAttributePoint =
85 std::dynamic_pointer_cast<GeomDataAPI_Point>(theAttribute);
86 if (anAttributePoint.get())
87 clearExpressions(anAttributePoint);
89 AttributePoint2DPtr anAttributePoint2D =
90 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
91 if (anAttributePoint2D.get())
92 clearExpressions(anAttributePoint2D);
95 void clearExpressions(FeaturePtr theFeature)
97 if (!theFeature.get())
100 std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
101 std::list<AttributePtr>::iterator anAttributeIt = anAttributes.begin();
102 for (; anAttributeIt != anAttributes.end(); ++anAttributeIt) {
103 clearExpressions(*anAttributeIt);
107 std::shared_ptr<GeomAPI_Pnt2d> getCoincidencePoint(const FeaturePtr theStartCoin)
109 std::shared_ptr<GeomAPI_Pnt2d> aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(),
110 SketchPlugin_Constraint::ENTITY_A());
111 if (aPnt.get() == NULL)
112 aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(), SketchPlugin_Constraint::ENTITY_B());
116 std::set<FeaturePtr> findCoincidentConstraints(const FeaturePtr& theFeature)
118 std::set<FeaturePtr> aCoincident;
119 const std::set<AttributePtr>& aRefsList = theFeature->data()->refsToMe();
120 std::set<AttributePtr>::const_iterator aIt;
121 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
122 FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aIt)->owner());
123 if (aConstrFeature && (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID() ||
124 aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidenceInternal::ID()))
125 aCoincident.insert(aConstrFeature);
130 void findCoincidences(const FeaturePtr theStartCoin,
131 const std::string& theAttr,
132 std::set<FeaturePtr>& theList,
133 const bool theIsAttrOnly)
135 AttributeRefAttrPtr aPnt = theStartCoin->refattr(theAttr);
139 FeaturePtr aObj = ModelAPI_Feature::feature(aPnt->object());
140 if(theList.find(aObj) == theList.end()) {
141 std::shared_ptr<GeomAPI_Pnt2d> aOrig = getCoincidencePoint(theStartCoin);
142 if(aOrig.get() == NULL) {
145 if(!theIsAttrOnly || !aPnt->isObject()) {
146 theList.insert(aObj);
148 std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(aObj);
149 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
150 for (; aCIt != aCoincidences.end(); ++aCIt) {
151 FeaturePtr aConstrFeature = *aCIt;
152 std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = getCoincidencePoint(aConstrFeature);
153 if(aPnt2d.get() && aOrig->isEqual(aPnt2d)) {
154 findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A(),
155 theList, theIsAttrOnly);
156 findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B(),
157 theList, theIsAttrOnly);
163 std::set<FeaturePtr> findFeaturesCoincidentToPoint(const AttributePoint2DPtr& thePoint)
165 std::set<FeaturePtr> aCoincidentFeatures;
167 FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
168 aCoincidentFeatures.insert(anOwner);
170 std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(anOwner);
171 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
172 for (; aCIt != aCoincidences.end(); ++aCIt) {
173 bool isPointUsedInCoincidence = false;
174 AttributeRefAttrPtr anOtherCoincidentAttr;
175 for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
176 AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
179 if (!aRefAttr->isObject() && aRefAttr->attr() == thePoint)
180 isPointUsedInCoincidence = true;
182 anOtherCoincidentAttr = aRefAttr;
185 if (isPointUsedInCoincidence) {
187 if (anOtherCoincidentAttr->isObject())
188 anObj = anOtherCoincidentAttr->object();
190 anObj = anOtherCoincidentAttr->attr()->owner();
191 aCoincidentFeatures.insert(ModelAPI_Feature::feature(anObj));
195 return aCoincidentFeatures;
198 // Container for point-point coincidences.
199 // Useful to find points coincident to a given point.
200 class CoincidentPoints
203 void addCoincidence(const AttributePoint2DPtr& thePoint1,
204 const AttributePoint2DPtr& thePoint2 = AttributePoint2DPtr())
206 std::list< std::set<AttributePoint2DPtr> >::iterator aFound1 = find(thePoint1);
207 std::list< std::set<AttributePoint2DPtr> >::iterator aFound2 = find(thePoint2);
208 if (aFound1 == myCoincidentPoints.end()) {
209 if (aFound2 == myCoincidentPoints.end()) {
210 std::set<AttributePoint2DPtr> aNewSet;
211 aNewSet.insert(thePoint1);
213 aNewSet.insert(thePoint2);
214 myCoincidentPoints.push_back(aNewSet);
216 aFound2->insert(thePoint1);
217 } else if (aFound2 == myCoincidentPoints.end()) {
219 aFound1->insert(thePoint2);
221 aFound1->insert(aFound2->begin(), aFound2->end());
222 myCoincidentPoints.erase(aFound2);
226 std::set<AttributePoint2DPtr> coincidentPoints(const AttributePoint2DPtr& thePoint)
228 collectCoincidentPoints(thePoint);
230 std::list< std::set<AttributePoint2DPtr> >::iterator aFound = find(thePoint);
231 if (aFound == myCoincidentPoints.end())
232 return std::set<AttributePoint2DPtr>();
237 void coincidences(const FeaturePtr& theFeature,
238 std::set<FeaturePtr>& theCoincidences) const
240 // iterate through coincideces for the given feature
241 std::set<FeaturePtr> aCoincidences = SketchPlugin_Tools::findCoincidentConstraints(theFeature);
242 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
243 for (; aCIt != aCoincidences.end(); ++aCIt)
245 if (theCoincidences.find(*aCIt) != theCoincidences.end())
246 continue; // already processed
247 theCoincidences.insert(*aCIt);
248 // iterate on coincident attributes
249 for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
250 AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
251 if (aRefAttr && !aRefAttr->isObject())
253 FeaturePtr anOwner = ModelAPI_Feature::feature(aRefAttr->attr()->owner());
254 if (anOwner != theFeature)
255 coincidences(anOwner, theCoincidences);
261 // Iteratively search points coincident to the given point
262 // (two points may be coincident through the third point)
263 void collectCoincidentPoints(const AttributePoint2DPtr& thePoint)
265 AttributePoint2DPtr aPoints[2];
267 FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
268 std::set<FeaturePtr> aCoincidences;
269 coincidences(anOwner, aCoincidences);
271 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
272 for (; aCIt != aCoincidences.end(); ++aCIt) {
273 aPoints[0] = AttributePoint2DPtr();
274 aPoints[1] = AttributePoint2DPtr();
275 for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
276 AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
277 if (aRefAttr && !aRefAttr->isObject())
278 aPoints[aPtInd++] = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
281 if (aPoints[0] && aPoints[1])
282 addCoincidence(aPoints[0], aPoints[1]);
286 std::list< std::set<AttributePoint2DPtr> >::iterator find(const AttributePoint2DPtr& thePoint)
288 std::list< std::set<AttributePoint2DPtr> >::iterator aSeek = myCoincidentPoints.begin();
289 for (; aSeek != myCoincidentPoints.end(); ++aSeek)
290 if (aSeek->find(thePoint) != aSeek->end())
292 return myCoincidentPoints.end();
296 std::list< std::set<AttributePoint2DPtr> > myCoincidentPoints;
299 std::set<AttributePoint2DPtr> findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint)
301 CoincidentPoints aCoincidentPoints;
302 return aCoincidentPoints.coincidentPoints(thePoint);
305 void resetAttribute(SketchPlugin_Feature* theFeature,
306 const std::string& theId)
308 AttributePtr anAttr = theFeature->attribute(theId);
314 void createCoincidenceOrTangency(SketchPlugin_Feature* theFeature,
315 const std::string& theId,
316 const AttributePtr theAttr,
317 const ObjectPtr theObject,
318 const bool theIsCanBeTangent)
320 AttributeRefAttrPtr aRefAttr = theFeature->refattr(theId);
321 if(aRefAttr.get() && aRefAttr->isInitialized()) {
322 FeaturePtr aConstraint;
323 if(!theIsCanBeTangent) {
324 aConstraint = theFeature->sketch()
325 ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
327 if(aRefAttr->isObject()) {
328 ObjectPtr anObject = aRefAttr->object();
329 FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
330 if(aFeature->getKind() == SketchPlugin_Point::ID()) {
331 aConstraint = theFeature->sketch()
332 ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
334 aConstraint = theFeature->sketch()
335 ->addFeature(SketchPlugin_ConstraintTangent::ID());
338 aConstraint = theFeature->sketch()
339 ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
342 AttributeRefAttrPtr aRefAttrA = aConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
343 aRefAttr->isObject() ? aRefAttrA->setObject(aRefAttr->object())
344 : aRefAttrA->setAttr(aRefAttr->attr());
345 AttributeRefAttrPtr aRefAttrB = aConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
346 if(theObject.get()) {
347 aRefAttrB->setObject(theObject);
348 } else if(theAttr.get()) {
349 aRefAttrB->setAttr(theAttr);
354 void convertRefAttrToPointOrTangentCurve(const AttributeRefAttrPtr& theRefAttr,
355 const AttributePtr& theDefaultAttr,
356 std::shared_ptr<GeomAPI_Shape>& theTangentCurve,
357 std::shared_ptr<GeomAPI_Pnt2d>& thePassingPoint)
359 AttributePtr anAttr = theDefaultAttr;
360 if (theRefAttr->isObject()) {
361 FeaturePtr aTgFeature = ModelAPI_Feature::feature(theRefAttr->object());
363 if (aTgFeature->getKind() != SketchPlugin_Point::ID()) {
364 theTangentCurve = aTgFeature->lastResult()->shape();
367 anAttr = aTgFeature->attribute(SketchPlugin_Point::COORD_ID());
370 anAttr = theRefAttr->attr();
372 thePassingPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr)->pnt();
376 FeaturePtr createConstraintAttrAttr(SketchPlugin_Sketch* theSketch,
377 const std::string& theConstraintId,
378 const AttributePtr& theFirstAttribute,
379 const AttributePtr& theSecondAttribute)
381 FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
382 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
383 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
384 aRefAttr->setAttr(theFirstAttribute);
386 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
387 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
388 aRefAttr->setAttr(theSecondAttribute);
390 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
391 std::cout << "<createConstraint to attribute> :"
392 << " first attribute - " << theFirstAttribute->id()
393 << " second attribute - " << theSecondAttribute->id()
400 FeaturePtr createConstraintAttrObject(SketchPlugin_Sketch* theSketch,
401 const std::string& theConstraintId,
402 const AttributePtr& theFirstAttribute,
403 const ObjectPtr& theSecondObject)
405 FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
406 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
407 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
408 aRefAttr->setAttr(theFirstAttribute);
410 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
411 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
412 aRefAttr->setObject(theSecondObject);
414 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
415 std::cout << "<createConstraint to attribute> :"
416 << " first attribute - " << theFirstAttribute->id()
417 << " second object - " << ModelAPI_Feature::feature(theSecondObject)->getKind()
424 FeaturePtr createConstraintObjectObject(SketchPlugin_Sketch* theSketch,
425 const std::string& theConstraintId,
426 const ObjectPtr& theFirstObject,
427 const ObjectPtr& theSecondObject)
429 FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
430 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
431 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
432 aRefAttr->setObject(theFirstObject);
434 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
435 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
436 aRefAttr->setObject(theSecondObject);
438 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
439 std::cout << "<createConstraint to attribute> :"
440 << " first object - " << ModelAPI_Feature::feature(theFirstObject)->getKind()
441 << " second object - " << ModelAPI_Feature::feature(theSecondObject)->getKind()
448 void createAuxiliaryPointOnEllipse(const FeaturePtr& theEllipseFeature,
449 const std::string& theEllipsePoint)
451 SketchPlugin_Sketch* aSketch =
452 std::dynamic_pointer_cast<SketchPlugin_Feature>(theEllipseFeature)->sketch();
454 FeaturePtr aPointFeature = aSketch->addFeature(SketchPlugin_Point::ID());
455 aPointFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
456 aPointFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipseFeature);
458 AttributePoint2DPtr anElPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
459 theEllipseFeature->attribute(theEllipsePoint));
461 AttributePoint2DPtr aCoord = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
462 aPointFeature->attribute(SketchPlugin_Point::COORD_ID()));
463 aCoord->setValue(anElPoint->x(), anElPoint->y());
465 aPointFeature->execute();
466 std::string aName = theEllipseFeature->name() + "_" + theEllipsePoint;
467 aPointFeature->data()->setName(aName);
468 aPointFeature->lastResult()->data()->setName(aName);
470 createConstraintAttrAttr(aSketch,
471 SketchPlugin_ConstraintCoincidenceInternal::ID(), anElPoint, aCoord);
474 void createAuxiliaryAxisOfEllipse(const FeaturePtr& theEllipseFeature,
475 const std::string& theStartPoint,
476 const std::string& theEndPoint)
478 SketchPlugin_Sketch* aSketch =
479 std::dynamic_pointer_cast<SketchPlugin_Feature>(theEllipseFeature)->sketch();
481 FeaturePtr aLineFeature = aSketch->addFeature(SketchPlugin_Line::ID());
482 aLineFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
483 aLineFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipseFeature);
485 AttributePoint2DPtr aStartPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
486 theEllipseFeature->attribute(theStartPoint));
487 AttributePoint2DPtr aEndPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
488 theEllipseFeature->attribute(theEndPoint));
490 AttributePoint2DPtr aLineStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
491 aLineFeature->attribute(SketchPlugin_Line::START_ID()));
492 aLineStart->setValue(aStartPoint->x(), aStartPoint->y());
494 AttributePoint2DPtr aLineEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
495 aLineFeature->attribute(SketchPlugin_Line::END_ID()));
496 aLineEnd->setValue(aEndPoint->x(), aEndPoint->y());
498 aLineFeature->execute();
499 std::string aName = theEllipseFeature->name() + "_" +
500 (theStartPoint == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() ? "major_axis" : "minor_axis");
501 aLineFeature->data()->setName(aName);
502 aLineFeature->lastResult()->data()->setName(aName);
504 createConstraintAttrAttr(aSketch,
505 SketchPlugin_ConstraintCoincidenceInternal::ID(), aStartPoint, aLineStart);
506 createConstraintAttrAttr(aSketch,
507 SketchPlugin_ConstraintCoincidenceInternal::ID(), aEndPoint, aLineEnd);
510 GeomPnt2dPtr flyoutPointCoordinates(const ConstraintPtr& theConstraint)
512 // currently process Length constraints only
513 if (theConstraint->getKind() != SketchPlugin_ConstraintLength::ID())
514 return GeomPnt2dPtr();
516 AttributeRefAttrPtr aLineAttr = theConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
517 if (!aLineAttr || !aLineAttr->isObject())
518 return GeomPnt2dPtr();
519 FeaturePtr aLine = ModelAPI_Feature::feature(aLineAttr->object());
520 if (!aLine || aLine->getKind() != SketchPlugin_Line::ID())
521 return GeomPnt2dPtr();
523 std::shared_ptr<GeomAPI_XY> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
524 aLine->attribute(SketchPlugin_Line::START_ID()))->pnt()->xy();
525 std::shared_ptr<GeomAPI_XY> aEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
526 aLine->attribute(SketchPlugin_Line::END_ID()))->pnt()->xy();
528 std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr =
529 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
530 theConstraint->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
531 std::shared_ptr<GeomAPI_Pnt2d> aFltPnt = aFlyoutAttr->pnt();
533 std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
535 double X = aStartPnt->x() + aFltPnt->x() * aLineDir->x() - aFltPnt->y() * aLineDir->y();
536 double Y = aStartPnt->y() + aFltPnt->x() * aLineDir->y() + aFltPnt->y() * aLineDir->x();
538 return GeomPnt2dPtr(new GeomAPI_Pnt2d(X, Y));
542 void customizeFeaturePrs(const AISObjectPtr& thePrs, bool isAxiliary)
544 std::vector<int> aColor;
547 thePrs->setLineStyle(SketchPlugin_SketchEntity::SKETCH_LINE_STYLE_AUXILIARY());
548 aColor = Config_PropManager::color("Visualization", "sketch_auxiliary_color");
549 aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH_AUXILIARY();
552 thePrs->setLineStyle(SketchPlugin_SketchEntity::SKETCH_LINE_STYLE());
553 aColor = Config_PropManager::color("Visualization", "sketch_entity_color");
554 aWidth = Config_PropManager::integer("Visualization", "sketch_line_width");
556 thePrs->setWidth(aWidth);
557 thePrs->setColor(aColor[0], aColor[1], aColor[2]);
560 void setDimensionColor(const AISObjectPtr& theDimPrs)
562 std::vector<int> aColor = Config_PropManager::color("Visualization", "sketch_dimension_color");
563 if (aColor.size() == 3)
564 theDimPrs->setColor(aColor[0], aColor[1], aColor[2]);
567 void replaceInName(ObjectPtr theObject, const std::string& theSource, const std::string& theDest)
569 std::string aName = theObject->data()->name();
570 size_t aPos = aName.find(theSource);
571 if (aPos != std::string::npos) {
572 std::string aNewName = aName.substr(0, aPos) + theDest
573 + aName.substr(aPos + theSource.size());
574 theObject->data()->setName(aNewName);
578 } // namespace SketchPlugin_Tools
581 // =================================================================================================
582 // namespace SketchPlugin_SegmentationTools
583 // =================================================================================================
585 void SketchPlugin_SegmentationTools::getFeaturePoints(const FeaturePtr& theFeature,
586 AttributePoint2DPtr& theStartPointAttr,
587 AttributePoint2DPtr& theEndPointAttr)
589 std::string aFeatureKind = theFeature->getKind();
590 std::string aStartAttributeName, anEndAttributeName;
591 if (aFeatureKind == SketchPlugin_Line::ID()) {
592 aStartAttributeName = SketchPlugin_Line::START_ID();
593 anEndAttributeName = SketchPlugin_Line::END_ID();
595 else if (aFeatureKind == SketchPlugin_Arc::ID()) {
596 aStartAttributeName = SketchPlugin_Arc::START_ID();
597 anEndAttributeName = SketchPlugin_Arc::END_ID();
599 else if (aFeatureKind == SketchPlugin_EllipticArc::ID()) {
600 aStartAttributeName = SketchPlugin_EllipticArc::START_POINT_ID();
601 anEndAttributeName = SketchPlugin_EllipticArc::END_POINT_ID();
603 if (!aStartAttributeName.empty() && !anEndAttributeName.empty()) {
604 theStartPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
605 theFeature->attribute(aStartAttributeName));
606 theEndPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
607 theFeature->attribute(anEndAttributeName));
612 void SketchPlugin_SegmentationTools::getRefAttributes(
613 const FeaturePtr& theFeature,
614 std::map<AttributePtr, std::list<AttributePtr> >& theRefs,
615 std::list<AttributePtr>& theRefsToFeature)
619 std::list<AttributePtr> aPointAttributes =
620 theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
621 std::set<AttributePtr> aPointAttributesSet;
623 std::list<AttributePtr>::const_iterator aPIt =
624 aPointAttributes.begin(), aPLast = aPointAttributes.end();
625 for (; aPIt != aPLast; aPIt++)
626 aPointAttributesSet.insert(*aPIt);
628 std::set<AttributePtr> aRefsAttributes = theFeature->lastResult()->data()->refsToMe();
629 std::set<AttributePtr> aFRefsList = theFeature->data()->refsToMe();
630 aRefsAttributes.insert(aFRefsList.begin(), aFRefsList.end());
632 std::set<AttributePtr>::const_iterator aIt;
633 for (aIt = aRefsAttributes.cbegin(); aIt != aRefsAttributes.cend(); ++aIt) {
634 AttributePtr anAttr = (*aIt);
635 FeaturePtr anAttrFeature = ModelAPI_Feature::feature(anAttr->owner());
636 if (!anAttrFeature->isMacro() && // <- skip reference from Trim or Split feature
637 anAttr.get() && anAttr->attributeType() == ModelAPI_AttributeRefAttr::typeId()) {
638 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
639 if (!aRefAttr->isObject()) { // find attributes referenced to feature point attributes
640 AttributePtr anAttrInRef = aRefAttr->attr();
641 if (anAttrInRef.get() &&
642 aPointAttributesSet.find(anAttrInRef) != aPointAttributesSet.end()) {
643 if (theRefs.find(anAttrInRef) != theRefs.end())
644 theRefs[anAttrInRef].push_back(aRefAttr);
646 std::list<AttributePtr> anAttrList;
647 anAttrList.push_back(aRefAttr);
648 theRefs[anAttrInRef] = anAttrList;
652 else { // find attributes referenced to feature itself
653 theRefsToFeature.push_back(anAttr);
659 GeomShapePtr SketchPlugin_SegmentationTools::getSubShape(
660 SketchPlugin_Feature* theFeature,
661 const std::string& theObjectAttributeId,
662 const std::string& thePointAttributeId,
663 std::map<ObjectPtr, std::set<GeomShapePtr> >& theCashedShapes,
664 std::map<ObjectPtr, GeomAlgoAPI_ShapeTools::PointToRefsMap>& theObjectToPoints)
666 GeomShapePtr aBaseShape;
668 AttributeReferencePtr anObjectAttr = theFeature->reference(theObjectAttributeId);
669 ObjectPtr aBaseObject = anObjectAttr->value();
670 if (!aBaseObject.get())
674 AttributePoint2DPtr aPointAttr =
675 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theFeature->attribute(thePointAttributeId));
676 std::shared_ptr<GeomAPI_Pnt2d> anAttributePnt2d = aPointAttr->pnt();
677 std::shared_ptr<GeomAPI_Pnt> anAttributePnt =
678 theFeature->sketch()->to3D(anAttributePnt2d->x(), anAttributePnt2d->y());
680 if (theCashedShapes.find(aBaseObject) == theCashedShapes.end())
681 fillObjectShapes(theFeature, aBaseObject, theCashedShapes, theObjectToPoints);
683 std::shared_ptr<GeomAPI_Pnt> aStartPoint;
684 std::shared_ptr<GeomAPI_Pnt> aSecondPoint;
685 const std::set<GeomShapePtr>& aShapes = theCashedShapes[aBaseObject];
686 std::set<GeomShapePtr>::const_iterator anIt = aShapes.begin(), aLast = aShapes.end();
687 for (; anIt != aLast; anIt++) {
688 GeomShapePtr aCurrentShape = *anIt;
689 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
690 if (ModelGeomAlgo_Point2D::isPointOnEdge(aCurrentShape, anAttributePnt, aProjectedPoint)) {
691 if (theFeature->getKind() == SketchPlugin_Split::ID()) {
692 // for Split operation collect start and end points of the shape
693 if (aCurrentShape->shapeType() == GeomAPI_Shape::EDGE) {
694 std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aCurrentShape));
695 aStartPoint = anEdge->firstPoint();
696 aSecondPoint = anEdge->lastPoint();
700 aBaseShape = aCurrentShape;
705 if (!aStartPoint.get() || !aSecondPoint.get())
708 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObject);
709 if (anObjectAttr->isInitialized() && aBaseFeature.get() && aPointAttr->isInitialized()) {
710 ResultPtr aResult = aBaseFeature->lastResult();
711 GeomShapePtr aResultShape = aResult->shape();
712 std::list<std::shared_ptr<GeomAPI_Pnt> > aPoints;
714 aPoints.push_back(aStartPoint);
715 aPoints.push_back(aSecondPoint);
717 std::set<std::shared_ptr<GeomAPI_Shape> > aSplitShapes;
718 GeomAlgoAPI_ShapeTools::splitShape_p(aResultShape, aPoints, aSplitShapes);
719 aBaseShape = GeomAlgoAPI_ShapeTools::findShape(aPoints, aSplitShapes);
724 void SketchPlugin_SegmentationTools::fillObjectShapes(
725 SketchPlugin_Feature* theOpFeature,
726 const ObjectPtr& theObject,
727 std::map<ObjectPtr, std::set<GeomShapePtr> >& theCashedShapes,
728 std::map<ObjectPtr, GeomAlgoAPI_ShapeTools::PointToRefsMap>& theObjectToPoints)
730 SketchPlugin_Sketch* aSketch = theOpFeature->sketch();
732 GeomAlgoAPI_ShapeTools::PointToRefsMap aPoints;
733 std::set<GeomShapePtr> aShapes;
735 std::set<AttributePoint2DPtr > aRefAttributes;
737 FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
738 std::set<ResultPtr> anEdgeShapes;
740 ModelGeomAlgo_Shape::shapesOfType(aFeature, GeomAPI_Shape::EDGE, anEdgeShapes);
741 if (!anEdgeShapes.empty()) {
742 GeomShapePtr aFeatureShape = (*anEdgeShapes.begin())->shape();
744 // coincidences to the feature
745 ModelGeomAlgo_Point2D::getPointsOfReference(aFeature, SketchPlugin_ConstraintCoincidence::ID(),
746 aRefAttributes, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID());
747 // layed on feature coincidences to divide it on several shapes
748 std::shared_ptr<ModelAPI_Data> aData = aSketch->data();
749 std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
750 aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
751 std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
752 aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
753 std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
754 aData->attribute(SketchPlugin_Sketch::NORM_ID()));
755 std::shared_ptr<GeomAPI_Dir> aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
757 ModelGeomAlgo_Point2D::getPointsInsideShape(aFeatureShape, aRefAttributes, aC->pnt(),
758 aX->dir(), aY, aPoints);
760 if (theOpFeature->getKind() == SketchPlugin_Trim::ID()) {
761 // collect all intersection points with other edges for Trim operation only
762 std::list<FeaturePtr> aFeatures;
763 for (int i = 0; i < aSketch->numberOfSubs(); i++) {
764 FeaturePtr aSubFeature = aSketch->subFeature(i);
765 if (aSubFeature.get() && aSubFeature->getKind() != SketchPlugin_Projection::ID())
766 aFeatures.push_back(aSubFeature);
768 ModelGeomAlgo_Point2D::getPointsIntersectedShape(aFeature, aFeatures, aPoints);
771 if (!aPoints.empty())
772 GeomAlgoAPI_ShapeTools::splitShape(aFeatureShape, aPoints, aShapes);
774 theObjectToPoints[theObject] = aPoints;
775 theCashedShapes[theObject] = aShapes;
778 void SketchPlugin_SegmentationTools::updateRefAttConstraints(
779 const std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
780 const std::set<std::pair<AttributePtr, AttributePtr> >& theModifiedAttributes)
782 #if defined DEBUG_SPLIT || defined DEBUG_TRIM
783 std::cout << "updateRefAttConstraints" << std::endl;
786 std::set<std::pair<AttributePtr, AttributePtr> >::const_iterator
787 anIt = theModifiedAttributes.begin(), aLast = theModifiedAttributes.end();
788 for (; anIt != aLast; anIt++) {
789 AttributePtr anAttribute = anIt->first;
790 AttributePtr aNewAttribute = anIt->second;
792 // not found in references
793 if (!aNewAttribute.get() ||
794 theBaseRefAttributes.find(anAttribute) == theBaseRefAttributes.end())
796 std::list<AttributePtr> aRefAttributes = theBaseRefAttributes.at(anAttribute);
797 std::list<AttributePtr>::const_iterator aRefIt = aRefAttributes.begin(),
798 aRLast = aRefAttributes.end();
800 for (; aRefIt != aRLast; aRefIt++) {
801 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefIt);
802 if (aRefAttr.get()) {
803 aRefAttr->setAttr(aNewAttribute);
805 FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->owner());
806 std::cout << " -" << getFeatureInfo(aFeature) << std::endl;
813 void SketchPlugin_SegmentationTools::updateFeaturesAfterOperation(
814 const std::set<FeaturePtr>& theFeaturesToUpdate)
816 std::set<FeaturePtr>::const_iterator anIt = theFeaturesToUpdate.begin(),
817 aLast = theFeaturesToUpdate.end();
818 for (; anIt != aLast; anIt++) {
819 FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*anIt);
820 std::string aRefFeatureKind = aRefFeature->getKind();
821 if (aRefFeatureKind == SketchPlugin_ConstraintLength::ID()) {
822 std::shared_ptr<SketchPlugin_ConstraintLength> aLenghtFeature =
823 std::dynamic_pointer_cast<SketchPlugin_ConstraintLength>(*anIt);
824 if (aLenghtFeature.get()) {
825 std::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = std::dynamic_pointer_cast<
826 ModelAPI_AttributeDouble>(aLenghtFeature->attribute(SketchPlugin_Constraint::VALUE()));
828 if (aLenghtFeature->computeLenghtValue(aValue) && aValueAttr.get())
829 aValueAttr->setValue(aValue);
835 AISObjectPtr SketchPlugin_SegmentationTools::getAISObject(
836 AISObjectPtr thePrevious,
837 SketchPlugin_Feature* theOpFeature,
838 const std::string& thePreviewObjectAttrName,
839 const std::string& thePreviewPointAttrName,
840 const std::string& theSelectedObjectAttrName,
841 const std::string& theSelectedPointAttrName)
843 #if defined DEBUG_SPLIT || defined DEBUG_TRIM_METHODS
844 std::cout << "getAISObject: " << theOpFeature->data()->name() << std::endl;
847 AISObjectPtr anAIS = thePrevious;
849 std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
850 std::map<ObjectPtr, std::set<GeomShapePtr> > aCashedShapes;
851 std::map<ObjectPtr, GeomAlgoAPI_ShapeTools::PointToRefsMap> aObjectToPoints;
852 GeomShapePtr aPreviewShape = getSubShape(theOpFeature,
853 thePreviewObjectAttrName, thePreviewPointAttrName, aCashedShapes, aObjectToPoints);
854 if (aPreviewShape.get())
855 aShapes.push_back(aPreviewShape);
856 GeomShapePtr aSelectedShape = getSubShape(theOpFeature,
857 theSelectedObjectAttrName, theSelectedPointAttrName, aCashedShapes, aObjectToPoints);
858 if (aSelectedShape.get())
859 aShapes.push_back(aSelectedShape);
862 return AISObjectPtr();
864 GeomShapePtr aBaseShape = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
865 if (!aBaseShape.get())
866 return AISObjectPtr();
868 if (aBaseShape.get()) {
870 anAIS = AISObjectPtr(new GeomAPI_AISObject);
871 anAIS->createShape(aBaseShape);
873 std::vector<int> aColor;
874 aColor = Config_PropManager::color("Visualization", "operation_remove_feature_color");
875 double aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH();
876 int aLineStyle = SketchPlugin_SketchEntity::SKETCH_LINE_STYLE();
877 anAIS->setColor(aColor[0], aColor[1], aColor[2]);
878 // width when there is not base object should be extened in several points
879 // in order to see this preview over highlight
880 anAIS->setWidth(aWidth+4);
881 anAIS->setLineStyle(aLineStyle);
884 anAIS = AISObjectPtr();
888 #define GEOM_DATA_POINT2D(f, a) std::dynamic_pointer_cast<GeomDataAPI_Point2D>((f)->attribute(a))
890 FeaturePtr SketchPlugin_SegmentationTools::createLineFeature(
891 const FeaturePtr& theBaseFeature,
892 const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
893 const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint)
896 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
897 std::dynamic_pointer_cast<SketchPlugin_Feature>(theBaseFeature);
898 SketchPlugin_Sketch* aSketch = aSketchFeature->sketch();
899 if (!aSketch || !theBaseFeature.get())
902 aFeature = aSketch->addFeature(SketchPlugin_Line::ID());
904 GEOM_DATA_POINT2D(aFeature, SketchPlugin_Line::START_ID())->setValue(theFirstPoint);
905 GEOM_DATA_POINT2D(aFeature, SketchPlugin_Line::END_ID())->setValue(theSecondPoint);
907 aFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(
908 theBaseFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value());
909 aFeature->execute(); // to obtain result
917 std::string myCenter;
921 std::string myReversed;
925 ArcAttributes(const std::string& theKind) : myKind(theKind)
927 if (myKind == SketchPlugin_Arc::ID()) {
928 myCenter = SketchPlugin_Arc::CENTER_ID();
929 myStart = SketchPlugin_Arc::START_ID();
930 myEnd = SketchPlugin_Arc::END_ID();
931 myReversed = SketchPlugin_Arc::REVERSED_ID();
933 else if (myKind == SketchPlugin_Circle::ID()) {
934 myCenter = SketchPlugin_Circle::CENTER_ID();
936 else if (myKind == SketchPlugin_Ellipse::ID()) {
937 myCenter = SketchPlugin_Ellipse::CENTER_ID();
938 myFocus = SketchPlugin_Ellipse::FIRST_FOCUS_ID();
940 else if (myKind == SketchPlugin_EllipticArc::ID()) {
941 myCenter = SketchPlugin_EllipticArc::CENTER_ID();
942 myFocus = SketchPlugin_EllipticArc::FIRST_FOCUS_ID();
943 myStart = SketchPlugin_EllipticArc::START_POINT_ID();
944 myEnd = SketchPlugin_EllipticArc::END_POINT_ID();
945 myReversed = SketchPlugin_EllipticArc::REVERSED_ID();
950 FeaturePtr SketchPlugin_SegmentationTools::createArcFeature(
951 const FeaturePtr& theBaseFeature,
952 const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
953 const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint)
956 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
957 std::dynamic_pointer_cast<SketchPlugin_Feature>(theBaseFeature);
958 SketchPlugin_Sketch* aSketch = aSketchFeature->sketch();
959 if (!aSketch || !theBaseFeature.get())
962 ArcAttributes aBaseAttrs(theBaseFeature->getKind());
963 ArcAttributes aTargetAttrs;
964 if (aBaseAttrs.myKind == SketchPlugin_Arc::ID() ||
965 aBaseAttrs.myKind == SketchPlugin_Circle::ID())
966 aTargetAttrs = ArcAttributes(SketchPlugin_Arc::ID());
967 else if (aBaseAttrs.myKind == SketchPlugin_Ellipse::ID() ||
968 aBaseAttrs.myKind == SketchPlugin_EllipticArc::ID())
969 aTargetAttrs = ArcAttributes(SketchPlugin_EllipticArc::ID());
971 if (aTargetAttrs.myKind.empty())
974 aFeature = aSketch->addFeature(aTargetAttrs.myKind);
975 // update fillet arc: make the arc correct for sure, so, it is not needed to process
976 // the "attribute updated"
977 // by arc; moreover, it may cause cyclicity in hte mechanism of updater
978 bool aWasBlocked = aFeature->data()->blockSendAttributeUpdated(true);
980 GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myCenter)->setValue(
981 GEOM_DATA_POINT2D(theBaseFeature, aBaseAttrs.myCenter)->pnt());
982 if (!aTargetAttrs.myFocus.empty()) {
983 GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myFocus)->setValue(
984 GEOM_DATA_POINT2D(theBaseFeature, aBaseAttrs.myFocus)->pnt());
986 GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myStart)->setValue(theFirstPoint);
987 GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myEnd)->setValue(theSecondPoint);
989 aFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(
990 theBaseFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value());
992 /// fill referersed state of created arc as it is on the base arc
993 bool aReversed = aBaseAttrs.myReversed.empty() ? false :
994 theBaseFeature->boolean(aBaseAttrs.myReversed)->value();
995 aFeature->boolean(aTargetAttrs.myReversed)->setValue(aReversed);
997 aFeature->execute(); // to obtain result (need to calculate arc parameters before sending Update)
998 aFeature->data()->blockSendAttributeUpdated(aWasBlocked);