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_BSpline.h"
24 #include "SketchPlugin_Circle.h"
25 #include "SketchPlugin_ConstraintCoincidence.h"
26 #include "SketchPlugin_ConstraintCoincidenceInternal.h"
27 #include "SketchPlugin_ConstraintLength.h"
28 #include "SketchPlugin_ConstraintTangent.h"
29 #include "SketchPlugin_Ellipse.h"
30 #include "SketchPlugin_EllipticArc.h"
31 #include "SketchPlugin_Line.h"
32 #include "SketchPlugin_Point.h"
33 #include "SketchPlugin_Projection.h"
34 #include "SketchPlugin_SketchEntity.h"
35 #include "SketchPlugin_Split.h"
36 #include "SketchPlugin_Trim.h"
38 #include <SketcherPrs_Tools.h>
40 #include <ModelAPI_AttributeDouble.h>
41 #include <ModelAPI_AttributeInteger.h>
43 #include <ModelGeomAlgo_Point2D.h>
44 #include <ModelGeomAlgo_Shape.h>
46 #include <GeomAPI_Dir2d.h>
47 #include <GeomAPI_Edge.h>
48 #include <GeomAPI_Pnt2d.h>
49 #include <GeomAPI_XY.h>
51 #include <GeomAlgoAPI_CompoundBuilder.h>
52 #include <GeomAlgoAPI_ShapeTools.h>
54 #include <GeomDataAPI_Point.h>
55 #include <GeomDataAPI_Point2D.h>
61 namespace SketchPlugin_Tools {
63 void clearExpressions(AttributeDoublePtr theAttribute)
65 theAttribute->setText(std::string());
68 void clearExpressions(AttributePointPtr theAttribute)
70 theAttribute->setText(std::string(), std::string(), std::string());
73 void clearExpressions(AttributePoint2DPtr theAttribute)
75 theAttribute->setText(std::string(), std::string());
78 void clearExpressions(AttributePtr theAttribute)
81 AttributeDoublePtr anAttributeDouble =
82 std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
83 if (anAttributeDouble.get())
84 clearExpressions(anAttributeDouble);
86 AttributePointPtr anAttributePoint =
87 std::dynamic_pointer_cast<GeomDataAPI_Point>(theAttribute);
88 if (anAttributePoint.get())
89 clearExpressions(anAttributePoint);
91 AttributePoint2DPtr anAttributePoint2D =
92 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
93 if (anAttributePoint2D.get())
94 clearExpressions(anAttributePoint2D);
97 void clearExpressions(FeaturePtr theFeature)
99 if (!theFeature.get())
102 std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
103 std::list<AttributePtr>::iterator anAttributeIt = anAttributes.begin();
104 for (; anAttributeIt != anAttributes.end(); ++anAttributeIt) {
105 clearExpressions(*anAttributeIt);
109 std::shared_ptr<GeomAPI_Pnt2d> getCoincidencePoint(const FeaturePtr theStartCoin)
111 std::shared_ptr<GeomAPI_Pnt2d> aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(),
112 SketchPlugin_Constraint::ENTITY_A());
113 if (aPnt.get() == NULL)
114 aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(), SketchPlugin_Constraint::ENTITY_B());
118 std::set<FeaturePtr> findCoincidentConstraints(const ObjectPtr& theObject)
120 std::set<FeaturePtr> aCoincident;
121 const std::set<AttributePtr>& aRefsList = theObject->data()->refsToMe();
122 std::set<AttributePtr>::const_iterator aIt;
123 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
124 FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aIt)->owner());
125 if (aConstrFeature && (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID() ||
126 aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidenceInternal::ID()))
127 aCoincident.insert(aConstrFeature);
132 void findCoincidences(const FeaturePtr theStartCoin,
133 const std::string& theAttr,
134 std::set<FeaturePtr>& theList,
135 const bool theIsAttrOnly)
137 AttributeRefAttrPtr aPnt = theStartCoin->refattr(theAttr);
141 FeaturePtr aObj = ModelAPI_Feature::feature(aPnt->object());
142 if(theList.find(aObj) == theList.end()) {
143 std::shared_ptr<GeomAPI_Pnt2d> aOrig = getCoincidencePoint(theStartCoin);
144 if(aOrig.get() == NULL) {
147 if(!theIsAttrOnly || !aPnt->isObject()) {
148 theList.insert(aObj);
150 std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(aObj);
151 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
152 for (; aCIt != aCoincidences.end(); ++aCIt) {
153 FeaturePtr aConstrFeature = *aCIt;
154 std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = getCoincidencePoint(aConstrFeature);
155 if(aPnt2d.get() && aOrig->isEqual(aPnt2d)) {
156 findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A(),
157 theList, theIsAttrOnly);
158 findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B(),
159 theList, theIsAttrOnly);
165 std::set<FeaturePtr> findFeaturesCoincidentToPoint(const AttributePoint2DPtr& thePoint)
167 std::set<FeaturePtr> aCoincidentFeatures;
169 FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
170 aCoincidentFeatures.insert(anOwner);
172 std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(anOwner);
173 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
174 for (; aCIt != aCoincidences.end(); ++aCIt) {
175 bool isPointUsedInCoincidence = false;
176 AttributeRefAttrPtr anOtherCoincidentAttr;
177 for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
178 AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
181 if (!aRefAttr->isObject() && aRefAttr->attr() == thePoint)
182 isPointUsedInCoincidence = true;
184 anOtherCoincidentAttr = aRefAttr;
187 if (isPointUsedInCoincidence) {
189 if (anOtherCoincidentAttr->isObject())
190 anObj = anOtherCoincidentAttr->object();
192 anObj = anOtherCoincidentAttr->attr()->owner();
193 aCoincidentFeatures.insert(ModelAPI_Feature::feature(anObj));
197 return aCoincidentFeatures;
200 // Container for point-point coincidences.
201 // Useful to find points coincident to a given point.
202 class CoincidentPoints
204 static const int THE_DEFAULT_INDEX = -1;
207 void addCoincidence(const AttributePtr& thePoint1, const int theIndex1,
208 const AttributePtr& thePoint2, const int theIndex2)
210 auto aFound1 = find(thePoint1, theIndex1);
211 auto aFound2 = find(thePoint2, theIndex2);
212 if (aFound1 == myCoincidentPoints.end()) {
213 if (aFound2 == myCoincidentPoints.end()) {
214 std::map<AttributePtr, std::set<int> > aNewSet;
215 aNewSet[thePoint1].insert(theIndex1);
217 aNewSet[thePoint2].insert(theIndex2);
218 myCoincidentPoints.push_back(aNewSet);
220 (*aFound2)[thePoint1].insert(theIndex1);
221 } else if (aFound2 == myCoincidentPoints.end()) {
223 (*aFound1)[thePoint2].insert(theIndex2);
225 for (auto it = aFound2->begin(); it != aFound2->end(); ++it)
226 (*aFound1)[it->first].insert(it->second.begin(), it->second.end());
227 myCoincidentPoints.erase(aFound2);
231 std::set<AttributePoint2DPtr> coincidentPoints(const AttributePoint2DPtr& thePoint)
233 collectCoincidentPoints(thePoint);
235 std::set<AttributePoint2DPtr> aCoincPoints;
236 auto aFound = find(thePoint, THE_DEFAULT_INDEX);
237 if (aFound != myCoincidentPoints.end()) {
238 for (auto it = aFound->begin(); it != aFound->end(); ++it) {
239 AttributePoint2DPtr aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(it->first);
241 aCoincPoints.insert(aPoint);
243 AttributePoint2DArrayPtr aPointArray =
244 std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(it->first);
246 // this is a B-spline feature, the connection is possible
247 // to the first or the last point
248 FeaturePtr anOwner = ModelAPI_Feature::feature(aPointArray->owner());
249 if (it->second.find(0) != it->second.end()) {
250 AttributePoint2DPtr aFirstPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
251 anOwner->attribute(SketchPlugin_BSpline::START_ID()));
252 aCoincPoints.insert(aFirstPoint);
254 if (it->second.find(aPointArray->size() - 1) != it->second.end()) {
255 AttributePoint2DPtr aFirstPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
256 anOwner->attribute(SketchPlugin_BSpline::END_ID()));
257 aCoincPoints.insert(aFirstPoint);
267 void coincidences(const FeaturePtr& theFeature,
268 std::set<FeaturePtr>& theCoincidences) const
270 // iterate through coincideces for the given feature
271 std::set<FeaturePtr> aCoincidences = SketchPlugin_Tools::findCoincidentConstraints(theFeature);
272 if (theFeature->getKind() == SketchPlugin_Point::ID()) {
273 std::set<FeaturePtr> aCoincToRes =
274 SketchPlugin_Tools::findCoincidentConstraints(theFeature->lastResult());
275 aCoincidences.insert(aCoincToRes.begin(), aCoincToRes.end());
276 }
\r std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
277 for (; aCIt != aCoincidences.end(); ++aCIt)
279 if (theCoincidences.find(*aCIt) != theCoincidences.end())
280 continue; // already processed
281 theCoincidences.insert(*aCIt);
282 // iterate on coincident attributes
283 for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
284 AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
288 if (aRefAttr->isObject()) {
289 FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
290 if (aFeature->getKind() == SketchPlugin_Point::ID())
294 anOwner = ModelAPI_Feature::feature(aRefAttr->attr()->owner());
295 if (anOwner && anOwner != theFeature)
296 coincidences(anOwner, theCoincidences);
301 // Iteratively search points coincident to the given point
302 // (two points may be coincident through the third point)
303 void collectCoincidentPoints(const AttributePoint2DPtr& thePoint)
305 AttributePtr aPoints[2];
306 int anIndicesInArray[2];
308 FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
309 std::set<FeaturePtr> aCoincidences;
310 coincidences(anOwner, aCoincidences);
312 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
313 for (; aCIt != aCoincidences.end(); ++aCIt) {
314 aPoints[0] = aPoints[1] = AttributePtr();
315 anIndicesInArray[0] = anIndicesInArray[1] = THE_DEFAULT_INDEX;
316 for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
317 AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
320 if (aRefAttr->isObject()) {
321 FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
322 if (aFeature && aFeature->getKind() == SketchPlugin_Point::ID())
323 aPoints[aPtInd++] = aFeature->attribute(SketchPlugin_Point::COORD_ID());
326 AttributePoint2DPtr aPointAttr =
327 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
328 AttributePoint2DArrayPtr aPointArray =
329 std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(aRefAttr->attr());
331 aPoints[aPtInd++] = aPointAttr;
332 else if (aPointArray) {
333 AttributeIntegerPtr anIndexAttr = (*aCIt)->integer(i == 0 ?
334 SketchPlugin_ConstraintCoincidenceInternal::INDEX_ENTITY_A() :
335 SketchPlugin_ConstraintCoincidenceInternal::INDEX_ENTITY_B());
336 aPoints[aPtInd] = aPointArray;
337 anIndicesInArray[aPtInd++] = anIndexAttr->value();
342 if (aPoints[0] && aPoints[1])
343 addCoincidence(aPoints[0], anIndicesInArray[0], aPoints[1], anIndicesInArray[1]);
347 std::list< std::map<AttributePtr, std::set<int> > >::iterator find(const AttributePtr& thePoint,
350 auto aSeek = myCoincidentPoints.begin();
351 for (; aSeek != myCoincidentPoints.end(); ++aSeek) {
352 auto aFound = aSeek->find(thePoint);
353 if (aFound != aSeek->end() && aFound->second.find(theIndex) != aFound->second.end())
356 // nothing is found, but if the point is a B-spline boundary point, lets check it as poles array
357 FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
358 if (anOwner->getKind() == SketchPlugin_BSpline::ID()) {
359 AttributePtr aPointsArray;
361 if (thePoint->id() == SketchPlugin_BSpline::START_ID()) {
362 aPointsArray = anOwner->attribute(SketchPlugin_BSpline::POLES_ID());
365 else if (thePoint->id() == SketchPlugin_BSpline::END_ID()) {
366 aPointsArray = anOwner->attribute(SketchPlugin_BSpline::POLES_ID());
367 anIndex = std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(aPointsArray)->size() - 1;
370 return find(aPointsArray, anIndex);
372 return myCoincidentPoints.end();
376 std::list< std::map<AttributePtr, std::set<int> > > myCoincidentPoints;
379 std::set<AttributePoint2DPtr> findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint)
381 CoincidentPoints aCoincidentPoints;
382 return aCoincidentPoints.coincidentPoints(thePoint);
386 void resetAttribute(SketchPlugin_Feature* theFeature,
387 const std::string& theId)
389 AttributePtr anAttr = theFeature->attribute(theId);
395 void createCoincidenceOrTangency(SketchPlugin_Feature* theFeature,
396 const std::string& theId,
397 const AttributePtr theAttr,
398 const ObjectPtr theObject,
399 const bool theIsCanBeTangent)
401 AttributeRefAttrPtr aRefAttr = theFeature->refattr(theId);
402 if(aRefAttr.get() && aRefAttr->isInitialized()) {
403 FeaturePtr aConstraint;
404 if(!theIsCanBeTangent) {
405 aConstraint = theFeature->sketch()
406 ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
408 if(aRefAttr->isObject()) {
409 ObjectPtr anObject = aRefAttr->object();
410 FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
411 if(aFeature->getKind() == SketchPlugin_Point::ID()) {
412 aConstraint = theFeature->sketch()
413 ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
415 aConstraint = theFeature->sketch()
416 ->addFeature(SketchPlugin_ConstraintTangent::ID());
419 aConstraint = theFeature->sketch()
420 ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
423 AttributeRefAttrPtr aRefAttrA = aConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
424 aRefAttr->isObject() ? aRefAttrA->setObject(aRefAttr->object())
425 : aRefAttrA->setAttr(aRefAttr->attr());
426 AttributeRefAttrPtr aRefAttrB = aConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
427 if(theObject.get()) {
428 aRefAttrB->setObject(theObject);
429 } else if(theAttr.get()) {
430 aRefAttrB->setAttr(theAttr);
435 void convertRefAttrToPointOrTangentCurve(const AttributeRefAttrPtr& theRefAttr,
436 const AttributePtr& theDefaultAttr,
437 std::shared_ptr<GeomAPI_Shape>& theTangentCurve,
438 std::shared_ptr<GeomAPI_Pnt2d>& thePassingPoint)
440 AttributePtr anAttr = theDefaultAttr;
441 if (theRefAttr->isObject()) {
442 FeaturePtr aTgFeature = ModelAPI_Feature::feature(theRefAttr->object());
444 if (aTgFeature->getKind() != SketchPlugin_Point::ID()) {
445 theTangentCurve = aTgFeature->lastResult()->shape();
448 anAttr = aTgFeature->attribute(SketchPlugin_Point::COORD_ID());
451 anAttr = theRefAttr->attr();
453 thePassingPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr)->pnt();
457 FeaturePtr createConstraintAttrAttr(SketchPlugin_Sketch* theSketch,
458 const std::string& theConstraintId,
459 const AttributePtr& theFirstAttribute,
460 const AttributePtr& theSecondAttribute)
462 FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
463 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
464 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
465 aRefAttr->setAttr(theFirstAttribute);
467 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
468 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
469 aRefAttr->setAttr(theSecondAttribute);
471 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
472 std::cout << "<createConstraint to attribute> :"
473 << " first attribute - " << theFirstAttribute->id()
474 << " second attribute - " << theSecondAttribute->id()
481 FeaturePtr createConstraintAttrObject(SketchPlugin_Sketch* theSketch,
482 const std::string& theConstraintId,
483 const AttributePtr& theFirstAttribute,
484 const ObjectPtr& theSecondObject)
486 FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
487 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
488 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
489 aRefAttr->setAttr(theFirstAttribute);
491 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
492 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
493 aRefAttr->setObject(theSecondObject);
495 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
496 std::cout << "<createConstraint to attribute> :"
497 << " first attribute - " << theFirstAttribute->id()
498 << " second object - " << ModelAPI_Feature::feature(theSecondObject)->getKind()
505 FeaturePtr createConstraintObjectObject(SketchPlugin_Sketch* theSketch,
506 const std::string& theConstraintId,
507 const ObjectPtr& theFirstObject,
508 const ObjectPtr& theSecondObject)
510 FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
511 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
512 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
513 aRefAttr->setObject(theFirstObject);
515 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
516 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
517 aRefAttr->setObject(theSecondObject);
519 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
520 std::cout << "<createConstraint to attribute> :"
521 << " first object - " << ModelAPI_Feature::feature(theFirstObject)->getKind()
522 << " second object - " << ModelAPI_Feature::feature(theSecondObject)->getKind()
529 void createAuxiliaryPointOnEllipse(const FeaturePtr& theEllipseFeature,
530 const std::string& theEllipsePoint)
532 SketchPlugin_Sketch* aSketch =
533 std::dynamic_pointer_cast<SketchPlugin_Feature>(theEllipseFeature)->sketch();
535 FeaturePtr aPointFeature = aSketch->addFeature(SketchPlugin_Point::ID());
536 aPointFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
537 aPointFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipseFeature);
539 AttributePoint2DPtr anElPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
540 theEllipseFeature->attribute(theEllipsePoint));
542 AttributePoint2DPtr aCoord = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
543 aPointFeature->attribute(SketchPlugin_Point::COORD_ID()));
544 aCoord->setValue(anElPoint->x(), anElPoint->y());
546 aPointFeature->execute();
547 std::string aName = theEllipseFeature->name() + "_" + theEllipsePoint;
548 aPointFeature->data()->setName(aName);
549 aPointFeature->lastResult()->data()->setName(aName);
551 createConstraintAttrAttr(aSketch,
552 SketchPlugin_ConstraintCoincidenceInternal::ID(), anElPoint, aCoord);
555 void createAuxiliaryAxisOfEllipse(const FeaturePtr& theEllipseFeature,
556 const std::string& theStartPoint,
557 const std::string& theEndPoint)
559 SketchPlugin_Sketch* aSketch =
560 std::dynamic_pointer_cast<SketchPlugin_Feature>(theEllipseFeature)->sketch();
562 FeaturePtr aLineFeature = aSketch->addFeature(SketchPlugin_Line::ID());
563 aLineFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
564 aLineFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipseFeature);
566 AttributePoint2DPtr aStartPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
567 theEllipseFeature->attribute(theStartPoint));
568 AttributePoint2DPtr aEndPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
569 theEllipseFeature->attribute(theEndPoint));
571 AttributePoint2DPtr aLineStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
572 aLineFeature->attribute(SketchPlugin_Line::START_ID()));
573 aLineStart->setValue(aStartPoint->x(), aStartPoint->y());
575 AttributePoint2DPtr aLineEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
576 aLineFeature->attribute(SketchPlugin_Line::END_ID()));
577 aLineEnd->setValue(aEndPoint->x(), aEndPoint->y());
579 aLineFeature->execute();
580 std::string aName = theEllipseFeature->name() + "_" +
581 (theStartPoint == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() ? "major_axis" : "minor_axis");
582 aLineFeature->data()->setName(aName);
583 aLineFeature->lastResult()->data()->setName(aName);
585 createConstraintAttrAttr(aSketch,
586 SketchPlugin_ConstraintCoincidenceInternal::ID(), aStartPoint, aLineStart);
587 createConstraintAttrAttr(aSketch,
588 SketchPlugin_ConstraintCoincidenceInternal::ID(), aEndPoint, aLineEnd);
591 GeomPnt2dPtr flyoutPointCoordinates(const ConstraintPtr& theConstraint)
593 // currently process Length constraints only
594 if (theConstraint->getKind() != SketchPlugin_ConstraintLength::ID())
595 return GeomPnt2dPtr();
597 AttributeRefAttrPtr aLineAttr = theConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
598 if (!aLineAttr || !aLineAttr->isObject())
599 return GeomPnt2dPtr();
600 FeaturePtr aLine = ModelAPI_Feature::feature(aLineAttr->object());
601 if (!aLine || aLine->getKind() != SketchPlugin_Line::ID())
602 return GeomPnt2dPtr();
604 std::shared_ptr<GeomAPI_XY> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
605 aLine->attribute(SketchPlugin_Line::START_ID()))->pnt()->xy();
606 std::shared_ptr<GeomAPI_XY> aEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
607 aLine->attribute(SketchPlugin_Line::END_ID()))->pnt()->xy();
609 std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr =
610 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
611 theConstraint->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
612 std::shared_ptr<GeomAPI_Pnt2d> aFltPnt = aFlyoutAttr->pnt();
614 std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
616 double X = aStartPnt->x() + aFltPnt->x() * aLineDir->x() - aFltPnt->y() * aLineDir->y();
617 double Y = aStartPnt->y() + aFltPnt->x() * aLineDir->y() + aFltPnt->y() * aLineDir->x();
619 return GeomPnt2dPtr(new GeomAPI_Pnt2d(X, Y));
623 void customizeFeaturePrs(const AISObjectPtr& thePrs, bool isAxiliary)
625 std::vector<int> aColor;
628 thePrs->setLineStyle(SketchPlugin_SketchEntity::SKETCH_LINE_STYLE_AUXILIARY());
629 aColor = Config_PropManager::color("Visualization", "sketch_auxiliary_color");
630 aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH_AUXILIARY();
633 thePrs->setLineStyle(SketchPlugin_SketchEntity::SKETCH_LINE_STYLE());
634 aColor = Config_PropManager::color("Visualization", "sketch_entity_color");
635 aWidth = Config_PropManager::integer("Visualization", "sketch_line_width");
637 thePrs->setWidth(aWidth);
638 thePrs->setColor(aColor[0], aColor[1], aColor[2]);
641 void setDimensionColor(const AISObjectPtr& theDimPrs)
643 std::vector<int> aColor = Config_PropManager::color("Visualization", "sketch_dimension_color");
644 if (aColor.size() == 3)
645 theDimPrs->setColor(aColor[0], aColor[1], aColor[2]);
648 void replaceInName(ObjectPtr theObject, const std::string& theSource, const std::string& theDest)
650 std::string aName = theObject->data()->name();
651 size_t aPos = aName.find(theSource);
652 if (aPos != std::string::npos) {
653 std::string aNewName = aName.substr(0, aPos) + theDest
654 + aName.substr(aPos + theSource.size());
655 theObject->data()->setName(aNewName);
659 } // namespace SketchPlugin_Tools
662 // =================================================================================================
663 // namespace SketchPlugin_SegmentationTools
664 // =================================================================================================
666 void SketchPlugin_SegmentationTools::getFeaturePoints(const FeaturePtr& theFeature,
667 AttributePoint2DPtr& theStartPointAttr,
668 AttributePoint2DPtr& theEndPointAttr)
670 std::string aFeatureKind = theFeature->getKind();
671 std::string aStartAttributeName, anEndAttributeName;
672 if (aFeatureKind == SketchPlugin_Line::ID()) {
673 aStartAttributeName = SketchPlugin_Line::START_ID();
674 anEndAttributeName = SketchPlugin_Line::END_ID();
676 else if (aFeatureKind == SketchPlugin_Arc::ID()) {
677 aStartAttributeName = SketchPlugin_Arc::START_ID();
678 anEndAttributeName = SketchPlugin_Arc::END_ID();
680 else if (aFeatureKind == SketchPlugin_EllipticArc::ID()) {
681 aStartAttributeName = SketchPlugin_EllipticArc::START_POINT_ID();
682 anEndAttributeName = SketchPlugin_EllipticArc::END_POINT_ID();
684 else if (aFeatureKind == SketchPlugin_BSpline::ID()) {
685 aStartAttributeName = SketchPlugin_BSpline::START_ID();
686 anEndAttributeName = SketchPlugin_BSpline::END_ID();
688 if (!aStartAttributeName.empty() && !anEndAttributeName.empty()) {
689 theStartPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
690 theFeature->attribute(aStartAttributeName));
691 theEndPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
692 theFeature->attribute(anEndAttributeName));
697 void SketchPlugin_SegmentationTools::getRefAttributes(
698 const FeaturePtr& theFeature,
699 std::map<AttributePtr, std::list<AttributePtr> >& theRefs,
700 std::list<AttributePtr>& theRefsToFeature)
704 std::list<AttributePtr> aPointAttributes =
705 theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
706 std::set<AttributePtr> aPointAttributesSet;
708 std::list<AttributePtr>::const_iterator aPIt =
709 aPointAttributes.begin(), aPLast = aPointAttributes.end();
710 for (; aPIt != aPLast; aPIt++)
711 aPointAttributesSet.insert(*aPIt);
713 std::set<AttributePtr> aRefsAttributes = theFeature->lastResult()->data()->refsToMe();
714 std::set<AttributePtr> aFRefsList = theFeature->data()->refsToMe();
715 aRefsAttributes.insert(aFRefsList.begin(), aFRefsList.end());
717 std::set<AttributePtr>::const_iterator aIt;
718 for (aIt = aRefsAttributes.cbegin(); aIt != aRefsAttributes.cend(); ++aIt) {
719 AttributePtr anAttr = (*aIt);
720 FeaturePtr anAttrFeature = ModelAPI_Feature::feature(anAttr->owner());
721 if (!anAttrFeature->isMacro() && // <- skip reference from Trim or Split feature
722 anAttr.get() && anAttr->attributeType() == ModelAPI_AttributeRefAttr::typeId()) {
723 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
724 if (!aRefAttr->isObject()) { // find attributes referenced to feature point attributes
725 AttributePtr anAttrInRef = aRefAttr->attr();
726 if (anAttrInRef.get() &&
727 aPointAttributesSet.find(anAttrInRef) != aPointAttributesSet.end()) {
728 if (theRefs.find(anAttrInRef) != theRefs.end())
729 theRefs[anAttrInRef].push_back(aRefAttr);
731 std::list<AttributePtr> anAttrList;
732 anAttrList.push_back(aRefAttr);
733 theRefs[anAttrInRef] = anAttrList;
737 else { // find attributes referenced to feature itself
738 theRefsToFeature.push_back(anAttr);
744 GeomShapePtr SketchPlugin_SegmentationTools::getSubShape(
745 SketchPlugin_Feature* theFeature,
746 const std::string& theObjectAttributeId,
747 const std::string& thePointAttributeId,
748 std::map<ObjectPtr, std::set<GeomShapePtr> >& theCashedShapes,
749 std::map<ObjectPtr, GeomAlgoAPI_ShapeTools::PointToRefsMap>& theObjectToPoints)
751 GeomShapePtr aBaseShape;
753 AttributeReferencePtr anObjectAttr = theFeature->reference(theObjectAttributeId);
754 ObjectPtr aBaseObject = anObjectAttr->value();
755 if (!aBaseObject.get())
759 AttributePoint2DPtr aPointAttr =
760 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theFeature->attribute(thePointAttributeId));
761 std::shared_ptr<GeomAPI_Pnt2d> anAttributePnt2d = aPointAttr->pnt();
762 std::shared_ptr<GeomAPI_Pnt> anAttributePnt =
763 theFeature->sketch()->to3D(anAttributePnt2d->x(), anAttributePnt2d->y());
765 if (theCashedShapes.find(aBaseObject) == theCashedShapes.end())
766 fillObjectShapes(theFeature, aBaseObject, theCashedShapes, theObjectToPoints);
768 std::shared_ptr<GeomAPI_Pnt> aStartPoint;
769 std::shared_ptr<GeomAPI_Pnt> aSecondPoint;
770 const std::set<GeomShapePtr>& aShapes = theCashedShapes[aBaseObject];
771 std::set<GeomShapePtr>::const_iterator anIt = aShapes.begin(), aLast = aShapes.end();
772 for (; anIt != aLast; anIt++) {
773 GeomShapePtr aCurrentShape = *anIt;
774 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
775 if (ModelGeomAlgo_Point2D::isPointOnEdge(aCurrentShape, anAttributePnt, aProjectedPoint)) {
776 if (theFeature->getKind() == SketchPlugin_Split::ID()) {
777 // for Split operation collect start and end points of the shape
778 if (aCurrentShape->shapeType() == GeomAPI_Shape::EDGE) {
779 std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aCurrentShape));
780 aStartPoint = anEdge->firstPoint();
781 aSecondPoint = anEdge->lastPoint();
785 aBaseShape = aCurrentShape;
790 if (!aStartPoint.get() || !aSecondPoint.get())
793 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObject);
794 if (anObjectAttr->isInitialized() && aBaseFeature.get() && aPointAttr->isInitialized()) {
795 ResultPtr aResult = aBaseFeature->lastResult();
796 GeomShapePtr aResultShape = aResult->shape();
797 std::list<std::shared_ptr<GeomAPI_Pnt> > aPoints;
799 aPoints.push_back(aStartPoint);
800 aPoints.push_back(aSecondPoint);
802 std::set<std::shared_ptr<GeomAPI_Shape> > aSplitShapes;
803 GeomAlgoAPI_ShapeTools::splitShape_p(aResultShape, aPoints, aSplitShapes);
804 aBaseShape = GeomAlgoAPI_ShapeTools::findShape(aPoints, aSplitShapes);
809 void SketchPlugin_SegmentationTools::fillObjectShapes(
810 SketchPlugin_Feature* theOpFeature,
811 const ObjectPtr& theObject,
812 std::map<ObjectPtr, std::set<GeomShapePtr> >& theCashedShapes,
813 std::map<ObjectPtr, GeomAlgoAPI_ShapeTools::PointToRefsMap>& theObjectToPoints)
815 SketchPlugin_Sketch* aSketch = theOpFeature->sketch();
817 GeomAlgoAPI_ShapeTools::PointToRefsMap aPoints;
818 std::set<GeomShapePtr> aShapes;
820 std::set<AttributePoint2DPtr > aRefAttributes;
822 FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
823 std::set<ResultPtr> anEdgeShapes;
825 ModelGeomAlgo_Shape::shapesOfType(aFeature, GeomAPI_Shape::EDGE, anEdgeShapes);
826 if (!anEdgeShapes.empty()) {
827 GeomShapePtr aFeatureShape = (*anEdgeShapes.begin())->shape();
829 // coincidences to the feature
830 ModelGeomAlgo_Point2D::getPointsOfReference(aFeature, SketchPlugin_ConstraintCoincidence::ID(),
831 aRefAttributes, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID());
832 // layed on feature coincidences to divide it on several shapes
833 std::shared_ptr<ModelAPI_Data> aData = aSketch->data();
834 std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
835 aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
836 std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
837 aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
838 std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
839 aData->attribute(SketchPlugin_Sketch::NORM_ID()));
840 std::shared_ptr<GeomAPI_Dir> aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
842 ModelGeomAlgo_Point2D::getPointsInsideShape(aFeatureShape, aRefAttributes, aC->pnt(),
843 aX->dir(), aY, aPoints);
845 if (theOpFeature->getKind() == SketchPlugin_Trim::ID()) {
846 // collect all intersection points with other edges for Trim operation only
847 std::list<FeaturePtr> aFeatures;
848 for (int i = 0; i < aSketch->numberOfSubs(); i++) {
849 FeaturePtr aSubFeature = aSketch->subFeature(i);
850 if (aSubFeature.get() && aSubFeature->getKind() != SketchPlugin_Projection::ID())
851 aFeatures.push_back(aSubFeature);
853 ModelGeomAlgo_Point2D::getPointsIntersectedShape(aFeature, aFeatures, aPoints);
856 if (!aPoints.empty())
857 GeomAlgoAPI_ShapeTools::splitShape(aFeatureShape, aPoints, aShapes);
859 theObjectToPoints[theObject] = aPoints;
860 theCashedShapes[theObject] = aShapes;
863 void SketchPlugin_SegmentationTools::updateRefAttConstraints(
864 const std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
865 const std::set<std::pair<AttributePtr, AttributePtr> >& theModifiedAttributes)
867 #if defined DEBUG_SPLIT || defined DEBUG_TRIM
868 std::cout << "updateRefAttConstraints" << std::endl;
871 std::set<std::pair<AttributePtr, AttributePtr> >::const_iterator
872 anIt = theModifiedAttributes.begin(), aLast = theModifiedAttributes.end();
873 for (; anIt != aLast; anIt++) {
874 AttributePtr anAttribute = anIt->first;
875 AttributePtr aNewAttribute = anIt->second;
877 // not found in references
878 if (!aNewAttribute.get() ||
879 theBaseRefAttributes.find(anAttribute) == theBaseRefAttributes.end())
881 std::list<AttributePtr> aRefAttributes = theBaseRefAttributes.at(anAttribute);
882 std::list<AttributePtr>::const_iterator aRefIt = aRefAttributes.begin(),
883 aRLast = aRefAttributes.end();
885 for (; aRefIt != aRLast; aRefIt++) {
886 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefIt);
887 if (aRefAttr.get()) {
888 aRefAttr->setAttr(aNewAttribute);
890 FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->owner());
891 std::cout << " -" << getFeatureInfo(aFeature) << std::endl;
898 void SketchPlugin_SegmentationTools::updateFeaturesAfterOperation(
899 const std::set<FeaturePtr>& theFeaturesToUpdate)
901 std::set<FeaturePtr>::const_iterator anIt = theFeaturesToUpdate.begin(),
902 aLast = theFeaturesToUpdate.end();
903 for (; anIt != aLast; anIt++) {
904 FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*anIt);
905 std::string aRefFeatureKind = aRefFeature->getKind();
906 if (aRefFeatureKind == SketchPlugin_ConstraintLength::ID()) {
907 std::shared_ptr<SketchPlugin_ConstraintLength> aLenghtFeature =
908 std::dynamic_pointer_cast<SketchPlugin_ConstraintLength>(*anIt);
909 if (aLenghtFeature.get()) {
910 std::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = std::dynamic_pointer_cast<
911 ModelAPI_AttributeDouble>(aLenghtFeature->attribute(SketchPlugin_Constraint::VALUE()));
913 if (aLenghtFeature->computeLenghtValue(aValue) && aValueAttr.get())
914 aValueAttr->setValue(aValue);
920 AISObjectPtr SketchPlugin_SegmentationTools::getAISObject(
921 AISObjectPtr thePrevious,
922 SketchPlugin_Feature* theOpFeature,
923 const std::string& thePreviewObjectAttrName,
924 const std::string& thePreviewPointAttrName,
925 const std::string& theSelectedObjectAttrName,
926 const std::string& theSelectedPointAttrName)
928 #if defined DEBUG_SPLIT || defined DEBUG_TRIM_METHODS
929 std::cout << "getAISObject: " << theOpFeature->data()->name() << std::endl;
932 AISObjectPtr anAIS = thePrevious;
934 std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
935 std::map<ObjectPtr, std::set<GeomShapePtr> > aCashedShapes;
936 std::map<ObjectPtr, GeomAlgoAPI_ShapeTools::PointToRefsMap> aObjectToPoints;
937 GeomShapePtr aPreviewShape = getSubShape(theOpFeature,
938 thePreviewObjectAttrName, thePreviewPointAttrName, aCashedShapes, aObjectToPoints);
939 if (aPreviewShape.get())
940 aShapes.push_back(aPreviewShape);
941 GeomShapePtr aSelectedShape = getSubShape(theOpFeature,
942 theSelectedObjectAttrName, theSelectedPointAttrName, aCashedShapes, aObjectToPoints);
943 if (aSelectedShape.get())
944 aShapes.push_back(aSelectedShape);
947 return AISObjectPtr();
949 GeomShapePtr aBaseShape = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
950 if (!aBaseShape.get())
951 return AISObjectPtr();
953 if (aBaseShape.get()) {
955 anAIS = AISObjectPtr(new GeomAPI_AISObject);
956 anAIS->createShape(aBaseShape);
958 std::vector<int> aColor;
959 aColor = Config_PropManager::color("Visualization", "operation_remove_feature_color");
960 double aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH();
961 int aLineStyle = SketchPlugin_SketchEntity::SKETCH_LINE_STYLE();
962 anAIS->setColor(aColor[0], aColor[1], aColor[2]);
963 // width when there is not base object should be extened in several points
964 // in order to see this preview over highlight
965 anAIS->setWidth(aWidth+4);
966 anAIS->setLineStyle(aLineStyle);
969 anAIS = AISObjectPtr();
973 #define GEOM_DATA_POINT2D(f, a) std::dynamic_pointer_cast<GeomDataAPI_Point2D>((f)->attribute(a))
975 FeaturePtr SketchPlugin_SegmentationTools::createLineFeature(
976 const FeaturePtr& theBaseFeature,
977 const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
978 const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint)
981 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
982 std::dynamic_pointer_cast<SketchPlugin_Feature>(theBaseFeature);
983 SketchPlugin_Sketch* aSketch = aSketchFeature->sketch();
984 if (!aSketch || !theBaseFeature.get())
987 aFeature = aSketch->addFeature(SketchPlugin_Line::ID());
989 GEOM_DATA_POINT2D(aFeature, SketchPlugin_Line::START_ID())->setValue(theFirstPoint);
990 GEOM_DATA_POINT2D(aFeature, SketchPlugin_Line::END_ID())->setValue(theSecondPoint);
992 aFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(
993 theBaseFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value());
994 aFeature->execute(); // to obtain result
1002 std::string myCenter;
1003 std::string myFocus;
1004 std::string myStart;
1006 std::string myReversed;
1010 ArcAttributes(const std::string& theKind) : myKind(theKind)
1012 if (myKind == SketchPlugin_Arc::ID()) {
1013 myCenter = SketchPlugin_Arc::CENTER_ID();
1014 myStart = SketchPlugin_Arc::START_ID();
1015 myEnd = SketchPlugin_Arc::END_ID();
1016 myReversed = SketchPlugin_Arc::REVERSED_ID();
1018 else if (myKind == SketchPlugin_Circle::ID()) {
1019 myCenter = SketchPlugin_Circle::CENTER_ID();
1021 else if (myKind == SketchPlugin_Ellipse::ID()) {
1022 myCenter = SketchPlugin_Ellipse::CENTER_ID();
1023 myFocus = SketchPlugin_Ellipse::FIRST_FOCUS_ID();
1025 else if (myKind == SketchPlugin_EllipticArc::ID()) {
1026 myCenter = SketchPlugin_EllipticArc::CENTER_ID();
1027 myFocus = SketchPlugin_EllipticArc::FIRST_FOCUS_ID();
1028 myStart = SketchPlugin_EllipticArc::START_POINT_ID();
1029 myEnd = SketchPlugin_EllipticArc::END_POINT_ID();
1030 myReversed = SketchPlugin_EllipticArc::REVERSED_ID();
1035 FeaturePtr SketchPlugin_SegmentationTools::createArcFeature(
1036 const FeaturePtr& theBaseFeature,
1037 const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
1038 const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint)
1040 FeaturePtr aFeature;
1041 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
1042 std::dynamic_pointer_cast<SketchPlugin_Feature>(theBaseFeature);
1043 SketchPlugin_Sketch* aSketch = aSketchFeature->sketch();
1044 if (!aSketch || !theBaseFeature.get())
1047 ArcAttributes aBaseAttrs(theBaseFeature->getKind());
1048 ArcAttributes aTargetAttrs;
1049 if (aBaseAttrs.myKind == SketchPlugin_Arc::ID() ||
1050 aBaseAttrs.myKind == SketchPlugin_Circle::ID())
1051 aTargetAttrs = ArcAttributes(SketchPlugin_Arc::ID());
1052 else if (aBaseAttrs.myKind == SketchPlugin_Ellipse::ID() ||
1053 aBaseAttrs.myKind == SketchPlugin_EllipticArc::ID())
1054 aTargetAttrs = ArcAttributes(SketchPlugin_EllipticArc::ID());
1056 if (aTargetAttrs.myKind.empty())
1059 aFeature = aSketch->addFeature(aTargetAttrs.myKind);
1060 // update fillet arc: make the arc correct for sure, so, it is not needed to process
1061 // the "attribute updated"
1062 // by arc; moreover, it may cause cyclicity in hte mechanism of updater
1063 bool aWasBlocked = aFeature->data()->blockSendAttributeUpdated(true);
1065 GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myCenter)->setValue(
1066 GEOM_DATA_POINT2D(theBaseFeature, aBaseAttrs.myCenter)->pnt());
1067 if (!aTargetAttrs.myFocus.empty()) {
1068 GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myFocus)->setValue(
1069 GEOM_DATA_POINT2D(theBaseFeature, aBaseAttrs.myFocus)->pnt());
1071 GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myStart)->setValue(theFirstPoint);
1072 GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myEnd)->setValue(theSecondPoint);
1074 aFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(
1075 theBaseFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value());
1077 /// fill referersed state of created arc as it is on the base arc
1078 bool aReversed = aBaseAttrs.myReversed.empty() ? false :
1079 theBaseFeature->boolean(aBaseAttrs.myReversed)->value();
1080 aFeature->boolean(aTargetAttrs.myReversed)->setValue(aReversed);
1082 aFeature->execute(); // to obtain result (need to calculate arc parameters before sending Update)
1083 aFeature->data()->blockSendAttributeUpdated(aWasBlocked);