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_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>
42 #include <ModelAPI_Tools.h>
44 #include <ModelGeomAlgo_Point2D.h>
45 #include <ModelGeomAlgo_Shape.h>
47 #include <GeomAPI_Dir2d.h>
48 #include <GeomAPI_Edge.h>
49 #include <GeomAPI_Pnt2d.h>
50 #include <GeomAPI_XY.h>
52 #include <GeomAlgoAPI_CompoundBuilder.h>
53 #include <GeomAlgoAPI_ShapeTools.h>
55 #include <GeomDataAPI_Point.h>
56 #include <GeomDataAPI_Point2D.h>
62 namespace SketchPlugin_Tools {
64 void clearExpressions(AttributeDoublePtr theAttribute)
66 theAttribute->setText(std::string());
69 void clearExpressions(AttributePointPtr theAttribute)
71 theAttribute->setText(std::string(), std::string(), std::string());
74 void clearExpressions(AttributePoint2DPtr theAttribute)
76 theAttribute->setText(std::string(), std::string());
79 void clearExpressions(AttributePtr theAttribute)
82 AttributeDoublePtr anAttributeDouble =
83 std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
84 if (anAttributeDouble.get())
85 clearExpressions(anAttributeDouble);
87 AttributePointPtr anAttributePoint =
88 std::dynamic_pointer_cast<GeomDataAPI_Point>(theAttribute);
89 if (anAttributePoint.get())
90 clearExpressions(anAttributePoint);
92 AttributePoint2DPtr anAttributePoint2D =
93 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
94 if (anAttributePoint2D.get())
95 clearExpressions(anAttributePoint2D);
98 void clearExpressions(FeaturePtr theFeature)
100 if (!theFeature.get())
103 std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
104 std::list<AttributePtr>::iterator anAttributeIt = anAttributes.begin();
105 for (; anAttributeIt != anAttributes.end(); ++anAttributeIt) {
106 clearExpressions(*anAttributeIt);
110 std::shared_ptr<GeomAPI_Pnt2d> getCoincidencePoint(const FeaturePtr theStartCoin)
112 std::shared_ptr<GeomAPI_Pnt2d> aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(),
113 SketchPlugin_Constraint::ENTITY_A());
114 if (aPnt.get() == NULL)
115 aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(), SketchPlugin_Constraint::ENTITY_B());
119 std::set<FeaturePtr> findCoincidentConstraints(const ObjectPtr& theObject)
121 std::set<FeaturePtr> aCoincident;
122 const std::set<AttributePtr>& aRefsList = theObject->data()->refsToMe();
123 std::set<AttributePtr>::const_iterator aIt;
124 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
125 FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aIt)->owner());
126 if (aConstrFeature && (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID() ||
127 aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidenceInternal::ID()))
128 aCoincident.insert(aConstrFeature);
133 void findCoincidences(const FeaturePtr theStartCoin,
134 const std::string& theAttr,
135 std::set<FeaturePtr>& theList,
136 const bool theIsAttrOnly)
138 AttributeRefAttrPtr aPnt = theStartCoin->refattr(theAttr);
142 FeaturePtr aObj = ModelAPI_Feature::feature(aPnt->object());
143 if(theList.find(aObj) == theList.end()) {
144 std::shared_ptr<GeomAPI_Pnt2d> aOrig = getCoincidencePoint(theStartCoin);
145 if(aOrig.get() == NULL) {
148 if(!theIsAttrOnly || !aPnt->isObject()) {
149 theList.insert(aObj);
151 std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(aObj);
152 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
153 for (; aCIt != aCoincidences.end(); ++aCIt) {
154 FeaturePtr aConstrFeature = *aCIt;
155 std::shared_ptr<GeomAPI_Pnt2d> aPnt = getCoincidencePoint(aConstrFeature);
156 if(aPnt.get() && aOrig->isEqual(aPnt)) {
157 findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A(),
158 theList, theIsAttrOnly);
159 findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B(),
160 theList, theIsAttrOnly);
166 std::set<FeaturePtr> findFeaturesCoincidentToPoint(const AttributePoint2DPtr& thePoint)
168 std::set<FeaturePtr> aCoincidentFeatures;
170 FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
171 aCoincidentFeatures.insert(anOwner);
173 std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(anOwner);
174 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
175 for (; aCIt != aCoincidences.end(); ++aCIt) {
176 bool isPointUsedInCoincidence = false;
177 AttributeRefAttrPtr anOtherCoincidentAttr;
178 for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
179 AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
182 if (!aRefAttr->isObject() && aRefAttr->attr() == thePoint)
183 isPointUsedInCoincidence = true;
185 anOtherCoincidentAttr = aRefAttr;
188 if (isPointUsedInCoincidence) {
190 if (anOtherCoincidentAttr->isObject())
191 anObj = anOtherCoincidentAttr->object();
193 anObj = anOtherCoincidentAttr->attr()->owner();
194 aCoincidentFeatures.insert(ModelAPI_Feature::feature(anObj));
198 return aCoincidentFeatures;
201 // Container for point-point coincidences.
202 // Useful to find points coincident to a given point.
203 class CoincidentPoints
205 static const int THE_DEFAULT_INDEX = -1;
208 void addCoincidence(const AttributePtr& thePoint1, const int theIndex1,
209 const AttributePtr& thePoint2, const int theIndex2)
211 auto aFound1 = find(thePoint1, theIndex1);
212 auto aFound2 = find(thePoint2, theIndex2);
213 if (aFound1 == myCoincidentPoints.end()) {
214 if (aFound2 == myCoincidentPoints.end()) {
215 std::map<AttributePtr, std::set<int> > aNewSet;
216 aNewSet[thePoint1].insert(theIndex1);
218 aNewSet[thePoint2].insert(theIndex2);
219 myCoincidentPoints.push_back(aNewSet);
221 (*aFound2)[thePoint1].insert(theIndex1);
222 } else if (aFound2 == myCoincidentPoints.end()) {
224 (*aFound1)[thePoint2].insert(theIndex2);
226 for (auto it = aFound2->begin(); it != aFound2->end(); ++it)
227 (*aFound1)[it->first].insert(it->second.begin(), it->second.end());
228 myCoincidentPoints.erase(aFound2);
232 void coincidentPoints(const AttributePoint2DPtr& thePoint,
233 std::set<AttributePoint2DPtr>& thePoints,
234 std::map<AttributePoint2DArrayPtr, int>& thePointsInArray)
236 collectCoincidentPoints(thePoint);
238 auto aFound = find(thePoint, THE_DEFAULT_INDEX);
239 if (aFound != myCoincidentPoints.end()) {
240 for (auto it = aFound->begin(); it != aFound->end(); ++it) {
241 AttributePoint2DPtr aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(it->first);
243 thePoints.insert(aPoint);
245 AttributePoint2DArrayPtr aPointArray =
246 std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(it->first);
248 thePointsInArray[aPointArray] = *it->second.begin();
255 void coincidences(const FeaturePtr& theFeature,
256 std::set<FeaturePtr>& theCoincidences) const
258 // iterate through coincideces for the given feature
259 std::set<FeaturePtr> aCoincidences = SketchPlugin_Tools::findCoincidentConstraints(theFeature);
260 if (theFeature->getKind() == SketchPlugin_Point::ID()) {
261 std::set<FeaturePtr> aCoincToRes =
262 SketchPlugin_Tools::findCoincidentConstraints(theFeature->lastResult());
263 aCoincidences.insert(aCoincToRes.begin(), aCoincToRes.end());
265 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
266 for (; aCIt != aCoincidences.end(); ++aCIt)
268 if (theCoincidences.find(*aCIt) != theCoincidences.end())
269 continue; // already processed
270 theCoincidences.insert(*aCIt);
271 // iterate on coincident attributes
272 for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
273 AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
277 if (aRefAttr->isObject()) {
278 FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
279 if (aFeature->getKind() == SketchPlugin_Point::ID())
283 anOwner = ModelAPI_Feature::feature(aRefAttr->attr()->owner());
284 if (anOwner && anOwner != theFeature)
285 coincidences(anOwner, theCoincidences);
290 // Iteratively search points coincident to the given point
291 // (two points may be coincident through the third point)
292 void collectCoincidentPoints(const AttributePoint2DPtr& thePoint)
294 AttributePtr aPoints[2];
295 int anIndicesInArray[2];
297 FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
298 std::set<FeaturePtr> aCoincidences;
299 coincidences(anOwner, aCoincidences);
301 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
302 for (; aCIt != aCoincidences.end(); ++aCIt) {
303 aPoints[0] = aPoints[1] = AttributePtr();
304 anIndicesInArray[0] = anIndicesInArray[1] = THE_DEFAULT_INDEX;
305 for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
306 AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
309 if (aRefAttr->isObject()) {
310 FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
311 if (aFeature && aFeature->getKind() == SketchPlugin_Point::ID())
312 aPoints[aPtInd++] = aFeature->attribute(SketchPlugin_Point::COORD_ID());
315 AttributePoint2DPtr aPointAttr =
316 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
317 AttributePoint2DArrayPtr aPointArray =
318 std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(aRefAttr->attr());
320 aPoints[aPtInd++] = aPointAttr;
321 else if (aPointArray) {
322 AttributeIntegerPtr anIndexAttr = (*aCIt)->integer(i == 0 ?
323 SketchPlugin_ConstraintCoincidenceInternal::INDEX_ENTITY_A() :
324 SketchPlugin_ConstraintCoincidenceInternal::INDEX_ENTITY_B());
325 aPoints[aPtInd] = aPointArray;
326 anIndicesInArray[aPtInd++] = anIndexAttr->value();
331 if (aPoints[0] && aPoints[1])
332 addCoincidence(aPoints[0], anIndicesInArray[0], aPoints[1], anIndicesInArray[1]);
336 std::list< std::map<AttributePtr, std::set<int> > >::iterator find(const AttributePtr& thePoint,
339 auto aSeek = myCoincidentPoints.begin();
340 for (; aSeek != myCoincidentPoints.end(); ++aSeek) {
341 auto aFound = aSeek->find(thePoint);
342 if (aFound != aSeek->end() && aFound->second.find(theIndex) != aFound->second.end())
345 return myCoincidentPoints.end();
349 std::list< std::map<AttributePtr, std::set<int> > > myCoincidentPoints;
352 std::set<AttributePoint2DPtr> findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint)
354 std::set<AttributePoint2DPtr> aPoints;
355 std::map<AttributePoint2DArrayPtr, int> aPointsInArray;
356 findPointsCoincidentToPoint(thePoint, aPoints, aPointsInArray);
360 void findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint,
361 std::set<AttributePoint2DPtr>& thePoints,
362 std::map<AttributePoint2DArrayPtr, int>& thePointsInArray)
364 CoincidentPoints aCoincidentPoints;
365 aCoincidentPoints.coincidentPoints(thePoint, thePoints, thePointsInArray);
369 void resetAttribute(SketchPlugin_Feature* theFeature,
370 const std::string& theId)
372 AttributePtr anAttr = theFeature->attribute(theId);
378 void createCoincidenceOrTangency(SketchPlugin_Feature* theFeature,
379 const std::string& theId,
380 const AttributePtr theAttr,
381 const ObjectPtr theObject,
382 const bool theIsCanBeTangent)
384 AttributeRefAttrPtr aRefAttr = theFeature->refattr(theId);
385 if(aRefAttr.get() && aRefAttr->isInitialized()) {
386 FeaturePtr aConstraint;
387 if(!theIsCanBeTangent) {
388 aConstraint = theFeature->sketch()
389 ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
391 if(aRefAttr->isObject()) {
392 ObjectPtr anObject = aRefAttr->object();
393 FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
394 if(aFeature->getKind() == SketchPlugin_Point::ID()) {
395 aConstraint = theFeature->sketch()
396 ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
398 aConstraint = theFeature->sketch()
399 ->addFeature(SketchPlugin_ConstraintTangent::ID());
402 aConstraint = theFeature->sketch()
403 ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
406 AttributeRefAttrPtr aRefAttrA = aConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
407 aRefAttr->isObject() ? aRefAttrA->setObject(aRefAttr->object())
408 : aRefAttrA->setAttr(aRefAttr->attr());
409 AttributeRefAttrPtr aRefAttrB = aConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
410 if(theObject.get()) {
411 aRefAttrB->setObject(theObject);
412 } else if(theAttr.get()) {
413 aRefAttrB->setAttr(theAttr);
418 void convertRefAttrToPointOrTangentCurve(const AttributeRefAttrPtr& theRefAttr,
419 const AttributePtr& theDefaultAttr,
420 std::shared_ptr<GeomAPI_Shape>& theTangentCurve,
421 std::shared_ptr<GeomAPI_Pnt2d>& thePassingPoint)
423 AttributePtr anAttr = theDefaultAttr;
424 if (theRefAttr->isObject()) {
425 FeaturePtr aTgFeature = ModelAPI_Feature::feature(theRefAttr->object());
427 if (aTgFeature->getKind() != SketchPlugin_Point::ID()) {
428 theTangentCurve = aTgFeature->lastResult()->shape();
431 anAttr = aTgFeature->attribute(SketchPlugin_Point::COORD_ID());
434 anAttr = theRefAttr->attr();
436 thePassingPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr)->pnt();
440 FeaturePtr createConstraintAttrAttr(SketchPlugin_Sketch* theSketch,
441 const std::string& theConstraintId,
442 const AttributePtr& theFirstAttribute,
443 const AttributePtr& theSecondAttribute)
445 FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
446 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
447 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
448 aRefAttr->setAttr(theFirstAttribute);
450 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
451 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
452 aRefAttr->setAttr(theSecondAttribute);
454 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
455 std::cout << "<createConstraint to attribute> :"
456 << " first attribute - " << theFirstAttribute->id()
457 << " second attribute - " << theSecondAttribute->id()
464 FeaturePtr createConstraintAttrObject(SketchPlugin_Sketch* theSketch,
465 const std::string& theConstraintId,
466 const AttributePtr& theFirstAttribute,
467 const ObjectPtr& theSecondObject)
469 FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
470 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
471 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
472 aRefAttr->setAttr(theFirstAttribute);
474 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
475 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
476 aRefAttr->setObject(theSecondObject);
478 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
479 std::cout << "<createConstraint to attribute> :"
480 << " first attribute - " << theFirstAttribute->id()
481 << " second object - " << ModelAPI_Feature::feature(theSecondObject)->getKind()
488 FeaturePtr createConstraintObjectObject(SketchPlugin_Sketch* theSketch,
489 const std::string& theConstraintId,
490 const ObjectPtr& theFirstObject,
491 const ObjectPtr& theSecondObject)
493 FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
494 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
495 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
496 aRefAttr->setObject(theFirstObject);
498 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
499 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
500 aRefAttr->setObject(theSecondObject);
502 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
503 std::cout << "<createConstraint to attribute> :"
504 << " first object - " << ModelAPI_Feature::feature(theFirstObject)->getKind()
505 << " second object - " << ModelAPI_Feature::feature(theSecondObject)->getKind()
512 void createAuxiliaryPointOnEllipse(const FeaturePtr& theEllipseFeature,
513 const std::string& theEllipsePoint)
515 SketchPlugin_Sketch* aSketch =
516 std::dynamic_pointer_cast<SketchPlugin_Feature>(theEllipseFeature)->sketch();
518 FeaturePtr aPointFeature = aSketch->addFeature(SketchPlugin_Point::ID());
519 aPointFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
520 aPointFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipseFeature);
522 AttributePoint2DPtr anElPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
523 theEllipseFeature->attribute(theEllipsePoint));
525 AttributePoint2DPtr aCoord = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
526 aPointFeature->attribute(SketchPlugin_Point::COORD_ID()));
527 aCoord->setValue(anElPoint->x(), anElPoint->y());
529 aPointFeature->execute();
530 std::wstring aName = theEllipseFeature->name() + L"_" +
531 ModelAPI_Tools::toWString(theEllipsePoint);
532 aPointFeature->data()->setName(aName);
533 aPointFeature->lastResult()->data()->setName(aName);
535 createConstraintAttrAttr(aSketch,
536 SketchPlugin_ConstraintCoincidenceInternal::ID(), anElPoint, aCoord);
539 void createAuxiliaryAxisOfEllipse(const FeaturePtr& theEllipseFeature,
540 const std::string& theStartPoint,
541 const std::string& theEndPoint)
543 SketchPlugin_Sketch* aSketch =
544 std::dynamic_pointer_cast<SketchPlugin_Feature>(theEllipseFeature)->sketch();
546 FeaturePtr aLineFeature = aSketch->addFeature(SketchPlugin_Line::ID());
547 aLineFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
548 aLineFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipseFeature);
550 AttributePoint2DPtr aStartPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
551 theEllipseFeature->attribute(theStartPoint));
552 AttributePoint2DPtr aEndPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
553 theEllipseFeature->attribute(theEndPoint));
555 AttributePoint2DPtr aLineStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
556 aLineFeature->attribute(SketchPlugin_Line::START_ID()));
557 aLineStart->setValue(aStartPoint->x(), aStartPoint->y());
559 AttributePoint2DPtr aLineEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
560 aLineFeature->attribute(SketchPlugin_Line::END_ID()));
561 aLineEnd->setValue(aEndPoint->x(), aEndPoint->y());
563 aLineFeature->execute();
564 std::wstring aName = theEllipseFeature->name() + L"_" +
565 (theStartPoint == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() ? L"major_axis" : L"minor_axis");
566 aLineFeature->data()->setName(aName);
567 aLineFeature->lastResult()->data()->setName(aName);
569 createConstraintAttrAttr(aSketch,
570 SketchPlugin_ConstraintCoincidenceInternal::ID(), aStartPoint, aLineStart);
571 createConstraintAttrAttr(aSketch,
572 SketchPlugin_ConstraintCoincidenceInternal::ID(), aEndPoint, aLineEnd);
575 GeomPnt2dPtr flyoutPointCoordinates(const ConstraintPtr& theConstraint)
577 // currently process Length constraints only
578 if (theConstraint->getKind() != SketchPlugin_ConstraintLength::ID())
579 return GeomPnt2dPtr();
581 AttributeRefAttrPtr aLineAttr = theConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
582 if (!aLineAttr || !aLineAttr->isObject())
583 return GeomPnt2dPtr();
584 FeaturePtr aLine = ModelAPI_Feature::feature(aLineAttr->object());
585 if (!aLine || aLine->getKind() != SketchPlugin_Line::ID())
586 return GeomPnt2dPtr();
588 std::shared_ptr<GeomAPI_XY> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
589 aLine->attribute(SketchPlugin_Line::START_ID()))->pnt()->xy();
590 std::shared_ptr<GeomAPI_XY> aEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
591 aLine->attribute(SketchPlugin_Line::END_ID()))->pnt()->xy();
593 std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr =
594 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
595 theConstraint->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
596 std::shared_ptr<GeomAPI_Pnt2d> aFltPnt = aFlyoutAttr->pnt();
598 std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
600 double X = aStartPnt->x() + aFltPnt->x() * aLineDir->x() - aFltPnt->y() * aLineDir->y();
601 double Y = aStartPnt->y() + aFltPnt->x() * aLineDir->y() + aFltPnt->y() * aLineDir->x();
603 return GeomPnt2dPtr(new GeomAPI_Pnt2d(X, Y));
607 void customizeFeaturePrs(const AISObjectPtr& thePrs, bool isAxiliary)
609 std::vector<int> aColor;
612 thePrs->setLineStyle(SketchPlugin_SketchEntity::SKETCH_LINE_STYLE_AUXILIARY());
613 aColor = Config_PropManager::color("Visualization", "sketch_auxiliary_color");
614 aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH_AUXILIARY();
617 thePrs->setLineStyle(SketchPlugin_SketchEntity::SKETCH_LINE_STYLE());
618 aColor = Config_PropManager::color("Visualization", "sketch_entity_color");
619 aWidth = Config_PropManager::integer("Visualization", "sketch_line_width");
621 thePrs->setWidth(aWidth);
622 thePrs->setColor(aColor[0], aColor[1], aColor[2]);
625 void setDimensionColor(const AISObjectPtr& theDimPrs)
627 std::vector<int> aColor = Config_PropManager::color("Visualization", "sketch_dimension_color");
628 if (aColor.size() == 3)
629 theDimPrs->setColor(aColor[0], aColor[1], aColor[2]);
632 void replaceInName(ObjectPtr theObject, const std::wstring& theSource, const std::wstring& theDest)
634 std::wstring aName = theObject->data()->name();
635 size_t aPos = aName.find(theSource);
636 if (aPos != std::string::npos) {
637 std::wstring aNewName = aName.substr(0, aPos) + theDest
638 + aName.substr(aPos + theSource.size());
639 theObject->data()->setName(aNewName);
643 } // namespace SketchPlugin_Tools
646 // =================================================================================================
647 // namespace SketchPlugin_SegmentationTools
648 // =================================================================================================
650 void SketchPlugin_SegmentationTools::getFeaturePoints(const FeaturePtr& theFeature,
651 AttributePoint2DPtr& theStartPointAttr,
652 AttributePoint2DPtr& theEndPointAttr)
654 std::string aFeatureKind = theFeature->getKind();
655 std::string aStartAttributeName, anEndAttributeName;
656 if (aFeatureKind == SketchPlugin_Line::ID()) {
657 aStartAttributeName = SketchPlugin_Line::START_ID();
658 anEndAttributeName = SketchPlugin_Line::END_ID();
660 else if (aFeatureKind == SketchPlugin_Arc::ID()) {
661 aStartAttributeName = SketchPlugin_Arc::START_ID();
662 anEndAttributeName = SketchPlugin_Arc::END_ID();
664 else if (aFeatureKind == SketchPlugin_EllipticArc::ID()) {
665 aStartAttributeName = SketchPlugin_EllipticArc::START_POINT_ID();
666 anEndAttributeName = SketchPlugin_EllipticArc::END_POINT_ID();
668 else if (aFeatureKind == SketchPlugin_BSpline::ID()) {
669 aStartAttributeName = SketchPlugin_BSpline::START_ID();
670 anEndAttributeName = SketchPlugin_BSpline::END_ID();
672 if (!aStartAttributeName.empty() && !anEndAttributeName.empty()) {
673 theStartPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
674 theFeature->attribute(aStartAttributeName));
675 theEndPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
676 theFeature->attribute(anEndAttributeName));
681 void SketchPlugin_SegmentationTools::getRefAttributes(
682 const FeaturePtr& theFeature,
683 std::map<AttributePtr, std::list<AttributePtr> >& theRefs,
684 std::list<AttributePtr>& theRefsToFeature)
688 std::list<AttributePtr> aPointAttributes =
689 theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
690 std::set<AttributePtr> aPointAttributesSet;
692 std::list<AttributePtr>::const_iterator aPIt =
693 aPointAttributes.begin(), aPLast = aPointAttributes.end();
694 for (; aPIt != aPLast; aPIt++)
695 aPointAttributesSet.insert(*aPIt);
697 std::set<AttributePtr> aRefsAttributes = theFeature->lastResult()->data()->refsToMe();
698 std::set<AttributePtr> aFRefsList = theFeature->data()->refsToMe();
699 aRefsAttributes.insert(aFRefsList.begin(), aFRefsList.end());
701 std::set<AttributePtr>::const_iterator aIt;
702 for (aIt = aRefsAttributes.cbegin(); aIt != aRefsAttributes.cend(); ++aIt) {
703 AttributePtr anAttr = (*aIt);
704 FeaturePtr anAttrFeature = ModelAPI_Feature::feature(anAttr->owner());
705 if (!anAttrFeature->isMacro() && // <- skip reference from Trim or Split feature
706 anAttr.get() && anAttr->attributeType() == ModelAPI_AttributeRefAttr::typeId()) {
707 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
708 if (!aRefAttr->isObject()) { // find attributes referenced to feature point attributes
709 AttributePtr anAttrInRef = aRefAttr->attr();
710 if (anAttrInRef.get() &&
711 aPointAttributesSet.find(anAttrInRef) != aPointAttributesSet.end()) {
712 if (theRefs.find(anAttrInRef) != theRefs.end())
713 theRefs[anAttrInRef].push_back(aRefAttr);
715 std::list<AttributePtr> anAttrList;
716 anAttrList.push_back(aRefAttr);
717 theRefs[anAttrInRef] = anAttrList;
721 else { // find attributes referenced to feature itself
722 theRefsToFeature.push_back(anAttr);
728 GeomShapePtr SketchPlugin_SegmentationTools::getSubShape(
729 SketchPlugin_Feature* theFeature,
730 const std::string& theObjectAttributeId,
731 const std::string& thePointAttributeId,
732 std::map<ObjectPtr, std::set<GeomShapePtr> >& theCashedShapes,
733 std::map<ObjectPtr, GeomAlgoAPI_ShapeTools::PointToRefsMap>& theObjectToPoints)
735 GeomShapePtr aBaseShape;
737 AttributeReferencePtr anObjectAttr = theFeature->reference(theObjectAttributeId);
738 ObjectPtr aBaseObject = anObjectAttr->value();
739 if (!aBaseObject.get())
743 AttributePoint2DPtr aPointAttr =
744 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theFeature->attribute(thePointAttributeId));
745 std::shared_ptr<GeomAPI_Pnt2d> anAttributePnt2d = aPointAttr->pnt();
746 std::shared_ptr<GeomAPI_Pnt> anAttributePnt =
747 theFeature->sketch()->to3D(anAttributePnt2d->x(), anAttributePnt2d->y());
749 if (theCashedShapes.find(aBaseObject) == theCashedShapes.end())
750 fillObjectShapes(theFeature, aBaseObject, theCashedShapes, theObjectToPoints);
752 std::shared_ptr<GeomAPI_Pnt> aStartPoint;
753 std::shared_ptr<GeomAPI_Pnt> aSecondPoint;
754 const std::set<GeomShapePtr>& aShapes = theCashedShapes[aBaseObject];
755 std::set<GeomShapePtr>::const_iterator anIt = aShapes.begin(), aLast = aShapes.end();
756 for (; anIt != aLast; anIt++) {
757 GeomShapePtr aCurrentShape = *anIt;
758 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
759 if (ModelGeomAlgo_Point2D::isPointOnEdge(aCurrentShape, anAttributePnt, aProjectedPoint)) {
760 if (theFeature->getKind() == SketchPlugin_Split::ID()) {
761 // for Split operation collect start and end points of the shape
762 if (aCurrentShape->shapeType() == GeomAPI_Shape::EDGE) {
763 std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aCurrentShape));
764 aStartPoint = anEdge->firstPoint();
765 aSecondPoint = anEdge->lastPoint();
769 aBaseShape = aCurrentShape;
774 if (!aStartPoint.get() || !aSecondPoint.get())
777 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObject);
778 if (anObjectAttr->isInitialized() && aBaseFeature.get() && aPointAttr->isInitialized()) {
779 ResultPtr aResult = aBaseFeature->lastResult();
780 GeomShapePtr aResultShape = aResult->shape();
781 std::list<std::shared_ptr<GeomAPI_Pnt> > aPoints;
783 aPoints.push_back(aStartPoint);
784 aPoints.push_back(aSecondPoint);
786 std::set<std::shared_ptr<GeomAPI_Shape> > aSplitShapes;
787 GeomAlgoAPI_ShapeTools::splitShape_p(aResultShape, aPoints, aSplitShapes);
788 aBaseShape = GeomAlgoAPI_ShapeTools::findShape(aPoints, aSplitShapes);
793 void SketchPlugin_SegmentationTools::fillObjectShapes(
794 SketchPlugin_Feature* theOpFeature,
795 const ObjectPtr& theObject,
796 std::map<ObjectPtr, std::set<GeomShapePtr> >& theCashedShapes,
797 std::map<ObjectPtr, GeomAlgoAPI_ShapeTools::PointToRefsMap>& theObjectToPoints)
799 SketchPlugin_Sketch* aSketch = theOpFeature->sketch();
801 GeomAlgoAPI_ShapeTools::PointToRefsMap aPoints;
802 std::set<GeomShapePtr> aShapes;
804 std::set<AttributePoint2DPtr > aRefAttributes;
806 FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
807 std::set<ResultPtr> anEdgeShapes;
809 ModelGeomAlgo_Shape::shapesOfType(aFeature, GeomAPI_Shape::EDGE, anEdgeShapes);
810 if (!anEdgeShapes.empty()) {
811 GeomShapePtr aFeatureShape = (*anEdgeShapes.begin())->shape();
813 // coincidences to the feature
814 ModelGeomAlgo_Point2D::getPointsOfReference(aFeature, SketchPlugin_ConstraintCoincidence::ID(),
815 aRefAttributes, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID());
816 // layed on feature coincidences to divide it on several shapes
817 std::shared_ptr<ModelAPI_Data> aData = aSketch->data();
818 std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
819 aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
820 std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
821 aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
822 std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
823 aData->attribute(SketchPlugin_Sketch::NORM_ID()));
824 std::shared_ptr<GeomAPI_Dir> aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
826 ModelGeomAlgo_Point2D::getPointsInsideShape(aFeatureShape, aRefAttributes, aC->pnt(),
827 aX->dir(), aY, aPoints);
829 if (theOpFeature->getKind() == SketchPlugin_Trim::ID()) {
830 // collect all intersection points with other edges for Trim operation only
831 std::list<FeaturePtr> aFeatures;
832 for (int i = 0; i < aSketch->numberOfSubs(); i++) {
833 FeaturePtr aFeature = aSketch->subFeature(i);
834 if (aFeature.get() && aFeature->getKind() != SketchPlugin_Projection::ID())
835 aFeatures.push_back(aFeature);
837 ModelGeomAlgo_Point2D::getPointsIntersectedShape(aFeature, aFeatures, aPoints);
840 if (!aPoints.empty())
841 GeomAlgoAPI_ShapeTools::splitShape(aFeatureShape, aPoints, aShapes);
843 theObjectToPoints[theObject] = aPoints;
844 theCashedShapes[theObject] = aShapes;
847 void SketchPlugin_SegmentationTools::updateRefAttConstraints(
848 const std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
849 const std::set<std::pair<AttributePtr, AttributePtr> >& theModifiedAttributes)
851 #if defined DEBUG_SPLIT || defined DEBUG_TRIM
852 std::cout << "updateRefAttConstraints" << std::endl;
855 std::set<std::pair<AttributePtr, AttributePtr> >::const_iterator
856 anIt = theModifiedAttributes.begin(), aLast = theModifiedAttributes.end();
857 for (; anIt != aLast; anIt++) {
858 AttributePtr anAttribute = anIt->first;
859 AttributePtr aNewAttribute = anIt->second;
861 // not found in references
862 if (!aNewAttribute.get() ||
863 theBaseRefAttributes.find(anAttribute) == theBaseRefAttributes.end())
865 std::list<AttributePtr> aRefAttributes = theBaseRefAttributes.at(anAttribute);
866 std::list<AttributePtr>::const_iterator aRefIt = aRefAttributes.begin(),
867 aRLast = aRefAttributes.end();
869 for (; aRefIt != aRLast; aRefIt++) {
870 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefIt);
871 if (aRefAttr.get()) {
872 aRefAttr->setAttr(aNewAttribute);
874 FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->owner());
875 std::cout << " -" << getFeatureInfo(aFeature) << std::endl;
882 void SketchPlugin_SegmentationTools::updateFeaturesAfterOperation(
883 const std::set<FeaturePtr>& theFeaturesToUpdate)
885 std::set<FeaturePtr>::const_iterator anIt = theFeaturesToUpdate.begin(),
886 aLast = theFeaturesToUpdate.end();
887 for (; anIt != aLast; anIt++) {
888 FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*anIt);
889 std::string aRefFeatureKind = aRefFeature->getKind();
890 if (aRefFeatureKind == SketchPlugin_ConstraintLength::ID()) {
891 std::shared_ptr<SketchPlugin_ConstraintLength> aLenghtFeature =
892 std::dynamic_pointer_cast<SketchPlugin_ConstraintLength>(*anIt);
893 if (aLenghtFeature.get()) {
894 std::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = std::dynamic_pointer_cast<
895 ModelAPI_AttributeDouble>(aLenghtFeature->attribute(SketchPlugin_Constraint::VALUE()));
897 if (aLenghtFeature->computeLenghtValue(aValue) && aValueAttr.get())
898 aValueAttr->setValue(aValue);
904 AISObjectPtr SketchPlugin_SegmentationTools::getAISObject(
905 AISObjectPtr thePrevious,
906 SketchPlugin_Feature* theOpFeature,
907 const std::string& thePreviewObjectAttrName,
908 const std::string& thePreviewPointAttrName,
909 const std::string& theSelectedObjectAttrName,
910 const std::string& theSelectedPointAttrName)
912 #if defined DEBUG_SPLIT || defined DEBUG_TRIM_METHODS
913 std::cout << "getAISObject: " << theOpFeature->data()->name() << std::endl;
916 AISObjectPtr anAIS = thePrevious;
918 std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
919 std::map<ObjectPtr, std::set<GeomShapePtr> > aCashedShapes;
920 std::map<ObjectPtr, GeomAlgoAPI_ShapeTools::PointToRefsMap> aObjectToPoints;
921 GeomShapePtr aPreviewShape = getSubShape(theOpFeature,
922 thePreviewObjectAttrName, thePreviewPointAttrName, aCashedShapes, aObjectToPoints);
923 if (aPreviewShape.get())
924 aShapes.push_back(aPreviewShape);
925 GeomShapePtr aSelectedShape = getSubShape(theOpFeature,
926 theSelectedObjectAttrName, theSelectedPointAttrName, aCashedShapes, aObjectToPoints);
927 if (aSelectedShape.get())
928 aShapes.push_back(aSelectedShape);
931 return AISObjectPtr();
933 GeomShapePtr aBaseShape = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
934 if (!aBaseShape.get())
935 return AISObjectPtr();
937 if (aBaseShape.get()) {
939 anAIS = AISObjectPtr(new GeomAPI_AISObject);
940 anAIS->createShape(aBaseShape);
942 std::vector<int> aColor;
943 aColor = Config_PropManager::color("Visualization", "operation_remove_feature_color");
944 double aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH();
945 int aLineStyle = SketchPlugin_SketchEntity::SKETCH_LINE_STYLE();
946 anAIS->setColor(aColor[0], aColor[1], aColor[2]);
947 // width when there is not base object should be extened in several points
948 // in order to see this preview over highlight
949 anAIS->setWidth(aWidth+4);
950 anAIS->setLineStyle(aLineStyle);
953 anAIS = AISObjectPtr();
957 #define GEOM_DATA_POINT2D(f, a) std::dynamic_pointer_cast<GeomDataAPI_Point2D>((f)->attribute(a))
959 FeaturePtr SketchPlugin_SegmentationTools::createLineFeature(
960 const FeaturePtr& theBaseFeature,
961 const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
962 const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint)
965 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
966 std::dynamic_pointer_cast<SketchPlugin_Feature>(theBaseFeature);
967 SketchPlugin_Sketch* aSketch = aSketchFeature->sketch();
968 if (!aSketch || !theBaseFeature.get())
971 aFeature = aSketch->addFeature(SketchPlugin_Line::ID());
973 GEOM_DATA_POINT2D(aFeature, SketchPlugin_Line::START_ID())->setValue(theFirstPoint);
974 GEOM_DATA_POINT2D(aFeature, SketchPlugin_Line::END_ID())->setValue(theSecondPoint);
976 aFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(
977 theBaseFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value());
978 aFeature->execute(); // to obtain result
986 std::string myCenter;
990 std::string myReversed;
994 ArcAttributes(const std::string& theKind) : myKind(theKind)
996 if (myKind == SketchPlugin_Arc::ID()) {
997 myCenter = SketchPlugin_Arc::CENTER_ID();
998 myStart = SketchPlugin_Arc::START_ID();
999 myEnd = SketchPlugin_Arc::END_ID();
1000 myReversed = SketchPlugin_Arc::REVERSED_ID();
1002 else if (myKind == SketchPlugin_Circle::ID()) {
1003 myCenter = SketchPlugin_Circle::CENTER_ID();
1005 else if (myKind == SketchPlugin_Ellipse::ID()) {
1006 myCenter = SketchPlugin_Ellipse::CENTER_ID();
1007 myFocus = SketchPlugin_Ellipse::FIRST_FOCUS_ID();
1009 else if (myKind == SketchPlugin_EllipticArc::ID()) {
1010 myCenter = SketchPlugin_EllipticArc::CENTER_ID();
1011 myFocus = SketchPlugin_EllipticArc::FIRST_FOCUS_ID();
1012 myStart = SketchPlugin_EllipticArc::START_POINT_ID();
1013 myEnd = SketchPlugin_EllipticArc::END_POINT_ID();
1014 myReversed = SketchPlugin_EllipticArc::REVERSED_ID();
1019 FeaturePtr SketchPlugin_SegmentationTools::createArcFeature(
1020 const FeaturePtr& theBaseFeature,
1021 const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
1022 const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint)
1024 FeaturePtr aFeature;
1025 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
1026 std::dynamic_pointer_cast<SketchPlugin_Feature>(theBaseFeature);
1027 SketchPlugin_Sketch* aSketch = aSketchFeature->sketch();
1028 if (!aSketch || !theBaseFeature.get())
1031 ArcAttributes aBaseAttrs(theBaseFeature->getKind());
1032 ArcAttributes aTargetAttrs;
1033 if (aBaseAttrs.myKind == SketchPlugin_Arc::ID() ||
1034 aBaseAttrs.myKind == SketchPlugin_Circle::ID())
1035 aTargetAttrs = ArcAttributes(SketchPlugin_Arc::ID());
1036 else if (aBaseAttrs.myKind == SketchPlugin_Ellipse::ID() ||
1037 aBaseAttrs.myKind == SketchPlugin_EllipticArc::ID())
1038 aTargetAttrs = ArcAttributes(SketchPlugin_EllipticArc::ID());
1040 if (aTargetAttrs.myKind.empty())
1043 aFeature = aSketch->addFeature(aTargetAttrs.myKind);
1044 // update fillet arc: make the arc correct for sure, so, it is not needed to process
1045 // the "attribute updated"
1046 // by arc; moreover, it may cause cyclicity in hte mechanism of updater
1047 bool aWasBlocked = aFeature->data()->blockSendAttributeUpdated(true);
1049 GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myCenter)->setValue(
1050 GEOM_DATA_POINT2D(theBaseFeature, aBaseAttrs.myCenter)->pnt());
1051 if (!aTargetAttrs.myFocus.empty()) {
1052 GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myFocus)->setValue(
1053 GEOM_DATA_POINT2D(theBaseFeature, aBaseAttrs.myFocus)->pnt());
1055 GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myStart)->setValue(theFirstPoint);
1056 GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myEnd)->setValue(theSecondPoint);
1058 aFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(
1059 theBaseFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value());
1061 /// fill referersed state of created arc as it is on the base arc
1062 bool aReversed = aBaseAttrs.myReversed.empty() ? false :
1063 theBaseFeature->boolean(aBaseAttrs.myReversed)->value();
1064 aFeature->boolean(aTargetAttrs.myReversed)->setValue(aReversed);
1066 aFeature->execute(); // to obtain result (need to calculate arc parameters before sending Update)
1067 aFeature->data()->blockSendAttributeUpdated(aWasBlocked);