1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
3 // File: SketchPlugin_Trim.cpp
4 // Created: 22 Feb 2017
5 // Author: Natalia ERMOLAEVA
7 #include "SketchPlugin_Trim.h"
9 #include <GeomAPI_Dir2d.h>
10 #include <GeomAPI_Edge.h>
11 #include <GeomAPI_Pnt2d.h>
12 #include <GeomAPI_XY.h>
13 #include <GeomDataAPI_Point2D.h>
14 #include <GeomAlgoAPI_ShapeTools.h>
15 #include <GeomAlgoAPI_CompoundBuilder.h>
17 #include <ModelAPI_AttributeReference.h>
18 #include <ModelAPI_AttributeString.h>
19 #include <ModelAPI_AttributeRefAttr.h>
20 #include <ModelAPI_Tools.h>
21 #include <ModelAPI_AttributeBoolean.h>
23 #include <ModelAPI_Validator.h>
24 #include <ModelAPI_Session.h>
25 #include <ModelAPI_AttributeDouble.h>
27 #include <ModelGeomAlgo_Shape.h>
29 #include <SketchPlugin_Arc.h>
30 #include <SketchPlugin_ConstraintMiddle.h>
31 #include <SketchPlugin_Circle.h>
32 #include <SketchPlugin_ConstraintCoincidence.h>
33 #include <SketchPlugin_ConstraintEqual.h>
34 //#include <SketchPlugin_ConstraintParallel.h>
35 #include <SketchPlugin_ConstraintTangent.h>
36 #include <SketchPlugin_ConstraintLength.h>
37 #include <SketchPlugin_ConstraintMirror.h>
38 #include <SketchPlugin_ConstraintCollinear.h>
39 #include <SketchPlugin_Line.h>
40 #include <SketchPlugin_MultiRotation.h>
41 #include <SketchPlugin_MultiTranslation.h>
42 #include <SketchPlugin_Point.h>
44 #include <ModelAPI_EventReentrantMessage.h>
46 #include <ModelAPI_Events.h>
47 #include <SketchPlugin_Line.h>
48 #include <SketchPlugin_Arc.h>
49 #include <SketchPlugin_Circle.h>
51 #include <ModelGeomAlgo_Point2D.h>
52 #include <Events_Loop.h>
56 //#define DEBUG_TRIM_METHODS
63 #ifdef DEBUG_TRIM_METHODS
67 static const double PI = 3.141592653589793238463;
69 static const std::string OPERATION_HIGHLIGHT_COLOR() { return "128, 0, 0"; }
70 static const std::string OPERATION_REMOVE_FEATURE_COLOR() { return "255, 174, 201"; }
72 SketchPlugin_Trim::SketchPlugin_Trim()
76 void SketchPlugin_Trim::initAttributes()
78 data()->addAttribute(SketchPlugin_Trim::SELECTED_OBJECT(),
79 ModelAPI_AttributeReference::typeId());
80 data()->addAttribute(SELECTED_POINT(), GeomDataAPI_Point2D::typeId());
82 data()->addAttribute(PREVIEW_POINT(), GeomDataAPI_Point2D::typeId());
83 data()->addAttribute(PREVIEW_OBJECT(), ModelAPI_AttributeReference::typeId());
85 data()->attribute(PREVIEW_POINT())->setIsArgument(false);
86 data()->attribute(SELECTED_POINT())->setIsArgument(false);
87 data()->attribute(PREVIEW_OBJECT())->setIsArgument(false);
89 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PREVIEW_POINT());
90 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PREVIEW_OBJECT());
93 void SketchPlugin_Trim::findShapePoints(const std::string& theObjectAttributeId,
94 const std::string& thePointAttributeId,
95 std::shared_ptr<GeomAPI_Pnt>& aStartPoint,
96 std::shared_ptr<GeomAPI_Pnt>& aLastPoint)
98 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
99 data()->attribute(theObjectAttributeId));
100 ObjectPtr aBaseObject = aBaseObjectAttr->value();
102 AttributePoint2DPtr aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
103 data()->attribute(thePointAttributeId));
104 std::shared_ptr<GeomAPI_Pnt2d> anAttributePnt2d = aPoint->pnt();
105 std::shared_ptr<GeomAPI_Pnt> anAttributePnt = sketch()->to3D(anAttributePnt2d->x(),
106 anAttributePnt2d->y());
108 if (myCashedShapes.find(aBaseObject) == myCashedShapes.end())
109 fillObjectShapes(aBaseObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints);
111 const std::set<GeomShapePtr>& aShapes = myCashedShapes[aBaseObject];
112 if (!aShapes.empty()) {
113 std::set<GeomShapePtr>::const_iterator anIt = aShapes.begin(), aLast = aShapes.end();
114 for (; anIt != aLast; anIt++) {
115 GeomShapePtr aBaseShape = *anIt;
116 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
117 if (ModelGeomAlgo_Point2D::isPointOnEdge(aBaseShape, anAttributePnt, aProjectedPoint)) {
119 if (aBaseShape->shapeType() == GeomAPI_Shape::EDGE) {
120 std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aBaseShape));
121 //GeomAPI_Shape::Orientation anOrientation = anEdge->orientation();
122 //if (anOrientation == GeomAPI_Shape::REVERSED) {
123 aStartPoint = anEdge->lastPoint();
124 aLastPoint = anEdge->firstPoint();
127 //aStartPoint = anEdge->firstPoint();
128 //aLastPoint = anEdge->lastPoint();
135 std::cout << "<findShapePoints> => "
136 << std::endl << "Attribute point: "
137 << anAttributePnt->x() << ", " << anAttributePnt->y() << ", " << anAttributePnt->z() << "]"
138 << std::endl << "Start Point: ["
139 << aStartPoint->x() << ", " << aStartPoint->y() << ", " << aStartPoint->z() << "]"
140 << std::endl << "Last Point: ["
141 << aLastPoint->x() << ", " << aLastPoint->y() << ", " << aLastPoint->z() << "]"
146 std::shared_ptr<GeomAPI_Pnt2d> SketchPlugin_Trim::convertPoint(
147 const std::shared_ptr<GeomAPI_Pnt>& thePoint)
149 std::shared_ptr<GeomAPI_Pnt2d> aPoint;
153 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
154 data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
155 ObjectPtr aBaseObject = aBaseObjectAttr->value();
156 if (myObjectToPoints.find(aBaseObject) == myObjectToPoints.end())
157 fillObjectShapes(aBaseObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints);
160 const PointToRefsMap& aRefsMap = myObjectToPoints.at(aBaseObject);
161 for (PointToRefsMap::const_iterator aPointIt = aRefsMap.begin();
162 aPointIt != aRefsMap.end() && !aFound; aPointIt++) {
163 if (aPointIt->first->isEqual(thePoint)) {
164 const std::pair<std::list<AttributePoint2DPtr >,
165 std::list<ObjectPtr > >& anInfo = aPointIt->second;
166 const std::list<AttributePoint2DPtr >& anAttributes = anInfo.first;
167 if (!anAttributes.empty()) {
168 aPoint = anAttributes.front()->pnt();
172 aPoint = sketch()->to2D(thePoint);
178 // returns an end of the shape to define direction of split if feature's attribute
180 aPoint = sketch()->to2D(thePoint);
185 void SketchPlugin_Trim::execute()
187 #ifdef DEBUG_TRIM_METHODS
188 std::cout << "SketchPlugin_Trim::execute: " << data()->name() << std::endl;
191 SketchPlugin_Sketch* aSketch = sketch();
195 // Check the base objects are initialized.
196 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
197 data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
198 if(!aBaseObjectAttr->isInitialized()) {
199 setError("Error: Base object is not initialized.");
202 ObjectPtr aBaseObject = aBaseObjectAttr->value();
203 if (!aBaseObject.get())
205 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
207 /// Remove reference of this feature to feature used in preview, it is not necessary anymore
208 /// as trim will be removed after execute
209 AttributeReferencePtr aPreviewObjectAttr =
210 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
211 data()->attribute(SketchPlugin_Trim::PREVIEW_OBJECT()));
213 ObjectPtr aPreviewObject = aPreviewObjectAttr->value();
214 AttributePoint2DPtr aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
215 data()->attribute(PREVIEW_POINT()));
216 std::shared_ptr<GeomAPI_Pnt2d> aPreviewPnt2d = aPoint->pnt();
217 // nullify pointer of preview attribute
218 aPreviewObjectAttr->setValue(ResultPtr());
220 bool anIsEqualPreviewAndSelected = aPreviewObject == aBaseObject;
223 std::shared_ptr<GeomAPI_Pnt> aStartShapePoint, aLastShapePoint;
225 std::cout << " Base Feature: " << aBaseFeature->data()->name() << std::endl;
227 findShapePoints(SELECTED_OBJECT(), SELECTED_POINT(), aStartShapePoint, aLastShapePoint);
229 std::shared_ptr<GeomAPI_Pnt2d> aStartShapePoint2d = convertPoint(aStartShapePoint);
230 std::shared_ptr<GeomAPI_Pnt2d> aLastShapePoint2d = convertPoint(aLastShapePoint);
232 std::set<FeaturePtr> aFeaturesToDelete;
233 getConstraints(aFeaturesToDelete);
235 std::map<AttributePtr, std::list<AttributePtr> > aBaseRefAttributes;
236 std::list<AttributePtr> aRefsToFeature;
237 getRefAttributes(aBaseFeature, aBaseRefAttributes, aRefsToFeature);
239 std::cout << "---- getRefAttributes ----" << std::endl;
240 std::map<AttributePtr, std::list<AttributePtr> >::const_iterator
241 aRefIt = aBaseRefAttributes.begin(), aRefLast = aBaseRefAttributes.end();
242 std::cout << std::endl << "References to attributes of base feature [" <<
243 aBaseRefAttributes.size() << "]" << std::endl;
244 for (; aRefIt != aRefLast; aRefIt++) {
245 AttributePtr aBaseAttr = aRefIt->first;
246 std::list<AttributePtr> aRefAttributes = aRefIt->second;
247 std::string aRefsInfo;
248 std::list<AttributePtr>::const_iterator aRefAttrIt = aRefAttributes.begin(),
249 aRefAttrLast = aRefAttributes.end();
250 for (; aRefAttrIt != aRefAttrLast; aRefAttrIt++) {
251 if (!aRefsInfo.empty())
252 aRefsInfo.append(",");
253 AttributePtr aRAttr = *aRefAttrIt;
254 aRefsInfo.append(aRAttr->id());
255 FeaturePtr aRFeature = ModelAPI_Feature::feature(aRAttr->owner());
256 aRefsInfo.append("(" + aRFeature->name() + ") ");
258 std::shared_ptr<GeomDataAPI_Point2D> aPointAttr =
259 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aBaseAttr);
260 std::cout << aPointAttr->id().c_str() <<
261 ": " << "[" << aRefAttributes.size() << "] " << aRefsInfo << std::endl;
263 std::cout << std::endl;
264 std::cout << std::endl << "References to base feature [" <<
265 aRefsToFeature.size() << "]" << std::endl;
266 std::list<AttributePtr>::const_iterator aRefAttrIt = aRefsToFeature.begin(),
267 aRefAttrLast = aRefsToFeature.end();
268 std::string aRefsInfo;
269 for (; aRefAttrIt != aRefAttrLast; aRefAttrIt++) {
270 if (!aRefsInfo.empty())
271 aRefsInfo.append(",");
272 AttributePtr aRAttr = *aRefAttrIt;
273 aRefsInfo.append(aRAttr->id());
274 FeaturePtr aRFeature = ModelAPI_Feature::feature(aRAttr->owner());
275 aRefsInfo.append("(" + aRFeature->name() + ") ");
277 std::cout << "[" << aRefsToFeature.size() << "] " << aRefsInfo << std::endl;
278 std::cout << "---- getRefAttributes:end ----" << std::endl;
280 // coincidence to result points
281 // find coincidences to the base object, it should be used when attribute is found
282 // in myObjectToPoints
283 //std::map<AttributePtr, FeaturePtr> aCoincidencesToBaseFeature;
284 //getCoincidencesToObject(aBaseObject, aCoincidencesToBaseFeature);
286 std::set<AttributePoint2DPtr> aFurtherCoincidences;
287 std::set<std::pair<AttributePtr, AttributePtr>> aModifiedAttributes;
288 const std::string& aKind = aBaseFeature->getKind();
289 FeaturePtr aReplacingFeature, aNewFeature;
290 if (aKind == SketchPlugin_Circle::ID()) {
291 aReplacingFeature = trimCircle(aStartShapePoint2d, aLastShapePoint2d,
292 aFurtherCoincidences, aModifiedAttributes);
294 aFeaturesToDelete.insert(aBaseFeature);
295 // as circle is removed, erase it from dependencies(arguments) of this feature
296 // otherwise Trim feature will be removed with the circle before
297 // this operation is finished
298 aBaseObjectAttr->setObject(ResultPtr());
300 else if (aKind == SketchPlugin_Line::ID()) {
301 aNewFeature = trimLine(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes,
302 aFurtherCoincidences, aModifiedAttributes);
304 else if (aKind == SketchPlugin_Arc::ID()) {
305 aNewFeature = trimArc(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes,
306 aFurtherCoincidences, aModifiedAttributes);
309 // constraints to end points of trim feature
310 if (myObjectToPoints.find(aBaseObject) == myObjectToPoints.end())
311 fillObjectShapes(aBaseObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints);
313 // create coincidence to objects, intersected the base object
314 const PointToRefsMap& aRefsMap = myObjectToPoints.at(aBaseObject);
315 for (std::set<AttributePoint2DPtr>::const_iterator anIt = aFurtherCoincidences.begin(),
316 aLast = aFurtherCoincidences.end();
317 anIt != aLast; anIt++) {
318 AttributePoint2DPtr aPointAttribute = (*anIt);
319 std::shared_ptr<GeomAPI_Pnt2d> aPoint2d = aPointAttribute->pnt();
322 std::cout << "<compare Points> => " << std::endl
323 << "aPoint2d: [" << aPoint2d->x() << ", " << aPoint2d->y() << "]" << std::endl;
324 if (aStartShapePoint2d.get())
325 std::cout << "Start Point: [" << aStartShapePoint2d->x() << ", " << aStartShapePoint2d->y()
327 if (aLastShapePoint2d.get())
328 std::cout << "Last Point: [" << aLastShapePoint2d->x() << ", " << aLastShapePoint2d->y()
332 std::shared_ptr<GeomAPI_Pnt> aPoint;
333 if (aStartShapePoint2d.get() && aPoint2d->isEqual(aStartShapePoint2d))
334 aPoint = aStartShapePoint;
335 else if (aLastShapePoint2d.get() && aPoint2d->isEqual(aLastShapePoint2d))
336 aPoint = aLastShapePoint;
341 std::pair<std::list<AttributePoint2DPtr >, std::list<ObjectPtr > > anInfo;
342 for (PointToRefsMap::const_iterator aRefIt = aRefsMap.begin(); aRefIt != aRefsMap.end();
345 if (aRefIt->first->isEqual(aPoint)) {
346 anInfo = aRefIt->second;
350 const std::list<ObjectPtr>& anObjects = anInfo.second;
351 for (std::list<ObjectPtr>::const_iterator anObjectIt = anObjects.begin();
352 anObjectIt != anObjects.end(); anObjectIt++) {
353 createConstraintToObject(SketchPlugin_ConstraintCoincidence::ID(), aPointAttribute,
358 // move constraints from base feature to replacing feature: ignore coincidences to feature
359 // if attributes of coincidence participated in split
360 ResultPtr aReplacingResult;
361 if (aReplacingFeature.get()) {
362 aReplacingFeature->execute(); // need it to obtain result
363 aReplacingResult = getFeatureResult(aReplacingFeature);
365 for(std::list<AttributePtr>::const_iterator anIt = aRefsToFeature.begin(),
366 aLast = aRefsToFeature.end();
367 anIt != aLast; anIt++) {
368 AttributePtr anAttribute = *anIt;
370 //if (replaceCoincidenceAttribute(anAttribute, aModifiedAttributes))
373 if (setCoincidenceToAttribute(anAttribute, aFurtherCoincidences))
376 if (aReplacingResult.get()) {
377 AttributeRefAttrPtr aRefAttr =
378 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
380 aRefAttr->setObject(aReplacingResult);
382 AttributeReferencePtr aReferenceAttr =
383 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(anAttribute);
384 if (aReferenceAttr.get())
385 aReferenceAttr->setObject(aReplacingResult);
390 updateRefAttConstraints(aBaseRefAttributes, aModifiedAttributes, aFeaturesToDelete);
392 // Wait all constraints being created, then send update events
393 static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
394 bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
396 Events_Loop::loop()->setFlushed(anUpdateEvent, false);
398 // delete constraints
400 if (aFeaturesToDelete.size() > 0) {
401 std::cout << "after SPlit: removeFeaturesAndReferences: " << std::endl;
403 for (std::set<FeaturePtr>::const_iterator anIt = aFeaturesToDelete.begin();
404 anIt != aFeaturesToDelete.end(); anIt++) {
405 FeaturePtr aFeature = *anIt;
406 std::cout << aFeature->data()->name() << std::endl;
410 ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToDelete);
411 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
413 // Send events to update the sub-features by the solver.
414 if(isUpdateFlushed) {
415 Events_Loop::loop()->setFlushed(anUpdateEvent, true);
418 if (anIsEqualPreviewAndSelected) {
419 // equal preview and selected objects
420 // nothing to do if the preview and selected objects are different
421 if (aReplacingResult.get()) { // base object was removed
422 aPreviewObject = aReplacingResult;
423 //aMessage->setSelectedObject(aReplacingResult);
425 GeomShapePtr aSelectedShape = aReplacingResult->shape();
426 std::shared_ptr<GeomAPI_Pnt> aPreviewPnt = sketch()->to3D(aPreviewPnt2d->x(),
428 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
429 if (ModelGeomAlgo_Point2D::isPointOnEdge(aSelectedShape, aPreviewPnt, aProjectedPoint)) {
432 //aBaseShape = aShape;
434 #ifdef DEBUG_TRIM_METHODS
435 if (!aSelectedShape.get())
436 std::cout << "Set empty selected object" << std::endl;
438 std::cout << "Set shape with ShapeType: " << aSelectedShape->shapeTypeStr() << std::endl;
443 aPreviewObject = ObjectPtr();
445 aBaseFeature->execute(); // should recompute shapes of result to do not check obsolete one
446 aBaseObject = getFeatureResult(aBaseFeature);
447 std::shared_ptr<GeomAPI_Pnt> aPreviewPnt = sketch()->to3D(aPreviewPnt2d->x(),
449 ResultPtr aBaseResult = std::dynamic_pointer_cast<ModelAPI_Result>(aBaseObject);
451 GeomShapePtr aShape = aBaseResult->shape();
452 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
453 if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, aPreviewPnt, aProjectedPoint))
454 aPreviewObject = aBaseResult;
456 if (!aPreviewObject.get() && aNewFeature.get()) {
457 ResultPtr aNewFeatureResult = getFeatureResult(aNewFeature);
458 if (aNewFeatureResult.get()) {
459 GeomShapePtr aShape = aNewFeatureResult->shape();
460 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
461 if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, aPreviewPnt, aProjectedPoint))
462 aPreviewObject = aNewFeatureResult;
467 if (aPreviewObject.get()) {
468 std::shared_ptr<ModelAPI_EventReentrantMessage> aMessage = std::shared_ptr
469 <ModelAPI_EventReentrantMessage>(new ModelAPI_EventReentrantMessage(
470 ModelAPI_EventReentrantMessage::eventId(), this));
471 aMessage->setSelectedObject(aPreviewObject);
472 Events_Loop::loop()->send(aMessage);
475 std::cout << "SketchPlugin_Trim::done" << std::endl;
479 std::string SketchPlugin_Trim::processEvent(const std::shared_ptr<Events_Message>& theMessage)
481 #ifdef DEBUG_TRIM_METHODS
482 std::cout << "SketchPlugin_Trim::processEvent:" << data()->name() << std::endl;
485 std::string aFilledAttributeName;
487 std::shared_ptr<ModelAPI_EventReentrantMessage> aMessage =
488 std::dynamic_pointer_cast<ModelAPI_EventReentrantMessage>(theMessage);
489 if (aMessage.get()) {
490 ObjectPtr anObject = aMessage->selectedObject();
491 std::shared_ptr<GeomAPI_Pnt2d> aPoint = aMessage->clickedPoint();
493 if (anObject.get() && aPoint.get()) {
494 std::shared_ptr<ModelAPI_AttributeReference> aRefSelectedAttr =
495 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
496 data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
497 std::shared_ptr<ModelAPI_AttributeReference> aRefPreviewAttr =
498 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
499 data()->attribute(SketchPlugin_Trim::PREVIEW_OBJECT()));
500 aRefSelectedAttr->setValue(anObject);
501 aRefPreviewAttr->setValue(anObject);
503 std::shared_ptr<GeomDataAPI_Point2D> aPointSelectedAttr =
504 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
505 data()->attribute(SketchPlugin_Trim::SELECTED_POINT()));
506 std::shared_ptr<GeomDataAPI_Point2D> aPointPreviewAttr =
507 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
508 data()->attribute(SketchPlugin_Trim::PREVIEW_POINT()));
509 aPointSelectedAttr->setValue(aPoint);
510 aPointPreviewAttr->setValue(aPoint);
512 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
514 GeomShapePtr aSelectedShape = getSubShape(SELECTED_OBJECT(), SELECTED_POINT());
515 #ifdef DEBUG_TRIM_METHODS
516 if (!aSelectedShape.get())
517 std::cout << "Set empty selected object" << std::endl;
519 std::cout << "Set shape with ShapeType: " << aSelectedShape->shapeTypeStr() << std::endl;
521 aFilledAttributeName = SketchPlugin_Trim::SELECTED_OBJECT();
524 return aFilledAttributeName;
527 bool SketchPlugin_Trim::setCoincidenceToAttribute(const AttributePtr& theAttribute,
528 const std::set<AttributePoint2DPtr>& theFurtherCoincidences)
530 FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
531 if (aFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID())
534 AttributePoint2DPtr aRefPointAttr = SketchPlugin_ConstraintCoincidence::getPoint(aFeature);
535 if (!aRefPointAttr.get())
537 std::shared_ptr<GeomAPI_Pnt2d> aRefPnt2d = aRefPointAttr->pnt();
539 std::set<AttributePoint2DPtr>::const_iterator anIt = theFurtherCoincidences.begin(),
540 aLast = theFurtherCoincidences.end();
541 bool aFoundPoint = false;
542 for (; anIt != aLast && !aFoundPoint; anIt++) {
543 AttributePoint2DPtr aPointAttribute = (*anIt);
544 std::shared_ptr<GeomAPI_Pnt2d> aPoint2d = aPointAttribute->pnt();
545 if (aPoint2d->isEqual(aRefPnt2d)) {
546 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
548 if (aRefAttr.get()) {
549 aRefAttr->setAttr(aPointAttribute);
557 bool SketchPlugin_Trim::replaceCoincidenceAttribute(const AttributePtr& theCoincidenceAttribute,
558 const std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
560 FeaturePtr aCoincidenceFeature = ModelAPI_Feature::feature(theCoincidenceAttribute->owner());
561 if (aCoincidenceFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID())
564 AttributeRefAttrPtr aCAttrA = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
565 aCoincidenceFeature->attribute(SketchPlugin_Constraint::ENTITY_A()));
566 AttributeRefAttrPtr aCAttrB = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
567 aCoincidenceFeature->attribute(SketchPlugin_Constraint::ENTITY_B()));
568 AttributePtr aCAttrRefA = aCAttrA->attr();
569 AttributePtr aCAttrRefB = aCAttrB->attr();
571 bool isProcessed = false;
572 for (std::set<std::pair<AttributePtr, AttributePtr>>::const_iterator
573 anIt = theModifiedAttributes.begin(); anIt != theModifiedAttributes.end(); anIt++) {
574 AttributePtr anAttributeBefore = anIt->first;
575 if (anAttributeBefore == aCAttrRefA) {
576 aCAttrA->setAttr(anIt->second);
579 if (anAttributeBefore == aCAttrRefB) {
580 aCAttrB->setAttr(anIt->second);
587 bool SketchPlugin_Trim::isMacro() const
592 AISObjectPtr SketchPlugin_Trim::getAISObject(AISObjectPtr thePrevious)
594 #ifdef DEBUG_TRIM_METHODS
595 std::cout << "SketchPlugin_Trim::getAISObject: " << data()->name() << std::endl;
598 AISObjectPtr anAIS = thePrevious;
600 std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
601 GeomShapePtr aPreviewShape = getSubShape(PREVIEW_OBJECT(), PREVIEW_POINT());
602 if (aPreviewShape.get())
603 aShapes.push_back(aPreviewShape);
604 GeomShapePtr aSelectedShape = getSubShape(SELECTED_OBJECT(), SELECTED_POINT());
605 if (aSelectedShape.get())
606 aShapes.push_back(aSelectedShape);
609 return AISObjectPtr();
611 GeomShapePtr aBaseShape = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
612 if (!aBaseShape.get())
613 return AISObjectPtr();
615 if (aBaseShape.get()) {
617 anAIS = AISObjectPtr(new GeomAPI_AISObject);
618 anAIS->createShape(aBaseShape);
620 std::vector<int> aColor;
621 aColor = Config_PropManager::color("Visualization", "operation_remove_feature_color");
622 double aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH();
623 int aLineStyle = SketchPlugin_SketchEntity::SKETCH_LINE_STYLE();
624 anAIS->setColor(aColor[0], aColor[1], aColor[2]);
625 // width when there is not base object should be extened in several points
626 // in order to see this preview over highlight
627 anAIS->setWidth(aWidth+4);
628 anAIS->setLineStyle(aLineStyle);
631 anAIS = AISObjectPtr();
636 GeomShapePtr SketchPlugin_Trim::getSubShape(const std::string& theObjectAttributeId,
637 const std::string& thePointAttributeId)
639 GeomShapePtr aBaseShape;
641 AttributeReferencePtr anObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
642 data()->attribute(theObjectAttributeId));
643 ObjectPtr aBaseObject = anObjectAttr->value();
644 if (!aBaseObject.get())
648 AttributePoint2DPtr aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
649 data()->attribute(thePointAttributeId));
650 std::shared_ptr<GeomAPI_Pnt2d> anAttributePnt2d = aPoint->pnt();
651 std::shared_ptr<GeomAPI_Pnt> anAttributePnt = sketch()->to3D(anAttributePnt2d->x(),
652 anAttributePnt2d->y());
654 if (myCashedShapes.find(aBaseObject) == myCashedShapes.end())
655 fillObjectShapes(aBaseObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints);
657 const std::set<GeomShapePtr>& aShapes = myCashedShapes[aBaseObject];
658 if (!aShapes.empty()) {
659 std::set<GeomShapePtr>::const_iterator anIt = aShapes.begin(), aLast = aShapes.end();
660 for (; anIt != aLast; anIt++) {
661 GeomShapePtr aShape = *anIt;
662 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
663 if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, anAttributePnt, aProjectedPoint))
670 void SketchPlugin_Trim::getFeaturePoints(const FeaturePtr& theFeature,
671 AttributePoint2DPtr& theStartPointAttr,
672 AttributePoint2DPtr& theEndPointAttr)
674 std::string aFeatureKind = theFeature->getKind();
675 std::string aStartAttributeName, anEndAttributeName;
676 if (aFeatureKind == SketchPlugin_Line::ID()) {
677 aStartAttributeName = SketchPlugin_Line::START_ID();
678 anEndAttributeName = SketchPlugin_Line::END_ID();
680 else if (aFeatureKind == SketchPlugin_Arc::ID()) {
681 aStartAttributeName = SketchPlugin_Arc::START_ID();
682 anEndAttributeName = SketchPlugin_Arc::END_ID();
684 if (!aStartAttributeName.empty() && !anEndAttributeName.empty()) {
685 theStartPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
686 theFeature->attribute(aStartAttributeName));
687 theEndPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
688 theFeature->attribute(anEndAttributeName));
692 void SketchPlugin_Trim::getConstraints(std::set<FeaturePtr>& theFeaturesToDelete)
694 std::shared_ptr<ModelAPI_Data> aData = data();
696 // Check the base objects are initialized.
697 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
698 aData->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
699 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
700 ResultPtr aBaseFeatureResult = getFeatureResult(aBaseFeature);
702 std::set<AttributePtr> aRefsList = aBaseFeatureResult->data()->refsToMe();
703 std::set<AttributePtr> aFRefsList = aBaseFeature->data()->refsToMe();
704 aRefsList.insert(aFRefsList.begin(), aFRefsList.end());
706 std::set<AttributePtr>::const_iterator aIt;
707 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
708 std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
709 FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
710 std::string aRefFeatureKind = aRefFeature->getKind();
711 if (aRefFeatureKind == SketchPlugin_ConstraintMirror::ID() ||
712 aRefFeatureKind == SketchPlugin_MultiRotation::ID() ||
713 aRefFeatureKind == SketchPlugin_MultiTranslation::ID() ||
714 aRefFeatureKind == SketchPlugin_ConstraintMiddle::ID())
715 theFeaturesToDelete.insert(aRefFeature);
719 void SketchPlugin_Trim::getRefAttributes(const FeaturePtr& theFeature,
720 std::map<AttributePtr, std::list<AttributePtr> >& theRefs,
721 std::list<AttributePtr>& theRefsToFeature)
725 std::list<AttributePtr> aPointAttributes =
726 theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
727 std::set<AttributePtr> aPointAttributesSet;
729 std::list<AttributePtr>::const_iterator aPIt =
730 aPointAttributes.begin(), aPLast = aPointAttributes.end();
731 for (; aPIt != aPLast; aPIt++)
732 aPointAttributesSet.insert(*aPIt);
734 std::set<AttributePtr> aRefsAttributes = getFeatureResult(theFeature)->data()->refsToMe();
735 std::set<AttributePtr> aFRefsList = theFeature->data()->refsToMe();
736 aRefsAttributes.insert(aFRefsList.begin(), aFRefsList.end());
738 std::set<AttributePtr>::const_iterator aIt;
739 for (aIt = aRefsAttributes.cbegin(); aIt != aRefsAttributes.cend(); ++aIt) {
740 AttributePtr anAttr = (*aIt);
741 FeaturePtr anAttrFeature = ModelAPI_Feature::feature(anAttr->owner());
742 if (anAttrFeature.get() != this &&
743 anAttr.get() && anAttr->attributeType() == ModelAPI_AttributeRefAttr::typeId()) {
744 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
745 if (!aRefAttr->isObject()) { /// find attributes referenced to feature point attributes
746 AttributePtr anAttrInRef = aRefAttr->attr();
747 if (anAttrInRef.get() &&
748 aPointAttributesSet.find(anAttrInRef) != aPointAttributesSet.end()) {
749 if (theRefs.find(anAttrInRef) != theRefs.end())
750 theRefs[anAttrInRef].push_back(aRefAttr);
752 std::list<AttributePtr> anAttrList;
753 anAttrList.push_back(aRefAttr);
754 theRefs[anAttrInRef] = anAttrList;
758 else { /// find attributes referenced to feature itself
759 theRefsToFeature.push_back(anAttr);
765 /*void SketchPlugin_Trim::getCoincidencesToObject(const ObjectPtr& theObject,
766 std::map<AttributePtr, FeaturePtr>& theCoincidencesToBaseFeature)
768 const std::set<AttributePtr>& aRefsList = theObject->data()->refsToMe();
769 std::set<AttributePtr>::const_iterator aIt;
770 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
771 std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
772 FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
773 if (aRefFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID())
775 AttributePtr anAttribute;
776 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>
777 (aRefFeature->attribute(SketchPlugin_Constraint::ENTITY_A()));
778 if (aRefAttr->isObject() && aRefAttr->object() == theObject)
780 anAttribute = aRefFeature->attribute(SketchPlugin_Constraint::ENTITY_B());
783 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>
784 (aRefFeature->attribute(SketchPlugin_Constraint::ENTITY_B()));
785 if (aRefAttr->isObject() && aRefAttr->object() == theObject)
786 anAttribute = aRefFeature->attribute(SketchPlugin_Constraint::ENTITY_A());
788 if (!anAttribute.get())
791 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
792 if (aRefAttr->isObject())
793 continue; // one of attributes of coincidence contains link to an attribute
795 anAttribute = aRefAttr->attr();
796 if (anAttribute.get())
798 theCoincidencesToBaseFeature[anAttribute] = aRefFeature;
803 void SketchPlugin_Trim::updateRefAttConstraints(
804 const std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
805 const std::set<std::pair<AttributePtr, AttributePtr> >& theModifiedAttributes,
806 std::set<FeaturePtr>& theFeaturesToDelete)
809 std::cout << "SketchPlugin_Trim::updateRefAttConstraints" << std::endl;
812 std::set<std::pair<AttributePtr, AttributePtr> >::const_iterator
813 anIt = theModifiedAttributes.begin(), aLast = theModifiedAttributes.end();
814 for (; anIt != aLast; anIt++) {
815 AttributePtr anAttribute = anIt->first;
817 /// not found in references
818 if (theBaseRefAttributes.find(anAttribute) == theBaseRefAttributes.end())
820 std::list<AttributePtr> aRefAttributes = theBaseRefAttributes.at(anAttribute);
821 std::list<AttributePtr>::const_iterator aRefIt = aRefAttributes.begin(),
822 aRLast = aRefAttributes.end();
824 AttributePtr aNewAttribute = anIt->second;
825 if (aNewAttribute.get()) {
826 for (; aRefIt != aRLast; aRefIt++) {
827 AttributeRefAttrPtr aRefAttr =
828 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefIt);
829 if (aRefAttr.get()) {
830 aRefAttr->setAttr(aNewAttribute);
837 void SketchPlugin_Trim::removeReferencesToAttribute(const AttributePtr& theAttribute,
838 std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes)
840 /// not found in references
841 if (theBaseRefAttributes.find(theAttribute) == theBaseRefAttributes.end())
844 std::list<AttributePtr> aRefAttributes = theBaseRefAttributes.at(theAttribute);
845 std::list<AttributePtr>::const_iterator aRefIt = aRefAttributes.begin(),
846 aRLast = aRefAttributes.end();
848 std::set<FeaturePtr> aFeaturesToDelete;
849 for (; aRefIt != aRLast; aRefIt++) {
850 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefIt);
851 if (aRefAttr.get()) {
852 aFeaturesToDelete.insert(ModelAPI_Feature::feature(aRefAttr->owner()));
857 // delete constraints
858 if (aFeaturesToDelete.size() > 0) {
859 std::cout << "removeReferencesToAttribute: " << std::endl;
861 for (std::set<FeaturePtr>::const_iterator anIt = aFeaturesToDelete.begin();
862 anIt != aFeaturesToDelete.end(); anIt++) {
863 FeaturePtr aFeature = *anIt;
864 std::cout << aFeature->data()->name() << std::endl;
868 ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToDelete);
869 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
872 FeaturePtr SketchPlugin_Trim::trimLine(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
873 const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
874 std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
875 std::set<AttributePoint2DPtr>& thePoints,
876 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
878 FeaturePtr anNewFeature;
880 // Check the base objects are initialized.
881 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
882 data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
883 ObjectPtr aBaseObject = aBaseObjectAttr->value();
884 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
887 AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
888 getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
890 std::shared_ptr<GeomAPI_Pnt2d> aStartFeaturePoint = aStartPointAttrOfBase->pnt();
891 std::shared_ptr<GeomAPI_Pnt2d> aLastFeaturePoint = anEndPointAttrOfBase->pnt();
893 std::shared_ptr<GeomAPI_Pnt2d> aStartShapePoint = theStartShapePoint;
894 std::shared_ptr<GeomAPI_Pnt2d> aLastShapePoint = theLastShapePoint;
895 arrangePointsOnLine(aStartPointAttrOfBase, anEndPointAttrOfBase,
896 aStartShapePoint, aLastShapePoint);
898 std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl;
899 if (aStartShapePoint.get())
900 std::cout << "Start point: [" << aStartShapePoint->x() << ", " <<
901 aStartShapePoint->y() << "]" << std::endl;
902 std::cout << "1st point: [" << aStartFeaturePoint->x() << ", " <<
903 aStartFeaturePoint->y() << "]" << std::endl;
904 if (aLastShapePoint.get())
905 std::cout << "2st point: [" << aLastShapePoint->x() << ", " <<
906 aLastShapePoint->y() << "]" << std::endl;
907 std::cout << "End point: [" << aLastFeaturePoint->x() << ", " <<
908 aLastFeaturePoint->y() << "]" << std::endl;
911 bool isStartPoint = !aStartShapePoint.get() || aStartFeaturePoint->isEqual(aStartShapePoint);
912 bool isLastPoint = !aLastShapePoint.get() || aLastFeaturePoint->isEqual(aLastShapePoint);
913 if (isStartPoint || isLastPoint) {
914 // result is one line: changed existing line
915 std::string aModifiedAttribute = isStartPoint ? SketchPlugin_Line::START_ID()
916 : SketchPlugin_Line::END_ID();
917 std::shared_ptr<GeomAPI_Pnt2d> aPoint;
918 if (aStartShapePoint.get() && aLastShapePoint.get())
919 aPoint = isStartPoint ? aLastShapePoint : aStartShapePoint;
921 aPoint = aStartShapePoint.get() ? aStartShapePoint : aLastShapePoint;
923 // it is important to delete references before the feature modification because
924 // if deletion will be after the feature modification, solver returns the feature back
925 removeReferencesToAttribute(aBaseFeature->attribute(aModifiedAttribute),
926 theBaseRefAttributes);
928 fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aPoint);
929 //theModifiedAttributes.insert(
930 // std::make_pair(aBaseFeature->attribute(aModifiedAttribute), AttributePtr()));
932 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
933 (aBaseFeature->attribute(aModifiedAttribute)));
936 // result is two lines: start line point - start shape point,
937 // last shape point - last line point
938 // create second line
939 anNewFeature = createLineFeature(aBaseFeature, aLastShapePoint, aLastFeaturePoint);
940 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
941 (anNewFeature->attribute(SketchPlugin_Line::START_ID())));
943 std::string aModifiedAttribute = SketchPlugin_Line::END_ID();
944 theModifiedAttributes.insert(
945 std::make_pair(aBaseFeature->attribute(aModifiedAttribute),
946 anNewFeature->attribute(SketchPlugin_Line::END_ID())));
949 fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aStartShapePoint);
951 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
952 (aBaseFeature->attribute(aModifiedAttribute)));
954 // Collinear constraint for lines
955 createConstraintForObjects(SketchPlugin_ConstraintCollinear::ID(),
956 getFeatureResult(aBaseFeature),
957 getFeatureResult(anNewFeature));
963 FeaturePtr SketchPlugin_Trim::trimArc(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
964 const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
965 std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
966 std::set<AttributePoint2DPtr>& thePoints,
967 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
969 FeaturePtr anNewFeature;
970 // Check the base objects are initialized.
971 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
972 data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
973 ObjectPtr aBaseObject = aBaseObjectAttr->value();
974 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
977 AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
978 getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
980 std::shared_ptr<GeomAPI_Pnt2d> aStartArcPoint = aStartPointAttrOfBase->pnt();
981 std::shared_ptr<GeomAPI_Pnt2d> aLastArcPoint = anEndPointAttrOfBase->pnt();
983 std::shared_ptr<GeomAPI_Pnt2d> aStartShapePoint = theStartShapePoint;
984 std::shared_ptr<GeomAPI_Pnt2d> aLastShapePoint = theLastShapePoint;
985 arrangePointsOnArc(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase,
986 aStartShapePoint, aLastShapePoint);
988 std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl;
989 if (aStartShapePoint.get())
990 std::cout << "Start shape point: [" << aStartShapePoint->x() << ", " <<
991 aStartShapePoint->y() << "]" << std::endl;
992 std::cout << "Start arc attribute point: [" << aStartArcPoint->x() << ", " <<
993 aStartArcPoint->y() << "]" << std::endl;
994 if (aLastShapePoint.get())
995 std::cout << "Last shape point: [" << aLastShapePoint->x() << ", " <<
996 aLastShapePoint->y() << "]" << std::endl;
997 std::cout << "Last arc attribute point: [" << aLastArcPoint->x() << ", " <<
998 aLastArcPoint->y() << "]" << std::endl;
1001 bool isStartPoint = !aStartShapePoint.get() || aStartArcPoint->isEqual(aStartShapePoint);
1002 bool isLastPoint = !aLastShapePoint.get() || aLastArcPoint->isEqual(aLastShapePoint);
1003 if (isStartPoint || isLastPoint) {
1004 // result is one arc: changed existing arc
1005 std::string aModifiedAttribute = isStartPoint ? SketchPlugin_Arc::START_ID()
1006 : SketchPlugin_Arc::END_ID();
1007 std::shared_ptr<GeomAPI_Pnt2d> aPoint;
1008 if (aStartShapePoint.get() && aLastShapePoint.get())
1009 aPoint = isStartPoint ? aLastShapePoint : aStartShapePoint;
1011 aPoint = aStartShapePoint.get() ? aStartShapePoint : aLastShapePoint;
1013 removeReferencesToAttribute(aBaseFeature->attribute(aModifiedAttribute),
1014 theBaseRefAttributes);
1016 fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aPoint);
1018 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1019 (aBaseFeature->attribute(aModifiedAttribute)));
1022 // result is two arcs: start arc point - start shape point, last shape point - last arc point
1023 // create second arc
1024 anNewFeature = createArcFeature(aBaseFeature, aLastShapePoint, aLastArcPoint);
1025 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1026 (anNewFeature->attribute(SketchPlugin_Arc::START_ID())));
1028 std::string aModifiedAttribute = SketchPlugin_Arc::END_ID();
1029 theModifiedAttributes.insert(
1030 std::make_pair(aBaseFeature->attribute(aModifiedAttribute),
1031 anNewFeature->attribute(SketchPlugin_Arc::END_ID())));
1034 fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aStartShapePoint);
1036 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1037 (aBaseFeature->attribute(aModifiedAttribute)));
1039 // equal Radius constraint for arcs
1040 anNewFeature->execute(); // we need the created arc result to set equal constraint
1041 createConstraintForObjects(SketchPlugin_ConstraintEqual::ID(),
1042 getFeatureResult(aBaseFeature),
1043 getFeatureResult(anNewFeature));
1044 // coincident centers constraint
1045 createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
1046 aBaseFeature->attribute(SketchPlugin_Arc::CENTER_ID()),
1047 anNewFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
1050 std::cout << "Created arc on points:" << std::endl;
1051 std::cout << "Start shape point: [" << aStartShapePoint->x() << ", " <<
1052 aStartShapePoint->y() << "]" << std::endl;
1055 return anNewFeature;
1058 FeaturePtr SketchPlugin_Trim::trimCircle(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
1059 const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
1060 std::set<AttributePoint2DPtr>& thePoints,
1061 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
1063 // Check the base objects are initialized.
1064 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
1065 data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
1066 ObjectPtr aBaseObject = aBaseObjectAttr->value();
1067 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
1070 //AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
1071 //getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
1074 FeaturePtr anNewFeature = createArcFeature(aBaseFeature, theStartShapePoint, theLastShapePoint);
1075 // arc created by trim of circle is always correct, that means that it is not inversed
1076 anNewFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(false);
1078 theModifiedAttributes.insert(
1079 std::make_pair(aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
1080 anNewFeature->attribute(SketchPlugin_Arc::CENTER_ID())));
1082 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1083 (anNewFeature->attribute(SketchPlugin_Arc::START_ID())));
1084 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1085 (anNewFeature->attribute(SketchPlugin_Arc::END_ID())));
1087 return anNewFeature;
1090 void SketchPlugin_Trim::arrangePointsOnLine(const AttributePoint2DPtr& theStartPointAttr,
1091 const AttributePoint2DPtr& theEndPointAttr,
1092 std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
1093 std::shared_ptr<GeomAPI_Pnt2d>& theLastPoint) const
1095 if (!theFirstPoint.get() || !theLastPoint.get())
1098 // if first point is closer to last point, swap first and last values
1099 if (theStartPointAttr->pnt()->distance(theFirstPoint) >
1100 theStartPointAttr->pnt()->distance(theLastPoint)) {
1101 std::shared_ptr<GeomAPI_Pnt2d> aTmpPoint = theFirstPoint;
1102 theFirstPoint = theLastPoint;
1103 theLastPoint = aTmpPoint;
1107 void SketchPlugin_Trim::arrangePointsOnArc(const FeaturePtr& theArc,
1108 const AttributePoint2DPtr& theStartPointAttr,
1109 const AttributePoint2DPtr& theEndPointAttr,
1110 std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
1111 std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint) const
1113 if (!theFirstPoint.get() || !theSecondPoint.get())
1116 static const double anAngleTol = 1.e-12;
1118 std::shared_ptr<GeomAPI_Pnt2d> aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1119 theArc->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt();
1120 bool isReversed = theArc->boolean(SketchPlugin_Arc::REVERSED_ID())->value();
1122 // collect directions to each point
1123 std::shared_ptr<GeomAPI_Dir2d> aStartDir(
1124 new GeomAPI_Dir2d(theStartPointAttr->pnt()->xy()->decreased(aCenter->xy())));
1125 std::shared_ptr<GeomAPI_Dir2d> aFirstPtDir(
1126 new GeomAPI_Dir2d(theFirstPoint->xy()->decreased(aCenter->xy())));
1127 std::shared_ptr<GeomAPI_Dir2d> aSecondPtDir(
1128 new GeomAPI_Dir2d(theSecondPoint->xy()->decreased(aCenter->xy())));
1130 // sort points by their angular values
1131 double aFirstPtAngle = aStartDir->angle(aFirstPtDir);
1132 double aSecondPtAngle = aStartDir->angle(aSecondPtDir);
1133 double aPeriod = isReversed ? -2.0 * PI : 2.0 * PI;
1134 if (fabs(aFirstPtAngle) > anAngleTol && isReversed == (aFirstPtAngle > 0.))
1135 aFirstPtAngle += aPeriod;
1136 if (fabs(aSecondPtAngle) > anAngleTol && isReversed == (aSecondPtAngle > 0.))
1137 aSecondPtAngle += aPeriod;
1139 if (fabs(aFirstPtAngle) > fabs(aSecondPtAngle)) {
1140 std::shared_ptr<GeomAPI_Pnt2d> aTmpPoint = theFirstPoint;
1141 theFirstPoint = theSecondPoint;
1142 theSecondPoint = aTmpPoint;
1146 void SketchPlugin_Trim::fillPointAttribute(const AttributePtr& theModifiedAttribute,
1147 const std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
1149 std::string anAttributeType = theModifiedAttribute->attributeType();
1150 if (anAttributeType == GeomDataAPI_Point2D::typeId()) {
1151 AttributePoint2DPtr aModifiedAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1152 theModifiedAttribute);
1153 aModifiedAttribute->setValue(thePoint);
1156 FeaturePtr aFeature = ModelAPI_Feature::feature(theModifiedAttribute->owner());
1157 std::cout << "<fillPointAttribute[" << aFeature->data()->name() << ": " <<
1158 theModifiedAttribute->id() <<
1159 "]> => Pnt2d - [" << thePoint->x() << ", " << thePoint->y() << "]" << std::endl;
1165 void SketchPlugin_Trim::fillAttribute(const AttributePtr& theModifiedAttribute,
1166 const AttributePtr& theSourceAttribute)
1168 std::string anAttributeType = theModifiedAttribute->attributeType();
1169 if (anAttributeType == GeomDataAPI_Point2D::typeId()) {
1170 AttributePoint2DPtr aModifiedAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1171 theModifiedAttribute);
1172 AttributePoint2DPtr aSourceAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1173 theSourceAttribute);
1175 if (aModifiedAttribute.get() && aSourceAttribute.get())
1176 aModifiedAttribute->setValue(aSourceAttribute->pnt());
1178 else if (anAttributeType == ModelAPI_AttributeBoolean::typeId()) {
1179 AttributeBooleanPtr aModifiedAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(
1180 theModifiedAttribute);
1181 AttributeBooleanPtr aSourceAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(
1182 theSourceAttribute);
1184 if (aModifiedAttribute.get() && aSourceAttribute.get())
1185 aModifiedAttribute->setValue(aSourceAttribute->value());
1187 else if (anAttributeType == ModelAPI_AttributeRefAttr::typeId()) {
1188 AttributeRefAttrPtr aRefAttributeToFill = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1189 theModifiedAttribute);
1190 AttributeRefAttrPtr aSourceRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1191 theSourceAttribute);
1192 if (!aSourceRefAttr.get())
1193 aRefAttributeToFill->setAttr(theSourceAttribute);
1195 if (aSourceRefAttr->isObject())
1196 aRefAttributeToFill->setObject(aSourceRefAttr->object());
1198 aRefAttributeToFill->setAttr(aSourceRefAttr->attr());
1203 FeaturePtr SketchPlugin_Trim::createLineFeature(const FeaturePtr& theBaseFeature,
1204 const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
1205 const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint)
1208 std::cout << "---- createLineFeature ---" << std::endl;
1211 FeaturePtr aFeature;
1212 SketchPlugin_Sketch* aSketch = sketch();
1213 if (!aSketch || !theBaseFeature.get())
1216 aFeature = aSketch->addFeature(SketchPlugin_Line::ID());
1218 fillPointAttribute(aFeature->attribute(SketchPlugin_Line::START_ID()), theFirstPoint);
1219 fillPointAttribute(aFeature->attribute(SketchPlugin_Line::END_ID()), theSecondPoint);
1221 fillAttribute(aFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()),
1222 theBaseFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()));
1224 aFeature->execute(); // to obtain result
1227 std::cout << "---- createLineFeature:end ---" << std::endl;
1233 FeaturePtr SketchPlugin_Trim::createArcFeature(const FeaturePtr& theBaseFeature,
1234 const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
1235 const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint)
1237 FeaturePtr aFeature;
1238 SketchPlugin_Sketch* aSketch = sketch();
1239 if (!aSketch || !theBaseFeature.get())
1242 std::string aCenterAttributeId;
1243 if (theBaseFeature->getKind() == SketchPlugin_Arc::ID())
1244 aCenterAttributeId = SketchPlugin_Arc::CENTER_ID();
1245 else if (theBaseFeature->getKind() == SketchPlugin_Circle::ID())
1246 aCenterAttributeId = SketchPlugin_Circle::CENTER_ID();
1248 if (aCenterAttributeId.empty())
1252 std::cout << "---- createArcFeature ---" << std::endl;
1255 aFeature = aSketch->addFeature(SketchPlugin_Arc::ID());
1256 // update fillet arc: make the arc correct for sure, so, it is not needed to process
1257 // the "attribute updated"
1258 // by arc; moreover, it may cause cyclicity in hte mechanism of updater
1259 bool aWasBlocked = aFeature->data()->blockSendAttributeUpdated(true);
1261 fillAttribute(aFeature->attribute(SketchPlugin_Arc::CENTER_ID()),
1262 theBaseFeature->attribute(aCenterAttributeId));
1263 fillPointAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), theFirstPoint);
1264 fillPointAttribute(aFeature->attribute(SketchPlugin_Arc::END_ID()), theSecondPoint);
1266 fillAttribute(aFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()),
1267 theBaseFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()));
1269 /// fill referersed state of created arc as it is on the base arc
1270 if (theBaseFeature->getKind() == SketchPlugin_Arc::ID()) {
1271 bool aReversed = theBaseFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->value();
1272 aFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(aReversed);
1274 //aFeature->execute(); // to obtain result
1275 aFeature->data()->blockSendAttributeUpdated(aWasBlocked);
1278 std::cout << "---- createArcFeature:end ---" << std::endl;
1284 FeaturePtr SketchPlugin_Trim::createConstraint(const std::string& theConstraintId,
1285 const AttributePtr& theFirstAttribute,
1286 const AttributePtr& theSecondAttribute)
1288 FeaturePtr aConstraint = sketch()->addFeature(theConstraintId);
1289 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1290 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
1291 aRefAttr->setAttr(theFirstAttribute);
1293 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1294 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
1295 aRefAttr->setAttr(theSecondAttribute);
1298 std::cout << "<createConstraint to attribute> :"
1299 << "first attribute - " << theFirstAttribute->id()
1300 << "second attribute - " << theSecondAttribute->id()
1307 FeaturePtr SketchPlugin_Trim::createConstraintToObject(const std::string& theConstraintId,
1308 const AttributePtr& theFirstAttribute,
1309 const ObjectPtr& theSecondObject)
1311 FeaturePtr aConstraint = sketch()->addFeature(theConstraintId);
1312 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1313 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
1314 aRefAttr->setAttr(theFirstAttribute);
1316 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1317 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
1318 aRefAttr->setObject(theSecondObject);
1321 std::cout << "<createConstraint to attribute> :"
1322 << "first attribute - " << theFirstAttribute->id()
1323 << "second object - " << ModelAPI_Feature::feature(theSecondObject)->getKind()
1330 FeaturePtr SketchPlugin_Trim::createConstraintForObjects(
1331 const std::string& theConstraintId,
1332 const ObjectPtr& theFirstObject,
1333 const ObjectPtr& theSecondObject)
1335 FeaturePtr aConstraint = sketch()->addFeature(theConstraintId);
1336 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1337 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
1338 aRefAttr->setObject(theFirstObject);
1340 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1341 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
1342 aRefAttr->setObject(theSecondObject);
1347 std::shared_ptr<ModelAPI_Result> SketchPlugin_Trim::getFeatureResult(
1348 const std::shared_ptr<ModelAPI_Feature>& theFeature)
1350 std::shared_ptr<ModelAPI_Result> aResult;
1352 std::string aFeatureKind = theFeature->getKind();
1353 if (aFeatureKind == SketchPlugin_Line::ID())
1354 aResult = theFeature->firstResult();
1355 else if (aFeatureKind == SketchPlugin_Arc::ID())
1356 aResult = theFeature->lastResult();
1357 else if (aFeatureKind == SketchPlugin_Circle::ID())
1358 aResult = theFeature->lastResult();
1363 //********************************************************************
1364 void SketchPlugin_Trim::fillObjectShapes(const ObjectPtr& theObject,
1365 const ObjectPtr& theSketch,
1366 std::map<ObjectPtr, std::set<GeomShapePtr> >& theCashedShapes,
1367 std::map<ObjectPtr, PointToRefsMap>& theObjectToPoints)
1369 PointToRefsMap aPointsInfo;
1371 std::set<std::shared_ptr<GeomAPI_Shape> > aShapes;
1372 std::map<std::shared_ptr<GeomAPI_Pnt>,
1373 std::list< AttributePoint2DPtr > > aPointToAttributes;
1374 std::map<std::shared_ptr<GeomAPI_Pnt>,
1375 std::list< ObjectPtr > > aPointToObjects;
1377 std::set<AttributePoint2DPtr > aRefAttributes;
1379 FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
1380 std::set<ResultPtr> anEdgeShapes;
1382 ModelGeomAlgo_Shape::shapesOfType(aFeature, GeomAPI_Shape::EDGE, anEdgeShapes);
1383 if (!anEdgeShapes.empty()) {
1384 GeomShapePtr aFeatureShape = (*anEdgeShapes.begin())->shape();
1386 // coincidences to the feature
1387 ModelGeomAlgo_Point2D::getPointsOfReference(aFeature, SketchPlugin_ConstraintCoincidence::ID(),
1388 aRefAttributes, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID());
1389 // layed on feature coincidences to divide it on several shapes
1390 //SketchPlugin_Sketch* aSketch = sketch();
1391 std::shared_ptr<ModelAPI_Data> aData = theSketch->data();
1392 std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
1393 aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
1394 std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
1395 aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
1396 std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
1397 aData->attribute(SketchPlugin_Sketch::NORM_ID()));
1398 std::shared_ptr<GeomAPI_Dir> aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
1400 ModelGeomAlgo_Point2D::getPointsInsideShape(aFeatureShape, aRefAttributes, aC->pnt(),
1401 aX->dir(), aY, aPointsInfo);
1403 std::list<FeaturePtr> aFeatures;
1404 CompositeFeaturePtr aSketchComposite =
1405 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theSketch);
1406 for (int i = 0; i < aSketchComposite->numberOfSubs(); i++) {
1407 FeaturePtr aFeature = aSketchComposite->subFeature(i);
1409 aFeatures.push_back(aFeature);
1411 ModelGeomAlgo_Point2D::getPointsIntersectedShape(aFeature, aFeatures, aPointsInfo);
1413 GeomAlgoAPI_ShapeTools::splitShape(aFeatureShape, aPointsInfo, aShapes);
1415 theObjectToPoints[theObject] = aPointsInfo;
1416 theCashedShapes[theObject] = aShapes;