1 // Copyright (C) 2014-2023 CEA, EDF
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 <Locale_Convert.h>
42 #include <ModelAPI_AttributeDouble.h>
43 #include <ModelAPI_AttributeInteger.h>
44 #include <ModelAPI_Tools.h>
46 #include <ModelGeomAlgo_Point2D.h>
47 #include <ModelGeomAlgo_Shape.h>
49 #include <GeomAPI_Dir2d.h>
50 #include <GeomAPI_Edge.h>
51 #include <GeomAPI_Pnt2d.h>
52 #include <GeomAPI_XY.h>
54 #include <GeomAlgoAPI_CompoundBuilder.h>
55 #include <GeomAlgoAPI_ShapeTools.h>
57 #include <GeomDataAPI_Point.h>
58 #include <GeomDataAPI_Point2D.h>
64 namespace SketchPlugin_Tools {
66 void clearExpressions(AttributeDoublePtr theAttribute)
68 theAttribute->setText(std::wstring());
71 void clearExpressions(AttributePointPtr theAttribute)
73 theAttribute->setText(std::wstring(), std::wstring(), std::wstring());
76 void clearExpressions(AttributePoint2DPtr theAttribute)
78 theAttribute->setText(std::wstring(), std::wstring());
81 void clearExpressions(AttributePtr theAttribute)
84 AttributeDoublePtr anAttributeDouble =
85 std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
86 if (anAttributeDouble.get())
87 clearExpressions(anAttributeDouble);
89 AttributePointPtr anAttributePoint =
90 std::dynamic_pointer_cast<GeomDataAPI_Point>(theAttribute);
91 if (anAttributePoint.get())
92 clearExpressions(anAttributePoint);
94 AttributePoint2DPtr anAttributePoint2D =
95 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
96 if (anAttributePoint2D.get())
97 clearExpressions(anAttributePoint2D);
100 void clearExpressions(FeaturePtr theFeature)
102 if (!theFeature.get())
105 std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
106 std::list<AttributePtr>::iterator anAttributeIt = anAttributes.begin();
107 for (; anAttributeIt != anAttributes.end(); ++anAttributeIt) {
108 clearExpressions(*anAttributeIt);
112 std::shared_ptr<GeomAPI_Pnt2d> getCoincidencePoint(const FeaturePtr theStartCoin)
114 std::shared_ptr<GeomAPI_Pnt2d> aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(),
115 SketchPlugin_Constraint::ENTITY_A());
116 if (aPnt.get() == NULL)
117 aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(), SketchPlugin_Constraint::ENTITY_B());
121 std::set<FeaturePtr> findCoincidentConstraints(const ObjectPtr& theObject)
123 std::set<FeaturePtr> aCoincident;
124 const std::set<AttributePtr>& aRefsList = theObject->data()->refsToMe();
125 std::set<AttributePtr>::const_iterator aIt;
126 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
127 FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aIt)->owner());
128 if (aConstrFeature && (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID() ||
129 aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidenceInternal::ID()))
130 aCoincident.insert(aConstrFeature);
135 void findCoincidences(const FeaturePtr theStartCoin,
136 const std::string& theAttr,
137 std::set<FeaturePtr>& theList,
138 const bool theIsAttrOnly)
140 AttributeRefAttrPtr aPnt = theStartCoin->refattr(theAttr);
144 FeaturePtr aObj = ModelAPI_Feature::feature(aPnt->object());
145 if(theList.find(aObj) == theList.end()) {
146 std::shared_ptr<GeomAPI_Pnt2d> aOrig = getCoincidencePoint(theStartCoin);
147 if(aOrig.get() == NULL) {
150 if(!theIsAttrOnly || !aPnt->isObject()) {
151 theList.insert(aObj);
153 std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(aObj);
154 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
155 for (; aCIt != aCoincidences.end(); ++aCIt) {
156 FeaturePtr aConstrFeature = *aCIt;
157 std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = getCoincidencePoint(aConstrFeature);
158 if(aPnt2d.get() && aOrig->isEqual(aPnt2d)) {
159 findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A(),
160 theList, theIsAttrOnly);
161 findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B(),
162 theList, theIsAttrOnly);
168 std::set<FeaturePtr> findFeaturesCoincidentToPoint(const AttributePoint2DPtr& thePoint)
170 std::set<FeaturePtr> aCoincidentFeatures;
172 FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
173 aCoincidentFeatures.insert(anOwner);
175 std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(anOwner);
176 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
177 for (; aCIt != aCoincidences.end(); ++aCIt) {
178 bool isPointUsedInCoincidence = false;
179 AttributeRefAttrPtr anOtherCoincidentAttr;
180 for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
181 AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
184 if (!aRefAttr->isObject() && aRefAttr->attr() == thePoint)
185 isPointUsedInCoincidence = true;
187 anOtherCoincidentAttr = aRefAttr;
190 if (isPointUsedInCoincidence) {
192 if (anOtherCoincidentAttr->isObject())
193 anObj = anOtherCoincidentAttr->object();
195 anObj = anOtherCoincidentAttr->attr()->owner();
196 aCoincidentFeatures.insert(ModelAPI_Feature::feature(anObj));
200 return aCoincidentFeatures;
203 // Container for point-point coincidences.
204 // Useful to find points coincident to a given point.
205 class CoincidentPoints
207 static const int THE_DEFAULT_INDEX = -1;
210 void addCoincidence(const AttributePtr& thePoint1, const int theIndex1,
211 const AttributePtr& thePoint2, const int theIndex2)
213 auto aFound1 = find(thePoint1, theIndex1);
214 auto aFound2 = find(thePoint2, theIndex2);
215 if (aFound1 == myCoincidentPoints.end()) {
216 if (aFound2 == myCoincidentPoints.end()) {
217 std::map<AttributePtr, std::set<int> > aNewSet;
218 aNewSet[thePoint1].insert(theIndex1);
220 aNewSet[thePoint2].insert(theIndex2);
221 myCoincidentPoints.push_back(aNewSet);
223 (*aFound2)[thePoint1].insert(theIndex1);
224 } else if (aFound2 == myCoincidentPoints.end()) {
226 (*aFound1)[thePoint2].insert(theIndex2);
228 for (auto it = aFound2->begin(); it != aFound2->end(); ++it)
229 (*aFound1)[it->first].insert(it->second.begin(), it->second.end());
230 myCoincidentPoints.erase(aFound2);
234 std::set<AttributePoint2DPtr> coincidentPoints(const AttributePoint2DPtr& thePoint)
236 collectCoincidentPoints(thePoint);
238 std::set<AttributePoint2DPtr> aCoincPoints;
239 auto aFound = find(thePoint, THE_DEFAULT_INDEX);
240 if (aFound != myCoincidentPoints.end()) {
241 for (auto it = aFound->begin(); it != aFound->end(); ++it) {
242 AttributePoint2DPtr aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(it->first);
244 aCoincPoints.insert(aPoint);
246 AttributePoint2DArrayPtr aPointArray =
247 std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(it->first);
249 // this is a B-spline feature, the connection is possible
250 // to the first or the last point
251 FeaturePtr anOwner = ModelAPI_Feature::feature(aPointArray->owner());
252 if (it->second.find(0) != it->second.end()) {
253 AttributePoint2DPtr aFirstPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
254 anOwner->attribute(SketchPlugin_BSpline::START_ID()));
255 aCoincPoints.insert(aFirstPoint);
257 if (it->second.find(aPointArray->size() - 1) != it->second.end()) {
258 AttributePoint2DPtr aFirstPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
259 anOwner->attribute(SketchPlugin_BSpline::END_ID()));
260 aCoincPoints.insert(aFirstPoint);
270 void coincidences(const FeaturePtr& theFeature,
271 std::set<FeaturePtr>& theCoincidences) const
273 // iterate through coincideces for the given feature
274 std::set<FeaturePtr> aCoincidences = SketchPlugin_Tools::findCoincidentConstraints(theFeature);
275 if (theFeature->getKind() == SketchPlugin_Point::ID()) {
276 std::set<FeaturePtr> aCoincToRes =
277 SketchPlugin_Tools::findCoincidentConstraints(theFeature->lastResult());
278 aCoincidences.insert(aCoincToRes.begin(), aCoincToRes.end());
280 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
281 for (; aCIt != aCoincidences.end(); ++aCIt)
283 if (theCoincidences.find(*aCIt) != theCoincidences.end())
284 continue; // already processed
285 theCoincidences.insert(*aCIt);
286 // iterate on coincident attributes
287 for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
288 AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
292 if (aRefAttr->isObject()) {
293 FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
294 if (aFeature->getKind() == SketchPlugin_Point::ID())
298 anOwner = ModelAPI_Feature::feature(aRefAttr->attr()->owner());
299 if (anOwner && anOwner != theFeature)
300 coincidences(anOwner, theCoincidences);
305 // Iteratively search points coincident to the given point
306 // (two points may be coincident through the third point)
307 void collectCoincidentPoints(const AttributePoint2DPtr& thePoint)
309 AttributePtr aPoints[2];
310 int anIndicesInArray[2];
312 FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
313 std::set<FeaturePtr> aCoincidences;
314 coincidences(anOwner, aCoincidences);
316 std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
317 for (; aCIt != aCoincidences.end(); ++aCIt) {
318 aPoints[0] = aPoints[1] = AttributePtr();
319 anIndicesInArray[0] = anIndicesInArray[1] = THE_DEFAULT_INDEX;
320 for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
321 AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
324 if (aRefAttr->isObject()) {
325 FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
326 if (aFeature && aFeature->getKind() == SketchPlugin_Point::ID())
327 aPoints[aPtInd++] = aFeature->attribute(SketchPlugin_Point::COORD_ID());
330 AttributePoint2DPtr aPointAttr =
331 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
332 AttributePoint2DArrayPtr aPointArray =
333 std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(aRefAttr->attr());
335 aPoints[aPtInd++] = aPointAttr;
336 else if (aPointArray) {
337 AttributeIntegerPtr anIndexAttr = (*aCIt)->integer(i == 0 ?
338 SketchPlugin_ConstraintCoincidenceInternal::INDEX_ENTITY_A() :
339 SketchPlugin_ConstraintCoincidenceInternal::INDEX_ENTITY_B());
340 aPoints[aPtInd] = aPointArray;
341 anIndicesInArray[aPtInd++] = anIndexAttr->value();
346 if (aPoints[0] && aPoints[1])
347 addCoincidence(aPoints[0], anIndicesInArray[0], aPoints[1], anIndicesInArray[1]);
351 std::list< std::map<AttributePtr, std::set<int> > >::iterator find(const AttributePtr& thePoint,
354 auto aSeek = myCoincidentPoints.begin();
355 for (; aSeek != myCoincidentPoints.end(); ++aSeek) {
356 auto aFound = aSeek->find(thePoint);
357 if (aFound != aSeek->end() && aFound->second.find(theIndex) != aFound->second.end())
360 // nothing is found, but if the point is a B-spline boundary point, lets check it as poles array
361 FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
362 if (anOwner->getKind() == SketchPlugin_BSpline::ID()) {
363 AttributePtr aPointsArray;
365 if (thePoint->id() == SketchPlugin_BSpline::START_ID()) {
366 aPointsArray = anOwner->attribute(SketchPlugin_BSpline::POLES_ID());
369 else if (thePoint->id() == SketchPlugin_BSpline::END_ID()) {
370 aPointsArray = anOwner->attribute(SketchPlugin_BSpline::POLES_ID());
371 anIndex = std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(aPointsArray)->size() - 1;
374 return find(aPointsArray, anIndex);
376 return myCoincidentPoints.end();
380 std::list< std::map<AttributePtr, std::set<int> > > myCoincidentPoints;
383 std::set<AttributePoint2DPtr> findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint)
385 CoincidentPoints aCoincidentPoints;
386 return aCoincidentPoints.coincidentPoints(thePoint);
390 void resetAttribute(SketchPlugin_Feature* theFeature,
391 const std::string& theId)
393 AttributePtr anAttr = theFeature->attribute(theId);
399 void createCoincidenceOrTangency(SketchPlugin_Feature* theFeature,
400 const std::string& theId,
401 const AttributePtr theAttr,
402 const ObjectPtr theObject,
403 const bool theIsCanBeTangent)
405 AttributeRefAttrPtr aRefAttr = theFeature->refattr(theId);
406 if(aRefAttr.get() && aRefAttr->isInitialized()) {
407 FeaturePtr aConstraint;
408 if(!theIsCanBeTangent) {
409 aConstraint = theFeature->sketch()
410 ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
412 if(aRefAttr->isObject()) {
413 ObjectPtr anObject = aRefAttr->object();
414 FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
415 if(aFeature->getKind() == SketchPlugin_Point::ID()) {
416 aConstraint = theFeature->sketch()
417 ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
419 aConstraint = theFeature->sketch()
420 ->addFeature(SketchPlugin_ConstraintTangent::ID());
423 aConstraint = theFeature->sketch()
424 ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
427 AttributeRefAttrPtr aRefAttrA = aConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
428 aRefAttr->isObject() ? aRefAttrA->setObject(aRefAttr->object())
429 : aRefAttrA->setAttr(aRefAttr->attr());
430 AttributeRefAttrPtr aRefAttrB = aConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
431 if(theObject.get()) {
432 aRefAttrB->setObject(theObject);
433 } else if(theAttr.get()) {
434 aRefAttrB->setAttr(theAttr);
439 void convertRefAttrToPointOrTangentCurve(const AttributeRefAttrPtr& theRefAttr,
440 const AttributePtr& theDefaultAttr,
441 std::shared_ptr<GeomAPI_Shape>& theTangentCurve,
442 std::shared_ptr<GeomAPI_Pnt2d>& thePassingPoint)
444 AttributePtr anAttr = theDefaultAttr;
445 if (theRefAttr->isObject()) {
446 FeaturePtr aTgFeature = ModelAPI_Feature::feature(theRefAttr->object());
448 if (aTgFeature->getKind() != SketchPlugin_Point::ID()) {
449 theTangentCurve = aTgFeature->lastResult()->shape();
452 anAttr = aTgFeature->attribute(SketchPlugin_Point::COORD_ID());
455 anAttr = theRefAttr->attr();
457 thePassingPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr)->pnt();
461 FeaturePtr createConstraintAttrAttr(SketchPlugin_Sketch* theSketch,
462 const std::string& theConstraintId,
463 const AttributePtr& theFirstAttribute,
464 const AttributePtr& theSecondAttribute)
466 FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
467 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
468 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
469 aRefAttr->setAttr(theFirstAttribute);
471 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
472 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
473 aRefAttr->setAttr(theSecondAttribute);
475 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
476 std::cout << "<createConstraint to attribute> :"
477 << " first attribute - " << theFirstAttribute->id()
478 << " second attribute - " << theSecondAttribute->id()
485 FeaturePtr createConstraintAttrObject(SketchPlugin_Sketch* theSketch,
486 const std::string& theConstraintId,
487 const AttributePtr& theFirstAttribute,
488 const ObjectPtr& theSecondObject)
490 FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
491 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
492 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
493 aRefAttr->setAttr(theFirstAttribute);
495 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
496 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
497 aRefAttr->setObject(theSecondObject);
499 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
500 std::cout << "<createConstraint to attribute> :"
501 << " first attribute - " << theFirstAttribute->id()
502 << " second object - " << ModelAPI_Feature::feature(theSecondObject)->getKind()
509 FeaturePtr createConstraintObjectObject(SketchPlugin_Sketch* theSketch,
510 const std::string& theConstraintId,
511 const ObjectPtr& theFirstObject,
512 const ObjectPtr& theSecondObject)
514 FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
515 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
516 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
517 aRefAttr->setObject(theFirstObject);
519 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
520 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
521 aRefAttr->setObject(theSecondObject);
523 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
524 std::cout << "<createConstraint to attribute> :"
525 << " first object - " << ModelAPI_Feature::feature(theFirstObject)->getKind()
526 << " second object - " << ModelAPI_Feature::feature(theSecondObject)->getKind()
533 void createAuxiliaryPointOnEllipse(const FeaturePtr& theEllipseFeature,
534 const std::string& theEllipsePoint)
536 SketchPlugin_Sketch* aSketch =
537 std::dynamic_pointer_cast<SketchPlugin_Feature>(theEllipseFeature)->sketch();
539 FeaturePtr aPointFeature = aSketch->addFeature(SketchPlugin_Point::ID());
540 aPointFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
541 aPointFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipseFeature);
543 AttributePoint2DPtr anElPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
544 theEllipseFeature->attribute(theEllipsePoint));
546 AttributePoint2DPtr aCoord = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
547 aPointFeature->attribute(SketchPlugin_Point::COORD_ID()));
548 aCoord->setValue(anElPoint->x(), anElPoint->y());
550 aPointFeature->execute();
551 std::wstring aName = theEllipseFeature->name() + L"_" +
552 Locale::Convert::toWString(theEllipsePoint);
553 aPointFeature->data()->setName(aName);
554 aPointFeature->lastResult()->data()->setName(aName);
556 createConstraintAttrAttr(aSketch,
557 SketchPlugin_ConstraintCoincidenceInternal::ID(), anElPoint, aCoord);
560 void createAuxiliaryAxisOfEllipse(const FeaturePtr& theEllipseFeature,
561 const std::string& theStartPoint,
562 const std::string& theEndPoint)
564 SketchPlugin_Sketch* aSketch =
565 std::dynamic_pointer_cast<SketchPlugin_Feature>(theEllipseFeature)->sketch();
567 FeaturePtr aLineFeature = aSketch->addFeature(SketchPlugin_Line::ID());
568 aLineFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
569 aLineFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipseFeature);
571 AttributePoint2DPtr aStartPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
572 theEllipseFeature->attribute(theStartPoint));
573 AttributePoint2DPtr aEndPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
574 theEllipseFeature->attribute(theEndPoint));
576 AttributePoint2DPtr aLineStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
577 aLineFeature->attribute(SketchPlugin_Line::START_ID()));
578 aLineStart->setValue(aStartPoint->x(), aStartPoint->y());
580 AttributePoint2DPtr aLineEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
581 aLineFeature->attribute(SketchPlugin_Line::END_ID()));
582 aLineEnd->setValue(aEndPoint->x(), aEndPoint->y());
584 aLineFeature->execute();
585 std::wstring aName = theEllipseFeature->name() + L"_" +
586 (theStartPoint == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() ? L"major_axis" : L"minor_axis");
587 aLineFeature->data()->setName(aName);
588 aLineFeature->lastResult()->data()->setName(aName);
590 createConstraintAttrAttr(aSketch,
591 SketchPlugin_ConstraintCoincidenceInternal::ID(), aStartPoint, aLineStart);
592 createConstraintAttrAttr(aSketch,
593 SketchPlugin_ConstraintCoincidenceInternal::ID(), aEndPoint, aLineEnd);
596 GeomPnt2dPtr flyoutPointCoordinates(const ConstraintPtr& theConstraint)
598 // currently process Length constraints only
599 if (theConstraint->getKind() != SketchPlugin_ConstraintLength::ID())
600 return GeomPnt2dPtr();
602 AttributeRefAttrPtr aLineAttr = theConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
603 if (!aLineAttr || !aLineAttr->isObject())
604 return GeomPnt2dPtr();
605 FeaturePtr aLine = ModelAPI_Feature::feature(aLineAttr->object());
606 if (!aLine || aLine->getKind() != SketchPlugin_Line::ID())
607 return GeomPnt2dPtr();
609 std::shared_ptr<GeomAPI_XY> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
610 aLine->attribute(SketchPlugin_Line::START_ID()))->pnt()->xy();
611 std::shared_ptr<GeomAPI_XY> aEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
612 aLine->attribute(SketchPlugin_Line::END_ID()))->pnt()->xy();
614 std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr =
615 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
616 theConstraint->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
617 std::shared_ptr<GeomAPI_Pnt2d> aFltPnt = aFlyoutAttr->pnt();
619 std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
621 double X = aStartPnt->x() + aFltPnt->x() * aLineDir->x() - aFltPnt->y() * aLineDir->y();
622 double Y = aStartPnt->y() + aFltPnt->x() * aLineDir->y() + aFltPnt->y() * aLineDir->x();
624 return GeomPnt2dPtr(new GeomAPI_Pnt2d(X, Y));
628 void customizeFeaturePrs(const AISObjectPtr& thePrs, bool isAxiliary)
630 std::vector<int> aColor;
633 thePrs->setLineStyle(SketchPlugin_SketchEntity::SKETCH_LINE_STYLE_AUXILIARY());
634 aColor = Config_PropManager::color("Visualization", "sketch_auxiliary_color");
635 aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH_AUXILIARY();
638 thePrs->setLineStyle(SketchPlugin_SketchEntity::SKETCH_LINE_STYLE());
639 aColor = Config_PropManager::color("Visualization", "sketch_entity_color");
640 aWidth = Config_PropManager::integer("Visualization", "sketch_line_width");
642 thePrs->setWidth(aWidth);
643 thePrs->setColor(aColor[0], aColor[1], aColor[2]);
646 void setDimensionColor(const AISObjectPtr& theDimPrs)
648 std::vector<int> aColor = Config_PropManager::color("Visualization", "sketch_dimension_color");
649 if (aColor.size() == 3)
650 theDimPrs->setColor(aColor[0], aColor[1], aColor[2]);
653 void replaceInName(ObjectPtr theObject, const std::wstring& theSource, const std::wstring& theDest)
655 std::wstring aName = theObject->data()->name();
656 size_t aPos = aName.find(theSource);
657 if (aPos != std::wstring::npos) {
658 std::wstring aNewName = aName.substr(0, aPos) + theDest
659 + aName.substr(aPos + theSource.size());
660 theObject->data()->setName(aNewName);
664 } // namespace SketchPlugin_Tools
667 // =================================================================================================
668 // namespace SketchPlugin_SegmentationTools
669 // =================================================================================================
671 void SketchPlugin_SegmentationTools::getFeaturePoints(const FeaturePtr& theFeature,
672 AttributePoint2DPtr& theStartPointAttr,
673 AttributePoint2DPtr& theEndPointAttr)
675 std::string aFeatureKind = theFeature->getKind();
676 std::string aStartAttributeName, anEndAttributeName;
677 if (aFeatureKind == SketchPlugin_Line::ID()) {
678 aStartAttributeName = SketchPlugin_Line::START_ID();
679 anEndAttributeName = SketchPlugin_Line::END_ID();
681 else if (aFeatureKind == SketchPlugin_Arc::ID()) {
682 aStartAttributeName = SketchPlugin_Arc::START_ID();
683 anEndAttributeName = SketchPlugin_Arc::END_ID();
685 else if (aFeatureKind == SketchPlugin_EllipticArc::ID()) {
686 aStartAttributeName = SketchPlugin_EllipticArc::START_POINT_ID();
687 anEndAttributeName = SketchPlugin_EllipticArc::END_POINT_ID();
689 else if (aFeatureKind == SketchPlugin_BSpline::ID()) {
690 aStartAttributeName = SketchPlugin_BSpline::START_ID();
691 anEndAttributeName = SketchPlugin_BSpline::END_ID();
693 if (!aStartAttributeName.empty() && !anEndAttributeName.empty()) {
694 theStartPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
695 theFeature->attribute(aStartAttributeName));
696 theEndPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
697 theFeature->attribute(anEndAttributeName));
702 void SketchPlugin_SegmentationTools::getRefAttributes(
703 const FeaturePtr& theFeature,
704 std::map<AttributePtr, std::list<AttributePtr> >& theRefs,
705 std::list<AttributePtr>& theRefsToFeature)
709 std::list<AttributePtr> aPointAttributes =
710 theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
711 std::set<AttributePtr> aPointAttributesSet;
713 std::list<AttributePtr>::const_iterator aPIt =
714 aPointAttributes.begin(), aPLast = aPointAttributes.end();
715 for (; aPIt != aPLast; aPIt++)
716 aPointAttributesSet.insert(*aPIt);
718 std::set<AttributePtr> aRefsAttributes = theFeature->lastResult()->data()->refsToMe();
719 std::set<AttributePtr> aFRefsList = theFeature->data()->refsToMe();
720 aRefsAttributes.insert(aFRefsList.begin(), aFRefsList.end());
722 std::set<AttributePtr>::const_iterator aIt;
723 for (aIt = aRefsAttributes.cbegin(); aIt != aRefsAttributes.cend(); ++aIt) {
724 AttributePtr anAttr = (*aIt);
725 FeaturePtr anAttrFeature = ModelAPI_Feature::feature(anAttr->owner());
726 if (!anAttrFeature->isMacro() && // <- skip reference from Trim or Split feature
727 anAttr.get() && anAttr->attributeType() == ModelAPI_AttributeRefAttr::typeId()) {
728 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
729 if (!aRefAttr->isObject()) { // find attributes referenced to feature point attributes
730 AttributePtr anAttrInRef = aRefAttr->attr();
731 if (anAttrInRef.get() &&
732 aPointAttributesSet.find(anAttrInRef) != aPointAttributesSet.end()) {
733 if (theRefs.find(anAttrInRef) != theRefs.end())
734 theRefs[anAttrInRef].push_back(aRefAttr);
736 std::list<AttributePtr> anAttrList;
737 anAttrList.push_back(aRefAttr);
738 theRefs[anAttrInRef] = anAttrList;
742 else { // find attributes referenced to feature itself
743 theRefsToFeature.push_back(anAttr);
749 GeomShapePtr SketchPlugin_SegmentationTools::getSubShape(
750 SketchPlugin_Feature* theFeature,
751 const std::string& theObjectAttributeId,
752 const std::string& thePointAttributeId,
753 std::map<ObjectPtr, std::set<GeomShapePtr> >& theCashedShapes,
754 std::map<ObjectPtr, GeomAlgoAPI_ShapeTools::PointToRefsMap>& theObjectToPoints)
756 GeomShapePtr aBaseShape;
758 AttributeReferencePtr anObjectAttr = theFeature->reference(theObjectAttributeId);
759 ObjectPtr aBaseObject = anObjectAttr->value();
760 if (!aBaseObject.get())
764 AttributePoint2DPtr aPointAttr =
765 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theFeature->attribute(thePointAttributeId));
766 std::shared_ptr<GeomAPI_Pnt2d> anAttributePnt2d = aPointAttr->pnt();
767 std::shared_ptr<GeomAPI_Pnt> anAttributePnt =
768 theFeature->sketch()->to3D(anAttributePnt2d->x(), anAttributePnt2d->y());
770 if (theCashedShapes.find(aBaseObject) == theCashedShapes.end())
771 fillObjectShapes(theFeature, aBaseObject, theCashedShapes, theObjectToPoints);
773 std::shared_ptr<GeomAPI_Pnt> aStartPoint;
774 std::shared_ptr<GeomAPI_Pnt> aSecondPoint;
775 const std::set<GeomShapePtr>& aShapes = theCashedShapes[aBaseObject];
776 std::set<GeomShapePtr>::const_iterator anIt = aShapes.begin(), aLast = aShapes.end();
777 for (; anIt != aLast; anIt++) {
778 GeomShapePtr aCurrentShape = *anIt;
779 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
780 if (ModelGeomAlgo_Point2D::isPointOnEdge(aCurrentShape, anAttributePnt, aProjectedPoint)) {
781 if (theFeature->getKind() == SketchPlugin_Split::ID()) {
782 // for Split operation collect start and end points of the shape
783 if (aCurrentShape->shapeType() == GeomAPI_Shape::EDGE) {
784 std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aCurrentShape));
785 aStartPoint = anEdge->firstPoint();
786 aSecondPoint = anEdge->lastPoint();
790 aBaseShape = aCurrentShape;
795 if (!aStartPoint.get() || !aSecondPoint.get())
798 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObject);
799 if (anObjectAttr->isInitialized() && aBaseFeature.get() && aPointAttr->isInitialized()) {
800 ResultPtr aResult = aBaseFeature->lastResult();
801 GeomShapePtr aResultShape = aResult->shape();
802 std::list<std::shared_ptr<GeomAPI_Pnt> > aPoints;
804 aPoints.push_back(aStartPoint);
805 aPoints.push_back(aSecondPoint);
807 std::set<std::shared_ptr<GeomAPI_Shape> > aSplitShapes;
808 GeomAlgoAPI_ShapeTools::splitShape_p(aResultShape, aPoints, aSplitShapes);
809 aBaseShape = GeomAlgoAPI_ShapeTools::findShape(aPoints, aSplitShapes);
814 void SketchPlugin_SegmentationTools::fillObjectShapes(
815 SketchPlugin_Feature* theOpFeature,
816 const ObjectPtr& theObject,
817 std::map<ObjectPtr, std::set<GeomShapePtr> >& theCashedShapes,
818 std::map<ObjectPtr, GeomAlgoAPI_ShapeTools::PointToRefsMap>& theObjectToPoints)
820 SketchPlugin_Sketch* aSketch = theOpFeature->sketch();
822 GeomAlgoAPI_ShapeTools::PointToRefsMap aPoints;
823 std::set<GeomShapePtr> aShapes;
825 std::set<AttributePoint2DPtr > aRefAttributes;
827 FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
828 std::set<ResultPtr> anEdgeShapes;
830 ModelGeomAlgo_Shape::shapesOfType(aFeature, GeomAPI_Shape::EDGE, anEdgeShapes);
831 if (!anEdgeShapes.empty()) {
832 GeomShapePtr aFeatureShape = (*anEdgeShapes.begin())->shape();
834 // coincidences to the feature
835 ModelGeomAlgo_Point2D::getPointsOfReference(aFeature, SketchPlugin_ConstraintCoincidence::ID(),
836 aRefAttributes, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID());
837 // layed on feature coincidences to divide it on several shapes
838 std::shared_ptr<ModelAPI_Data> aData = aSketch->data();
839 std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
840 aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
841 std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
842 aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
843 std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
844 aData->attribute(SketchPlugin_Sketch::NORM_ID()));
845 std::shared_ptr<GeomAPI_Dir> aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
847 ModelGeomAlgo_Point2D::getPointsInsideShape(aFeatureShape, aRefAttributes, aC->pnt(),
848 aX->dir(), aY, aPoints);
850 if (theOpFeature->getKind() == SketchPlugin_Trim::ID()) {
851 // collect all intersection points with other edges for Trim operation only
852 std::list<FeaturePtr> aFeatures;
853 for (int i = 0; i < aSketch->numberOfSubs(); i++) {
854 FeaturePtr aSubFeature = aSketch->subFeature(i);
855 if (aSubFeature.get() && aSubFeature->getKind() != SketchPlugin_Projection::ID())
856 aFeatures.push_back(aSubFeature);
858 ModelGeomAlgo_Point2D::getPointsIntersectedShape(aFeature, aFeatures, aPoints);
861 if (!aPoints.empty())
862 GeomAlgoAPI_ShapeTools::splitShape(aFeatureShape, aPoints, aShapes);
864 theObjectToPoints[theObject] = aPoints;
865 theCashedShapes[theObject] = aShapes;
868 void SketchPlugin_SegmentationTools::updateRefAttConstraints(
869 const std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
870 const std::set<std::pair<AttributePtr, AttributePtr> >& theModifiedAttributes)
872 #if defined DEBUG_SPLIT || defined DEBUG_TRIM
873 std::cout << "updateRefAttConstraints" << std::endl;
876 std::set<std::pair<AttributePtr, AttributePtr> >::const_iterator
877 anIt = theModifiedAttributes.begin(), aLast = theModifiedAttributes.end();
878 for (; anIt != aLast; anIt++) {
879 AttributePtr anAttribute = anIt->first;
880 AttributePtr aNewAttribute = anIt->second;
882 // not found in references
883 if (!aNewAttribute.get() ||
884 theBaseRefAttributes.find(anAttribute) == theBaseRefAttributes.end())
886 std::list<AttributePtr> aRefAttributes = theBaseRefAttributes.at(anAttribute);
887 std::list<AttributePtr>::const_iterator aRefIt = aRefAttributes.begin(),
888 aRLast = aRefAttributes.end();
890 for (; aRefIt != aRLast; aRefIt++) {
891 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefIt);
892 if (aRefAttr.get()) {
893 aRefAttr->setAttr(aNewAttribute);
895 FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->owner());
896 std::cout << " -" << getFeatureInfo(aFeature) << std::endl;
903 void SketchPlugin_SegmentationTools::updateFeaturesAfterOperation(
904 const std::set<FeaturePtr>& theFeaturesToUpdate)
906 std::set<FeaturePtr>::const_iterator anIt = theFeaturesToUpdate.begin(),
907 aLast = theFeaturesToUpdate.end();
908 for (; anIt != aLast; anIt++) {
909 FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*anIt);
910 std::string aRefFeatureKind = aRefFeature->getKind();
911 if (aRefFeatureKind == SketchPlugin_ConstraintLength::ID()) {
912 std::shared_ptr<SketchPlugin_ConstraintLength> aLenghtFeature =
913 std::dynamic_pointer_cast<SketchPlugin_ConstraintLength>(*anIt);
914 if (aLenghtFeature.get()) {
915 std::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = std::dynamic_pointer_cast<
916 ModelAPI_AttributeDouble>(aLenghtFeature->attribute(SketchPlugin_Constraint::VALUE()));
918 if (aLenghtFeature->computeLenghtValue(aValue) && aValueAttr.get())
919 aValueAttr->setValue(aValue);
925 AISObjectPtr SketchPlugin_SegmentationTools::getAISObject(
926 AISObjectPtr thePrevious,
927 SketchPlugin_Feature* theOpFeature,
928 const std::string& thePreviewObjectAttrName,
929 const std::string& thePreviewPointAttrName,
930 const std::string& theSelectedObjectAttrName,
931 const std::string& theSelectedPointAttrName)
933 #if defined DEBUG_SPLIT || defined DEBUG_TRIM_METHODS
934 std::cout << "getAISObject: " << theOpFeature->data()->name() << std::endl;
937 AISObjectPtr anAIS = thePrevious;
939 std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
940 std::map<ObjectPtr, std::set<GeomShapePtr> > aCashedShapes;
941 std::map<ObjectPtr, GeomAlgoAPI_ShapeTools::PointToRefsMap> aObjectToPoints;
942 GeomShapePtr aPreviewShape = getSubShape(theOpFeature,
943 thePreviewObjectAttrName, thePreviewPointAttrName, aCashedShapes, aObjectToPoints);
944 if (aPreviewShape.get())
945 aShapes.push_back(aPreviewShape);
946 GeomShapePtr aSelectedShape = getSubShape(theOpFeature,
947 theSelectedObjectAttrName, theSelectedPointAttrName, aCashedShapes, aObjectToPoints);
948 if (aSelectedShape.get())
949 aShapes.push_back(aSelectedShape);
952 return AISObjectPtr();
954 GeomShapePtr aBaseShape = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
955 if (!aBaseShape.get())
956 return AISObjectPtr();
958 if (aBaseShape.get()) {
960 anAIS = AISObjectPtr(new GeomAPI_AISObject);
961 anAIS->createShape(aBaseShape);
963 std::vector<int> aColor;
964 aColor = Config_PropManager::color("Visualization", "operation_remove_feature_color");
965 double aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH();
966 int aLineStyle = SketchPlugin_SketchEntity::SKETCH_LINE_STYLE();
967 anAIS->setColor(aColor[0], aColor[1], aColor[2]);
968 // width when there is not base object should be extened in several points
969 // in order to see this preview over highlight
970 anAIS->setWidth(aWidth+4);
971 anAIS->setLineStyle(aLineStyle);
974 anAIS = AISObjectPtr();
978 #define GEOM_DATA_POINT2D(f, a) std::dynamic_pointer_cast<GeomDataAPI_Point2D>((f)->attribute(a))
980 FeaturePtr SketchPlugin_SegmentationTools::createLineFeature(
981 const FeaturePtr& theBaseFeature,
982 const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
983 const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint)
986 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
987 std::dynamic_pointer_cast<SketchPlugin_Feature>(theBaseFeature);
988 SketchPlugin_Sketch* aSketch = aSketchFeature->sketch();
989 if (!aSketch || !theBaseFeature.get())
992 aFeature = aSketch->addFeature(SketchPlugin_Line::ID());
994 GEOM_DATA_POINT2D(aFeature, SketchPlugin_Line::START_ID())->setValue(theFirstPoint);
995 GEOM_DATA_POINT2D(aFeature, SketchPlugin_Line::END_ID())->setValue(theSecondPoint);
997 aFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(
998 theBaseFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value());
999 aFeature->execute(); // to obtain result
1004 struct ArcAttributes
1007 std::string myCenter;
1008 std::string myFocus;
1009 std::string myStart;
1011 std::string myReversed;
1015 ArcAttributes(const std::string& theKind) : myKind(theKind)
1017 if (myKind == SketchPlugin_Arc::ID()) {
1018 myCenter = SketchPlugin_Arc::CENTER_ID();
1019 myStart = SketchPlugin_Arc::START_ID();
1020 myEnd = SketchPlugin_Arc::END_ID();
1021 myReversed = SketchPlugin_Arc::REVERSED_ID();
1023 else if (myKind == SketchPlugin_Circle::ID()) {
1024 myCenter = SketchPlugin_Circle::CENTER_ID();
1026 else if (myKind == SketchPlugin_Ellipse::ID()) {
1027 myCenter = SketchPlugin_Ellipse::CENTER_ID();
1028 myFocus = SketchPlugin_Ellipse::FIRST_FOCUS_ID();
1030 else if (myKind == SketchPlugin_EllipticArc::ID()) {
1031 myCenter = SketchPlugin_EllipticArc::CENTER_ID();
1032 myFocus = SketchPlugin_EllipticArc::FIRST_FOCUS_ID();
1033 myStart = SketchPlugin_EllipticArc::START_POINT_ID();
1034 myEnd = SketchPlugin_EllipticArc::END_POINT_ID();
1035 myReversed = SketchPlugin_EllipticArc::REVERSED_ID();
1040 FeaturePtr SketchPlugin_SegmentationTools::createArcFeature(
1041 const FeaturePtr& theBaseFeature,
1042 const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
1043 const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint)
1045 FeaturePtr aFeature;
1046 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
1047 std::dynamic_pointer_cast<SketchPlugin_Feature>(theBaseFeature);
1048 SketchPlugin_Sketch* aSketch = aSketchFeature->sketch();
1049 if (!aSketch || !theBaseFeature.get())
1052 ArcAttributes aBaseAttrs(theBaseFeature->getKind());
1053 ArcAttributes aTargetAttrs;
1054 if (aBaseAttrs.myKind == SketchPlugin_Arc::ID() ||
1055 aBaseAttrs.myKind == SketchPlugin_Circle::ID())
1056 aTargetAttrs = ArcAttributes(SketchPlugin_Arc::ID());
1057 else if (aBaseAttrs.myKind == SketchPlugin_Ellipse::ID() ||
1058 aBaseAttrs.myKind == SketchPlugin_EllipticArc::ID())
1059 aTargetAttrs = ArcAttributes(SketchPlugin_EllipticArc::ID());
1061 if (aTargetAttrs.myKind.empty())
1064 aFeature = aSketch->addFeature(aTargetAttrs.myKind);
1065 // update fillet arc: make the arc correct for sure, so, it is not needed to process
1066 // the "attribute updated"
1067 // by arc; moreover, it may cause cyclicity in hte mechanism of updater
1068 bool aWasBlocked = aFeature->data()->blockSendAttributeUpdated(true);
1070 GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myCenter)->setValue(
1071 GEOM_DATA_POINT2D(theBaseFeature, aBaseAttrs.myCenter)->pnt());
1072 if (!aTargetAttrs.myFocus.empty()) {
1073 GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myFocus)->setValue(
1074 GEOM_DATA_POINT2D(theBaseFeature, aBaseAttrs.myFocus)->pnt());
1076 GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myStart)->setValue(theFirstPoint);
1077 GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myEnd)->setValue(theSecondPoint);
1079 aFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(
1080 theBaseFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value());
1082 /// fill referersed state of created arc as it is on the base arc
1083 bool aReversed = aBaseAttrs.myReversed.empty() ? false :
1084 theBaseFeature->boolean(aBaseAttrs.myReversed)->value();
1085 aFeature->boolean(aTargetAttrs.myReversed)->setValue(aReversed);
1087 aFeature->execute(); // to obtain result (need to calculate arc parameters before sending Update)
1088 aFeature->data()->blockSendAttributeUpdated(aWasBlocked);