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_Split.h"
22 #include <Events_Message.h>
24 #include <GeomAPI_Dir2d.h>
25 #include <GeomAPI_Edge.h>
26 #include <GeomAPI_Pnt2d.h>
27 #include <GeomAPI_XY.h>
28 #include <GeomDataAPI_Point2D.h>
29 #include <GeomAlgoAPI_ShapeTools.h>
31 #include <ModelAPI_AttributeBoolean.h>
32 #include <ModelAPI_AttributeDouble.h>
33 #include <ModelAPI_AttributeRefAttr.h>
34 #include <ModelAPI_AttributeReference.h>
35 #include <ModelAPI_AttributeString.h>
36 #include <ModelAPI_Events.h>
37 #include <ModelAPI_Validator.h>
38 #include <ModelAPI_Session.h>
39 #include <ModelAPI_Tools.h>
41 #include <ModelGeomAlgo_Shape.h>
43 #include <SketchPlugin_Arc.h>
44 #include <SketchPlugin_Circle.h>
45 #include <SketchPlugin_ConstraintCoincidence.h>
46 #include <SketchPlugin_ConstraintCoincidenceInternal.h>
47 #include <SketchPlugin_ConstraintEqual.h>
48 #include <SketchPlugin_ConstraintLength.h>
49 #include <SketchPlugin_ConstraintMiddle.h>
50 #include <SketchPlugin_ConstraintMirror.h>
51 #include <SketchPlugin_ConstraintParallel.h>
52 #include <SketchPlugin_ConstraintTangent.h>
53 #include <SketchPlugin_Ellipse.h>
54 #include <SketchPlugin_EllipticArc.h>
55 #include <SketchPlugin_Line.h>
56 #include <SketchPlugin_MultiRotation.h>
57 #include <SketchPlugin_MultiTranslation.h>
58 #include <SketchPlugin_Point.h>
60 #include <ModelGeomAlgo_Point2D.h>
61 #include <ModelAPI_EventReentrantMessage.h>
62 #include <Events_Loop.h>
66 //#define CREATE_CONSTRAINTS
72 static const double PI = 3.141592653589793238463;
74 SketchPlugin_Split::SketchPlugin_Split()
78 void SketchPlugin_Split::initAttributes()
80 data()->addAttribute(SELECTED_OBJECT(), ModelAPI_AttributeReference::typeId());
81 data()->addAttribute(SELECTED_POINT(), GeomDataAPI_Point2D::typeId());
83 data()->addAttribute(PREVIEW_POINT(), GeomDataAPI_Point2D::typeId());
84 data()->addAttribute(PREVIEW_OBJECT(), ModelAPI_AttributeReference::typeId());
86 data()->attribute(PREVIEW_POINT())->setIsArgument(false);
87 data()->attribute(SELECTED_POINT())->setIsArgument(false);
88 data()->attribute(PREVIEW_OBJECT())->setIsArgument(false);
90 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PREVIEW_POINT());
91 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PREVIEW_OBJECT());
94 void SketchPlugin_Split::execute()
96 std::shared_ptr<ModelAPI_Data> aData = data();
98 // Check the base objects are initialized.
99 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
100 data()->attribute(SELECTED_OBJECT()));
101 if(!aBaseObjectAttr->isInitialized()) {
102 setError("Error: Base object is not initialized.");
105 ObjectPtr aBaseObject = aBaseObjectAttr->value();
106 AttributePoint2DPtr aFirstPointAttrOfSplit = getPointAttribute(true);
107 AttributePoint2DPtr aSecondPointAttrOfSplit = getPointAttribute(false);
108 if (!aFirstPointAttrOfSplit.get() || !aFirstPointAttrOfSplit->isInitialized() ||
109 !aSecondPointAttrOfSplit.get() || !aSecondPointAttrOfSplit->isInitialized()) {
110 setError("Error: Sub-shape is not initialized.");
114 // Remove reference of this feature to feature used in preview, it is not necessary anymore
115 // as trim will be removed after execute
116 AttributeReferencePtr aPreviewObjectAttr =
117 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
118 data()->attribute(PREVIEW_OBJECT()));
120 ObjectPtr aPreviewObject = aPreviewObjectAttr->value();
121 AttributePoint2DPtr aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
122 data()->attribute(PREVIEW_POINT()));
123 std::shared_ptr<GeomAPI_Pnt2d> aPreviewPnt2d = aPoint->pnt();
124 // nullify pointer of preview attribute
125 aPreviewObjectAttr->setValue(ResultPtr());
126 bool anIsEqualPreviewAndSelected = aPreviewObject == aBaseObject;
128 // Wait all constraints being created, then send update events
129 static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
130 bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
132 Events_Loop::loop()->setFlushed(anUpdateEvent, false);
134 // Find feature constraints
135 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObject);
136 ResultPtr aBaseFeatureResult = aBaseFeature->lastResult();
137 std::set<FeaturePtr> aFeaturesToDelete, aFeaturesToUpdate;
139 //std::map<FeaturePtr, IdToPointPair> aTangentFeatures;
140 std::map<FeaturePtr, IdToPointPair> aCoincidenceToFeature;
141 getConstraints(aFeaturesToDelete, aFeaturesToUpdate, aCoincidenceToFeature);
143 std::map<AttributePtr, std::list<AttributePtr> > aBaseRefAttributes;
144 std::list<AttributePtr> aRefsToFeature;
145 SketchPlugin_SegmentationTools::getRefAttributes(
146 aBaseFeature, aBaseRefAttributes, aRefsToFeature);
148 std::map<AttributePtr, AttributePtr> aBasePointModifiedAttributes;
151 std::cout << std::endl;
152 std::cout << "SketchPlugin_Split::execute()" << std::endl;
153 std::cout << std::endl;
155 SketchPlugin_Sketch* aSketch = sketch();
156 std::cout << "SKETCH FEATURES (before split) [" << aSketch->numberOfSubs() << "]:" << std::endl;
157 for (int i = 0, aNbSubs = aSketch->numberOfSubs(); i < aNbSubs; i++) {
158 std::cout << getFeatureInfo(aSketch->subFeature(i), false) << std::endl;
161 std::cout << std::endl;
162 std::cout << "---- IN PARAMETERS ----" << std::endl;
163 std::cout << "Base feature:" << getFeatureInfo(aBaseFeature) << std::endl;
164 std::cout << std::endl;
166 if (!aCoincidenceToFeature.empty()) {
167 std::cout << "Coincidences to base feature[" <<
168 aCoincidenceToFeature.size() << "]: " << std::endl;
169 std::map<FeaturePtr, IdToPointPair>::const_iterator anIt = aCoincidenceToFeature.begin(),
170 aLast = aCoincidenceToFeature.end();
171 for (int i = 1; anIt != aLast; anIt++, i++) {
172 FeaturePtr aFeature = (*anIt).first;
173 std::string anAttributeId = (*anIt).second.first;
174 std::shared_ptr<GeomDataAPI_Point2D> aPointAttr = (*anIt).second.second;
176 std::cout << i << "-" << getFeatureInfo(aFeature) << std::endl;
177 std::cout << " -Attribute to correct:" << anAttributeId << std::endl;
178 std::cout << " -Point attribute:" <<
179 ModelGeomAlgo_Point2D::getPointAttributeInfo(aPointAttr) << std::endl;
183 std::map<AttributePtr, std::list<AttributePtr> >::const_iterator
184 aRefIt = aBaseRefAttributes.begin(), aRefLast = aBaseRefAttributes.end();
185 std::cout << std::endl << "References to attributes of base feature [" <<
186 aBaseRefAttributes.size() << "]" << std::endl;
187 for (; aRefIt != aRefLast; aRefIt++) {
188 AttributePtr aBaseAttr = aRefIt->first;
189 std::list<AttributePtr> aRefAttributes = aRefIt->second;
190 std::string aRefsInfo;
191 std::list<AttributePtr>::const_iterator aRefAttrIt = aRefAttributes.begin(),
192 aRefAttrLast = aRefAttributes.end();
193 for (; aRefAttrIt != aRefAttrLast; aRefAttrIt++) {
194 if (!aRefsInfo.empty())
195 aRefsInfo.append(",");
196 AttributePtr aRAttr = *aRefAttrIt;
197 aRefsInfo.append(aRAttr->id());
198 FeaturePtr aRFeature = ModelAPI_Feature::feature(aRAttr->owner());
199 aRefsInfo.append("(" + aRFeature->name() + ") ");
201 std::shared_ptr<GeomDataAPI_Point2D> aPointAttr =
202 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aBaseAttr);
203 std::cout << aPointAttr->id().c_str() <<
204 ": " << "[" << aRefAttributes.size() << "] " << aRefsInfo << std::endl;
206 std::cout << std::endl;
207 std::cout << std::endl << "References to base feature [" <<
208 aRefsToFeature.size() << "]" << std::endl;
209 std::list<AttributePtr>::const_iterator aRefAttrIt = aRefsToFeature.begin(),
210 aRefAttrLast = aRefsToFeature.end();
211 std::string aRefsInfo;
212 for (; aRefAttrIt != aRefAttrLast; aRefAttrIt++) {
213 if (!aRefsInfo.empty())
214 aRefsInfo.append(",");
215 AttributePtr aRAttr = *aRefAttrIt;
216 aRefsInfo.append(aRAttr->id());
217 FeaturePtr aRFeature = ModelAPI_Feature::feature(aRAttr->owner());
218 aRefsInfo.append("(" + aRFeature->name() + ") ");
220 std::cout << "[" << aRefsToFeature.size() << "] " << aRefsInfo << std::endl;
223 std::cout << std::endl;
224 std::cout << "---- SPLIT ----" << std::endl;
225 std::cout << std::endl;
228 keepCurrentFeature();
230 std::string aFeatureKind = aBaseFeature->getKind();
231 FeaturePtr aSplitFeature, anAfterFeature;
232 std::set<AttributePoint2DPtr> aFurtherCoincidences;
233 std::set<FeaturePtr> aCreatedFeatures;
234 std::set<std::pair<AttributePtr, AttributePtr>> aModifiedAttributes;
235 FeaturePtr aReplacingFeature, aNewFeature;
236 if (aFeatureKind == SketchPlugin_Line::ID())
237 aNewFeature = splitLine(aSplitFeature, aBaseFeature, anAfterFeature,
238 aFurtherCoincidences, aCreatedFeatures, aModifiedAttributes);
239 else if (aFeatureKind == SketchPlugin_Arc::ID())
240 aNewFeature = splitArc(aSplitFeature, aBaseFeature, anAfterFeature, aFurtherCoincidences,
241 aCreatedFeatures, aModifiedAttributes);
242 else if (aFeatureKind == SketchPlugin_EllipticArc::ID())
243 aNewFeature = splitEllipticArc(aSplitFeature, aBaseFeature, anAfterFeature,
244 aFurtherCoincidences, aCreatedFeatures, aModifiedAttributes);
246 restoreCurrentFeature();
248 if (aFeatureKind == SketchPlugin_Circle::ID() || aFeatureKind == SketchPlugin_Ellipse::ID()) {
249 aFeaturesToDelete.insert(aBaseFeature);
250 aReplacingFeature = splitClosed(aSplitFeature, aBaseFeature, anAfterFeature,
251 aFurtherCoincidences, aCreatedFeatures, aModifiedAttributes);
253 updateRefFeatureConstraints(aBaseFeature->lastResult(), aRefsToFeature);
255 // as circle is removed, temporary fill this attribute*/
256 aBaseObjectAttr->setObject(ResultPtr());
260 std::cout << "---- OUT PARAMETERS ----" << std::endl;
261 std::cout << "Base modified feature:" << getFeatureInfo(aBaseFeature) << std::endl;
262 std::cout << "Split feature:" << getFeatureInfo(aSplitFeature) << std::endl;
263 std::cout << "After feature:" << getFeatureInfo(anAfterFeature) << std::endl;
264 std::cout << std::endl;
266 std::cout << "Created features by split:[" << aCreatedFeatures.size() << "]" << std::endl;
267 std::set<FeaturePtr>::const_iterator aFIt = aCreatedFeatures.begin(),
268 aFLast = aCreatedFeatures.end();
269 for (; aFIt != aFLast; aFIt++) {
270 std::cout << getFeatureInfo(*aFIt) << std::endl;
272 std::cout << std::endl;
274 std::cout << "Attributes for further Coincidences:" << std::endl;
275 std::set<AttributePoint2DPtr>::const_iterator anIt = aFurtherCoincidences.begin(),
276 aLast = aFurtherCoincidences.end();
277 for (; anIt != aLast; anIt++) {
278 AttributePtr anAttribute = *anIt;
279 FeaturePtr aFeature = ModelAPI_Feature::feature(anAttribute->owner());
280 std::cout << ModelGeomAlgo_Point2D::getPointAttributeInfo(anAttribute)
281 << " [" << getFeatureInfo(aFeature, false) << "]" << std::endl;
284 std::cout << "Modifed attributes (constraints to attributes are moved here):" << std::endl;
285 std::set<std::pair<AttributePtr, AttributePtr> >::const_iterator
286 aPIt = aModifiedAttributes.begin(), aPLast = aModifiedAttributes.end();
287 std::string aResInfo;
288 for (; aPIt != aPLast; aPIt++) {
289 if (!aResInfo.empty())
292 std::pair<AttributePtr, AttributePtr> aPair = *aPIt;
294 AttributePtr anAttr = aPair.first;
295 aResInfo.append(anAttr->id());
296 FeaturePtr aFeature = ModelAPI_Feature::feature(anAttr->owner());
297 aResInfo.append("(" + aFeature->name() + ") ");
299 aResInfo.append(" - is modified to - ");
301 anAttr = aPair.second;
302 aResInfo.append(anAttr->id());
303 aFeature = ModelAPI_Feature::feature(anAttr->owner());
304 aResInfo.append("(" + aFeature->name() + ") ");
306 std::cout << aResInfo << std::endl;
309 std::set<ResultPtr> aFeatureResults;
310 aFeatureResults.insert(aBaseFeature->lastResult());
311 if (anAfterFeature.get() && anAfterFeature != aBaseFeature)
312 aFeatureResults.insert(anAfterFeature->lastResult());
314 // coincidence to feature
315 updateCoincidenceConstraintsToFeature(aCoincidenceToFeature, aFurtherCoincidences,
316 aFeatureResults, aSplitFeature, aFeaturesToDelete);
318 SketchPlugin_SegmentationTools::updateRefAttConstraints(aBaseRefAttributes, aModifiedAttributes);
320 // delete constraints
322 std::cout << "remove features and references:" << std::endl;
323 std::set<FeaturePtr>::const_iterator aDIt = aFeaturesToDelete.begin(),
324 aDLast = aFeaturesToDelete.end();
325 for (; aDIt != aDLast; aDIt++) {
326 std::cout << getFeatureInfo(*aDIt, false) << std::endl;
327 std::cout << std::endl;
330 ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToDelete);
331 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
334 std::cout << "update features after split:" << std::endl;
335 std::set<FeaturePtr>::const_iterator anUIt = aFeaturesToUpdate.begin(),
336 anULast = aFeaturesToUpdate.end();
337 for (; anUIt != anULast; anUIt++) {
338 std::cout << getFeatureInfo(*anUIt, false) << std::endl;
339 std::cout << std::endl;
342 SketchPlugin_SegmentationTools::updateFeaturesAfterOperation(aFeaturesToUpdate);
344 // Send events to update the sub-features by the solver.
345 if(isUpdateFlushed) {
346 Events_Loop::loop()->setFlushed(anUpdateEvent, true);
349 if (anIsEqualPreviewAndSelected) {
350 // equal preview and selected objects
351 // nothing to do if the preview and selected objects are different
352 ResultPtr aReplacingResult;
353 if (aReplacingFeature.get()) {
354 aReplacingFeature->execute(); // need it to obtain result
355 aReplacingResult = aReplacingFeature->lastResult();
357 if (aReplacingResult.get()) { // base object was removed
358 aPreviewObject = aReplacingResult;
359 //aMessage->setSelectedObject(aReplacingResult);
361 //GeomShapePtr aSelectedShape = aReplacingResult->shape();
362 //std::shared_ptr<GeomAPI_Pnt> aPreviewPnt = sketch()->to3D(aPreviewPnt2d->x(),
363 // aPreviewPnt2d->y());
364 //std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
365 //if (ModelGeomAlgo_Point2D::isPointOnEdge(aSelectedShape, aPreviewPnt, aProjectedPoint)) {
366 //bool aValue = true;
368 //aBaseShape = aShape;
371 if (!aSelectedShape.get())
372 std::cout << "Set empty selected object" << std::endl;
374 std::cout << "Set shape with ShapeType: " << aSelectedShape->shapeTypeStr() << std::endl;
376 //bool aValue = true;
379 aPreviewObject = ObjectPtr();
381 aBaseFeature->execute(); // should recompute shapes of result to do not check obsolete one
382 aBaseObject = aBaseFeature->lastResult();
383 std::shared_ptr<GeomAPI_Pnt> aPreviewPnt = sketch()->to3D(aPreviewPnt2d->x(),
385 ResultPtr aBaseResult = std::dynamic_pointer_cast<ModelAPI_Result>(aBaseObject);
387 GeomShapePtr aShape = aBaseResult->shape();
388 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
389 if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, aPreviewPnt, aProjectedPoint))
390 aPreviewObject = aBaseResult;
392 if (!aPreviewObject.get() && aNewFeature.get()) {
393 ResultPtr aNewFeatureResult = aNewFeature->lastResult();
394 if (aNewFeatureResult.get()) {
395 GeomShapePtr aShape = aNewFeatureResult->shape();
396 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
397 if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, aPreviewPnt, aProjectedPoint))
398 aPreviewObject = aNewFeatureResult;
403 if (aPreviewObject.get()) {
404 std::shared_ptr<ModelAPI_EventReentrantMessage> aMessage = std::shared_ptr
405 <ModelAPI_EventReentrantMessage>(new ModelAPI_EventReentrantMessage(
406 ModelAPI_EventReentrantMessage::eventId(), this));
407 aMessage->setSelectedObject(aPreviewObject);
408 Events_Loop::loop()->send(aMessage);
413 std::cout << "SKETCH FEATURES (after split) [" << aSketch->numberOfSubs() << "]:" << std::endl;
414 for (int i = 0, aNbSubs = aSketch->numberOfSubs(); i < aNbSubs; i++) {
415 std::cout << getFeatureInfo(aSketch->subFeature(i), false) << std::endl;
421 std::string SketchPlugin_Split::processEvent(const std::shared_ptr<Events_Message>& theMessage)
424 std::cout << "SketchPlugin_Split::processEvent:" << data()->name() << std::endl;
426 std::string aFilledAttributeName;
428 std::shared_ptr<ModelAPI_EventReentrantMessage> aMessage =
429 std::dynamic_pointer_cast<ModelAPI_EventReentrantMessage>(theMessage);
430 if (aMessage.get()) {
431 ObjectPtr anObject = aMessage->selectedObject();
432 std::shared_ptr<GeomAPI_Pnt2d> aPoint = aMessage->clickedPoint();
434 if (anObject.get() && aPoint.get()) {
435 if (myCashedShapes.find(anObject) == myCashedShapes.end()) {
436 SketchPlugin_SegmentationTools::fillObjectShapes(
437 this, anObject, myCashedShapes, myCashedReferences);
439 const std::set<GeomShapePtr>& aShapes = myCashedShapes[anObject];
440 if (aShapes.size() > 1) {
441 std::shared_ptr<ModelAPI_AttributeReference> aRefSelectedAttr =
442 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
443 data()->attribute(SELECTED_OBJECT()));
444 std::shared_ptr<ModelAPI_AttributeReference> aRefPreviewAttr =
445 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
446 data()->attribute(PREVIEW_OBJECT()));
447 aRefSelectedAttr->setValue(anObject);
448 aRefPreviewAttr->setValue(anObject);
450 std::shared_ptr<GeomDataAPI_Point2D> aPointSelectedAttr =
451 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
452 data()->attribute(SELECTED_POINT()));
453 std::shared_ptr<GeomDataAPI_Point2D> aPointPreviewAttr =
454 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
455 data()->attribute(PREVIEW_POINT()));
456 aPointSelectedAttr->setValue(aPoint);
457 aPointPreviewAttr->setValue(aPoint);
459 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
461 GeomShapePtr aSelectedShape = SketchPlugin_SegmentationTools::getSubShape(this,
462 SELECTED_OBJECT(), SELECTED_POINT(), myCashedShapes, myCashedReferences);
463 if (aSelectedShape.get()) {
464 aFilledAttributeName = SELECTED_OBJECT();
467 // #2480 - sub shape is not initialized when split sketch
468 // If restarted operation use some selection on the shape that is split and
469 // result selectiona can not participate in new split(checked shape above is null),
470 // reset filled values of selection set in this method above
471 aRefSelectedAttr->setValue(ResultPtr());
472 aRefPreviewAttr->setValue(ResultPtr());
475 if (!aSelectedShape.get())
476 std::cout << "Set empty selected object" << std::endl;
478 std::cout << "Set shape with ShapeType: " << aSelectedShape->shapeTypeStr() << std::endl;
483 return aFilledAttributeName;
487 AISObjectPtr SketchPlugin_Split::getAISObject(AISObjectPtr thePrevious)
489 return SketchPlugin_SegmentationTools::getAISObject(thePrevious,
490 this, PREVIEW_OBJECT(), PREVIEW_POINT(), SELECTED_OBJECT(), SELECTED_POINT());
493 //********************************************************************
494 void SketchPlugin_Split::getConstraints(std::set<FeaturePtr>& theFeaturesToDelete,
495 std::set<FeaturePtr>& theFeaturesToUpdate,
496 std::map<FeaturePtr, IdToPointPair>& theCoincidenceToFeature)
498 std::shared_ptr<ModelAPI_Data> aData = data();
500 // Check the base objects are initialized.
501 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
502 data()->attribute(SELECTED_OBJECT()));
503 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
504 ResultPtr aBaseFeatureResult = aBaseFeature->lastResult();
506 std::set<AttributePtr> aRefsList = aBaseFeatureResult->data()->refsToMe();
507 std::set<AttributePtr> aFRefsList = aBaseFeature->data()->refsToMe();
508 aRefsList.insert(aFRefsList.begin(), aFRefsList.end());
510 std::set<AttributePtr>::const_iterator aIt;
511 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
512 std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
513 FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
514 std::string aRefFeatureKind = aRefFeature->getKind();
515 if (aRefFeatureKind == SketchPlugin_ConstraintMirror::ID() ||
516 aRefFeatureKind == SketchPlugin_MultiRotation::ID() ||
517 aRefFeatureKind == SketchPlugin_MultiTranslation::ID() ||
518 aRefFeatureKind == SketchPlugin_ConstraintMiddle::ID())
519 theFeaturesToDelete.insert(aRefFeature);
520 else if (aRefFeatureKind == SketchPlugin_ConstraintLength::ID())
521 theFeaturesToUpdate.insert(aRefFeature);
522 else if (aRefFeatureKind == SketchPlugin_ConstraintCoincidence::ID() ||
523 aRefFeatureKind == SketchPlugin_ConstraintCoincidenceInternal::ID()) {
524 std::string anAttributeToBeModified;
525 AttributePoint2DPtr aCoincidentPoint;
526 AttributeRefAttrPtr anAttrA = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_A());
527 AttributeRefAttrPtr anAttrB = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_B());
528 bool isToFeature = false;
529 if (anAttrA->isObject() || anAttrB->isObject()) { // coincidence to base feature
530 FeaturePtr aFeature = anAttrA->isObject() ? ModelAPI_Feature::feature(anAttrA->object())
532 isToFeature = aFeature.get() && aFeature == aBaseFeature;
533 anAttributeToBeModified = anAttrA->id();
535 aFeature = anAttrB->isObject() ? ModelAPI_Feature::feature(anAttrB->object())
537 isToFeature = aFeature.get() && aFeature == aBaseFeature;
538 anAttributeToBeModified = anAttrB->id();
541 aCoincidentPoint = SketchPlugin_ConstraintCoincidence::getPoint(aRefFeature);
543 if (!isToFeature) { // coincidence to point on base feature
544 AttributePtr anAttribute;
546 if (!anAttrA->isObject()) {
547 AttributePtr aCurAttribute = anAttrA->attr();
548 if (aCurAttribute.get()) {
549 FeaturePtr aCurFeature = ModelAPI_Feature::feature(aCurAttribute->owner());
550 if (aCurFeature.get() && aCurFeature == aBaseFeature) {
551 anAttribute = anAttrB->attr();
552 anAttributeToBeModified = anAttrA->id();
556 if (!anAttribute.get() && !anAttrB->isObject()) {
557 AttributePtr aCurAttribute = anAttrB->attr();
558 if (aCurAttribute.get()) {
559 FeaturePtr aCurFeature = ModelAPI_Feature::feature(aCurAttribute->owner());
560 if (aCurFeature.get() && aCurFeature == aBaseFeature) {
561 anAttribute = anAttrA->attr();
562 anAttributeToBeModified = anAttrB->id();
566 if (anAttribute.get())
567 aCoincidentPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttribute);
569 if (aCoincidentPoint.get() && isToFeature)
570 theCoincidenceToFeature[aRefFeature] = std::make_pair(anAttributeToBeModified,
576 void SketchPlugin_Split::updateCoincidenceConstraintsToFeature(
577 const std::map<std::shared_ptr<ModelAPI_Feature>, IdToPointPair>& theCoincidenceToFeature,
578 const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theFurtherCoincidences,
579 const std::set<ResultPtr>& theFeatureResults,
580 const FeaturePtr& theSplitFeature,
581 std::set<FeaturePtr>& theFeaturesToDelete)
583 if (theCoincidenceToFeature.empty())
586 // we should build coincidence constraints to end of the split feature
587 std::set<std::shared_ptr<GeomDataAPI_Point2D> > aNewCoincidencesToSplitFeature;
588 AttributePoint2DPtr aStartPointAttr, anEndPointAttr;
589 SketchPlugin_SegmentationTools::getFeaturePoints(
590 theSplitFeature, aStartPointAttr, anEndPointAttr);
591 if (theFurtherCoincidences.find(aStartPointAttr) == theFurtherCoincidences.end())
592 aNewCoincidencesToSplitFeature.insert(aStartPointAttr);
593 if (theFurtherCoincidences.find(anEndPointAttr) == theFurtherCoincidences.end())
594 aNewCoincidencesToSplitFeature.insert(anEndPointAttr);
596 std::map<FeaturePtr, IdToPointPair>::const_iterator aCIt = theCoincidenceToFeature.begin(),
597 aCLast = theCoincidenceToFeature.end();
599 std::cout << std::endl;
600 std::cout << "Coincidences to feature(modified):"<< std::endl;
602 for (; aCIt != aCLast; aCIt++) {
603 FeaturePtr aCoincFeature = aCIt->first;
604 std::string anAttributeId = aCIt->second.first;
605 std::string aSecondAttribute = anAttributeId == SketchPlugin_Constraint::ENTITY_A() ?
606 SketchPlugin_Constraint::ENTITY_B() : SketchPlugin_Constraint::ENTITY_A();
608 AttributePoint2DPtr aCoincPoint = aCIt->second.second;
609 std::set<AttributePoint2DPtr>::const_iterator aFCIt = theFurtherCoincidences.begin(),
610 aFCLast = theFurtherCoincidences.end();
611 std::shared_ptr<GeomAPI_Pnt2d> aCoincPnt = aCoincPoint->pnt();
612 AttributePoint2DPtr aFeaturePointAttribute;
613 for (; aFCIt != aFCLast && !aFeaturePointAttribute.get(); aFCIt++) {
614 AttributePoint2DPtr aFCAttribute = *aFCIt;
615 if (aCoincPnt->isEqual(aFCAttribute->pnt()))
616 aFeaturePointAttribute = aFCAttribute;
618 if (aFeaturePointAttribute.get()) {
619 // create new constraint and remove the current
620 aCoincFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
621 SketchPlugin_ConstraintCoincidence::ID(),
622 aFeaturePointAttribute, aCoincFeature->refattr(aSecondAttribute)->attr());
623 theFeaturesToDelete.insert(aCIt->first);
624 // create new coincidences to split feature points
625 std::set<AttributePoint2DPtr>::const_iterator aSFIt = aNewCoincidencesToSplitFeature.begin(),
626 aSFLast = aNewCoincidencesToSplitFeature.end();
627 for (; aSFIt != aSFLast; aSFIt++) {
628 AttributePoint2DPtr aSFAttribute = *aSFIt;
629 if (aCoincPnt->isEqual(aSFAttribute->pnt())) {
630 SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
631 SketchPlugin_ConstraintCoincidence::ID(),
632 aSFAttribute, aCoincFeature->refattr(aSecondAttribute)->attr());
637 // find feature by shape intersected the point
638 ResultPtr aResultForCoincidence = *(theFeatureResults.begin());
640 if (theFeatureResults.size() > 1) { // try to find point on additional feature
641 ResultPtr anAddtionalResult = *(theFeatureResults.begin()++);
642 GeomShapePtr aShape = anAddtionalResult->shape();
644 std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = aCoincPoint->pnt();
645 std::shared_ptr<GeomAPI_Pnt> aPoint = sketch()->to3D(aPnt2d->x(), aPnt2d->y());
647 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
648 if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, aPoint, aProjectedPoint))
649 aResultForCoincidence = anAddtionalResult;
651 aCoincFeature->refattr(anAttributeId)->setObject(aResultForCoincidence);
654 std::cout << " -" << getFeatureInfo(aCoincFeature) << std::endl;
659 void SketchPlugin_Split::updateRefFeatureConstraints(
660 const ResultPtr& theFeatureBaseResult,
661 const std::list<AttributePtr>& theRefsToFeature)
663 std::list<AttributePtr>::const_iterator anIt = theRefsToFeature.begin(),
664 aLast = theRefsToFeature.end();
665 for (; anIt != aLast; anIt++) {
666 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIt);
668 aRefAttr->setObject(theFeatureBaseResult);
672 FeaturePtr SketchPlugin_Split::splitLine(FeaturePtr& theSplitFeature,
673 FeaturePtr& theBaseFeatureModified,
674 FeaturePtr& theAfterFeature,
675 std::set<AttributePoint2DPtr>& thePoints,
676 std::set<FeaturePtr>& theCreatedFeatures,
677 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
679 FeaturePtr anNewFeature;
681 std::set<FeaturePtr> aCreatedFeatures;
682 FeaturePtr aConstraintFeature;
683 theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
685 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
686 data()->attribute(SELECTED_OBJECT()));
687 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
689 AttributePoint2DPtr aFirstPointAttrOfSplit = getPointAttribute(true);
690 AttributePoint2DPtr aSecondPointAttrOfSplit = getPointAttribute(false);
691 AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
693 SketchPlugin_SegmentationTools::getFeaturePoints(
694 aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
695 if (!aStartPointAttrOfBase.get() && !anEndPointAttrOfBase.get()) {
696 setError("Error: Feature has no start and end points.");
700 arrangePointsOnLine(aStartPointAttrOfBase, anEndPointAttrOfBase,
701 aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
704 std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl;
705 std::cout << "Start point: " <<
706 ModelGeomAlgo_Point2D::getPointAttributeInfo(aStartPointAttrOfBase) << std::endl;
707 std::cout << "1st point: " <<
708 ModelGeomAlgo_Point2D::getPointAttributeInfo(aFirstPointAttrOfSplit) << std::endl;
709 std::cout << "2nd point: " <<
710 ModelGeomAlgo_Point2D::getPointAttributeInfo(aSecondPointAttrOfSplit) << std::endl;
711 std::cout << "End point: " <<
712 ModelGeomAlgo_Point2D::getPointAttributeInfo(anEndPointAttrOfBase) << std::endl;
715 // create a split feature
716 theSplitFeature = SketchPlugin_SegmentationTools::createLineFeature(
717 aBaseFeature, aFirstPointAttrOfSplit->pnt(), aSecondPointAttrOfSplit->pnt());
718 theCreatedFeatures.insert(theSplitFeature);
720 // before split feature
721 if (aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
722 theModifiedAttributes.insert(std::make_pair(aStartPointAttrOfBase,
723 theSplitFeature->attribute(SketchPlugin_Line::START_ID())));
726 theBaseFeatureModified = aBaseFeature; // use base feature to store all constraints here
727 // move end arc point to start of split
730 // after split feature
731 if (!aSecondPointAttrOfSplit->pnt()->isEqual(anEndPointAttrOfBase->pnt())) {
733 if (!theBaseFeatureModified.get()) {
734 aFeature = aBaseFeature; // use base feature to store all constraints here
735 fillAttribute(aFeature->attribute(SketchPlugin_Line::START_ID()), aSecondPointAttrOfSplit);
736 aFeature->execute(); // to update result
739 aFeature = SketchPlugin_SegmentationTools::createLineFeature(
740 aBaseFeature, aSecondPointAttrOfSplit->pnt(), anEndPointAttrOfBase->pnt());
741 theCreatedFeatures.insert(aFeature);
742 theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
743 aFeature->attribute(SketchPlugin_Line::END_ID())));
744 anNewFeature = aFeature;
746 aConstraintFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
747 SketchPlugin_ConstraintCoincidence::ID(),
748 theSplitFeature->attribute(SketchPlugin_Line::END_ID()),
749 aFeature->attribute(SketchPlugin_Line::START_ID()));
750 theCreatedFeatures.insert(aConstraintFeature);
752 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
753 (aFeature->attribute(SketchPlugin_Line::START_ID())));
754 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
755 (aFeature->attribute(SketchPlugin_Line::END_ID())));
757 if (!theBaseFeatureModified.get())
758 theBaseFeatureModified = aFeature;
760 theAfterFeature = aFeature;
763 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
764 (theSplitFeature->attribute(SketchPlugin_Line::END_ID())));
765 theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
766 theSplitFeature->attribute(SketchPlugin_Line::END_ID())));
768 // base split, that is defined before split feature should be changed at end
769 // (after the after feature creation). Otherwise modified value will be used in after feature
770 // before split feature
771 if (!aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
772 // move end arc point to start of split
773 fillAttribute(theBaseFeatureModified->attribute(SketchPlugin_Line::END_ID()),
774 aFirstPointAttrOfSplit);
775 theBaseFeatureModified->execute(); // to update result
776 aConstraintFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
777 SketchPlugin_ConstraintCoincidence::ID(),
778 theBaseFeatureModified->attribute(SketchPlugin_Line::END_ID()),
779 theSplitFeature->attribute(SketchPlugin_Line::START_ID()));
780 theCreatedFeatures.insert(aConstraintFeature);
782 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
783 (theBaseFeatureModified->attribute(SketchPlugin_Line::START_ID())));
784 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
785 (theBaseFeatureModified->attribute(SketchPlugin_Line::END_ID())));
788 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
789 (theSplitFeature->attribute(SketchPlugin_Line::START_ID())));
791 #ifdef CREATE_CONSTRAINTS
792 // additional constraints between split and base features
793 aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
794 SketchPlugin_ConstraintParallel::ID(),
795 aBaseFeature->lastResult(),
796 theSplitFeature->lastResult());
797 theCreatedFeatures.insert(aConstraintFeature);
798 if (theAfterFeature.get()) {
799 aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
800 SketchPlugin_ConstraintParallel::ID(),
801 aBaseFeature->lastResult(),
802 theAfterFeature->lastResult());
803 theCreatedFeatures.insert(aConstraintFeature);
809 FeaturePtr SketchPlugin_Split::splitArc(FeaturePtr& theSplitFeature,
810 FeaturePtr& theBaseFeatureModified,
811 FeaturePtr& theAfterFeature,
812 std::set<AttributePoint2DPtr>& thePoints,
813 std::set<FeaturePtr>& theCreatedFeatures,
814 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
816 FeaturePtr anNewFeature;
818 std::set<FeaturePtr> aCreatedFeatures;
819 FeaturePtr aConstraintFeature;
820 theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
822 AttributeReferencePtr aBaseObjectAttr = reference(SELECTED_OBJECT());
823 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
825 AttributePoint2DPtr aFirstPointAttrOfSplit = getPointAttribute(true);
826 AttributePoint2DPtr aSecondPointAttrOfSplit = getPointAttribute(false);
827 AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
828 SketchPlugin_SegmentationTools::getFeaturePoints(
829 aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
830 if (!aStartPointAttrOfBase.get() && !anEndPointAttrOfBase.get()) {
831 setError("Error: Feature has no start and end points.");
835 arrangePointsOnArc(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase,
836 aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
838 std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl;
839 std::cout << "Start point: " <<
840 ModelGeomAlgo_Point2D::getPointAttributeInfo(aStartPointAttrOfBase) << std::endl;
841 std::cout << "1st point: " <<
842 ModelGeomAlgo_Point2D::getPointAttributeInfo(aFirstPointAttrOfSplit) << std::endl;
843 std::cout << "2nd point: " <<
844 ModelGeomAlgo_Point2D::getPointAttributeInfo(aSecondPointAttrOfSplit) << std::endl;
845 std::cout << "End point: " <<
846 ModelGeomAlgo_Point2D::getPointAttributeInfo(anEndPointAttrOfBase) << std::endl;
850 theSplitFeature = SketchPlugin_SegmentationTools::createArcFeature(
851 aBaseFeature, aFirstPointAttrOfSplit->pnt(), aSecondPointAttrOfSplit->pnt());
852 theCreatedFeatures.insert(theSplitFeature);
854 // before split feature
855 if (aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
856 theModifiedAttributes.insert(std::make_pair(aStartPointAttrOfBase,
857 theSplitFeature->attribute(SketchPlugin_Arc::START_ID())));
860 theBaseFeatureModified = aBaseFeature; // use base feature to store all constraints here
861 // move end arc point to start of split
864 // after split feature
865 if (!aSecondPointAttrOfSplit->pnt()->isEqual(anEndPointAttrOfBase->pnt())) {
867 if (!theBaseFeatureModified.get()) {
868 aFeature = aBaseFeature; // use base feature to store all constraints here
869 fillAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), aSecondPointAttrOfSplit);
870 aFeature->execute(); // to update result
873 aFeature = SketchPlugin_SegmentationTools::createArcFeature(
874 aBaseFeature, aSecondPointAttrOfSplit->pnt(), anEndPointAttrOfBase->pnt());
875 theCreatedFeatures.insert(aFeature);
876 theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
877 aFeature->attribute(SketchPlugin_Arc::END_ID())));
878 anNewFeature = aFeature;
880 aConstraintFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
881 SketchPlugin_ConstraintCoincidence::ID(),
882 theSplitFeature->attribute(SketchPlugin_Arc::END_ID()),
883 aFeature->attribute(SketchPlugin_Arc::START_ID()));
884 theCreatedFeatures.insert(aConstraintFeature);
886 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
887 (aFeature->attribute(SketchPlugin_Arc::START_ID())));
888 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
889 (aFeature->attribute(SketchPlugin_Arc::END_ID())));
891 if (!theBaseFeatureModified.get())
892 theBaseFeatureModified = aFeature;
894 theAfterFeature = aFeature;
897 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
898 (theSplitFeature->attribute(SketchPlugin_Arc::END_ID())));
899 theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
900 theSplitFeature->attribute(SketchPlugin_Arc::END_ID())));
902 // base split, that is defined before split feature should be changed at end
903 // (after the after feature creation). Otherwise modified value will be used in after feature
904 // before split feature
905 if (!aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
906 // move end arc point to start of split
907 fillAttribute(theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID()),
908 aFirstPointAttrOfSplit);
909 theBaseFeatureModified->execute(); // to update result
910 aConstraintFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
911 SketchPlugin_ConstraintCoincidence::ID(),
912 theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID()),
913 theSplitFeature->attribute(SketchPlugin_Arc::START_ID()));
914 theCreatedFeatures.insert(aConstraintFeature);
916 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
917 (theBaseFeatureModified->attribute(SketchPlugin_Arc::START_ID())));
918 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
919 (theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID())));
922 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
923 (theSplitFeature->attribute(SketchPlugin_Arc::START_ID())));
925 // additional constraints between split and base features
926 #ifdef CREATE_CONSTRAINTS
927 aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
928 SketchPlugin_ConstraintEqual::ID(),
929 aBaseFeature->lastResult(),
930 theSplitFeature->lastResult());
931 theCreatedFeatures.insert(aConstraintFeature);
932 aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
933 SketchPlugin_ConstraintTangent::ID(),
934 theSplitFeature->lastResult(),
935 aBaseFeature->lastResult());
936 theCreatedFeatures.insert(aConstraintFeature);
937 if (theAfterFeature.get()) {
938 aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
939 SketchPlugin_ConstraintEqual::ID(),
940 aBaseFeature->lastResult(),
941 theAfterFeature->lastResult());
942 theCreatedFeatures.insert(aConstraintFeature);
943 aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
944 SketchPlugin_ConstraintTangent::ID(),
945 theSplitFeature->lastResult(),
946 theAfterFeature->lastResult());
947 theCreatedFeatures.insert(aConstraintFeature);
953 FeaturePtr SketchPlugin_Split::splitEllipticArc(FeaturePtr& theSplitFeature,
954 FeaturePtr& theBaseFeatureModified,
955 FeaturePtr& theAfterFeature,
956 std::set<AttributePoint2DPtr>& thePoints,
957 std::set<FeaturePtr>& theCreatedFeatures,
958 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
960 FeaturePtr anNewFeature;
962 std::set<FeaturePtr> aCreatedFeatures;
963 FeaturePtr aConstraintFeature;
964 theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
966 AttributeReferencePtr aBaseObjectAttr = reference(SELECTED_OBJECT());
967 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
969 AttributePoint2DPtr aFirstPointAttrOfSplit = getPointAttribute(true);
970 AttributePoint2DPtr aSecondPointAttrOfSplit = getPointAttribute(false);
971 AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
972 SketchPlugin_SegmentationTools::getFeaturePoints(
973 aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
974 if (!aStartPointAttrOfBase.get() && !anEndPointAttrOfBase.get()) {
975 setError("Error: Feature has no start and end points.");
979 arrangePointsOnArc(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase,
980 aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
982 std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl;
983 std::cout << "Start point: " <<
984 ModelGeomAlgo_Point2D::getPointAttributeInfo(aStartPointAttrOfBase) << std::endl;
985 std::cout << "1st point: " <<
986 ModelGeomAlgo_Point2D::getPointAttributeInfo(aFirstPointAttrOfSplit) << std::endl;
987 std::cout << "2nd point: " <<
988 ModelGeomAlgo_Point2D::getPointAttributeInfo(aSecondPointAttrOfSplit) << std::endl;
989 std::cout << "End point: " <<
990 ModelGeomAlgo_Point2D::getPointAttributeInfo(anEndPointAttrOfBase) << std::endl;
994 theSplitFeature = SketchPlugin_SegmentationTools::createArcFeature(
995 aBaseFeature, aFirstPointAttrOfSplit->pnt(), aSecondPointAttrOfSplit->pnt());
996 theCreatedFeatures.insert(theSplitFeature);
998 // before split feature
999 if (aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
1000 theModifiedAttributes.insert(std::make_pair(aStartPointAttrOfBase,
1001 theSplitFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID())));
1004 theBaseFeatureModified = aBaseFeature; // use base feature to store all constraints here
1005 // move end arc point to start of split
1008 // after split feature
1009 if (!aSecondPointAttrOfSplit->pnt()->isEqual(anEndPointAttrOfBase->pnt())) {
1010 FeaturePtr aFeature;
1011 if (!theBaseFeatureModified.get()) {
1012 aFeature = aBaseFeature; // use base feature to store all constraints here
1013 fillAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), aSecondPointAttrOfSplit);
1014 aFeature->execute(); // to update result
1017 aFeature = SketchPlugin_SegmentationTools::createArcFeature(
1018 aBaseFeature, aSecondPointAttrOfSplit->pnt(), anEndPointAttrOfBase->pnt());
1019 theCreatedFeatures.insert(aFeature);
1020 theModifiedAttributes.insert(std::make_pair(
1021 anEndPointAttrOfBase, aFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID())));
1022 anNewFeature = aFeature;
1024 aConstraintFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
1025 SketchPlugin_ConstraintCoincidence::ID(),
1026 theSplitFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID()),
1027 aFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID()));
1028 theCreatedFeatures.insert(aConstraintFeature);
1030 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1031 (aFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID())));
1032 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1033 (aFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID())));
1035 if (!theBaseFeatureModified.get())
1036 theBaseFeatureModified = aFeature;
1038 theAfterFeature = aFeature;
1041 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1042 theSplitFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID())));
1043 theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
1044 theSplitFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID())));
1046 // base split, that is defined before split feature should be changed at end
1047 // (after the after feature creation). Otherwise modified value will be used in after feature
1048 // before split feature
1049 if (!aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
1050 // move end arc point to start of split
1051 fillAttribute(theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::END_POINT_ID()),
1052 aFirstPointAttrOfSplit);
1053 theBaseFeatureModified->execute(); // to update result
1054 aConstraintFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
1055 SketchPlugin_ConstraintCoincidence::ID(),
1056 theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::END_POINT_ID()),
1057 theSplitFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID()));
1058 theCreatedFeatures.insert(aConstraintFeature);
1060 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1061 theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::START_POINT_ID())));
1062 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1063 theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::END_POINT_ID())));
1066 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1067 theSplitFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID())));
1069 // additional constraints between split and base features
1070 #ifdef CREATE_CONSTRAINTS
1071 aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
1072 SketchPlugin_ConstraintEqual::ID(),
1073 aBaseFeature->lastResult(),
1074 theSplitFeature->lastResult());
1075 theCreatedFeatures.insert(aConstraintFeature);
1076 aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
1077 SketchPlugin_ConstraintTangent::ID(),
1078 theSplitFeature->lastResult(),
1079 aBaseFeature->lastResult());
1080 theCreatedFeatures.insert(aConstraintFeature);
1081 if (theAfterFeature.get()) {
1082 aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
1083 SketchPlugin_ConstraintEqual::ID(),
1084 aBaseFeature->lastResult(),
1085 theAfterFeature->lastResult());
1086 theCreatedFeatures.insert(aConstraintFeature);
1087 aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
1088 SketchPlugin_ConstraintTangent::ID(),
1089 theSplitFeature->lastResult(),
1090 theAfterFeature->lastResult());
1091 theCreatedFeatures.insert(aConstraintFeature);
1094 return anNewFeature;
1097 FeaturePtr SketchPlugin_Split::splitClosed(FeaturePtr& theSplitFeature,
1098 FeaturePtr& theBaseFeatureModified,
1099 FeaturePtr& theAfterFeature,
1100 std::set<AttributePoint2DPtr>& thePoints,
1101 std::set<FeaturePtr>& theCreatedFeatures,
1102 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
1104 FeaturePtr anNewFeature;
1106 std::set<FeaturePtr> aCreatedFeatures;
1107 FeaturePtr aConstraintFeature;
1108 theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
1110 AttributeReferencePtr aBaseObjectAttr = reference(SELECTED_OBJECT());
1111 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
1113 AttributePoint2DPtr aFirstPointAttrOfSplit = getPointAttribute(true);
1114 AttributePoint2DPtr aSecondPointAttrOfSplit = getPointAttribute(false);
1117 theSplitFeature = SketchPlugin_SegmentationTools::createArcFeature(
1118 aBaseFeature, aFirstPointAttrOfSplit->pnt(), aSecondPointAttrOfSplit->pnt());
1119 const std::string& aReversedAttrName = theSplitFeature->getKind() == SketchPlugin_Arc::ID() ?
1120 SketchPlugin_Arc::REVERSED_ID() : SketchPlugin_EllipticArc::REVERSED_ID();
1121 bool aSplitReversed = theSplitFeature->boolean(aReversedAttrName)->value();
1122 theCreatedFeatures.insert(theSplitFeature);
1124 // base feature is a left part of the circle
1125 theBaseFeatureModified = SketchPlugin_SegmentationTools::createArcFeature(
1126 aBaseFeature, aFirstPointAttrOfSplit->pnt(), aSecondPointAttrOfSplit->pnt());
1127 anNewFeature = theBaseFeatureModified;
1128 theBaseFeatureModified->boolean(aReversedAttrName)->setValue(!aSplitReversed);
1129 theBaseFeatureModified->execute();
1131 if (aBaseFeature->getKind() == SketchPlugin_Circle::ID()) {
1132 theModifiedAttributes.insert(std::make_pair(
1133 aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
1134 theBaseFeatureModified->attribute(SketchPlugin_Arc::CENTER_ID())));
1136 else if (aBaseFeature->getKind() == SketchPlugin_Ellipse::ID()) {
1137 theModifiedAttributes.insert(std::make_pair(
1138 aBaseFeature->attribute(SketchPlugin_Ellipse::CENTER_ID()),
1139 theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::CENTER_ID())));
1140 theModifiedAttributes.insert(std::make_pair(
1141 aBaseFeature->attribute(SketchPlugin_Ellipse::FIRST_FOCUS_ID()),
1142 theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::FIRST_FOCUS_ID())));
1143 theModifiedAttributes.insert(std::make_pair(
1144 aBaseFeature->attribute(SketchPlugin_Ellipse::SECOND_FOCUS_ID()),
1145 theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::SECOND_FOCUS_ID())));
1146 theModifiedAttributes.insert(std::make_pair(
1147 aBaseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID()),
1148 theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::MAJOR_AXIS_START_ID())));
1149 theModifiedAttributes.insert(std::make_pair(
1150 aBaseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()),
1151 theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID())));
1152 theModifiedAttributes.insert(std::make_pair(
1153 aBaseFeature->attribute(SketchPlugin_Ellipse::MINOR_AXIS_START_ID()),
1154 theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::MINOR_AXIS_START_ID())));
1155 theModifiedAttributes.insert(std::make_pair(
1156 aBaseFeature->attribute(SketchPlugin_Ellipse::MINOR_AXIS_END_ID()),
1157 theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::MINOR_AXIS_END_ID())));
1159 // update the PARENT_ID reference for all the features created by the ellipse
1160 const std::set<AttributePtr>& aRefs = aBaseFeature->data()->refsToMe();
1161 std::list<AttributePtr> aRefsToParent;
1162 for (std::set<AttributePtr>::const_iterator aRef = aRefs.begin(); aRef != aRefs.end(); ++aRef) {
1163 if ((*aRef)->id() == SketchPlugin_Line::PARENT_ID() ||
1164 (*aRef)->id() == SketchPlugin_Point::PARENT_ID())
1165 aRefsToParent.push_back(*aRef);
1167 for (std::list<AttributePtr>::iterator aRef = aRefsToParent.begin();
1168 aRef != aRefsToParent.end(); ++aRef)
1169 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(*aRef)->setValue(theSplitFeature);
1172 theCreatedFeatures.insert(theBaseFeatureModified);
1174 const std::string& aStartAttrName = theSplitFeature->getKind() == SketchPlugin_Arc::ID() ?
1175 SketchPlugin_Arc::START_ID() : SketchPlugin_EllipticArc::START_POINT_ID();
1176 const std::string& aEndAttrName = theSplitFeature->getKind() == SketchPlugin_Arc::ID() ?
1177 SketchPlugin_Arc::END_ID() : SketchPlugin_EllipticArc::END_POINT_ID();
1179 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1180 (theBaseFeatureModified->attribute(aStartAttrName)));
1181 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1182 (theBaseFeatureModified->attribute(aEndAttrName)));
1184 // additional constraints between split and base features
1185 aConstraintFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
1186 SketchPlugin_ConstraintCoincidence::ID(),
1187 theBaseFeatureModified->attribute(aEndAttrName),
1188 theSplitFeature->attribute(aEndAttrName));
1189 theCreatedFeatures.insert(aConstraintFeature);
1190 aConstraintFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
1191 SketchPlugin_ConstraintCoincidence::ID(),
1192 theBaseFeatureModified->attribute(aStartAttrName),
1193 theSplitFeature->attribute(aStartAttrName));
1194 theCreatedFeatures.insert(aConstraintFeature);
1196 #ifdef CREATE_CONSTRAINTS
1197 aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
1198 SketchPlugin_ConstraintTangent::ID(),
1199 theSplitFeature->lastResult(),
1200 theBaseFeatureModified->lastResult());
1201 theCreatedFeatures.insert(aConstraintFeature);
1203 return anNewFeature;
1206 void SketchPlugin_Split::arrangePointsOnLine(
1207 const AttributePoint2DPtr& theStartPointAttr,
1208 const AttributePoint2DPtr& theEndPointAttr,
1209 AttributePoint2DPtr& theFirstPointAttr,
1210 AttributePoint2DPtr& theLastPointAttr) const
1212 // if first point is closer to last point, swap first and last values
1213 if (theStartPointAttr->pnt()->distance(theFirstPointAttr->pnt()) >
1214 theStartPointAttr->pnt()->distance(theLastPointAttr->pnt())) {
1215 AttributePoint2DPtr aTmpPoint = theFirstPointAttr;
1216 theFirstPointAttr = theLastPointAttr;
1217 theLastPointAttr = aTmpPoint;
1221 void SketchPlugin_Split::arrangePointsOnArc(
1222 const FeaturePtr& theArc,
1223 const std::shared_ptr<GeomDataAPI_Point2D>& theStartPointAttr,
1224 const std::shared_ptr<GeomDataAPI_Point2D>& theEndPointAttr,
1225 std::shared_ptr<GeomDataAPI_Point2D>& theFirstPointAttr,
1226 std::shared_ptr<GeomDataAPI_Point2D>& theSecondPointAttr) const
1228 static const double anAngleTol = 1.e-12;
1230 const std::string& aCenterAttrName = theArc->getKind() == SketchPlugin_Arc::ID() ?
1231 SketchPlugin_Arc::CENTER_ID() : SketchPlugin_EllipticArc::CENTER_ID();
1232 const std::string& aReversedAttrName = theArc->getKind() == SketchPlugin_Arc::ID() ?
1233 SketchPlugin_Arc::REVERSED_ID() : SketchPlugin_EllipticArc::REVERSED_ID();
1235 std::shared_ptr<GeomAPI_Pnt2d> aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1236 theArc->attribute(aCenterAttrName))->pnt();
1237 bool isReversed = theArc->boolean(aReversedAttrName)->value();
1239 // collect directions to each point
1240 std::shared_ptr<GeomAPI_Dir2d> aStartDir(
1241 new GeomAPI_Dir2d(theStartPointAttr->pnt()->xy()->decreased(aCenter->xy())));
1242 std::shared_ptr<GeomAPI_Dir2d> aFirstPtDir(
1243 new GeomAPI_Dir2d(theFirstPointAttr->pnt()->xy()->decreased(aCenter->xy())));
1244 std::shared_ptr<GeomAPI_Dir2d> aSecondPtDir(
1245 new GeomAPI_Dir2d(theSecondPointAttr->pnt()->xy()->decreased(aCenter->xy())));
1247 // sort points by their angular values
1248 double aFirstPtAngle = aStartDir->angle(aFirstPtDir);
1249 double aSecondPtAngle = aStartDir->angle(aSecondPtDir);
1250 double aPeriod = isReversed ? -2.0 * PI : 2.0 * PI;
1251 if (fabs(aFirstPtAngle) > anAngleTol && isReversed == (aFirstPtAngle > 0.))
1252 aFirstPtAngle += aPeriod;
1253 if (fabs(aSecondPtAngle) > anAngleTol && isReversed == (aSecondPtAngle > 0.))
1254 aSecondPtAngle += aPeriod;
1256 if (fabs(aFirstPtAngle) > fabs(aSecondPtAngle)) {
1257 AttributePoint2DPtr aTmpPoint = theFirstPointAttr;
1258 theFirstPointAttr = theSecondPointAttr;
1259 theSecondPointAttr = aTmpPoint;
1263 void SketchPlugin_Split::fillAttribute(const AttributePtr& theModifiedAttribute,
1264 const AttributePtr& theSourceAttribute)
1266 std::string anAttributeType = theModifiedAttribute->attributeType();
1267 if (anAttributeType == GeomDataAPI_Point2D::typeId()) {
1268 AttributePoint2DPtr aModifiedAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1269 theModifiedAttribute);
1270 AttributePoint2DPtr aSourceAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1271 theSourceAttribute);
1273 if (aModifiedAttribute.get() && aSourceAttribute.get())
1274 aModifiedAttribute->setValue(aSourceAttribute->pnt());
1276 else if (anAttributeType == ModelAPI_AttributeBoolean::typeId()) {
1277 AttributeBooleanPtr aModifiedAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(
1278 theModifiedAttribute);
1279 AttributeBooleanPtr aSourceAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(
1280 theSourceAttribute);
1282 if (aModifiedAttribute.get() && aSourceAttribute.get())
1283 aModifiedAttribute->setValue(aSourceAttribute->value());
1288 std::set<std::shared_ptr<ModelAPI_Attribute> > SketchPlugin_Split::getEdgeAttributes(
1289 const std::shared_ptr<ModelAPI_Feature>& theFeature)
1291 std::set<std::shared_ptr<ModelAPI_Attribute> > anAttributes;
1293 std::string aFeatureKind = theFeature->getKind();
1294 if (aFeatureKind == SketchPlugin_Line::ID()) {
1295 anAttributes.insert(theFeature->attribute(SketchPlugin_Line::START_ID()));
1296 anAttributes.insert(theFeature->attribute(SketchPlugin_Line::END_ID()));
1298 else if (aFeatureKind == SketchPlugin_Arc::ID()) {
1299 anAttributes.insert(theFeature->attribute(SketchPlugin_Arc::START_ID()));
1300 anAttributes.insert(theFeature->attribute(SketchPlugin_Arc::END_ID()));
1302 else if (aFeatureKind == SketchPlugin_EllipticArc::ID()) {
1303 anAttributes.insert(theFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID()));
1304 anAttributes.insert(theFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID()));
1306 else if (aFeatureKind == SketchPlugin_Circle::ID()) {
1309 return anAttributes;
1313 std::shared_ptr<GeomDataAPI_Point2D> SketchPlugin_Split::getPointAttribute
1314 (const bool isFirstAttribute)
1316 std::shared_ptr<GeomDataAPI_Point2D> anAttribute;
1318 GeomShapePtr aSelectedShape = SketchPlugin_SegmentationTools::getSubShape(this,
1319 SELECTED_OBJECT(), SELECTED_POINT(), myCashedShapes, myCashedReferences);
1320 if (!aSelectedShape.get())
1323 if (aSelectedShape->shapeType() != GeomAPI_Shape::EDGE)
1326 AttributeReferencePtr anObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
1327 data()->attribute(SELECTED_OBJECT()));
1328 ObjectPtr aBaseObject = anObjectAttr->value();
1329 if (!aBaseObject.get())
1332 std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aSelectedShape));
1334 std::shared_ptr<GeomAPI_Pnt> aFirstPnt = anEdge->firstPoint();
1335 std::shared_ptr<GeomAPI_Pnt> aLastPnt = anEdge->lastPoint();
1337 std::shared_ptr<GeomDataAPI_Point2D> aFirstPointAttr, aLastPointAttr;
1338 // find the points in feature attributes
1339 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObject);
1340 std::list<AttributePtr> a2DPointAttributes = aBaseFeature->data()->attributes(
1341 GeomDataAPI_Point2D::typeId());
1342 std::list<AttributePtr>::const_iterator anIt = a2DPointAttributes.begin(),
1343 aLast = a2DPointAttributes.end();
1344 for (; anIt != aLast; anIt++) {
1345 std::shared_ptr<GeomDataAPI_Point2D> anAttributePoint =
1346 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt);
1347 std::shared_ptr<GeomAPI_Pnt2d> aPoint2D = anAttributePoint->pnt();
1348 std::shared_ptr<GeomAPI_Pnt> aPoint3D = sketch()->to3D(aPoint2D->x(), aPoint2D->y());
1349 if (aFirstPnt->isEqual(aPoint3D))
1350 aFirstPointAttr = anAttributePoint;
1351 else if (aLastPnt->isEqual(aPoint3D))
1352 aLastPointAttr = anAttributePoint;
1355 // find the points in coincident features
1356 const GeomAlgoAPI_ShapeTools::PointToRefsMap& aRefAttributes = myCashedReferences.at(aBaseObject);
1357 GeomAlgoAPI_ShapeTools::PointToRefsMap::const_iterator
1358 aRIt = aRefAttributes.begin(), aRLast = aRefAttributes.end();
1359 for (; aRIt != aRLast; aRIt++) {
1360 const std::list<AttributePoint2DPtr>& anAttributes = aRIt->second.first;
1361 GeomPointPtr aPoint = aRIt->first;
1362 if (!aFirstPointAttr.get() && aFirstPnt->isEqual(aPoint))
1363 aFirstPointAttr = anAttributes.front();
1364 if (!aLastPointAttr.get() && aLastPnt->isEqual(aPoint))
1365 aLastPointAttr = anAttributes.front();
1366 if (aFirstPointAttr.get() && aLastPointAttr.get())
1369 if (!aFirstPointAttr.get() || !aLastPointAttr)
1372 return isFirstAttribute ? aFirstPointAttr : aLastPointAttr;
1376 std::string SketchPlugin_Split::getFeatureInfo(const std::shared_ptr<ModelAPI_Feature>& theFeature,
1377 const bool isUseAttributesInfo)
1380 if (!theFeature.get()) {
1384 if (theFeature->data()->isValid())
1385 anInfo.append(theFeature->data()->name().c_str());
1387 if (isUseAttributesInfo) {
1388 std::string aPointsInfo = ModelGeomAlgo_Point2D::getPontAttributesInfo(theFeature,
1389 getEdgeAttributes(theFeature));
1390 // processing of feature with point 2d attributes, like line, arc, circle
1391 if (!aPointsInfo.empty()) {
1394 anInfo += aPointsInfo;
1396 else { // process constraint coincidence, find points in ref attr attributes
1397 std::list<AttributePtr> anAttrs = theFeature->data()->attributes(
1398 ModelAPI_AttributeRefAttr::typeId());
1399 std::list<AttributePtr>::const_iterator anIt = anAttrs.begin(), aLast = anAttrs.end();
1400 std::string anAttributesInfo;
1401 for(; anIt != aLast; anIt++) {
1402 if (!anAttributesInfo.empty()) {
1403 anAttributesInfo.append(", ");
1404 anAttributesInfo += "\n";
1406 AttributePtr anAttr = *anIt;
1407 std::string aValue = "not defined";
1408 std::string aType = anAttr->attributeType();
1409 if (aType == ModelAPI_AttributeRefAttr::typeId()) {
1410 std::shared_ptr<ModelAPI_AttributeRefAttr> aRefAttr =
1411 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
1412 if (aRefAttr.get()) {
1413 if (aRefAttr->isObject()) {
1414 FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
1415 aValue = "<object:>" + getFeatureInfo(aFeature, false);
1418 AttributePtr anAttribute = aRefAttr->attr();
1419 if (anAttribute.get()) {
1420 FeaturePtr aFeature = ModelAPI_Feature::feature(anAttribute->owner());
1421 aValue = "<attr:>" + ModelGeomAlgo_Point2D::getPointAttributeInfo(anAttribute) +
1422 " [" + getFeatureInfo(aFeature, false) + "]";
1427 anAttributesInfo.append(" " + anAttr->id() + ": " + aValue);
1429 if (!anAttributesInfo.empty())
1430 anInfo = anInfo + "\n" + anAttributesInfo;