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_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 <Locale_Convert.h>
33 #include <ModelAPI_AttributeBoolean.h>
34 #include <ModelAPI_AttributeDouble.h>
35 #include <ModelAPI_AttributeRefAttr.h>
36 #include <ModelAPI_AttributeReference.h>
37 #include <ModelAPI_AttributeString.h>
38 #include <ModelAPI_Events.h>
39 #include <ModelAPI_Validator.h>
40 #include <ModelAPI_Session.h>
41 #include <ModelAPI_Tools.h>
43 #include <ModelGeomAlgo_Shape.h>
45 #include <SketchPlugin_Arc.h>
46 #include <SketchPlugin_Circle.h>
47 #include <SketchPlugin_ConstraintCoincidence.h>
48 #include <SketchPlugin_ConstraintCoincidenceInternal.h>
49 #include <SketchPlugin_ConstraintEqual.h>
50 #include <SketchPlugin_ConstraintLength.h>
51 #include <SketchPlugin_ConstraintMiddle.h>
52 #include <SketchPlugin_ConstraintMirror.h>
53 #include <SketchPlugin_ConstraintParallel.h>
54 #include <SketchPlugin_ConstraintTangent.h>
55 #include <SketchPlugin_Ellipse.h>
56 #include <SketchPlugin_EllipticArc.h>
57 #include <SketchPlugin_Line.h>
58 #include <SketchPlugin_MultiRotation.h>
59 #include <SketchPlugin_MultiTranslation.h>
60 #include <SketchPlugin_Point.h>
62 #include <ModelGeomAlgo_Point2D.h>
63 #include <ModelAPI_EventReentrantMessage.h>
64 #include <Events_Loop.h>
68 //#define CREATE_CONSTRAINTS
74 static const double PI = 3.141592653589793238463;
76 SketchPlugin_Split::SketchPlugin_Split()
80 void SketchPlugin_Split::initAttributes()
82 data()->addAttribute(SELECTED_OBJECT(), ModelAPI_AttributeReference::typeId());
83 data()->addAttribute(SELECTED_POINT(), GeomDataAPI_Point2D::typeId());
85 data()->addAttribute(PREVIEW_POINT(), GeomDataAPI_Point2D::typeId());
86 data()->addAttribute(PREVIEW_OBJECT(), ModelAPI_AttributeReference::typeId());
88 data()->attribute(PREVIEW_POINT())->setIsArgument(false);
89 data()->attribute(SELECTED_POINT())->setIsArgument(false);
90 data()->attribute(PREVIEW_OBJECT())->setIsArgument(false);
92 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PREVIEW_POINT());
93 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PREVIEW_OBJECT());
96 void SketchPlugin_Split::execute()
98 std::shared_ptr<ModelAPI_Data> aData = data();
100 // Check the base objects are initialized.
101 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
102 data()->attribute(SELECTED_OBJECT()));
103 if(!aBaseObjectAttr->isInitialized()) {
104 setError("Error: Base object is not initialized.");
107 ObjectPtr aBaseObject = aBaseObjectAttr->value();
108 AttributePoint2DPtr aFirstPointAttrOfSplit = getPointAttribute(true);
109 AttributePoint2DPtr aSecondPointAttrOfSplit = getPointAttribute(false);
110 if (!aFirstPointAttrOfSplit.get() || !aFirstPointAttrOfSplit->isInitialized() ||
111 !aSecondPointAttrOfSplit.get() || !aSecondPointAttrOfSplit->isInitialized()) {
112 setError("Error: Sub-shape is not initialized.");
116 // Remove reference of this feature to feature used in preview, it is not necessary anymore
117 // as trim will be removed after execute
118 AttributeReferencePtr aPreviewObjectAttr =
119 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
120 data()->attribute(PREVIEW_OBJECT()));
122 ObjectPtr aPreviewObject = aPreviewObjectAttr->value();
123 AttributePoint2DPtr aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
124 data()->attribute(PREVIEW_POINT()));
125 std::shared_ptr<GeomAPI_Pnt2d> aPreviewPnt2d = aPoint->pnt();
126 // nullify pointer of preview attribute
127 aPreviewObjectAttr->setValue(ResultPtr());
128 bool anIsEqualPreviewAndSelected = aPreviewObject == aBaseObject;
130 // Wait all constraints being created, then send update events
131 static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
132 bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
134 Events_Loop::loop()->setFlushed(anUpdateEvent, false);
136 // Find feature constraints
137 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObject);
138 ResultPtr aBaseFeatureResult = aBaseFeature->lastResult();
139 std::set<FeaturePtr> aFeaturesToDelete, aFeaturesToUpdate;
141 //std::map<FeaturePtr, IdToPointPair> aTangentFeatures;
142 std::map<FeaturePtr, IdToPointPair> aCoincidenceToFeature;
143 getConstraints(aFeaturesToDelete, aFeaturesToUpdate, aCoincidenceToFeature);
145 std::map<AttributePtr, std::list<AttributePtr> > aBaseRefAttributes;
146 std::list<AttributePtr> aRefsToFeature;
147 SketchPlugin_SegmentationTools::getRefAttributes(
148 aBaseFeature, aBaseRefAttributes, aRefsToFeature);
150 std::map<AttributePtr, AttributePtr> aBasePointModifiedAttributes;
153 std::cout << std::endl;
154 std::cout << "SketchPlugin_Split::execute()" << std::endl;
155 std::cout << std::endl;
157 SketchPlugin_Sketch* aSketch = sketch();
158 std::cout << "SKETCH FEATURES (before split) [" << aSketch->numberOfSubs() << "]:" << std::endl;
159 for (int i = 0, aNbSubs = aSketch->numberOfSubs(); i < aNbSubs; i++) {
160 std::cout << getFeatureInfo(aSketch->subFeature(i), false) << std::endl;
163 std::cout << std::endl;
164 std::cout << "---- IN PARAMETERS ----" << std::endl;
165 std::cout << "Base feature:" << getFeatureInfo(aBaseFeature) << std::endl;
166 std::cout << std::endl;
168 if (!aCoincidenceToFeature.empty()) {
169 std::cout << "Coincidences to base feature[" <<
170 aCoincidenceToFeature.size() << "]: " << std::endl;
171 std::map<FeaturePtr, IdToPointPair>::const_iterator anIt = aCoincidenceToFeature.begin(),
172 aLast = aCoincidenceToFeature.end();
173 for (int i = 1; anIt != aLast; anIt++, i++) {
174 FeaturePtr aFeature = (*anIt).first;
175 std::string anAttributeId = (*anIt).second.first;
176 std::shared_ptr<GeomDataAPI_Point2D> aPointAttr = (*anIt).second.second;
178 std::cout << i << "-" << getFeatureInfo(aFeature) << std::endl;
179 std::cout << " -Attribute to correct:" << anAttributeId << std::endl;
180 std::cout << " -Point attribute:" <<
181 ModelGeomAlgo_Point2D::getPointAttributeInfo(aPointAttr) << std::endl;
185 std::map<AttributePtr, std::list<AttributePtr> >::const_iterator
186 aRefIt = aBaseRefAttributes.begin(), aRefLast = aBaseRefAttributes.end();
187 std::cout << std::endl << "References to attributes of base feature [" <<
188 aBaseRefAttributes.size() << "]" << std::endl;
189 for (; aRefIt != aRefLast; aRefIt++) {
190 AttributePtr aBaseAttr = aRefIt->first;
191 std::list<AttributePtr> aRefAttributes = aRefIt->second;
192 std::string aRefsInfo;
193 std::list<AttributePtr>::const_iterator aRefAttrIt = aRefAttributes.begin(),
194 aRefAttrLast = aRefAttributes.end();
195 for (; aRefAttrIt != aRefAttrLast; aRefAttrIt++) {
196 if (!aRefsInfo.empty())
197 aRefsInfo.append(",");
198 AttributePtr aRAttr = *aRefAttrIt;
199 aRefsInfo.append(aRAttr->id());
200 FeaturePtr aRFeature = ModelAPI_Feature::feature(aRAttr->owner());
201 aRefsInfo.append("(" + aRFeature->name() + ") ");
203 std::shared_ptr<GeomDataAPI_Point2D> aPointAttr =
204 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aBaseAttr);
205 std::cout << aPointAttr->id().c_str() <<
206 ": " << "[" << aRefAttributes.size() << "] " << aRefsInfo << std::endl;
208 std::cout << std::endl;
209 std::cout << std::endl << "References to base feature [" <<
210 aRefsToFeature.size() << "]" << std::endl;
211 std::list<AttributePtr>::const_iterator aRefAttrIt = aRefsToFeature.begin(),
212 aRefAttrLast = aRefsToFeature.end();
213 std::string aRefsInfo;
214 for (; aRefAttrIt != aRefAttrLast; aRefAttrIt++) {
215 if (!aRefsInfo.empty())
216 aRefsInfo.append(",");
217 AttributePtr aRAttr = *aRefAttrIt;
218 aRefsInfo.append(aRAttr->id());
219 FeaturePtr aRFeature = ModelAPI_Feature::feature(aRAttr->owner());
220 aRefsInfo.append("(" + aRFeature->name() + ") ");
222 std::cout << "[" << aRefsToFeature.size() << "] " << aRefsInfo << std::endl;
225 std::cout << std::endl;
226 std::cout << "---- SPLIT ----" << std::endl;
227 std::cout << std::endl;
230 keepCurrentFeature();
232 std::string aFeatureKind = aBaseFeature->getKind();
233 FeaturePtr aSplitFeature, anAfterFeature;
234 std::set<AttributePoint2DPtr> aFurtherCoincidences;
235 std::set<FeaturePtr> aCreatedFeatures;
236 std::set<std::pair<AttributePtr, AttributePtr>> aModifiedAttributes;
237 FeaturePtr aReplacingFeature, aNewFeature;
238 if (aFeatureKind == SketchPlugin_Line::ID())
239 aNewFeature = splitLine(aSplitFeature, aBaseFeature, anAfterFeature,
240 aFurtherCoincidences, aCreatedFeatures, aModifiedAttributes);
241 else if (aFeatureKind == SketchPlugin_Arc::ID())
242 aNewFeature = splitArc(aSplitFeature, aBaseFeature, anAfterFeature, aFurtherCoincidences,
243 aCreatedFeatures, aModifiedAttributes);
244 else if (aFeatureKind == SketchPlugin_EllipticArc::ID())
245 aNewFeature = splitEllipticArc(aSplitFeature, aBaseFeature, anAfterFeature,
246 aFurtherCoincidences, aCreatedFeatures, aModifiedAttributes);
248 restoreCurrentFeature();
250 if (aFeatureKind == SketchPlugin_Circle::ID() || aFeatureKind == SketchPlugin_Ellipse::ID()) {
251 aFeaturesToDelete.insert(aBaseFeature);
252 aReplacingFeature = splitClosed(aSplitFeature, aBaseFeature, anAfterFeature,
253 aFurtherCoincidences, aCreatedFeatures, aModifiedAttributes);
255 updateRefFeatureConstraints(aBaseFeature->lastResult(), aRefsToFeature);
257 // as circle is removed, temporary fill this attribute*/
258 aBaseObjectAttr->setObject(ResultPtr());
262 std::cout << "---- OUT PARAMETERS ----" << std::endl;
263 std::cout << "Base modified feature:" << getFeatureInfo(aBaseFeature) << std::endl;
264 std::cout << "Split feature:" << getFeatureInfo(aSplitFeature) << std::endl;
265 std::cout << "After feature:" << getFeatureInfo(anAfterFeature) << std::endl;
266 std::cout << std::endl;
268 std::cout << "Created features by split:[" << aCreatedFeatures.size() << "]" << std::endl;
269 std::set<FeaturePtr>::const_iterator aFIt = aCreatedFeatures.begin(),
270 aFLast = aCreatedFeatures.end();
271 for (; aFIt != aFLast; aFIt++) {
272 std::cout << getFeatureInfo(*aFIt) << std::endl;
274 std::cout << std::endl;
276 std::cout << "Attributes for further Coincidences:" << std::endl;
277 std::set<AttributePoint2DPtr>::const_iterator anIt = aFurtherCoincidences.begin(),
278 aLast = aFurtherCoincidences.end();
279 for (; anIt != aLast; anIt++) {
280 AttributePtr anAttribute = *anIt;
281 FeaturePtr aFeature = ModelAPI_Feature::feature(anAttribute->owner());
282 std::cout << ModelGeomAlgo_Point2D::getPointAttributeInfo(anAttribute)
283 << " [" << getFeatureInfo(aFeature, false) << "]" << std::endl;
286 std::cout << "Modifed attributes (constraints to attributes are moved here):" << std::endl;
287 std::set<std::pair<AttributePtr, AttributePtr> >::const_iterator
288 aPIt = aModifiedAttributes.begin(), aPLast = aModifiedAttributes.end();
289 std::string aResInfo;
290 for (; aPIt != aPLast; aPIt++) {
291 if (!aResInfo.empty())
294 std::pair<AttributePtr, AttributePtr> aPair = *aPIt;
296 AttributePtr anAttr = aPair.first;
297 aResInfo.append(anAttr->id());
298 FeaturePtr aFeature = ModelAPI_Feature::feature(anAttr->owner());
299 aResInfo.append("(" + aFeature->name() + ") ");
301 aResInfo.append(" - is modified to - ");
303 anAttr = aPair.second;
304 aResInfo.append(anAttr->id());
305 aFeature = ModelAPI_Feature::feature(anAttr->owner());
306 aResInfo.append("(" + aFeature->name() + ") ");
308 std::cout << aResInfo << std::endl;
311 std::set<ResultPtr> aFeatureResults;
312 aFeatureResults.insert(aBaseFeature->lastResult());
313 if (anAfterFeature.get() && anAfterFeature != aBaseFeature)
314 aFeatureResults.insert(anAfterFeature->lastResult());
316 // coincidence to feature
317 updateCoincidenceConstraintsToFeature(aCoincidenceToFeature, aFurtherCoincidences,
318 aFeatureResults, aSplitFeature, aFeaturesToDelete);
320 SketchPlugin_SegmentationTools::updateRefAttConstraints(aBaseRefAttributes, aModifiedAttributes);
322 // delete constraints
324 std::cout << "remove features and references:" << std::endl;
325 std::set<FeaturePtr>::const_iterator aDIt = aFeaturesToDelete.begin(),
326 aDLast = aFeaturesToDelete.end();
327 for (; aDIt != aDLast; aDIt++) {
328 std::cout << getFeatureInfo(*aDIt, false) << std::endl;
329 std::cout << std::endl;
332 ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToDelete);
333 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
336 std::cout << "update features after split:" << std::endl;
337 std::set<FeaturePtr>::const_iterator anUIt = aFeaturesToUpdate.begin(),
338 anULast = aFeaturesToUpdate.end();
339 for (; anUIt != anULast; anUIt++) {
340 std::cout << getFeatureInfo(*anUIt, false) << std::endl;
341 std::cout << std::endl;
344 SketchPlugin_SegmentationTools::updateFeaturesAfterOperation(aFeaturesToUpdate);
346 // Send events to update the sub-features by the solver.
347 if(isUpdateFlushed) {
348 Events_Loop::loop()->setFlushed(anUpdateEvent, true);
351 if (anIsEqualPreviewAndSelected) {
352 // equal preview and selected objects
353 // nothing to do if the preview and selected objects are different
354 ResultPtr aReplacingResult;
355 if (aReplacingFeature.get()) {
356 aReplacingFeature->execute(); // need it to obtain result
357 aReplacingResult = aReplacingFeature->lastResult();
359 if (aReplacingResult.get()) { // base object was removed
360 aPreviewObject = aReplacingResult;
361 //aMessage->setSelectedObject(aReplacingResult);
363 //GeomShapePtr aSelectedShape = aReplacingResult->shape();
364 //std::shared_ptr<GeomAPI_Pnt> aPreviewPnt = sketch()->to3D(aPreviewPnt2d->x(),
365 // aPreviewPnt2d->y());
366 //std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
367 //if (ModelGeomAlgo_Point2D::isPointOnEdge(aSelectedShape, aPreviewPnt, aProjectedPoint)) {
368 //bool aValue = true;
370 //aBaseShape = aShape;
373 if (!aSelectedShape.get())
374 std::cout << "Set empty selected object" << std::endl;
376 std::cout << "Set shape with ShapeType: " << aSelectedShape->shapeTypeStr() << std::endl;
378 //bool aValue = true;
381 aPreviewObject = ObjectPtr();
383 aBaseFeature->execute(); // should recompute shapes of result to do not check obsolete one
384 aBaseObject = aBaseFeature->lastResult();
385 std::shared_ptr<GeomAPI_Pnt> aPreviewPnt = sketch()->to3D(aPreviewPnt2d->x(),
387 ResultPtr aBaseResult = std::dynamic_pointer_cast<ModelAPI_Result>(aBaseObject);
389 GeomShapePtr aShape = aBaseResult->shape();
390 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
391 if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, aPreviewPnt, aProjectedPoint))
392 aPreviewObject = aBaseResult;
394 if (!aPreviewObject.get() && aNewFeature.get()) {
395 ResultPtr aNewFeatureResult = aNewFeature->lastResult();
396 if (aNewFeatureResult.get()) {
397 GeomShapePtr aShape = aNewFeatureResult->shape();
398 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
399 if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, aPreviewPnt, aProjectedPoint))
400 aPreviewObject = aNewFeatureResult;
405 if (aPreviewObject.get()) {
406 std::shared_ptr<ModelAPI_EventReentrantMessage> aMessage = std::shared_ptr
407 <ModelAPI_EventReentrantMessage>(new ModelAPI_EventReentrantMessage(
408 ModelAPI_EventReentrantMessage::eventId(), this));
409 aMessage->setSelectedObject(aPreviewObject);
410 Events_Loop::loop()->send(aMessage);
415 std::cout << "SKETCH FEATURES (after split) [" << aSketch->numberOfSubs() << "]:" << std::endl;
416 for (int i = 0, aNbSubs = aSketch->numberOfSubs(); i < aNbSubs; i++) {
417 std::cout << getFeatureInfo(aSketch->subFeature(i), false) << std::endl;
423 std::string SketchPlugin_Split::processEvent(const std::shared_ptr<Events_Message>& theMessage)
426 std::cout << "SketchPlugin_Split::processEvent:" << data()->name() << std::endl;
428 std::string aFilledAttributeName;
430 std::shared_ptr<ModelAPI_EventReentrantMessage> aMessage =
431 std::dynamic_pointer_cast<ModelAPI_EventReentrantMessage>(theMessage);
432 if (aMessage.get()) {
433 ObjectPtr anObject = aMessage->selectedObject();
434 std::shared_ptr<GeomAPI_Pnt2d> aPoint = aMessage->clickedPoint();
436 if (anObject.get() && aPoint.get()) {
437 if (myCashedShapes.find(anObject) == myCashedShapes.end()) {
438 SketchPlugin_SegmentationTools::fillObjectShapes(
439 this, anObject, myCashedShapes, myCashedReferences);
441 const std::set<GeomShapePtr>& aShapes = myCashedShapes[anObject];
442 if (aShapes.size() > 1) {
443 std::shared_ptr<ModelAPI_AttributeReference> aRefSelectedAttr =
444 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
445 data()->attribute(SELECTED_OBJECT()));
446 std::shared_ptr<ModelAPI_AttributeReference> aRefPreviewAttr =
447 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
448 data()->attribute(PREVIEW_OBJECT()));
449 aRefSelectedAttr->setValue(anObject);
450 aRefPreviewAttr->setValue(anObject);
452 std::shared_ptr<GeomDataAPI_Point2D> aPointSelectedAttr =
453 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
454 data()->attribute(SELECTED_POINT()));
455 std::shared_ptr<GeomDataAPI_Point2D> aPointPreviewAttr =
456 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
457 data()->attribute(PREVIEW_POINT()));
458 aPointSelectedAttr->setValue(aPoint);
459 aPointPreviewAttr->setValue(aPoint);
461 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
463 GeomShapePtr aSelectedShape = SketchPlugin_SegmentationTools::getSubShape(this,
464 SELECTED_OBJECT(), SELECTED_POINT(), myCashedShapes, myCashedReferences);
465 if (aSelectedShape.get()) {
466 aFilledAttributeName = SELECTED_OBJECT();
469 // #2480 - sub shape is not initialized when split sketch
470 // If restarted operation use some selection on the shape that is split and
471 // result selectiona can not participate in new split(checked shape above is null),
472 // reset filled values of selection set in this method above
473 aRefSelectedAttr->setValue(ResultPtr());
474 aRefPreviewAttr->setValue(ResultPtr());
477 if (!aSelectedShape.get())
478 std::cout << "Set empty selected object" << std::endl;
480 std::cout << "Set shape with ShapeType: " << aSelectedShape->shapeTypeStr() << std::endl;
485 return aFilledAttributeName;
489 AISObjectPtr SketchPlugin_Split::getAISObject(AISObjectPtr thePrevious)
491 return SketchPlugin_SegmentationTools::getAISObject(thePrevious,
492 this, PREVIEW_OBJECT(), PREVIEW_POINT(), SELECTED_OBJECT(), SELECTED_POINT());
495 //********************************************************************
496 void SketchPlugin_Split::getConstraints(std::set<FeaturePtr>& theFeaturesToDelete,
497 std::set<FeaturePtr>& theFeaturesToUpdate,
498 std::map<FeaturePtr, IdToPointPair>& theCoincidenceToFeature)
500 std::shared_ptr<ModelAPI_Data> aData = data();
502 // Check the base objects are initialized.
503 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
504 data()->attribute(SELECTED_OBJECT()));
505 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
506 ResultPtr aBaseFeatureResult = aBaseFeature->lastResult();
508 std::set<AttributePtr> aRefsList = aBaseFeatureResult->data()->refsToMe();
509 std::set<AttributePtr> aFRefsList = aBaseFeature->data()->refsToMe();
510 aRefsList.insert(aFRefsList.begin(), aFRefsList.end());
512 std::set<AttributePtr>::const_iterator aIt;
513 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
514 std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
515 FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
516 std::string aRefFeatureKind = aRefFeature->getKind();
517 if (aRefFeatureKind == SketchPlugin_ConstraintMirror::ID() ||
518 aRefFeatureKind == SketchPlugin_MultiRotation::ID() ||
519 aRefFeatureKind == SketchPlugin_MultiTranslation::ID() ||
520 aRefFeatureKind == SketchPlugin_ConstraintMiddle::ID())
521 theFeaturesToDelete.insert(aRefFeature);
522 else if (aRefFeatureKind == SketchPlugin_ConstraintLength::ID())
523 theFeaturesToUpdate.insert(aRefFeature);
524 else if (aRefFeatureKind == SketchPlugin_ConstraintCoincidence::ID() ||
525 aRefFeatureKind == SketchPlugin_ConstraintCoincidenceInternal::ID()) {
526 std::string anAttributeToBeModified;
527 AttributePoint2DPtr aCoincidentPoint;
528 AttributeRefAttrPtr anAttrA = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_A());
529 AttributeRefAttrPtr anAttrB = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_B());
530 bool isToFeature = false;
531 if (anAttrA->isObject() || anAttrB->isObject()) { // coincidence to base feature
532 FeaturePtr aFeature = anAttrA->isObject() ? ModelAPI_Feature::feature(anAttrA->object())
534 isToFeature = aFeature.get() && aFeature == aBaseFeature;
535 anAttributeToBeModified = anAttrA->id();
537 aFeature = anAttrB->isObject() ? ModelAPI_Feature::feature(anAttrB->object())
539 isToFeature = aFeature.get() && aFeature == aBaseFeature;
540 anAttributeToBeModified = anAttrB->id();
543 aCoincidentPoint = SketchPlugin_ConstraintCoincidence::getPoint(aRefFeature);
545 if (!isToFeature) { // coincidence to point on base feature
546 AttributePtr anAttribute;
548 if (!anAttrA->isObject()) {
549 AttributePtr aCurAttribute = anAttrA->attr();
550 if (aCurAttribute.get()) {
551 FeaturePtr aCurFeature = ModelAPI_Feature::feature(aCurAttribute->owner());
552 if (aCurFeature.get() && aCurFeature == aBaseFeature) {
553 anAttribute = anAttrB->attr();
554 anAttributeToBeModified = anAttrA->id();
558 if (!anAttribute.get() && !anAttrB->isObject()) {
559 AttributePtr aCurAttribute = anAttrB->attr();
560 if (aCurAttribute.get()) {
561 FeaturePtr aCurFeature = ModelAPI_Feature::feature(aCurAttribute->owner());
562 if (aCurFeature.get() && aCurFeature == aBaseFeature) {
563 anAttribute = anAttrA->attr();
564 anAttributeToBeModified = anAttrB->id();
568 if (anAttribute.get())
569 aCoincidentPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttribute);
571 if (aCoincidentPoint.get() && isToFeature)
572 theCoincidenceToFeature[aRefFeature] = std::make_pair(anAttributeToBeModified,
578 void SketchPlugin_Split::updateCoincidenceConstraintsToFeature(
579 const std::map<std::shared_ptr<ModelAPI_Feature>, IdToPointPair>& theCoincidenceToFeature,
580 const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theFurtherCoincidences,
581 const std::set<ResultPtr>& theFeatureResults,
582 const FeaturePtr& theSplitFeature,
583 std::set<FeaturePtr>& theFeaturesToDelete)
585 if (theCoincidenceToFeature.empty())
588 // we should build coincidence constraints to end of the split feature
589 std::set<std::shared_ptr<GeomDataAPI_Point2D> > aNewCoincidencesToSplitFeature;
590 AttributePoint2DPtr aStartPointAttr, anEndPointAttr;
591 SketchPlugin_SegmentationTools::getFeaturePoints(
592 theSplitFeature, aStartPointAttr, anEndPointAttr);
593 if (theFurtherCoincidences.find(aStartPointAttr) == theFurtherCoincidences.end())
594 aNewCoincidencesToSplitFeature.insert(aStartPointAttr);
595 if (theFurtherCoincidences.find(anEndPointAttr) == theFurtherCoincidences.end())
596 aNewCoincidencesToSplitFeature.insert(anEndPointAttr);
598 std::map<FeaturePtr, IdToPointPair>::const_iterator aCIt = theCoincidenceToFeature.begin(),
599 aCLast = theCoincidenceToFeature.end();
601 std::cout << std::endl;
602 std::cout << "Coincidences to feature(modified):"<< std::endl;
604 for (; aCIt != aCLast; aCIt++) {
605 FeaturePtr aCoincFeature = aCIt->first;
606 std::string anAttributeId = aCIt->second.first;
607 std::string aSecondAttribute = anAttributeId == SketchPlugin_Constraint::ENTITY_A() ?
608 SketchPlugin_Constraint::ENTITY_B() : SketchPlugin_Constraint::ENTITY_A();
610 AttributePoint2DPtr aCoincPoint = aCIt->second.second;
611 std::set<AttributePoint2DPtr>::const_iterator aFCIt = theFurtherCoincidences.begin(),
612 aFCLast = theFurtherCoincidences.end();
613 std::shared_ptr<GeomAPI_Pnt2d> aCoincPnt = aCoincPoint->pnt();
614 AttributePoint2DPtr aFeaturePointAttribute;
615 for (; aFCIt != aFCLast && !aFeaturePointAttribute.get(); aFCIt++) {
616 AttributePoint2DPtr aFCAttribute = *aFCIt;
617 if (aCoincPnt->isEqual(aFCAttribute->pnt()))
618 aFeaturePointAttribute = aFCAttribute;
620 if (aFeaturePointAttribute.get()) {
621 // create new constraint and remove the current
622 aCoincFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
623 SketchPlugin_ConstraintCoincidence::ID(),
624 aFeaturePointAttribute, aCoincFeature->refattr(aSecondAttribute)->attr());
625 theFeaturesToDelete.insert(aCIt->first);
626 // create new coincidences to split feature points
627 std::set<AttributePoint2DPtr>::const_iterator aSFIt = aNewCoincidencesToSplitFeature.begin(),
628 aSFLast = aNewCoincidencesToSplitFeature.end();
629 for (; aSFIt != aSFLast; aSFIt++) {
630 AttributePoint2DPtr aSFAttribute = *aSFIt;
631 if (aCoincPnt->isEqual(aSFAttribute->pnt())) {
632 SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
633 SketchPlugin_ConstraintCoincidence::ID(),
634 aSFAttribute, aCoincFeature->refattr(aSecondAttribute)->attr());
639 // find feature by shape intersected the point
640 ResultPtr aResultForCoincidence = *(theFeatureResults.begin());
642 if (theFeatureResults.size() > 1) { // try to find point on additional feature
643 ResultPtr anAddtionalResult = *(theFeatureResults.begin()++);
644 GeomShapePtr aShape = anAddtionalResult->shape();
646 std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = aCoincPoint->pnt();
647 std::shared_ptr<GeomAPI_Pnt> aPoint = sketch()->to3D(aPnt2d->x(), aPnt2d->y());
649 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
650 if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, aPoint, aProjectedPoint))
651 aResultForCoincidence = anAddtionalResult;
653 aCoincFeature->refattr(anAttributeId)->setObject(aResultForCoincidence);
656 std::cout << " -" << getFeatureInfo(aCoincFeature) << std::endl;
661 void SketchPlugin_Split::updateRefFeatureConstraints(
662 const ResultPtr& theFeatureBaseResult,
663 const std::list<AttributePtr>& theRefsToFeature)
665 std::list<AttributePtr>::const_iterator anIt = theRefsToFeature.begin(),
666 aLast = theRefsToFeature.end();
667 for (; anIt != aLast; anIt++) {
668 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIt);
670 aRefAttr->setObject(theFeatureBaseResult);
674 FeaturePtr SketchPlugin_Split::splitLine(FeaturePtr& theSplitFeature,
675 FeaturePtr& theBaseFeatureModified,
676 FeaturePtr& theAfterFeature,
677 std::set<AttributePoint2DPtr>& thePoints,
678 std::set<FeaturePtr>& theCreatedFeatures,
679 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
681 FeaturePtr anNewFeature;
683 std::set<FeaturePtr> aCreatedFeatures;
684 FeaturePtr aConstraintFeature;
685 theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
687 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
688 data()->attribute(SELECTED_OBJECT()));
689 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
691 AttributePoint2DPtr aFirstPointAttrOfSplit = getPointAttribute(true);
692 AttributePoint2DPtr aSecondPointAttrOfSplit = getPointAttribute(false);
693 AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
695 SketchPlugin_SegmentationTools::getFeaturePoints(
696 aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
697 if (!aStartPointAttrOfBase.get() && !anEndPointAttrOfBase.get()) {
698 setError("Error: Feature has no start and end points.");
702 arrangePointsOnLine(aStartPointAttrOfBase, anEndPointAttrOfBase,
703 aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
706 std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl;
707 std::cout << "Start point: " <<
708 ModelGeomAlgo_Point2D::getPointAttributeInfo(aStartPointAttrOfBase) << std::endl;
709 std::cout << "1st point: " <<
710 ModelGeomAlgo_Point2D::getPointAttributeInfo(aFirstPointAttrOfSplit) << std::endl;
711 std::cout << "2nd point: " <<
712 ModelGeomAlgo_Point2D::getPointAttributeInfo(aSecondPointAttrOfSplit) << std::endl;
713 std::cout << "End point: " <<
714 ModelGeomAlgo_Point2D::getPointAttributeInfo(anEndPointAttrOfBase) << std::endl;
717 // create a split feature
718 theSplitFeature = SketchPlugin_SegmentationTools::createLineFeature(
719 aBaseFeature, aFirstPointAttrOfSplit->pnt(), aSecondPointAttrOfSplit->pnt());
720 theCreatedFeatures.insert(theSplitFeature);
722 // before split feature
723 if (aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
724 theModifiedAttributes.insert(std::make_pair(aStartPointAttrOfBase,
725 theSplitFeature->attribute(SketchPlugin_Line::START_ID())));
728 theBaseFeatureModified = aBaseFeature; // use base feature to store all constraints here
729 // move end arc point to start of split
732 // after split feature
733 if (!aSecondPointAttrOfSplit->pnt()->isEqual(anEndPointAttrOfBase->pnt())) {
735 if (!theBaseFeatureModified.get()) {
736 aFeature = aBaseFeature; // use base feature to store all constraints here
737 fillAttribute(aFeature->attribute(SketchPlugin_Line::START_ID()), aSecondPointAttrOfSplit);
738 aFeature->execute(); // to update result
741 aFeature = SketchPlugin_SegmentationTools::createLineFeature(
742 aBaseFeature, aSecondPointAttrOfSplit->pnt(), anEndPointAttrOfBase->pnt());
743 theCreatedFeatures.insert(aFeature);
744 theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
745 aFeature->attribute(SketchPlugin_Line::END_ID())));
746 anNewFeature = aFeature;
748 aConstraintFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
749 SketchPlugin_ConstraintCoincidence::ID(),
750 theSplitFeature->attribute(SketchPlugin_Line::END_ID()),
751 aFeature->attribute(SketchPlugin_Line::START_ID()));
752 theCreatedFeatures.insert(aConstraintFeature);
754 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
755 (aFeature->attribute(SketchPlugin_Line::START_ID())));
756 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
757 (aFeature->attribute(SketchPlugin_Line::END_ID())));
759 if (!theBaseFeatureModified.get())
760 theBaseFeatureModified = aFeature;
762 theAfterFeature = aFeature;
765 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
766 (theSplitFeature->attribute(SketchPlugin_Line::END_ID())));
767 theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
768 theSplitFeature->attribute(SketchPlugin_Line::END_ID())));
770 // base split, that is defined before split feature should be changed at end
771 // (after the after feature creation). Otherwise modified value will be used in after feature
772 // before split feature
773 if (!aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
774 // move end arc point to start of split
775 fillAttribute(theBaseFeatureModified->attribute(SketchPlugin_Line::END_ID()),
776 aFirstPointAttrOfSplit);
777 theBaseFeatureModified->execute(); // to update result
778 aConstraintFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
779 SketchPlugin_ConstraintCoincidence::ID(),
780 theBaseFeatureModified->attribute(SketchPlugin_Line::END_ID()),
781 theSplitFeature->attribute(SketchPlugin_Line::START_ID()));
782 theCreatedFeatures.insert(aConstraintFeature);
784 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
785 (theBaseFeatureModified->attribute(SketchPlugin_Line::START_ID())));
786 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
787 (theBaseFeatureModified->attribute(SketchPlugin_Line::END_ID())));
790 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
791 (theSplitFeature->attribute(SketchPlugin_Line::START_ID())));
793 #ifdef CREATE_CONSTRAINTS
794 // additional constraints between split and base features
795 aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
796 SketchPlugin_ConstraintParallel::ID(),
797 aBaseFeature->lastResult(),
798 theSplitFeature->lastResult());
799 theCreatedFeatures.insert(aConstraintFeature);
800 if (theAfterFeature.get()) {
801 aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
802 SketchPlugin_ConstraintParallel::ID(),
803 aBaseFeature->lastResult(),
804 theAfterFeature->lastResult());
805 theCreatedFeatures.insert(aConstraintFeature);
811 FeaturePtr SketchPlugin_Split::splitArc(FeaturePtr& theSplitFeature,
812 FeaturePtr& theBaseFeatureModified,
813 FeaturePtr& theAfterFeature,
814 std::set<AttributePoint2DPtr>& thePoints,
815 std::set<FeaturePtr>& theCreatedFeatures,
816 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
818 FeaturePtr anNewFeature;
820 std::set<FeaturePtr> aCreatedFeatures;
821 FeaturePtr aConstraintFeature;
822 theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
824 AttributeReferencePtr aBaseObjectAttr = reference(SELECTED_OBJECT());
825 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
827 AttributePoint2DPtr aFirstPointAttrOfSplit = getPointAttribute(true);
828 AttributePoint2DPtr aSecondPointAttrOfSplit = getPointAttribute(false);
829 AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
830 SketchPlugin_SegmentationTools::getFeaturePoints(
831 aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
832 if (!aStartPointAttrOfBase.get() && !anEndPointAttrOfBase.get()) {
833 setError("Error: Feature has no start and end points.");
837 arrangePointsOnArc(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase,
838 aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
840 std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl;
841 std::cout << "Start point: " <<
842 ModelGeomAlgo_Point2D::getPointAttributeInfo(aStartPointAttrOfBase) << std::endl;
843 std::cout << "1st point: " <<
844 ModelGeomAlgo_Point2D::getPointAttributeInfo(aFirstPointAttrOfSplit) << std::endl;
845 std::cout << "2nd point: " <<
846 ModelGeomAlgo_Point2D::getPointAttributeInfo(aSecondPointAttrOfSplit) << std::endl;
847 std::cout << "End point: " <<
848 ModelGeomAlgo_Point2D::getPointAttributeInfo(anEndPointAttrOfBase) << std::endl;
852 theSplitFeature = SketchPlugin_SegmentationTools::createArcFeature(
853 aBaseFeature, aFirstPointAttrOfSplit->pnt(), aSecondPointAttrOfSplit->pnt());
854 theCreatedFeatures.insert(theSplitFeature);
856 // before split feature
857 if (aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
858 theModifiedAttributes.insert(std::make_pair(aStartPointAttrOfBase,
859 theSplitFeature->attribute(SketchPlugin_Arc::START_ID())));
862 theBaseFeatureModified = aBaseFeature; // use base feature to store all constraints here
863 // move end arc point to start of split
866 // after split feature
867 if (!aSecondPointAttrOfSplit->pnt()->isEqual(anEndPointAttrOfBase->pnt())) {
869 if (!theBaseFeatureModified.get()) {
870 aFeature = aBaseFeature; // use base feature to store all constraints here
871 fillAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), aSecondPointAttrOfSplit);
872 aFeature->execute(); // to update result
875 aFeature = SketchPlugin_SegmentationTools::createArcFeature(
876 aBaseFeature, aSecondPointAttrOfSplit->pnt(), anEndPointAttrOfBase->pnt());
877 theCreatedFeatures.insert(aFeature);
878 theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
879 aFeature->attribute(SketchPlugin_Arc::END_ID())));
880 anNewFeature = aFeature;
882 aConstraintFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
883 SketchPlugin_ConstraintCoincidence::ID(),
884 theSplitFeature->attribute(SketchPlugin_Arc::END_ID()),
885 aFeature->attribute(SketchPlugin_Arc::START_ID()));
886 theCreatedFeatures.insert(aConstraintFeature);
888 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
889 (aFeature->attribute(SketchPlugin_Arc::START_ID())));
890 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
891 (aFeature->attribute(SketchPlugin_Arc::END_ID())));
893 if (!theBaseFeatureModified.get())
894 theBaseFeatureModified = aFeature;
896 theAfterFeature = aFeature;
899 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
900 (theSplitFeature->attribute(SketchPlugin_Arc::END_ID())));
901 theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
902 theSplitFeature->attribute(SketchPlugin_Arc::END_ID())));
904 // base split, that is defined before split feature should be changed at end
905 // (after the after feature creation). Otherwise modified value will be used in after feature
906 // before split feature
907 if (!aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
908 // move end arc point to start of split
909 fillAttribute(theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID()),
910 aFirstPointAttrOfSplit);
911 theBaseFeatureModified->execute(); // to update result
912 aConstraintFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
913 SketchPlugin_ConstraintCoincidence::ID(),
914 theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID()),
915 theSplitFeature->attribute(SketchPlugin_Arc::START_ID()));
916 theCreatedFeatures.insert(aConstraintFeature);
918 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
919 (theBaseFeatureModified->attribute(SketchPlugin_Arc::START_ID())));
920 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
921 (theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID())));
924 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
925 (theSplitFeature->attribute(SketchPlugin_Arc::START_ID())));
927 // additional constraints between split and base features
928 #ifdef CREATE_CONSTRAINTS
929 aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
930 SketchPlugin_ConstraintEqual::ID(),
931 aBaseFeature->lastResult(),
932 theSplitFeature->lastResult());
933 theCreatedFeatures.insert(aConstraintFeature);
934 aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
935 SketchPlugin_ConstraintTangent::ID(),
936 theSplitFeature->lastResult(),
937 aBaseFeature->lastResult());
938 theCreatedFeatures.insert(aConstraintFeature);
939 if (theAfterFeature.get()) {
940 aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
941 SketchPlugin_ConstraintEqual::ID(),
942 aBaseFeature->lastResult(),
943 theAfterFeature->lastResult());
944 theCreatedFeatures.insert(aConstraintFeature);
945 aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
946 SketchPlugin_ConstraintTangent::ID(),
947 theSplitFeature->lastResult(),
948 theAfterFeature->lastResult());
949 theCreatedFeatures.insert(aConstraintFeature);
955 FeaturePtr SketchPlugin_Split::splitEllipticArc(FeaturePtr& theSplitFeature,
956 FeaturePtr& theBaseFeatureModified,
957 FeaturePtr& theAfterFeature,
958 std::set<AttributePoint2DPtr>& thePoints,
959 std::set<FeaturePtr>& theCreatedFeatures,
960 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
962 FeaturePtr anNewFeature;
964 std::set<FeaturePtr> aCreatedFeatures;
965 FeaturePtr aConstraintFeature;
966 theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
968 AttributeReferencePtr aBaseObjectAttr = reference(SELECTED_OBJECT());
969 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
971 AttributePoint2DPtr aFirstPointAttrOfSplit = getPointAttribute(true);
972 AttributePoint2DPtr aSecondPointAttrOfSplit = getPointAttribute(false);
973 AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
974 SketchPlugin_SegmentationTools::getFeaturePoints(
975 aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
976 if (!aStartPointAttrOfBase.get() && !anEndPointAttrOfBase.get()) {
977 setError("Error: Feature has no start and end points.");
981 arrangePointsOnArc(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase,
982 aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
984 std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl;
985 std::cout << "Start point: " <<
986 ModelGeomAlgo_Point2D::getPointAttributeInfo(aStartPointAttrOfBase) << std::endl;
987 std::cout << "1st point: " <<
988 ModelGeomAlgo_Point2D::getPointAttributeInfo(aFirstPointAttrOfSplit) << std::endl;
989 std::cout << "2nd point: " <<
990 ModelGeomAlgo_Point2D::getPointAttributeInfo(aSecondPointAttrOfSplit) << std::endl;
991 std::cout << "End point: " <<
992 ModelGeomAlgo_Point2D::getPointAttributeInfo(anEndPointAttrOfBase) << std::endl;
996 theSplitFeature = SketchPlugin_SegmentationTools::createArcFeature(
997 aBaseFeature, aFirstPointAttrOfSplit->pnt(), aSecondPointAttrOfSplit->pnt());
998 theCreatedFeatures.insert(theSplitFeature);
1000 // before split feature
1001 if (aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
1002 theModifiedAttributes.insert(std::make_pair(aStartPointAttrOfBase,
1003 theSplitFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID())));
1006 theBaseFeatureModified = aBaseFeature; // use base feature to store all constraints here
1007 // move end arc point to start of split
1010 // after split feature
1011 if (!aSecondPointAttrOfSplit->pnt()->isEqual(anEndPointAttrOfBase->pnt())) {
1012 FeaturePtr aFeature;
1013 if (!theBaseFeatureModified.get()) {
1014 aFeature = aBaseFeature; // use base feature to store all constraints here
1015 fillAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), aSecondPointAttrOfSplit);
1016 aFeature->execute(); // to update result
1019 aFeature = SketchPlugin_SegmentationTools::createArcFeature(
1020 aBaseFeature, aSecondPointAttrOfSplit->pnt(), anEndPointAttrOfBase->pnt());
1021 theCreatedFeatures.insert(aFeature);
1022 theModifiedAttributes.insert(std::make_pair(
1023 anEndPointAttrOfBase, aFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID())));
1024 anNewFeature = aFeature;
1026 aConstraintFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
1027 SketchPlugin_ConstraintCoincidence::ID(),
1028 theSplitFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID()),
1029 aFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID()));
1030 theCreatedFeatures.insert(aConstraintFeature);
1032 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1033 (aFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID())));
1034 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1035 (aFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID())));
1037 if (!theBaseFeatureModified.get())
1038 theBaseFeatureModified = aFeature;
1040 theAfterFeature = aFeature;
1043 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1044 theSplitFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID())));
1045 theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
1046 theSplitFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID())));
1048 // base split, that is defined before split feature should be changed at end
1049 // (after the after feature creation). Otherwise modified value will be used in after feature
1050 // before split feature
1051 if (!aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
1052 // move end arc point to start of split
1053 fillAttribute(theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::END_POINT_ID()),
1054 aFirstPointAttrOfSplit);
1055 theBaseFeatureModified->execute(); // to update result
1056 aConstraintFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
1057 SketchPlugin_ConstraintCoincidence::ID(),
1058 theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::END_POINT_ID()),
1059 theSplitFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID()));
1060 theCreatedFeatures.insert(aConstraintFeature);
1062 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1063 theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::START_POINT_ID())));
1064 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1065 theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::END_POINT_ID())));
1068 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1069 theSplitFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID())));
1071 // additional constraints between split and base features
1072 #ifdef CREATE_CONSTRAINTS
1073 aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
1074 SketchPlugin_ConstraintEqual::ID(),
1075 aBaseFeature->lastResult(),
1076 theSplitFeature->lastResult());
1077 theCreatedFeatures.insert(aConstraintFeature);
1078 aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
1079 SketchPlugin_ConstraintTangent::ID(),
1080 theSplitFeature->lastResult(),
1081 aBaseFeature->lastResult());
1082 theCreatedFeatures.insert(aConstraintFeature);
1083 if (theAfterFeature.get()) {
1084 aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
1085 SketchPlugin_ConstraintEqual::ID(),
1086 aBaseFeature->lastResult(),
1087 theAfterFeature->lastResult());
1088 theCreatedFeatures.insert(aConstraintFeature);
1089 aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
1090 SketchPlugin_ConstraintTangent::ID(),
1091 theSplitFeature->lastResult(),
1092 theAfterFeature->lastResult());
1093 theCreatedFeatures.insert(aConstraintFeature);
1096 return anNewFeature;
1099 FeaturePtr SketchPlugin_Split::splitClosed(FeaturePtr& theSplitFeature,
1100 FeaturePtr& theBaseFeatureModified,
1101 FeaturePtr& /*theAfterFeature*/,
1102 std::set<AttributePoint2DPtr>& thePoints,
1103 std::set<FeaturePtr>& theCreatedFeatures,
1104 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
1106 FeaturePtr anNewFeature;
1108 std::set<FeaturePtr> aCreatedFeatures;
1109 FeaturePtr aConstraintFeature;
1110 theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
1112 AttributeReferencePtr aBaseObjectAttr = reference(SELECTED_OBJECT());
1113 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
1115 AttributePoint2DPtr aFirstPointAttrOfSplit = getPointAttribute(true);
1116 AttributePoint2DPtr aSecondPointAttrOfSplit = getPointAttribute(false);
1119 theSplitFeature = SketchPlugin_SegmentationTools::createArcFeature(
1120 aBaseFeature, aFirstPointAttrOfSplit->pnt(), aSecondPointAttrOfSplit->pnt());
1121 const std::string& aReversedAttrName = theSplitFeature->getKind() == SketchPlugin_Arc::ID() ?
1122 SketchPlugin_Arc::REVERSED_ID() : SketchPlugin_EllipticArc::REVERSED_ID();
1123 bool aSplitReversed = theSplitFeature->boolean(aReversedAttrName)->value();
1124 theCreatedFeatures.insert(theSplitFeature);
1126 // base feature is a left part of the circle
1127 theBaseFeatureModified = SketchPlugin_SegmentationTools::createArcFeature(
1128 aBaseFeature, aFirstPointAttrOfSplit->pnt(), aSecondPointAttrOfSplit->pnt());
1129 anNewFeature = theBaseFeatureModified;
1130 theBaseFeatureModified->boolean(aReversedAttrName)->setValue(!aSplitReversed);
1131 theBaseFeatureModified->execute();
1133 if (aBaseFeature->getKind() == SketchPlugin_Circle::ID()) {
1134 theModifiedAttributes.insert(std::make_pair(
1135 aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
1136 theBaseFeatureModified->attribute(SketchPlugin_Arc::CENTER_ID())));
1138 else if (aBaseFeature->getKind() == SketchPlugin_Ellipse::ID()) {
1139 theModifiedAttributes.insert(std::make_pair(
1140 aBaseFeature->attribute(SketchPlugin_Ellipse::CENTER_ID()),
1141 theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::CENTER_ID())));
1142 theModifiedAttributes.insert(std::make_pair(
1143 aBaseFeature->attribute(SketchPlugin_Ellipse::FIRST_FOCUS_ID()),
1144 theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::FIRST_FOCUS_ID())));
1145 theModifiedAttributes.insert(std::make_pair(
1146 aBaseFeature->attribute(SketchPlugin_Ellipse::SECOND_FOCUS_ID()),
1147 theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::SECOND_FOCUS_ID())));
1148 theModifiedAttributes.insert(std::make_pair(
1149 aBaseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID()),
1150 theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::MAJOR_AXIS_START_ID())));
1151 theModifiedAttributes.insert(std::make_pair(
1152 aBaseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()),
1153 theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID())));
1154 theModifiedAttributes.insert(std::make_pair(
1155 aBaseFeature->attribute(SketchPlugin_Ellipse::MINOR_AXIS_START_ID()),
1156 theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::MINOR_AXIS_START_ID())));
1157 theModifiedAttributes.insert(std::make_pair(
1158 aBaseFeature->attribute(SketchPlugin_Ellipse::MINOR_AXIS_END_ID()),
1159 theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::MINOR_AXIS_END_ID())));
1161 // update the PARENT_ID reference for all the features created by the ellipse
1162 const std::set<AttributePtr>& aRefs = aBaseFeature->data()->refsToMe();
1163 std::list<AttributePtr> aRefsToParent;
1164 for (std::set<AttributePtr>::const_iterator aRef = aRefs.begin(); aRef != aRefs.end(); ++aRef) {
1165 if ((*aRef)->id() == SketchPlugin_SketchEntity::PARENT_ID())
1166 aRefsToParent.push_back(*aRef);
1168 for (std::list<AttributePtr>::iterator aRef = aRefsToParent.begin();
1169 aRef != aRefsToParent.end(); ++aRef) {
1170 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(*aRef)->setValue(
1171 theBaseFeatureModified);
1173 FeaturePtr anOwner = ModelAPI_Feature::feature((*aRef)->owner());
1174 SketchPlugin_Tools::replaceInName(anOwner,
1175 aBaseFeature->name(), theBaseFeatureModified->name());
1176 SketchPlugin_Tools::replaceInName(anOwner->lastResult(),
1177 aBaseFeature->name(), theBaseFeatureModified->name());
1181 theCreatedFeatures.insert(theBaseFeatureModified);
1183 const std::string& aStartAttrName = theSplitFeature->getKind() == SketchPlugin_Arc::ID() ?
1184 SketchPlugin_Arc::START_ID() : SketchPlugin_EllipticArc::START_POINT_ID();
1185 const std::string& aEndAttrName = theSplitFeature->getKind() == SketchPlugin_Arc::ID() ?
1186 SketchPlugin_Arc::END_ID() : SketchPlugin_EllipticArc::END_POINT_ID();
1188 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1189 (theBaseFeatureModified->attribute(aStartAttrName)));
1190 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1191 (theBaseFeatureModified->attribute(aEndAttrName)));
1193 // additional constraints between split and base features
1194 aConstraintFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
1195 SketchPlugin_ConstraintCoincidence::ID(),
1196 theBaseFeatureModified->attribute(aEndAttrName),
1197 theSplitFeature->attribute(aEndAttrName));
1198 theCreatedFeatures.insert(aConstraintFeature);
1199 aConstraintFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
1200 SketchPlugin_ConstraintCoincidence::ID(),
1201 theBaseFeatureModified->attribute(aStartAttrName),
1202 theSplitFeature->attribute(aStartAttrName));
1203 theCreatedFeatures.insert(aConstraintFeature);
1205 #ifdef CREATE_CONSTRAINTS
1206 aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
1207 SketchPlugin_ConstraintTangent::ID(),
1208 theSplitFeature->lastResult(),
1209 theBaseFeatureModified->lastResult());
1210 theCreatedFeatures.insert(aConstraintFeature);
1212 return anNewFeature;
1215 void SketchPlugin_Split::arrangePointsOnLine(
1216 const AttributePoint2DPtr& theStartPointAttr,
1217 const AttributePoint2DPtr& /*theEndPointAttr*/,
1218 AttributePoint2DPtr& theFirstPointAttr,
1219 AttributePoint2DPtr& theLastPointAttr) const
1221 // if first point is closer to last point, swap first and last values
1222 if (theStartPointAttr->pnt()->distance(theFirstPointAttr->pnt()) >
1223 theStartPointAttr->pnt()->distance(theLastPointAttr->pnt())) {
1224 AttributePoint2DPtr aTmpPoint = theFirstPointAttr;
1225 theFirstPointAttr = theLastPointAttr;
1226 theLastPointAttr = aTmpPoint;
1230 void SketchPlugin_Split::arrangePointsOnArc(
1231 const FeaturePtr& theArc,
1232 const std::shared_ptr<GeomDataAPI_Point2D>& theStartPointAttr,
1233 const std::shared_ptr<GeomDataAPI_Point2D>& /*theEndPointAttr*/,
1234 std::shared_ptr<GeomDataAPI_Point2D>& theFirstPointAttr,
1235 std::shared_ptr<GeomDataAPI_Point2D>& theSecondPointAttr) const
1237 static const double anAngleTol = 1.e-12;
1239 const std::string& aCenterAttrName = theArc->getKind() == SketchPlugin_Arc::ID() ?
1240 SketchPlugin_Arc::CENTER_ID() : SketchPlugin_EllipticArc::CENTER_ID();
1241 const std::string& aReversedAttrName = theArc->getKind() == SketchPlugin_Arc::ID() ?
1242 SketchPlugin_Arc::REVERSED_ID() : SketchPlugin_EllipticArc::REVERSED_ID();
1244 std::shared_ptr<GeomAPI_Pnt2d> aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1245 theArc->attribute(aCenterAttrName))->pnt();
1246 bool isReversed = theArc->boolean(aReversedAttrName)->value();
1248 // collect directions to each point
1249 std::shared_ptr<GeomAPI_Dir2d> aStartDir(
1250 new GeomAPI_Dir2d(theStartPointAttr->pnt()->xy()->decreased(aCenter->xy())));
1251 std::shared_ptr<GeomAPI_Dir2d> aFirstPtDir(
1252 new GeomAPI_Dir2d(theFirstPointAttr->pnt()->xy()->decreased(aCenter->xy())));
1253 std::shared_ptr<GeomAPI_Dir2d> aSecondPtDir(
1254 new GeomAPI_Dir2d(theSecondPointAttr->pnt()->xy()->decreased(aCenter->xy())));
1256 // sort points by their angular values
1257 double aFirstPtAngle = aStartDir->angle(aFirstPtDir);
1258 double aSecondPtAngle = aStartDir->angle(aSecondPtDir);
1259 double aPeriod = isReversed ? -2.0 * PI : 2.0 * PI;
1260 if (fabs(aFirstPtAngle) > anAngleTol && isReversed == (aFirstPtAngle > 0.))
1261 aFirstPtAngle += aPeriod;
1262 if (fabs(aSecondPtAngle) > anAngleTol && isReversed == (aSecondPtAngle > 0.))
1263 aSecondPtAngle += aPeriod;
1265 if (fabs(aFirstPtAngle) > fabs(aSecondPtAngle)) {
1266 AttributePoint2DPtr aTmpPoint = theFirstPointAttr;
1267 theFirstPointAttr = theSecondPointAttr;
1268 theSecondPointAttr = aTmpPoint;
1272 void SketchPlugin_Split::fillAttribute(const AttributePtr& theModifiedAttribute,
1273 const AttributePtr& theSourceAttribute)
1275 std::string anAttributeType = theModifiedAttribute->attributeType();
1276 if (anAttributeType == GeomDataAPI_Point2D::typeId()) {
1277 AttributePoint2DPtr aModifiedAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1278 theModifiedAttribute);
1279 AttributePoint2DPtr aSourceAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1280 theSourceAttribute);
1282 if (aModifiedAttribute.get() && aSourceAttribute.get())
1283 aModifiedAttribute->setValue(aSourceAttribute->pnt());
1285 else if (anAttributeType == ModelAPI_AttributeBoolean::typeId()) {
1286 AttributeBooleanPtr aModifiedAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(
1287 theModifiedAttribute);
1288 AttributeBooleanPtr aSourceAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(
1289 theSourceAttribute);
1291 if (aModifiedAttribute.get() && aSourceAttribute.get())
1292 aModifiedAttribute->setValue(aSourceAttribute->value());
1297 std::set<std::shared_ptr<ModelAPI_Attribute> > SketchPlugin_Split::getEdgeAttributes(
1298 const std::shared_ptr<ModelAPI_Feature>& theFeature)
1300 std::set<std::shared_ptr<ModelAPI_Attribute> > anAttributes;
1302 std::string aFeatureKind = theFeature->getKind();
1303 if (aFeatureKind == SketchPlugin_Line::ID()) {
1304 anAttributes.insert(theFeature->attribute(SketchPlugin_Line::START_ID()));
1305 anAttributes.insert(theFeature->attribute(SketchPlugin_Line::END_ID()));
1307 else if (aFeatureKind == SketchPlugin_Arc::ID()) {
1308 anAttributes.insert(theFeature->attribute(SketchPlugin_Arc::START_ID()));
1309 anAttributes.insert(theFeature->attribute(SketchPlugin_Arc::END_ID()));
1311 else if (aFeatureKind == SketchPlugin_EllipticArc::ID()) {
1312 anAttributes.insert(theFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID()));
1313 anAttributes.insert(theFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID()));
1315 else if (aFeatureKind == SketchPlugin_Circle::ID()) {
1318 return anAttributes;
1322 std::shared_ptr<GeomDataAPI_Point2D> SketchPlugin_Split::getPointAttribute
1323 (const bool isFirstAttribute)
1325 std::shared_ptr<GeomDataAPI_Point2D> anAttribute;
1327 GeomShapePtr aSelectedShape = SketchPlugin_SegmentationTools::getSubShape(this,
1328 SELECTED_OBJECT(), SELECTED_POINT(), myCashedShapes, myCashedReferences);
1329 if (!aSelectedShape.get())
1332 if (aSelectedShape->shapeType() != GeomAPI_Shape::EDGE)
1335 AttributeReferencePtr anObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
1336 data()->attribute(SELECTED_OBJECT()));
1337 ObjectPtr aBaseObject = anObjectAttr->value();
1338 if (!aBaseObject.get())
1341 std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aSelectedShape));
1343 std::shared_ptr<GeomAPI_Pnt> aFirstPnt = anEdge->firstPoint();
1344 std::shared_ptr<GeomAPI_Pnt> aLastPnt = anEdge->lastPoint();
1346 std::shared_ptr<GeomDataAPI_Point2D> aFirstPointAttr, aLastPointAttr;
1347 // find the points in feature attributes
1348 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObject);
1349 std::list<AttributePtr> a2DPointAttributes = aBaseFeature->data()->attributes(
1350 GeomDataAPI_Point2D::typeId());
1351 std::list<AttributePtr>::const_iterator anIt = a2DPointAttributes.begin(),
1352 aLast = a2DPointAttributes.end();
1353 for (; anIt != aLast; anIt++) {
1354 std::shared_ptr<GeomDataAPI_Point2D> anAttributePoint =
1355 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt);
1356 std::shared_ptr<GeomAPI_Pnt2d> aPoint2D = anAttributePoint->pnt();
1357 std::shared_ptr<GeomAPI_Pnt> aPoint3D = sketch()->to3D(aPoint2D->x(), aPoint2D->y());
1358 if (aFirstPnt->isEqual(aPoint3D))
1359 aFirstPointAttr = anAttributePoint;
1360 else if (aLastPnt->isEqual(aPoint3D))
1361 aLastPointAttr = anAttributePoint;
1364 // find the points in coincident features
1365 const GeomAlgoAPI_ShapeTools::PointToRefsMap& aRefAttributes = myCashedReferences.at(aBaseObject);
1366 GeomAlgoAPI_ShapeTools::PointToRefsMap::const_iterator
1367 aRIt = aRefAttributes.begin(), aRLast = aRefAttributes.end();
1368 for (; aRIt != aRLast; aRIt++) {
1369 const std::list<AttributePoint2DPtr>& anAttributes = aRIt->second.first;
1370 GeomPointPtr aPoint = aRIt->first;
1371 if (!aFirstPointAttr.get() && aFirstPnt->isEqual(aPoint))
1372 aFirstPointAttr = anAttributes.front();
1373 if (!aLastPointAttr.get() && aLastPnt->isEqual(aPoint))
1374 aLastPointAttr = anAttributes.front();
1375 if (aFirstPointAttr.get() && aLastPointAttr.get())
1378 if (!aFirstPointAttr.get() || !aLastPointAttr)
1381 return isFirstAttribute ? aFirstPointAttr : aLastPointAttr;
1385 std::string SketchPlugin_Split::getFeatureInfo(const std::shared_ptr<ModelAPI_Feature>& theFeature,
1386 const bool isUseAttributesInfo)
1389 if (!theFeature.get()) {
1393 if (theFeature->data()->isValid())
1394 anInfo.append(Locale::Convert::toString(theFeature->data()->name()));
1396 if (isUseAttributesInfo) {
1397 std::string aPointsInfo = ModelGeomAlgo_Point2D::getPontAttributesInfo(theFeature,
1398 getEdgeAttributes(theFeature));
1399 // processing of feature with point 2d attributes, like line, arc, circle
1400 if (!aPointsInfo.empty()) {
1403 anInfo += aPointsInfo;
1405 else { // process constraint coincidence, find points in ref attr attributes
1406 std::list<AttributePtr> anAttrs = theFeature->data()->attributes(
1407 ModelAPI_AttributeRefAttr::typeId());
1408 std::list<AttributePtr>::const_iterator anIt = anAttrs.begin(), aLast = anAttrs.end();
1409 std::string anAttributesInfo;
1410 for(; anIt != aLast; anIt++) {
1411 if (!anAttributesInfo.empty()) {
1412 anAttributesInfo.append(", ");
1413 anAttributesInfo += "\n";
1415 AttributePtr anAttr = *anIt;
1416 std::string aValue = "not defined";
1417 std::string aType = anAttr->attributeType();
1418 if (aType == ModelAPI_AttributeRefAttr::typeId()) {
1419 std::shared_ptr<ModelAPI_AttributeRefAttr> aRefAttr =
1420 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
1421 if (aRefAttr.get()) {
1422 if (aRefAttr->isObject()) {
1423 FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
1424 aValue = "<object:>" + getFeatureInfo(aFeature, false);
1427 AttributePtr anAttribute = aRefAttr->attr();
1428 if (anAttribute.get()) {
1429 FeaturePtr aFeature = ModelAPI_Feature::feature(anAttribute->owner());
1430 aValue = "<attr:>" + ModelGeomAlgo_Point2D::getPointAttributeInfo(anAttribute) +
1431 " [" + getFeatureInfo(aFeature, false) + "]";
1436 anAttributesInfo.append(" " + anAttr->id() + ": " + aValue);
1438 if (!anAttributesInfo.empty())
1439 anInfo = anInfo + "\n" + anAttributesInfo;