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_Events.h>
45 #include <SketchPlugin_Line.h>
46 #include <SketchPlugin_Arc.h>
47 #include <SketchPlugin_Circle.h>
49 #include <ModelGeomAlgo_Point2D.h>
50 #include <Events_Loop.h>
59 static const double PI = 3.141592653589793238463;
61 static const std::string OPERATION_HIGHLIGHT_COLOR() { return "128, 0, 0"; }
62 static const std::string OPERATION_REMOVE_FEATURE_COLOR() { return "255, 174, 201"; }
64 SketchPlugin_Trim::SketchPlugin_Trim()
68 void SketchPlugin_Trim::initAttributes()
70 data()->addAttribute(SketchPlugin_Trim::SELECTED_OBJECT(),
71 ModelAPI_AttributeReference::typeId());
72 data()->addAttribute(SELECTED_POINT(), GeomDataAPI_Point2D::typeId());
74 data()->addAttribute(PREVIEW_POINT(), GeomDataAPI_Point2D::typeId());
75 data()->addAttribute(PREVIEW_OBJECT(), ModelAPI_AttributeReference::typeId());
77 data()->attribute(PREVIEW_POINT())->setIsArgument(false);
78 data()->attribute(SELECTED_POINT())->setIsArgument(false);
79 data()->attribute(PREVIEW_OBJECT())->setIsArgument(false);
81 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PREVIEW_POINT());
82 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PREVIEW_OBJECT());
85 void SketchPlugin_Trim::findShapePoints(const std::string& theObjectAttributeId,
86 const std::string& thePointAttributeId,
87 std::shared_ptr<GeomAPI_Pnt>& aStartPoint,
88 std::shared_ptr<GeomAPI_Pnt>& aLastPoint)
90 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
91 data()->attribute(theObjectAttributeId));
92 ObjectPtr aBaseObject = aBaseObjectAttr->value();
94 AttributePoint2DPtr aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
95 data()->attribute(thePointAttributeId));
96 std::shared_ptr<GeomAPI_Pnt2d> anAttributePnt2d = aPoint->pnt();
97 std::shared_ptr<GeomAPI_Pnt> anAttributePnt = sketch()->to3D(anAttributePnt2d->x(),
98 anAttributePnt2d->y());
100 if (myCashedShapes.find(aBaseObject) == myCashedShapes.end())
101 fillObjectShapes(aBaseObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints);
103 const std::set<GeomShapePtr>& aShapes = myCashedShapes[aBaseObject];
104 if (!aShapes.empty()) {
105 std::set<GeomShapePtr>::const_iterator anIt = aShapes.begin(), aLast = aShapes.end();
106 for (; anIt != aLast; anIt++) {
107 GeomShapePtr aBaseShape = *anIt;
108 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
109 if (ModelGeomAlgo_Point2D::isPointOnEdge(aBaseShape, anAttributePnt, aProjectedPoint)) {
111 if (aBaseShape->shapeType() == GeomAPI_Shape::EDGE) {
112 std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aBaseShape));
113 //GeomAPI_Shape::Orientation anOrientation = anEdge->orientation();
114 //if (anOrientation == GeomAPI_Shape::REVERSED) {
115 aStartPoint = anEdge->lastPoint();
116 aLastPoint = anEdge->firstPoint();
119 //aStartPoint = anEdge->firstPoint();
120 //aLastPoint = anEdge->lastPoint();
127 std::cout << "<findShapePoints> => "
128 << std::endl << "Attribute point: "
129 << anAttributePnt->x() << ", " << anAttributePnt->y() << ", " << anAttributePnt->z() << "]"
130 << std::endl << "Start Point: ["
131 << aStartPoint->x() << ", " << aStartPoint->y() << ", " << aStartPoint->z() << "]"
132 << std::endl << "Last Point: ["
133 << aLastPoint->x() << ", " << aLastPoint->y() << ", " << aLastPoint->z() << "]"
138 std::shared_ptr<GeomAPI_Pnt2d> SketchPlugin_Trim::convertPoint(
139 const std::shared_ptr<GeomAPI_Pnt>& thePoint)
141 std::shared_ptr<GeomAPI_Pnt2d> aPoint;
143 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
144 data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
145 ObjectPtr aBaseObject = aBaseObjectAttr->value();
146 if (myObjectToPoints.find(aBaseObject) == myObjectToPoints.end())
147 fillObjectShapes(aBaseObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints);
150 const PointToRefsMap& aRefsMap = myObjectToPoints.at(aBaseObject);
151 for (PointToRefsMap::const_iterator aPointIt = aRefsMap.begin();
152 aPointIt != aRefsMap.end() && !aFound; aPointIt++) {
153 if (aPointIt->first->isEqual(thePoint)) {
154 const std::pair<std::list<AttributePoint2DPtr >,
155 std::list<ObjectPtr > >& anInfo = aPointIt->second;
156 const std::list<AttributePoint2DPtr >& anAttributes = anInfo.first;
157 if (!anAttributes.empty()) {
158 aPoint = anAttributes.front()->pnt();
162 aPoint = sketch()->to2D(thePoint);
168 // returns an end of the shape to define direction of split if feature's attribute
170 aPoint = sketch()->to2D(thePoint);
175 void SketchPlugin_Trim::execute()
178 std::cout << "SketchPlugin_Trim::execute" << std::endl;
181 SketchPlugin_Sketch* aSketch = sketch();
185 // Check the base objects are initialized.
186 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
187 data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
188 if(!aBaseObjectAttr->isInitialized()) {
189 setError("Error: Base object is not initialized.");
192 ObjectPtr aBaseObject = aBaseObjectAttr->value();
193 if (!aBaseObject.get())
195 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
197 /// Remove reference of this feature to feature used in preview, it is not necessary anymore
198 /// as trim will be removed after execute
199 AttributeReferencePtr aPreviewObjectAttr =
200 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
201 data()->attribute(SketchPlugin_Trim::PREVIEW_OBJECT()));
202 aPreviewObjectAttr->setValue(ResultPtr());
205 std::shared_ptr<GeomAPI_Pnt> aStartShapePoint, aLastShapePoint;
207 std::cout << " Base Feature: " << aBaseFeature->data()->name() << std::endl;
209 findShapePoints(SELECTED_OBJECT(), SELECTED_POINT(), aStartShapePoint, aLastShapePoint);
211 std::shared_ptr<GeomAPI_Pnt2d> aStartShapePoint2d = convertPoint(aStartShapePoint);
213 std::shared_ptr<GeomAPI_Pnt2d> aLastShapePoint2d = convertPoint(aLastShapePoint);
215 std::set<FeaturePtr> aFeaturesToDelete;
216 getConstraints(aFeaturesToDelete);
218 std::map<AttributePtr, std::list<AttributePtr> > aBaseRefAttributes;
219 std::list<AttributePtr> aRefsToFeature;
220 getRefAttributes(aBaseFeature, aBaseRefAttributes, aRefsToFeature);
222 std::cout << "---- getRefAttributes ----" << std::endl;
223 std::map<AttributePtr, std::list<AttributePtr> >::const_iterator
224 aRefIt = aBaseRefAttributes.begin(), aRefLast = aBaseRefAttributes.end();
225 std::cout << std::endl << "References to attributes of base feature [" <<
226 aBaseRefAttributes.size() << "]" << std::endl;
227 for (; aRefIt != aRefLast; aRefIt++) {
228 AttributePtr aBaseAttr = aRefIt->first;
229 std::list<AttributePtr> aRefAttributes = aRefIt->second;
230 std::string aRefsInfo;
231 std::list<AttributePtr>::const_iterator aRefAttrIt = aRefAttributes.begin(),
232 aRefAttrLast = aRefAttributes.end();
233 for (; aRefAttrIt != aRefAttrLast; aRefAttrIt++) {
234 if (!aRefsInfo.empty())
235 aRefsInfo.append(",");
236 AttributePtr aRAttr = *aRefAttrIt;
237 aRefsInfo.append(aRAttr->id());
238 FeaturePtr aRFeature = ModelAPI_Feature::feature(aRAttr->owner());
239 aRefsInfo.append("(" + aRFeature->name() + ") ");
241 std::shared_ptr<GeomDataAPI_Point2D> aPointAttr =
242 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aBaseAttr);
243 std::cout << aPointAttr->id().c_str() <<
244 ": " << "[" << aRefAttributes.size() << "] " << aRefsInfo << std::endl;
246 std::cout << std::endl;
247 std::cout << std::endl << "References to base feature [" <<
248 aRefsToFeature.size() << "]" << std::endl;
249 std::list<AttributePtr>::const_iterator aRefAttrIt = aRefsToFeature.begin(),
250 aRefAttrLast = aRefsToFeature.end();
251 std::string aRefsInfo;
252 for (; aRefAttrIt != aRefAttrLast; aRefAttrIt++) {
253 if (!aRefsInfo.empty())
254 aRefsInfo.append(",");
255 AttributePtr aRAttr = *aRefAttrIt;
256 aRefsInfo.append(aRAttr->id());
257 FeaturePtr aRFeature = ModelAPI_Feature::feature(aRAttr->owner());
258 aRefsInfo.append("(" + aRFeature->name() + ") ");
260 std::cout << "[" << aRefsToFeature.size() << "] " << aRefsInfo << std::endl;
261 std::cout << "---- getRefAttributes:end ----" << std::endl;
263 // coincidence to result points
264 // find coincidences to the base object, it should be used when attribute is found
265 // in myObjectToPoints
266 //std::map<AttributePtr, FeaturePtr> aCoincidencesToBaseFeature;
267 //getCoincidencesToObject(aBaseObject, aCoincidencesToBaseFeature);
269 std::set<AttributePoint2DPtr> aFurtherCoincidences;
270 std::set<std::pair<AttributePtr, AttributePtr>> aModifiedAttributes;
271 const std::string& aKind = aBaseFeature->getKind();
272 FeaturePtr aReplacingFeature;
273 if (aKind == SketchPlugin_Circle::ID()) {
274 aReplacingFeature = trimCircle(aStartShapePoint2d, aLastShapePoint2d,
275 aFurtherCoincidences, aModifiedAttributes);
277 aFeaturesToDelete.insert(aBaseFeature);
278 // as circle is removed, erase it from dependencies(arguments) of this feature
279 // otherwise Trim feature will be removed with the circle before
280 // this operation is finished
281 aBaseObjectAttr->setObject(ResultPtr());
283 else if (aKind == SketchPlugin_Line::ID()) {
284 trimLine(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes,
285 aFurtherCoincidences, aModifiedAttributes);
287 else if (aKind == SketchPlugin_Arc::ID()) {
288 trimArc(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes,
289 aFurtherCoincidences, aModifiedAttributes);
292 // constraints to end points of trim feature
293 if (myObjectToPoints.find(aBaseObject) == myObjectToPoints.end())
294 fillObjectShapes(aBaseObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints);
296 // create coincidence to objects, intersected the base object
297 const PointToRefsMap& aRefsMap = myObjectToPoints.at(aBaseObject);
298 for (std::set<AttributePoint2DPtr>::const_iterator anIt = aFurtherCoincidences.begin(),
299 aLast = aFurtherCoincidences.end();
300 anIt != aLast; anIt++) {
301 AttributePoint2DPtr aPointAttribute = (*anIt);
302 std::shared_ptr<GeomAPI_Pnt2d> aPoint2d = aPointAttribute->pnt();
305 std::cout << "<compare Points> => " << std::endl
306 << "aPoint2d: [" << aPoint2d->x() << ", " << aPoint2d->y() << "]" << std::endl;
307 if (aStartShapePoint2d.get())
308 std::cout << "Start Point: [" << aStartShapePoint2d->x() << ", " << aStartShapePoint2d->y()
310 if (aLastShapePoint2d.get())
311 std::cout << "Last Point: [" << aLastShapePoint2d->x() << ", " << aLastShapePoint2d->y()
315 std::shared_ptr<GeomAPI_Pnt> aPoint;
316 if (aStartShapePoint2d.get() && aPoint2d->isEqual(aStartShapePoint2d))
317 aPoint = aStartShapePoint;
318 else if (aLastShapePoint2d.get() && aPoint2d->isEqual(aLastShapePoint2d))
319 aPoint = aLastShapePoint;
324 std::pair<std::list<AttributePoint2DPtr >, std::list<ObjectPtr > > anInfo;
325 for (PointToRefsMap::const_iterator aRefIt = aRefsMap.begin(); aRefIt != aRefsMap.end();
328 if (aRefIt->first->isEqual(aPoint)) {
329 anInfo = aRefIt->second;
333 const std::list<ObjectPtr>& anObjects = anInfo.second;
334 for (std::list<ObjectPtr>::const_iterator anObjectIt = anObjects.begin();
335 anObjectIt != anObjects.end(); anObjectIt++) {
336 createConstraintToObject(SketchPlugin_ConstraintCoincidence::ID(), aPointAttribute,
341 // move constraints from base feature to replacing feature: ignore coincidences to feature
342 // if attributes of coincidence participated in split
343 ResultPtr aReplacingResult;
344 if (aReplacingFeature.get()) {
345 aReplacingFeature->execute(); // need it to obtain result
346 aReplacingResult = getFeatureResult(aReplacingFeature);
348 for(std::list<AttributePtr>::const_iterator anIt = aRefsToFeature.begin(),
349 aLast = aRefsToFeature.end();
350 anIt != aLast; anIt++) {
351 AttributePtr anAttribute = *anIt;
353 //if (replaceCoincidenceAttribute(anAttribute, aModifiedAttributes))
356 if (setCoincidenceToAttribute(anAttribute, aFurtherCoincidences))
359 if (aReplacingResult.get()) {
360 AttributeRefAttrPtr aRefAttr =
361 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
363 aRefAttr->setObject(aReplacingResult);
365 AttributeReferencePtr aReferenceAttr =
366 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(anAttribute);
367 if (aReferenceAttr.get())
368 aReferenceAttr->setObject(aReplacingResult);
373 updateRefAttConstraints(aBaseRefAttributes, aModifiedAttributes, aFeaturesToDelete);
375 // Wait all constraints being created, then send update events
376 static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
377 bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
379 Events_Loop::loop()->setFlushed(anUpdateEvent, false);
381 // delete constraints
383 if (aFeaturesToDelete.size() > 0) {
384 std::cout << "after SPlit: removeFeaturesAndReferences: " << std::endl;
386 for (std::set<FeaturePtr>::const_iterator anIt = aFeaturesToDelete.begin();
387 anIt != aFeaturesToDelete.end(); anIt++) {
388 FeaturePtr aFeature = *anIt;
389 std::cout << aFeature->data()->name() << std::endl;
393 ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToDelete);
394 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
396 // Send events to update the sub-features by the solver.
397 if(isUpdateFlushed) {
398 Events_Loop::loop()->setFlushed(anUpdateEvent, true);
402 std::cout << "SketchPlugin_Trim::done" << std::endl;
406 bool SketchPlugin_Trim::setCoincidenceToAttribute(const AttributePtr& theAttribute,
407 const std::set<AttributePoint2DPtr>& theFurtherCoincidences)
409 FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
410 if (aFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID())
413 AttributePoint2DPtr aRefPointAttr = SketchPlugin_ConstraintCoincidence::getPoint(aFeature);
414 if (!aRefPointAttr.get())
416 std::shared_ptr<GeomAPI_Pnt2d> aRefPnt2d = aRefPointAttr->pnt();
418 std::set<AttributePoint2DPtr>::const_iterator anIt = theFurtherCoincidences.begin(),
419 aLast = theFurtherCoincidences.end();
420 bool aFoundPoint = false;
421 for (; anIt != aLast && !aFoundPoint; anIt++) {
422 AttributePoint2DPtr aPointAttribute = (*anIt);
423 std::shared_ptr<GeomAPI_Pnt2d> aPoint2d = aPointAttribute->pnt();
424 if (aPoint2d->isEqual(aRefPnt2d)) {
425 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
427 if (aRefAttr.get()) {
428 aRefAttr->setAttr(aPointAttribute);
436 bool SketchPlugin_Trim::replaceCoincidenceAttribute(const AttributePtr& theCoincidenceAttribute,
437 const std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
439 FeaturePtr aCoincidenceFeature = ModelAPI_Feature::feature(theCoincidenceAttribute->owner());
440 if (aCoincidenceFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID())
443 AttributeRefAttrPtr aCAttrA = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
444 aCoincidenceFeature->attribute(SketchPlugin_Constraint::ENTITY_A()));
445 AttributeRefAttrPtr aCAttrB = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
446 aCoincidenceFeature->attribute(SketchPlugin_Constraint::ENTITY_B()));
447 AttributePtr aCAttrRefA = aCAttrA->attr();
448 AttributePtr aCAttrRefB = aCAttrB->attr();
450 bool isProcessed = false;
451 for (std::set<std::pair<AttributePtr, AttributePtr>>::const_iterator
452 anIt = theModifiedAttributes.begin(); anIt != theModifiedAttributes.end(); anIt++) {
453 AttributePtr anAttributeBefore = anIt->first;
454 if (anAttributeBefore == aCAttrRefA) {
455 aCAttrA->setAttr(anIt->second);
458 if (anAttributeBefore == aCAttrRefB) {
459 aCAttrB->setAttr(anIt->second);
466 bool SketchPlugin_Trim::isMacro() const
471 AISObjectPtr SketchPlugin_Trim::getAISObject(AISObjectPtr thePrevious)
473 AISObjectPtr anAIS = thePrevious;
475 std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
476 GeomShapePtr aPreviewShape = getSubShape(PREVIEW_OBJECT(), PREVIEW_POINT());
477 if (aPreviewShape.get())
478 aShapes.push_back(aPreviewShape);
479 GeomShapePtr aSelectedShape = getSubShape(SELECTED_OBJECT(), SELECTED_POINT());
480 if (aSelectedShape.get())
481 aShapes.push_back(aSelectedShape);
484 return AISObjectPtr();
486 GeomShapePtr aBaseShape = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
487 if (!aBaseShape.get())
488 return AISObjectPtr();
490 if (aBaseShape.get()) {
492 anAIS = AISObjectPtr(new GeomAPI_AISObject);
493 anAIS->createShape(aBaseShape);
495 std::vector<int> aColor;
496 aColor = Config_PropManager::color("Visualization", "operation_remove_feature_color");
497 double aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH();
498 int aLineStyle = SketchPlugin_SketchEntity::SKETCH_LINE_STYLE();
499 anAIS->setColor(aColor[0], aColor[1], aColor[2]);
500 // width when there is not base object should be extened in several points
501 // in order to see this preview over highlight
502 anAIS->setWidth(aWidth+4);
503 anAIS->setLineStyle(aLineStyle);
506 anAIS = AISObjectPtr();
511 GeomShapePtr SketchPlugin_Trim::getSubShape(const std::string& theObjectAttributeId,
512 const std::string& thePointAttributeId)
514 GeomShapePtr aBaseShape;
516 AttributeReferencePtr anObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
517 data()->attribute(theObjectAttributeId));
518 ObjectPtr aBaseObject = anObjectAttr->value();
519 if (!aBaseObject.get())
523 AttributePoint2DPtr aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
524 data()->attribute(thePointAttributeId));
525 std::shared_ptr<GeomAPI_Pnt2d> anAttributePnt2d = aPoint->pnt();
526 std::shared_ptr<GeomAPI_Pnt> anAttributePnt = sketch()->to3D(anAttributePnt2d->x(),
527 anAttributePnt2d->y());
529 if (myCashedShapes.find(aBaseObject) == myCashedShapes.end())
530 fillObjectShapes(aBaseObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints);
532 const std::set<GeomShapePtr>& aShapes = myCashedShapes[aBaseObject];
533 if (!aShapes.empty()) {
534 std::set<GeomShapePtr>::const_iterator anIt = aShapes.begin(), aLast = aShapes.end();
535 for (; anIt != aLast; anIt++) {
536 GeomShapePtr aShape = *anIt;
537 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
538 if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, anAttributePnt, aProjectedPoint))
545 void SketchPlugin_Trim::getFeaturePoints(const FeaturePtr& theFeature,
546 AttributePoint2DPtr& theStartPointAttr,
547 AttributePoint2DPtr& theEndPointAttr)
549 std::string aFeatureKind = theFeature->getKind();
550 std::string aStartAttributeName, anEndAttributeName;
551 if (aFeatureKind == SketchPlugin_Line::ID()) {
552 aStartAttributeName = SketchPlugin_Line::START_ID();
553 anEndAttributeName = SketchPlugin_Line::END_ID();
555 else if (aFeatureKind == SketchPlugin_Arc::ID()) {
556 aStartAttributeName = SketchPlugin_Arc::START_ID();
557 anEndAttributeName = SketchPlugin_Arc::END_ID();
559 if (!aStartAttributeName.empty() && !anEndAttributeName.empty()) {
560 theStartPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
561 theFeature->attribute(aStartAttributeName));
562 theEndPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
563 theFeature->attribute(anEndAttributeName));
567 void SketchPlugin_Trim::getConstraints(std::set<FeaturePtr>& theFeaturesToDelete)
569 std::shared_ptr<ModelAPI_Data> aData = data();
571 // Check the base objects are initialized.
572 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
573 aData->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
574 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
575 ResultPtr aBaseFeatureResult = getFeatureResult(aBaseFeature);
577 std::set<AttributePtr> aRefsList = aBaseFeatureResult->data()->refsToMe();
578 std::set<AttributePtr> aFRefsList = aBaseFeature->data()->refsToMe();
579 aRefsList.insert(aFRefsList.begin(), aFRefsList.end());
581 std::set<AttributePtr>::const_iterator aIt;
582 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
583 std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
584 FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
585 std::string aRefFeatureKind = aRefFeature->getKind();
586 if (aRefFeatureKind == SketchPlugin_ConstraintMirror::ID() ||
587 aRefFeatureKind == SketchPlugin_MultiRotation::ID() ||
588 aRefFeatureKind == SketchPlugin_MultiTranslation::ID() ||
589 aRefFeatureKind == SketchPlugin_ConstraintMiddle::ID())
590 theFeaturesToDelete.insert(aRefFeature);
594 void SketchPlugin_Trim::getRefAttributes(const FeaturePtr& theFeature,
595 std::map<AttributePtr, std::list<AttributePtr> >& theRefs,
596 std::list<AttributePtr>& theRefsToFeature)
600 std::list<AttributePtr> aPointAttributes =
601 theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
602 std::set<AttributePtr> aPointAttributesSet;
604 std::list<AttributePtr>::const_iterator aPIt =
605 aPointAttributes.begin(), aPLast = aPointAttributes.end();
606 for (; aPIt != aPLast; aPIt++)
607 aPointAttributesSet.insert(*aPIt);
609 std::set<AttributePtr> aRefsAttributes = getFeatureResult(theFeature)->data()->refsToMe();
610 std::set<AttributePtr> aFRefsList = theFeature->data()->refsToMe();
611 aRefsAttributes.insert(aFRefsList.begin(), aFRefsList.end());
613 std::set<AttributePtr>::const_iterator aIt;
614 for (aIt = aRefsAttributes.cbegin(); aIt != aRefsAttributes.cend(); ++aIt) {
615 AttributePtr anAttr = (*aIt);
616 FeaturePtr anAttrFeature = ModelAPI_Feature::feature(anAttr->owner());
617 if (anAttrFeature.get() != this &&
618 anAttr.get() && anAttr->attributeType() == ModelAPI_AttributeRefAttr::typeId()) {
619 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
620 if (!aRefAttr->isObject()) { /// find attributes referenced to feature point attributes
621 AttributePtr anAttrInRef = aRefAttr->attr();
622 if (anAttrInRef.get() &&
623 aPointAttributesSet.find(anAttrInRef) != aPointAttributesSet.end()) {
624 if (theRefs.find(anAttrInRef) != theRefs.end())
625 theRefs[anAttrInRef].push_back(aRefAttr);
627 std::list<AttributePtr> anAttrList;
628 anAttrList.push_back(aRefAttr);
629 theRefs[anAttrInRef] = anAttrList;
633 else { /// find attributes referenced to feature itself
634 theRefsToFeature.push_back(anAttr);
640 /*void SketchPlugin_Trim::getCoincidencesToObject(const ObjectPtr& theObject,
641 std::map<AttributePtr, FeaturePtr>& theCoincidencesToBaseFeature)
643 const std::set<AttributePtr>& aRefsList = theObject->data()->refsToMe();
644 std::set<AttributePtr>::const_iterator aIt;
645 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
646 std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
647 FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
648 if (aRefFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID())
650 AttributePtr anAttribute;
651 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>
652 (aRefFeature->attribute(SketchPlugin_Constraint::ENTITY_A()));
653 if (aRefAttr->isObject() && aRefAttr->object() == theObject)
655 anAttribute = aRefFeature->attribute(SketchPlugin_Constraint::ENTITY_B());
658 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>
659 (aRefFeature->attribute(SketchPlugin_Constraint::ENTITY_B()));
660 if (aRefAttr->isObject() && aRefAttr->object() == theObject)
661 anAttribute = aRefFeature->attribute(SketchPlugin_Constraint::ENTITY_A());
663 if (!anAttribute.get())
666 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
667 if (aRefAttr->isObject())
668 continue; // one of attributes of coincidence contains link to an attribute
670 anAttribute = aRefAttr->attr();
671 if (anAttribute.get())
673 theCoincidencesToBaseFeature[anAttribute] = aRefFeature;
678 void SketchPlugin_Trim::updateRefAttConstraints(
679 const std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
680 const std::set<std::pair<AttributePtr, AttributePtr> >& theModifiedAttributes,
681 std::set<FeaturePtr>& theFeaturesToDelete)
684 std::cout << "SketchPlugin_Trim::updateRefAttConstraints" << std::endl;
687 std::set<std::pair<AttributePtr, AttributePtr> >::const_iterator
688 anIt = theModifiedAttributes.begin(), aLast = theModifiedAttributes.end();
689 for (; anIt != aLast; anIt++) {
690 AttributePtr anAttribute = anIt->first;
692 /// not found in references
693 if (theBaseRefAttributes.find(anAttribute) == theBaseRefAttributes.end())
695 std::list<AttributePtr> aRefAttributes = theBaseRefAttributes.at(anAttribute);
696 std::list<AttributePtr>::const_iterator aRefIt = aRefAttributes.begin(),
697 aRLast = aRefAttributes.end();
699 AttributePtr aNewAttribute = anIt->second;
700 if (aNewAttribute.get()) {
701 for (; aRefIt != aRLast; aRefIt++) {
702 AttributeRefAttrPtr aRefAttr =
703 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefIt);
704 if (aRefAttr.get()) {
705 aRefAttr->setAttr(aNewAttribute);
712 void SketchPlugin_Trim::removeReferencesToAttribute(const AttributePtr& theAttribute,
713 std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes)
715 /// not found in references
716 if (theBaseRefAttributes.find(theAttribute) == theBaseRefAttributes.end())
719 std::list<AttributePtr> aRefAttributes = theBaseRefAttributes.at(theAttribute);
720 std::list<AttributePtr>::const_iterator aRefIt = aRefAttributes.begin(),
721 aRLast = aRefAttributes.end();
723 std::set<FeaturePtr> aFeaturesToDelete;
724 for (; aRefIt != aRLast; aRefIt++) {
725 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefIt);
726 if (aRefAttr.get()) {
727 aFeaturesToDelete.insert(ModelAPI_Feature::feature(aRefAttr->owner()));
732 // delete constraints
733 if (aFeaturesToDelete.size() > 0) {
734 std::cout << "removeReferencesToAttribute: " << std::endl;
736 for (std::set<FeaturePtr>::const_iterator anIt = aFeaturesToDelete.begin();
737 anIt != aFeaturesToDelete.end(); anIt++) {
738 FeaturePtr aFeature = *anIt;
739 std::cout << aFeature->data()->name() << std::endl;
743 ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToDelete);
744 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
747 void SketchPlugin_Trim::trimLine(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
748 const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
749 std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
750 std::set<AttributePoint2DPtr>& thePoints,
751 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
753 // Check the base objects are initialized.
754 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
755 data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
756 ObjectPtr aBaseObject = aBaseObjectAttr->value();
757 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
760 AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
761 getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
763 std::shared_ptr<GeomAPI_Pnt2d> aStartFeaturePoint = aStartPointAttrOfBase->pnt();
764 std::shared_ptr<GeomAPI_Pnt2d> aLastFeaturePoint = anEndPointAttrOfBase->pnt();
766 std::shared_ptr<GeomAPI_Pnt2d> aStartShapePoint = theStartShapePoint;
767 std::shared_ptr<GeomAPI_Pnt2d> aLastShapePoint = theLastShapePoint;
768 arrangePointsOnLine(aStartPointAttrOfBase, anEndPointAttrOfBase,
769 aStartShapePoint, aLastShapePoint);
771 std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl;
772 if (aStartShapePoint.get())
773 std::cout << "Start point: [" << aStartShapePoint->x() << ", " <<
774 aStartShapePoint->y() << "]" << std::endl;
775 std::cout << "1st point: [" << aStartFeaturePoint->x() << ", " <<
776 aStartFeaturePoint->y() << "]" << std::endl;
777 if (aLastShapePoint.get())
778 std::cout << "2st point: [" << aLastShapePoint->x() << ", " <<
779 aLastShapePoint->y() << "]" << std::endl;
780 std::cout << "End point: [" << aLastFeaturePoint->x() << ", " <<
781 aLastFeaturePoint->y() << "]" << std::endl;
784 bool isStartPoint = !aStartShapePoint.get() || aStartFeaturePoint->isEqual(aStartShapePoint);
785 bool isLastPoint = !aLastShapePoint.get() || aLastFeaturePoint->isEqual(aLastShapePoint);
786 if (isStartPoint || isLastPoint) {
787 // result is one line: changed existing line
788 std::string aModifiedAttribute = isStartPoint ? SketchPlugin_Line::START_ID()
789 : SketchPlugin_Line::END_ID();
790 std::shared_ptr<GeomAPI_Pnt2d> aPoint;
791 if (aStartShapePoint.get() && aLastShapePoint.get())
792 aPoint = isStartPoint ? aLastShapePoint : aStartShapePoint;
794 aPoint = aStartShapePoint.get() ? aStartShapePoint : aLastShapePoint;
796 // it is important to delete references before the feature modification because
797 // if deletion will be after the feature modification, solver returns the feature back
798 removeReferencesToAttribute(aBaseFeature->attribute(aModifiedAttribute),
799 theBaseRefAttributes);
801 fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aPoint);
802 //theModifiedAttributes.insert(
803 // std::make_pair(aBaseFeature->attribute(aModifiedAttribute), AttributePtr()));
805 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
806 (aBaseFeature->attribute(aModifiedAttribute)));
809 // result is two lines: start line point - start shape point,
810 // last shape point - last line point
811 // create second line
812 FeaturePtr anNewFeature = createLineFeature(aBaseFeature, aLastShapePoint, aLastFeaturePoint);
813 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
814 (anNewFeature->attribute(SketchPlugin_Line::START_ID())));
816 std::string aModifiedAttribute = SketchPlugin_Line::END_ID();
817 theModifiedAttributes.insert(
818 std::make_pair(aBaseFeature->attribute(aModifiedAttribute),
819 anNewFeature->attribute(SketchPlugin_Line::END_ID())));
822 fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aStartShapePoint);
824 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
825 (aBaseFeature->attribute(aModifiedAttribute)));
827 // Collinear constraint for lines
828 createConstraintForObjects(SketchPlugin_ConstraintCollinear::ID(),
829 getFeatureResult(aBaseFeature),
830 getFeatureResult(anNewFeature));
835 void SketchPlugin_Trim::trimArc(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
836 const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
837 std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
838 std::set<AttributePoint2DPtr>& thePoints,
839 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
841 // Check the base objects are initialized.
842 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
843 data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
844 ObjectPtr aBaseObject = aBaseObjectAttr->value();
845 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
848 AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
849 getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
851 std::shared_ptr<GeomAPI_Pnt2d> aStartArcPoint = aStartPointAttrOfBase->pnt();
852 std::shared_ptr<GeomAPI_Pnt2d> aLastArcPoint = anEndPointAttrOfBase->pnt();
854 std::shared_ptr<GeomAPI_Pnt2d> aStartShapePoint = theStartShapePoint;
855 std::shared_ptr<GeomAPI_Pnt2d> aLastShapePoint = theLastShapePoint;
856 arrangePointsOnArc(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase,
857 aStartShapePoint, aLastShapePoint);
859 std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl;
860 if (aStartShapePoint.get())
861 std::cout << "Start shape point: [" << aStartShapePoint->x() << ", " <<
862 aStartShapePoint->y() << "]" << std::endl;
863 std::cout << "Start arc attribute point: [" << aStartArcPoint->x() << ", " <<
864 aStartArcPoint->y() << "]" << std::endl;
865 if (aLastShapePoint.get())
866 std::cout << "Last shape point: [" << aLastShapePoint->x() << ", " <<
867 aLastShapePoint->y() << "]" << std::endl;
868 std::cout << "Last arc attribute point: [" << aLastArcPoint->x() << ", " <<
869 aLastArcPoint->y() << "]" << std::endl;
872 bool isStartPoint = !aStartShapePoint.get() || aStartArcPoint->isEqual(aStartShapePoint);
873 bool isLastPoint = !aLastShapePoint.get() || aLastArcPoint->isEqual(aLastShapePoint);
874 if (isStartPoint || isLastPoint) {
875 // result is one arc: changed existing arc
876 std::string aModifiedAttribute = isStartPoint ? SketchPlugin_Arc::START_ID()
877 : SketchPlugin_Arc::END_ID();
878 std::shared_ptr<GeomAPI_Pnt2d> aPoint;
879 if (aStartShapePoint.get() && aLastShapePoint.get())
880 aPoint = isStartPoint ? aLastShapePoint : aStartShapePoint;
882 aPoint = aStartShapePoint.get() ? aStartShapePoint : aLastShapePoint;
884 removeReferencesToAttribute(aBaseFeature->attribute(aModifiedAttribute),
885 theBaseRefAttributes);
887 fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aPoint);
889 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
890 (aBaseFeature->attribute(aModifiedAttribute)));
893 // result is two arcs: start arc point - start shape point, last shape point - last arc point
895 FeaturePtr anArcFeature = createArcFeature(aBaseFeature, aLastShapePoint, aLastArcPoint);
896 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
897 (anArcFeature->attribute(SketchPlugin_Arc::START_ID())));
899 std::string aModifiedAttribute = SketchPlugin_Arc::END_ID();
900 theModifiedAttributes.insert(
901 std::make_pair(aBaseFeature->attribute(aModifiedAttribute),
902 anArcFeature->attribute(SketchPlugin_Arc::END_ID())));
905 fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aStartShapePoint);
907 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
908 (aBaseFeature->attribute(aModifiedAttribute)));
910 // equal Radius constraint for arcs
911 anArcFeature->execute(); // we need the created arc result to set equal constraint
912 createConstraintForObjects(SketchPlugin_ConstraintEqual::ID(),
913 getFeatureResult(aBaseFeature),
914 getFeatureResult(anArcFeature));
915 // coincident centers constraint
916 createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
917 aBaseFeature->attribute(SketchPlugin_Arc::CENTER_ID()),
918 anArcFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
920 std::cout << "Created arc on points:" << std::endl;
921 std::cout << "Start shape point: [" << aStartShapePoint->x() << ", " <<
922 aStartShapePoint->y() << "]" << std::endl;
927 FeaturePtr SketchPlugin_Trim::trimCircle(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
928 const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
929 std::set<AttributePoint2DPtr>& thePoints,
930 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
932 // Check the base objects are initialized.
933 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
934 data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
935 ObjectPtr aBaseObject = aBaseObjectAttr->value();
936 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
939 //AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
940 //getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
943 FeaturePtr anArcFeature = createArcFeature(aBaseFeature, theStartShapePoint, theLastShapePoint);
944 // arc created by trim of circle is always correct, that means that it is not inversed
945 anArcFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(false);
947 theModifiedAttributes.insert(
948 std::make_pair(aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
949 anArcFeature->attribute(SketchPlugin_Arc::CENTER_ID())));
951 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
952 (anArcFeature->attribute(SketchPlugin_Arc::START_ID())));
953 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
954 (anArcFeature->attribute(SketchPlugin_Arc::END_ID())));
959 void SketchPlugin_Trim::arrangePointsOnLine(const AttributePoint2DPtr& theStartPointAttr,
960 const AttributePoint2DPtr& theEndPointAttr,
961 std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
962 std::shared_ptr<GeomAPI_Pnt2d>& theLastPoint) const
964 if (!theFirstPoint.get() || !theLastPoint.get())
967 // if first point is closer to last point, swap first and last values
968 if (theStartPointAttr->pnt()->distance(theFirstPoint) >
969 theStartPointAttr->pnt()->distance(theLastPoint)) {
970 std::shared_ptr<GeomAPI_Pnt2d> aTmpPoint = theFirstPoint;
971 theFirstPoint = theLastPoint;
972 theLastPoint = aTmpPoint;
976 void SketchPlugin_Trim::arrangePointsOnArc(const FeaturePtr& theArc,
977 const AttributePoint2DPtr& theStartPointAttr,
978 const AttributePoint2DPtr& theEndPointAttr,
979 std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
980 std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint) const
982 if (!theFirstPoint.get() || !theSecondPoint.get())
985 static const double anAngleTol = 1.e-12;
987 std::shared_ptr<GeomAPI_Pnt2d> aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
988 theArc->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt();
989 bool isReversed = theArc->boolean(SketchPlugin_Arc::REVERSED_ID())->value();
991 // collect directions to each point
992 std::shared_ptr<GeomAPI_Dir2d> aStartDir(
993 new GeomAPI_Dir2d(theStartPointAttr->pnt()->xy()->decreased(aCenter->xy())));
994 std::shared_ptr<GeomAPI_Dir2d> aFirstPtDir(
995 new GeomAPI_Dir2d(theFirstPoint->xy()->decreased(aCenter->xy())));
996 std::shared_ptr<GeomAPI_Dir2d> aSecondPtDir(
997 new GeomAPI_Dir2d(theSecondPoint->xy()->decreased(aCenter->xy())));
999 // sort points by their angular values
1000 double aFirstPtAngle = aStartDir->angle(aFirstPtDir);
1001 double aSecondPtAngle = aStartDir->angle(aSecondPtDir);
1002 double aPeriod = isReversed ? -2.0 * PI : 2.0 * PI;
1003 if (fabs(aFirstPtAngle) > anAngleTol && isReversed == (aFirstPtAngle > 0.))
1004 aFirstPtAngle += aPeriod;
1005 if (fabs(aSecondPtAngle) > anAngleTol && isReversed == (aSecondPtAngle > 0.))
1006 aSecondPtAngle += aPeriod;
1008 if (fabs(aFirstPtAngle) > fabs(aSecondPtAngle)) {
1009 std::shared_ptr<GeomAPI_Pnt2d> aTmpPoint = theFirstPoint;
1010 theFirstPoint = theSecondPoint;
1011 theSecondPoint = aTmpPoint;
1015 void SketchPlugin_Trim::fillPointAttribute(const AttributePtr& theModifiedAttribute,
1016 const std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
1018 std::string anAttributeType = theModifiedAttribute->attributeType();
1019 if (anAttributeType == GeomDataAPI_Point2D::typeId()) {
1020 AttributePoint2DPtr aModifiedAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1021 theModifiedAttribute);
1022 aModifiedAttribute->setValue(thePoint);
1025 FeaturePtr aFeature = ModelAPI_Feature::feature(theModifiedAttribute->owner());
1026 std::cout << "<fillPointAttribute[" << aFeature->data()->name() << ": " <<
1027 theModifiedAttribute->id() <<
1028 "]> => Pnt2d - [" << thePoint->x() << ", " << thePoint->y() << "]" << std::endl;
1034 void SketchPlugin_Trim::fillAttribute(const AttributePtr& theModifiedAttribute,
1035 const AttributePtr& theSourceAttribute)
1037 std::string anAttributeType = theModifiedAttribute->attributeType();
1038 if (anAttributeType == GeomDataAPI_Point2D::typeId()) {
1039 AttributePoint2DPtr aModifiedAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1040 theModifiedAttribute);
1041 AttributePoint2DPtr aSourceAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1042 theSourceAttribute);
1044 if (aModifiedAttribute.get() && aSourceAttribute.get())
1045 aModifiedAttribute->setValue(aSourceAttribute->pnt());
1047 else if (anAttributeType == ModelAPI_AttributeBoolean::typeId()) {
1048 AttributeBooleanPtr aModifiedAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(
1049 theModifiedAttribute);
1050 AttributeBooleanPtr aSourceAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(
1051 theSourceAttribute);
1053 if (aModifiedAttribute.get() && aSourceAttribute.get())
1054 aModifiedAttribute->setValue(aSourceAttribute->value());
1056 else if (anAttributeType == ModelAPI_AttributeRefAttr::typeId()) {
1057 AttributeRefAttrPtr aRefAttributeToFill = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1058 theModifiedAttribute);
1059 AttributeRefAttrPtr aSourceRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1060 theSourceAttribute);
1061 if (!aSourceRefAttr.get())
1062 aRefAttributeToFill->setAttr(theSourceAttribute);
1064 if (aSourceRefAttr->isObject())
1065 aRefAttributeToFill->setObject(aSourceRefAttr->object());
1067 aRefAttributeToFill->setAttr(aSourceRefAttr->attr());
1072 FeaturePtr SketchPlugin_Trim::createLineFeature(const FeaturePtr& theBaseFeature,
1073 const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
1074 const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint)
1077 std::cout << "---- createLineFeature ---" << std::endl;
1080 FeaturePtr aFeature;
1081 SketchPlugin_Sketch* aSketch = sketch();
1082 if (!aSketch || !theBaseFeature.get())
1085 aFeature = aSketch->addFeature(SketchPlugin_Line::ID());
1087 fillPointAttribute(aFeature->attribute(SketchPlugin_Line::START_ID()), theFirstPoint);
1088 fillPointAttribute(aFeature->attribute(SketchPlugin_Line::END_ID()), theSecondPoint);
1090 fillAttribute(aFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()),
1091 theBaseFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()));
1093 aFeature->execute(); // to obtain result
1096 std::cout << "---- createLineFeature:end ---" << std::endl;
1102 FeaturePtr SketchPlugin_Trim::createArcFeature(const FeaturePtr& theBaseFeature,
1103 const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
1104 const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint)
1106 FeaturePtr aFeature;
1107 SketchPlugin_Sketch* aSketch = sketch();
1108 if (!aSketch || !theBaseFeature.get())
1111 std::string aCenterAttributeId;
1112 if (theBaseFeature->getKind() == SketchPlugin_Arc::ID())
1113 aCenterAttributeId = SketchPlugin_Arc::CENTER_ID();
1114 else if (theBaseFeature->getKind() == SketchPlugin_Circle::ID())
1115 aCenterAttributeId = SketchPlugin_Circle::CENTER_ID();
1117 if (aCenterAttributeId.empty())
1121 std::cout << "---- createArcFeature ---" << std::endl;
1124 aFeature = aSketch->addFeature(SketchPlugin_Arc::ID());
1125 // update fillet arc: make the arc correct for sure, so, it is not needed to process
1126 // the "attribute updated"
1127 // by arc; moreover, it may cause cyclicity in hte mechanism of updater
1128 bool aWasBlocked = aFeature->data()->blockSendAttributeUpdated(true);
1130 fillAttribute(aFeature->attribute(SketchPlugin_Arc::CENTER_ID()),
1131 theBaseFeature->attribute(aCenterAttributeId));
1132 fillPointAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), theFirstPoint);
1133 fillPointAttribute(aFeature->attribute(SketchPlugin_Arc::END_ID()), theSecondPoint);
1135 fillAttribute(aFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()),
1136 theBaseFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()));
1138 /// fill referersed state of created arc as it is on the base arc
1139 if (theBaseFeature->getKind() == SketchPlugin_Arc::ID()) {
1140 bool aReversed = theBaseFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->value();
1141 aFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(aReversed);
1143 //aFeature->execute(); // to obtain result
1144 aFeature->data()->blockSendAttributeUpdated(aWasBlocked);
1147 std::cout << "---- createArcFeature:end ---" << std::endl;
1153 FeaturePtr SketchPlugin_Trim::createConstraint(const std::string& theConstraintId,
1154 const AttributePtr& theFirstAttribute,
1155 const AttributePtr& theSecondAttribute)
1157 FeaturePtr aConstraint = sketch()->addFeature(theConstraintId);
1158 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1159 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
1160 aRefAttr->setAttr(theFirstAttribute);
1162 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1163 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
1164 aRefAttr->setAttr(theSecondAttribute);
1167 std::cout << "<createConstraint to attribute> :"
1168 << "first attribute - " << theFirstAttribute->id()
1169 << "second attribute - " << theSecondAttribute->id()
1176 FeaturePtr SketchPlugin_Trim::createConstraintToObject(const std::string& theConstraintId,
1177 const AttributePtr& theFirstAttribute,
1178 const ObjectPtr& theSecondObject)
1180 FeaturePtr aConstraint = sketch()->addFeature(theConstraintId);
1181 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1182 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
1183 aRefAttr->setAttr(theFirstAttribute);
1185 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1186 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
1187 aRefAttr->setObject(theSecondObject);
1190 std::cout << "<createConstraint to attribute> :"
1191 << "first attribute - " << theFirstAttribute->id()
1192 << "second object - " << ModelAPI_Feature::feature(theSecondObject)->getKind()
1199 FeaturePtr SketchPlugin_Trim::createConstraintForObjects(
1200 const std::string& theConstraintId,
1201 const ObjectPtr& theFirstObject,
1202 const ObjectPtr& theSecondObject)
1204 FeaturePtr aConstraint = sketch()->addFeature(theConstraintId);
1205 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1206 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
1207 aRefAttr->setObject(theFirstObject);
1209 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1210 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
1211 aRefAttr->setObject(theSecondObject);
1216 std::shared_ptr<ModelAPI_Result> SketchPlugin_Trim::getFeatureResult(
1217 const std::shared_ptr<ModelAPI_Feature>& theFeature)
1219 std::shared_ptr<ModelAPI_Result> aResult;
1221 std::string aFeatureKind = theFeature->getKind();
1222 if (aFeatureKind == SketchPlugin_Line::ID())
1223 aResult = theFeature->firstResult();
1224 else if (aFeatureKind == SketchPlugin_Arc::ID())
1225 aResult = theFeature->lastResult();
1226 else if (aFeatureKind == SketchPlugin_Circle::ID())
1227 aResult = theFeature->lastResult();
1232 //********************************************************************
1233 void SketchPlugin_Trim::fillObjectShapes(const ObjectPtr& theObject,
1234 const ObjectPtr& theSketch,
1235 std::map<ObjectPtr, std::set<GeomShapePtr> >& theCashedShapes,
1236 std::map<ObjectPtr, PointToRefsMap>& theObjectToPoints)
1238 PointToRefsMap aPointsInfo;
1240 std::set<std::shared_ptr<GeomAPI_Shape> > aShapes;
1241 std::map<std::shared_ptr<GeomAPI_Pnt>,
1242 std::list< AttributePoint2DPtr > > aPointToAttributes;
1243 std::map<std::shared_ptr<GeomAPI_Pnt>,
1244 std::list< ObjectPtr > > aPointToObjects;
1246 std::set<AttributePoint2DPtr > aRefAttributes;
1248 FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
1249 std::set<ResultPtr> anEdgeShapes;
1251 ModelGeomAlgo_Shape::shapesOfType(aFeature, GeomAPI_Shape::EDGE, anEdgeShapes);
1252 if (!anEdgeShapes.empty()) {
1253 GeomShapePtr aFeatureShape = (*anEdgeShapes.begin())->shape();
1255 // coincidences to the feature
1256 ModelGeomAlgo_Point2D::getPointsOfReference(aFeature, SketchPlugin_ConstraintCoincidence::ID(),
1257 aRefAttributes, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID());
1258 // layed on feature coincidences to divide it on several shapes
1259 //SketchPlugin_Sketch* aSketch = sketch();
1260 std::shared_ptr<ModelAPI_Data> aData = theSketch->data();
1261 std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
1262 aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
1263 std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
1264 aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
1265 std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
1266 aData->attribute(SketchPlugin_Sketch::NORM_ID()));
1267 std::shared_ptr<GeomAPI_Dir> aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
1269 ModelGeomAlgo_Point2D::getPointsInsideShape(aFeatureShape, aRefAttributes, aC->pnt(),
1270 aX->dir(), aY, aPointsInfo);
1272 std::list<FeaturePtr> aFeatures;
1273 CompositeFeaturePtr aSketchComposite =
1274 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theSketch);
1275 for (int i = 0; i < aSketchComposite->numberOfSubs(); i++) {
1276 FeaturePtr aFeature = aSketchComposite->subFeature(i);
1278 aFeatures.push_back(aFeature);
1280 ModelGeomAlgo_Point2D::getPointsIntersectedShape(aFeature, aFeatures, aPointsInfo);
1282 GeomAlgoAPI_ShapeTools::splitShape(aFeatureShape, aPointsInfo, aShapes);
1284 theObjectToPoints[theObject] = aPointsInfo;
1285 theCashedShapes[theObject] = aShapes;