1 // Copyright (C) 2014-2019 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "SketchPlugin_Trim.h"
22 #include <GeomAPI_Dir2d.h>
23 #include <GeomAPI_Edge.h>
24 #include <GeomAPI_Pnt2d.h>
25 #include <GeomAPI_XY.h>
26 #include <GeomDataAPI_Point2D.h>
27 #include <GeomAlgoAPI_ShapeTools.h>
29 #include <ModelAPI_AttributeReference.h>
30 #include <ModelAPI_AttributeString.h>
31 #include <ModelAPI_AttributeRefAttr.h>
32 #include <ModelAPI_Tools.h>
33 #include <ModelAPI_AttributeBoolean.h>
35 #include <ModelAPI_Validator.h>
36 #include <ModelAPI_Session.h>
37 #include <ModelAPI_AttributeDouble.h>
39 #include <ModelGeomAlgo_Shape.h>
41 #include <SketchPlugin_Arc.h>
42 #include <SketchPlugin_ConstraintMiddle.h>
43 #include <SketchPlugin_Circle.h>
44 #include <SketchPlugin_ConstraintCoincidence.h>
45 #include <SketchPlugin_ConstraintEqual.h>
46 #include <SketchPlugin_ConstraintTangent.h>
47 #include <SketchPlugin_ConstraintLength.h>
48 #include <SketchPlugin_ConstraintMirror.h>
49 #include <SketchPlugin_ConstraintCollinear.h>
50 #include <SketchPlugin_Ellipse.h>
51 #include <SketchPlugin_EllipticArc.h>
52 #include <SketchPlugin_Line.h>
53 #include <SketchPlugin_MultiRotation.h>
54 #include <SketchPlugin_MultiTranslation.h>
55 #include <SketchPlugin_Point.h>
57 #include <ModelAPI_EventReentrantMessage.h>
59 #include <ModelAPI_Events.h>
60 #include <SketchPlugin_Line.h>
61 #include <SketchPlugin_Arc.h>
62 #include <SketchPlugin_Circle.h>
64 #include <ModelGeomAlgo_Point2D.h>
65 #include <Events_Loop.h>
74 #ifdef DEBUG_TRIM_METHODS
78 static const double PI = 3.141592653589793238463;
80 static const std::string OPERATION_HIGHLIGHT_COLOR() { return "128, 0, 0"; }
81 static const std::string OPERATION_REMOVE_FEATURE_COLOR() { return "255, 174, 201"; }
83 SketchPlugin_Trim::SketchPlugin_Trim()
87 void SketchPlugin_Trim::initAttributes()
89 data()->addAttribute(SELECTED_OBJECT(), ModelAPI_AttributeReference::typeId());
90 data()->addAttribute(SELECTED_POINT(), GeomDataAPI_Point2D::typeId());
92 data()->addAttribute(PREVIEW_POINT(), GeomDataAPI_Point2D::typeId());
93 data()->addAttribute(PREVIEW_OBJECT(), ModelAPI_AttributeReference::typeId());
95 data()->attribute(PREVIEW_POINT())->setIsArgument(false);
96 data()->attribute(SELECTED_POINT())->setIsArgument(false);
97 data()->attribute(PREVIEW_OBJECT())->setIsArgument(false);
99 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PREVIEW_POINT());
100 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PREVIEW_OBJECT());
103 void SketchPlugin_Trim::findShapePoints(const std::string& theObjectAttributeId,
104 const std::string& thePointAttributeId,
105 std::shared_ptr<GeomAPI_Pnt>& aStartPoint,
106 std::shared_ptr<GeomAPI_Pnt>& aLastPoint)
108 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
109 data()->attribute(theObjectAttributeId));
110 ObjectPtr aBaseObject = aBaseObjectAttr->value();
112 AttributePoint2DPtr aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
113 data()->attribute(thePointAttributeId));
114 std::shared_ptr<GeomAPI_Pnt2d> anAttributePnt2d = aPoint->pnt();
115 std::shared_ptr<GeomAPI_Pnt> anAttributePnt = sketch()->to3D(anAttributePnt2d->x(),
116 anAttributePnt2d->y());
118 if (myCashedShapes.find(aBaseObject) == myCashedShapes.end()) {
119 SketchPlugin_SegmentationTools::fillObjectShapes(
120 this, aBaseObject, myCashedShapes, myObjectToPoints);
123 const std::set<GeomShapePtr>& aShapes = myCashedShapes[aBaseObject];
124 if (!aShapes.empty()) {
125 std::set<GeomShapePtr>::const_iterator anIt = aShapes.begin(), aLast = aShapes.end();
126 for (; anIt != aLast; anIt++) {
127 GeomShapePtr aBaseShape = *anIt;
128 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
129 if (ModelGeomAlgo_Point2D::isPointOnEdge(aBaseShape, anAttributePnt, aProjectedPoint)) {
131 if (aBaseShape->shapeType() == GeomAPI_Shape::EDGE) {
132 std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aBaseShape));
133 //GeomAPI_Shape::Orientation anOrientation = anEdge->orientation();
134 //if (anOrientation == GeomAPI_Shape::REVERSED) {
135 aStartPoint = anEdge->lastPoint();
136 aLastPoint = anEdge->firstPoint();
139 //aStartPoint = anEdge->firstPoint();
140 //aLastPoint = anEdge->lastPoint();
147 std::cout << "<findShapePoints> => "
148 << std::endl << "Attribute point: "
149 << anAttributePnt->x() << ", " << anAttributePnt->y() << ", " << anAttributePnt->z() << "]"
150 << std::endl << "Start Point: ["
151 << aStartPoint->x() << ", " << aStartPoint->y() << ", " << aStartPoint->z() << "]"
152 << std::endl << "Last Point: ["
153 << aLastPoint->x() << ", " << aLastPoint->y() << ", " << aLastPoint->z() << "]"
158 std::shared_ptr<GeomAPI_Pnt2d> SketchPlugin_Trim::convertPoint(
159 const std::shared_ptr<GeomAPI_Pnt>& thePoint)
161 std::shared_ptr<GeomAPI_Pnt2d> aPoint;
165 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
166 data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
167 ObjectPtr aBaseObject = aBaseObjectAttr->value();
168 if (myObjectToPoints.find(aBaseObject) == myObjectToPoints.end()) {
169 SketchPlugin_SegmentationTools::fillObjectShapes(
170 this, aBaseObject, myCashedShapes, myObjectToPoints);
174 const GeomAlgoAPI_ShapeTools::PointToRefsMap& aRefsMap = myObjectToPoints.at(aBaseObject);
175 for (GeomAlgoAPI_ShapeTools::PointToRefsMap::const_iterator aPointIt = aRefsMap.begin();
176 aPointIt != aRefsMap.end() && !aFound; aPointIt++) {
177 if (aPointIt->first->isEqual(thePoint)) {
178 const std::pair<std::list<AttributePoint2DPtr >,
179 std::list<ObjectPtr > >& anInfo = aPointIt->second;
180 const std::list<AttributePoint2DPtr >& anAttributes = anInfo.first;
181 if (!anAttributes.empty()) {
182 aPoint = anAttributes.front()->pnt();
186 aPoint = sketch()->to2D(thePoint);
192 // returns an end of the shape to define direction of split if feature's attribute
194 aPoint = sketch()->to2D(thePoint);
199 void SketchPlugin_Trim::execute()
201 #ifdef DEBUG_TRIM_METHODS
202 std::cout << "SketchPlugin_Trim::execute: " << data()->name() << std::endl;
205 SketchPlugin_Sketch* aSketch = sketch();
207 setError("Error: Sketch object is empty.");
211 // Check the base objects are initialized.
212 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
213 data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
214 if(!aBaseObjectAttr->isInitialized()) {
215 setError("Error: Base object is not initialized.");
218 ObjectPtr aBaseObject = aBaseObjectAttr->value();
219 if (!aBaseObject.get()) {
220 setError("Error: Base object is not initialized.");
223 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
225 /// Remove reference of this feature to feature used in preview, it is not necessary anymore
226 /// as trim will be removed after execute
227 AttributeReferencePtr aPreviewObjectAttr =
228 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
229 data()->attribute(SketchPlugin_Trim::PREVIEW_OBJECT()));
231 ObjectPtr aPreviewObject = aPreviewObjectAttr->value();
232 AttributePoint2DPtr aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
233 data()->attribute(PREVIEW_POINT()));
234 std::shared_ptr<GeomAPI_Pnt2d> aPreviewPnt2d = aPoint->pnt();
235 // nullify pointer of preview attribute
236 aPreviewObjectAttr->setValue(ResultPtr());
238 bool anIsEqualPreviewAndSelected = aPreviewObject == aBaseObject;
241 std::shared_ptr<GeomAPI_Pnt> aStartShapePoint, aLastShapePoint;
243 std::cout << " Base Feature: " << aBaseFeature->data()->name() << std::endl;
245 findShapePoints(SELECTED_OBJECT(), SELECTED_POINT(), aStartShapePoint, aLastShapePoint);
246 if (!aStartShapePoint || !aLastShapePoint) {
247 setError("Error: Selected point is not placed on any edge");
251 std::shared_ptr<GeomAPI_Pnt2d> aStartShapePoint2d = convertPoint(aStartShapePoint);
252 std::shared_ptr<GeomAPI_Pnt2d> aLastShapePoint2d = convertPoint(aLastShapePoint);
253 /// find features that should be deleted (e.g. Middle Point) or updated (e.g. Length)
254 std::set<FeaturePtr> aFeaturesToDelete, aFeaturesToUpdate;
255 getConstraints(aFeaturesToDelete, aFeaturesToUpdate);
256 // find references(attributes and features) to the base feature
257 std::map<AttributePtr, std::list<AttributePtr> > aBaseRefAttributes;
258 std::list<AttributePtr> aRefsToFeature;
259 SketchPlugin_SegmentationTools::getRefAttributes(
260 aBaseFeature, aBaseRefAttributes, aRefsToFeature);
262 std::cout << "---- getRefAttributes ----" << std::endl;
263 std::map<AttributePtr, std::list<AttributePtr> >::const_iterator
264 aRefIt = aBaseRefAttributes.begin(), aRefLast = aBaseRefAttributes.end();
265 std::cout << std::endl << "References to attributes of base feature [" <<
266 aBaseRefAttributes.size() << "]" << std::endl;
267 for (; aRefIt != aRefLast; aRefIt++) {
268 AttributePtr aBaseAttr = aRefIt->first;
269 std::list<AttributePtr> aRefAttributes = aRefIt->second;
270 std::string aRefsInfo;
271 std::list<AttributePtr>::const_iterator aRefAttrIt = aRefAttributes.begin(),
272 aRefAttrLast = aRefAttributes.end();
273 for (; aRefAttrIt != aRefAttrLast; aRefAttrIt++) {
274 if (!aRefsInfo.empty())
275 aRefsInfo.append(",");
276 AttributePtr aRAttr = *aRefAttrIt;
277 aRefsInfo.append(aRAttr->id());
278 FeaturePtr aRFeature = ModelAPI_Feature::feature(aRAttr->owner());
279 aRefsInfo.append("(" + aRFeature->name() + ") ");
281 std::shared_ptr<GeomDataAPI_Point2D> aPointAttr =
282 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aBaseAttr);
283 std::cout << aPointAttr->id().c_str() <<
284 ": " << "[" << aRefAttributes.size() << "] " << aRefsInfo << std::endl;
286 std::cout << std::endl;
287 std::cout << std::endl << "References to base feature [" <<
288 aRefsToFeature.size() << "]" << std::endl;
289 std::list<AttributePtr>::const_iterator aRefAttrIt = aRefsToFeature.begin(),
290 aRefAttrLast = aRefsToFeature.end();
291 std::string aRefsInfo;
292 for (; aRefAttrIt != aRefAttrLast; aRefAttrIt++) {
293 if (!aRefsInfo.empty())
294 aRefsInfo.append(",");
295 AttributePtr aRAttr = *aRefAttrIt;
296 aRefsInfo.append(aRAttr->id());
297 FeaturePtr aRFeature = ModelAPI_Feature::feature(aRAttr->owner());
298 aRefsInfo.append("(" + aRFeature->name() + ") ");
300 std::cout << "[" << aRefsToFeature.size() << "] " << aRefsInfo << std::endl;
301 std::cout << "---- getRefAttributes:end ----" << std::endl;
304 keepCurrentFeature();
306 std::set<AttributePoint2DPtr> aFurtherCoincidences;
307 std::set<std::pair<AttributePtr, AttributePtr>> aModifiedAttributes;
308 const std::string& aKind = aBaseFeature->getKind();
309 FeaturePtr aReplacingFeature, aNewFeature;
310 if (aKind == SketchPlugin_Circle::ID() ||
311 aKind == SketchPlugin_Ellipse::ID()) {
312 aReplacingFeature = trimClosed(aStartShapePoint2d, aLastShapePoint2d,
313 aFurtherCoincidences, aModifiedAttributes);
315 aFeaturesToDelete.insert(aBaseFeature);
316 // as circle is removed, erase it from dependencies(arguments) of this feature
317 // otherwise Trim feature will be removed with the circle before
318 // this operation is finished
319 aBaseObjectAttr->setObject(ResultPtr());
321 else if (aKind == SketchPlugin_Line::ID()) {
322 aNewFeature = trimLine(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes,
323 aFurtherCoincidences, aModifiedAttributes);
325 else if (aKind == SketchPlugin_Arc::ID()) {
326 aNewFeature = trimArc(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes,
327 aFurtherCoincidences, aModifiedAttributes);
329 else if (aKind == SketchPlugin_EllipticArc::ID()) {
330 aNewFeature = trimEllipticArc(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes,
331 aFurtherCoincidences, aModifiedAttributes);
334 restoreCurrentFeature();
336 // constraints to end points of trim feature
337 if (myObjectToPoints.find(aBaseObject) == myObjectToPoints.end()) {
338 SketchPlugin_SegmentationTools::fillObjectShapes(
339 this, aBaseObject, myCashedShapes, myObjectToPoints);
342 // create coincidence to objects, intersected the base object
343 const GeomAlgoAPI_ShapeTools::PointToRefsMap& aRefsMap = myObjectToPoints.at(aBaseObject);
344 for (std::set<AttributePoint2DPtr>::const_iterator anIt = aFurtherCoincidences.begin(),
345 aLast = aFurtherCoincidences.end();
346 anIt != aLast; anIt++) {
347 AttributePoint2DPtr aPointAttribute = (*anIt);
348 std::shared_ptr<GeomAPI_Pnt2d> aPoint2d = aPointAttribute->pnt();
351 std::cout << "<compare Points> => " << std::endl
352 << "aPoint2d: [" << aPoint2d->x() << ", " << aPoint2d->y() << "]" << std::endl;
353 if (aStartShapePoint2d.get())
354 std::cout << "Start Point: [" << aStartShapePoint2d->x() << ", " << aStartShapePoint2d->y()
356 if (aLastShapePoint2d.get())
357 std::cout << "Last Point: [" << aLastShapePoint2d->x() << ", " << aLastShapePoint2d->y()
361 std::shared_ptr<GeomAPI_Pnt> aPoint;
362 if (aStartShapePoint2d.get() && aPoint2d->isEqual(aStartShapePoint2d))
363 aPoint = aStartShapePoint;
364 else if (aLastShapePoint2d.get() && aPoint2d->isEqual(aLastShapePoint2d))
365 aPoint = aLastShapePoint;
370 std::pair<std::list<AttributePoint2DPtr >, std::list<ObjectPtr > > anInfo;
371 for (GeomAlgoAPI_ShapeTools::PointToRefsMap::const_iterator aRefIt = aRefsMap.begin();
372 aRefIt != aRefsMap.end(); aRefIt++)
374 if (aRefIt->first->isEqual(aPoint)) {
375 anInfo = aRefIt->second;
379 const std::list<ObjectPtr>& anObjects = anInfo.second;
380 for (std::list<ObjectPtr>::const_iterator anObjectIt = anObjects.begin();
381 anObjectIt != anObjects.end(); anObjectIt++) {
382 SketchPlugin_Tools::createConstraintAttrObject(sketch(),
383 SketchPlugin_ConstraintCoincidence::ID(),
384 aPointAttribute, *anObjectIt);
388 // move constraints from base feature to replacing feature: ignore coincidences to feature
389 // if attributes of coincidence participated in split
390 ResultPtr aReplacingResult;
391 if (aReplacingFeature.get()) {
392 aReplacingFeature->execute(); // need it to obtain result
393 aReplacingResult = aReplacingFeature->lastResult();
395 for(std::list<AttributePtr>::const_iterator anIt = aRefsToFeature.begin(),
396 aLast = aRefsToFeature.end();
397 anIt != aLast; anIt++) {
398 AttributePtr anAttribute = *anIt;
400 if (setCoincidenceToAttribute(anAttribute, aFurtherCoincidences, aFeaturesToDelete))
403 // move tangency constraint to the nearest feature if possible
404 if (aNewFeature.get() && moveTangency(anAttribute, aNewFeature))
407 if (aReplacingResult.get()) {
408 AttributeRefAttrPtr aRefAttr =
409 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
411 aRefAttr->setObject(aReplacingResult);
413 AttributeReferencePtr aReferenceAttr =
414 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(anAttribute);
415 if (aReferenceAttr.get())
416 aReferenceAttr->setObject(aReplacingResult);
421 SketchPlugin_SegmentationTools::updateRefAttConstraints(aBaseRefAttributes, aModifiedAttributes);
423 // Wait all constraints being created, then send update events
424 static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
425 bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
427 Events_Loop::loop()->setFlushed(anUpdateEvent, false);
429 // delete constraints
431 if (aFeaturesToDelete.size() > 0) {
432 std::cout << "after SPlit: removeFeaturesAndReferences: " << std::endl;
434 for (std::set<FeaturePtr>::const_iterator anIt = aFeaturesToDelete.begin();
435 anIt != aFeaturesToDelete.end(); anIt++) {
436 FeaturePtr aFeature = *anIt;
437 std::cout << aFeature->data()->name() << std::endl;
441 ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToDelete);
442 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
444 SketchPlugin_SegmentationTools::updateFeaturesAfterOperation(aFeaturesToUpdate);
446 // Send events to update the sub-features by the solver.
447 if(isUpdateFlushed) {
448 Events_Loop::loop()->setFlushed(anUpdateEvent, true);
451 if (anIsEqualPreviewAndSelected) {
452 // equal preview and selected objects
453 // nothing to do if the preview and selected objects are different
454 if (aReplacingResult.get()) { // base object was removed
455 aPreviewObject = aReplacingResult;
456 //aMessage->setSelectedObject(aReplacingResult);
457 #ifdef DEBUG_TRIM_METHODS
458 if (!aSelectedShape.get())
459 std::cout << "Set empty selected object" << std::endl;
461 std::cout << "Set shape with ShapeType: " << aSelectedShape->shapeTypeStr() << std::endl;
465 aPreviewObject = ObjectPtr();
467 aBaseFeature->execute(); // should recompute shapes of result to do not check obsolete one
468 aBaseObject = aBaseFeature->lastResult();
469 std::shared_ptr<GeomAPI_Pnt> aPreviewPnt = sketch()->to3D(aPreviewPnt2d->x(),
471 ResultPtr aBaseResult = std::dynamic_pointer_cast<ModelAPI_Result>(aBaseObject);
473 GeomShapePtr aShape = aBaseResult->shape();
474 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
475 if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, aPreviewPnt, aProjectedPoint))
476 aPreviewObject = aBaseResult;
478 if (!aPreviewObject.get() && aNewFeature.get()) {
479 ResultPtr aNewFeatureResult = aNewFeature->lastResult();
480 if (aNewFeatureResult.get()) {
481 GeomShapePtr aShape = aNewFeatureResult->shape();
482 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
483 if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, aPreviewPnt, aProjectedPoint))
484 aPreviewObject = aNewFeatureResult;
489 if (aPreviewObject.get()) {
490 std::shared_ptr<ModelAPI_EventReentrantMessage> aMessage = std::shared_ptr
491 <ModelAPI_EventReentrantMessage>(new ModelAPI_EventReentrantMessage(
492 ModelAPI_EventReentrantMessage::eventId(), this));
493 aMessage->setSelectedObject(aPreviewObject);
494 Events_Loop::loop()->send(aMessage);
497 std::cout << "SketchPlugin_Trim::done" << std::endl;
502 std::string SketchPlugin_Trim::processEvent(const std::shared_ptr<Events_Message>& theMessage)
504 #ifdef DEBUG_TRIM_METHODS
505 std::cout << "SketchPlugin_Trim::processEvent:" << data()->name() << std::endl;
507 std::string aFilledAttributeName;
509 std::shared_ptr<ModelAPI_EventReentrantMessage> aMessage =
510 std::dynamic_pointer_cast<ModelAPI_EventReentrantMessage>(theMessage);
511 if (aMessage.get()) {
512 ObjectPtr anObject = aMessage->selectedObject();
513 std::shared_ptr<GeomAPI_Pnt2d> aPoint = aMessage->clickedPoint();
515 if (anObject.get() && aPoint.get()) {
516 if (myCashedShapes.find(anObject) == myCashedShapes.end()) {
517 SketchPlugin_SegmentationTools::fillObjectShapes(
518 this, anObject, myCashedShapes, myObjectToPoints);
520 const std::set<GeomShapePtr>& aShapes = myCashedShapes[anObject];
521 if (aShapes.size() > 1) {
522 std::shared_ptr<ModelAPI_AttributeReference> aRefSelectedAttr =
523 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
524 data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
525 std::shared_ptr<ModelAPI_AttributeReference> aRefPreviewAttr =
526 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
527 data()->attribute(SketchPlugin_Trim::PREVIEW_OBJECT()));
528 aRefSelectedAttr->setValue(anObject);
529 aRefPreviewAttr->setValue(anObject);
531 std::shared_ptr<GeomDataAPI_Point2D> aPointSelectedAttr =
532 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
533 data()->attribute(SketchPlugin_Trim::SELECTED_POINT()));
534 std::shared_ptr<GeomDataAPI_Point2D> aPointPreviewAttr =
535 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
536 data()->attribute(SketchPlugin_Trim::PREVIEW_POINT()));
537 aPointSelectedAttr->setValue(aPoint);
538 aPointPreviewAttr->setValue(aPoint);
540 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
542 GeomShapePtr aSelectedShape = SketchPlugin_SegmentationTools::getSubShape(this,
543 SELECTED_OBJECT(), SELECTED_POINT(), myCashedShapes, myObjectToPoints);
544 #ifdef DEBUG_TRIM_METHODS
545 if (!aSelectedShape.get())
546 std::cout << "Set empty selected object" << std::endl;
548 std::cout << "Set shape with ShapeType: " << aSelectedShape->shapeTypeStr() << std::endl;
550 aFilledAttributeName = SketchPlugin_Trim::SELECTED_OBJECT();
554 return aFilledAttributeName;
558 bool SketchPlugin_Trim::setCoincidenceToAttribute(const AttributePtr& theAttribute,
559 const std::set<AttributePoint2DPtr>& theFurtherCoincidences,
560 std::set<std::shared_ptr<ModelAPI_Feature>>& theFeaturesToDelete)
562 FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
563 if (aFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID())
566 AttributePoint2DPtr aRefPointAttr = SketchPlugin_ConstraintCoincidence::getPoint(aFeature);
567 if (!aRefPointAttr.get())
569 std::shared_ptr<GeomAPI_Pnt2d> aRefPnt2d = aRefPointAttr->pnt();
571 std::set<AttributePoint2DPtr>::const_iterator anIt = theFurtherCoincidences.begin(),
572 aLast = theFurtherCoincidences.end();
573 bool aFoundPoint = false;
574 for (; anIt != aLast && !aFoundPoint; anIt++) {
575 AttributePoint2DPtr aPointAttribute = (*anIt);
576 std::shared_ptr<GeomAPI_Pnt2d> aPoint2d = aPointAttribute->pnt();
577 if (aPoint2d->isEqual(aRefPnt2d)) {
578 // create new coincidence and then remove the old one
579 SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
580 SketchPlugin_ConstraintCoincidence::ID(),
581 aRefPointAttr, aPointAttribute);
582 theFeaturesToDelete.insert(aFeature);
588 bool SketchPlugin_Trim::moveTangency(const AttributePtr& theAttribute,
589 const FeaturePtr& theFeature)
591 FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
592 if (aFeature->getKind() != SketchPlugin_ConstraintTangent::ID())
595 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
600 // get shape of tangent object to the current
601 std::string aTangentAttr = SketchPlugin_Constraint::ENTITY_A();
602 if (aRefAttr->id() == SketchPlugin_Constraint::ENTITY_A())
603 aTangentAttr = SketchPlugin_Constraint::ENTITY_B();
604 AttributeRefAttrPtr aTangentRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
605 aFeature->attribute(aTangentAttr));
606 FeaturePtr aTangentFeature = ModelAPI_Feature::feature(aTangentRefAttr->object());
608 // get shape of the feature of the attribute
609 FeaturePtr anAttributeFeature = ModelAPI_Feature::feature(aRefAttr->object());
610 anAttributeFeature->execute(); // the modified value should be applyed to recompute shape
611 GeomAlgoAPI_ShapeTools::PointToRefsMap aPointToAttributeOrObject;
612 std::list<FeaturePtr> aFeatures;
613 aFeatures.push_back(anAttributeFeature);
614 ModelGeomAlgo_Point2D::getPointsIntersectedShape(aTangentFeature, aFeatures,
615 aPointToAttributeOrObject);
616 if (!aPointToAttributeOrObject.empty())
617 return true; // the attribute feature has a point of intersection, so we do not replace it
619 // get shape of the feature
620 aPointToAttributeOrObject.clear();
622 aFeatures.push_back(theFeature);
623 ModelGeomAlgo_Point2D::getPointsIntersectedShape(aTangentFeature, aFeatures,
624 aPointToAttributeOrObject);
625 if (!aPointToAttributeOrObject.empty()) {
626 std::set<ResultPtr> anEdgeShapes;
627 ModelGeomAlgo_Shape::shapesOfType(theFeature, GeomAPI_Shape::EDGE, anEdgeShapes);
628 if (!anEdgeShapes.empty()) {
629 ResultPtr aResult = *anEdgeShapes.begin();
631 aRefAttr->setObject(aResult);
632 return true; // the attribute feature has a point of intersection, so we do not replace it
639 AISObjectPtr SketchPlugin_Trim::getAISObject(AISObjectPtr thePrevious)
641 return SketchPlugin_SegmentationTools::getAISObject(thePrevious,
642 this, PREVIEW_OBJECT(), PREVIEW_POINT(), SELECTED_OBJECT(), SELECTED_POINT());
645 void SketchPlugin_Trim::getConstraints(std::set<FeaturePtr>& theFeaturesToDelete,
646 std::set<FeaturePtr>& theFeaturesToUpdate)
648 std::shared_ptr<ModelAPI_Data> aData = data();
650 // Check the base objects are initialized.
651 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
652 aData->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
653 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
654 ResultPtr aBaseFeatureResult = aBaseFeature->lastResult();
656 std::set<AttributePtr> aRefsList = aBaseFeatureResult->data()->refsToMe();
657 std::set<AttributePtr> aFRefsList = aBaseFeature->data()->refsToMe();
658 aRefsList.insert(aFRefsList.begin(), aFRefsList.end());
660 std::set<AttributePtr>::const_iterator aIt;
661 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
662 std::shared_ptr<ModelAPI_Attribute> anAttr = (*aIt);
663 FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anAttr->owner());
664 std::string aRefFeatureKind = aRefFeature->getKind();
665 std::string anAttributeId = anAttr->id();
666 if ((aRefFeatureKind == SketchPlugin_ConstraintMirror::ID() &&
667 anAttributeId == SketchPlugin_ConstraintMirror::MIRROR_LIST_ID()) ||
668 (aRefFeatureKind == SketchPlugin_MultiRotation::ID() &&
669 anAttributeId == SketchPlugin_MultiRotation::ROTATION_LIST_ID()) ||
670 (aRefFeatureKind == SketchPlugin_MultiTranslation::ID() &&
671 anAttributeId == SketchPlugin_MultiTranslation::TRANSLATION_LIST_ID()) ||
672 aRefFeatureKind == SketchPlugin_ConstraintMiddle::ID())
673 theFeaturesToDelete.insert(aRefFeature);
674 else if (aRefFeatureKind == SketchPlugin_ConstraintLength::ID())
675 theFeaturesToUpdate.insert(aRefFeature);
679 void SketchPlugin_Trim::removeReferencesToAttribute(const AttributePtr& theAttribute,
680 std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes)
682 /// not found in references
683 if (theBaseRefAttributes.find(theAttribute) == theBaseRefAttributes.end())
686 std::list<AttributePtr> aRefAttributes = theBaseRefAttributes.at(theAttribute);
687 std::list<AttributePtr>::const_iterator aRefIt = aRefAttributes.begin(),
688 aRLast = aRefAttributes.end();
690 std::set<FeaturePtr> aFeaturesToDelete;
691 for (; aRefIt != aRLast; aRefIt++) {
692 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefIt);
693 if (aRefAttr.get()) {
694 aFeaturesToDelete.insert(ModelAPI_Feature::feature(aRefAttr->owner()));
699 // delete constraints
700 if (aFeaturesToDelete.size() > 0) {
701 std::cout << "removeReferencesToAttribute: " << std::endl;
703 for (std::set<FeaturePtr>::const_iterator anIt = aFeaturesToDelete.begin();
704 anIt != aFeaturesToDelete.end(); anIt++) {
705 FeaturePtr aFeature = *anIt;
706 std::cout << aFeature->data()->name() << std::endl;
710 ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToDelete);
711 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
714 FeaturePtr SketchPlugin_Trim::trimLine(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
715 const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
716 std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
717 std::set<AttributePoint2DPtr>& thePoints,
718 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
720 FeaturePtr anNewFeature;
722 // Check the base objects are initialized.
723 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
724 data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
725 ObjectPtr aBaseObject = aBaseObjectAttr->value();
726 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
729 AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
730 SketchPlugin_SegmentationTools::getFeaturePoints(
731 aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
733 std::shared_ptr<GeomAPI_Pnt2d> aStartFeaturePoint = aStartPointAttrOfBase->pnt();
734 std::shared_ptr<GeomAPI_Pnt2d> aLastFeaturePoint = anEndPointAttrOfBase->pnt();
736 std::shared_ptr<GeomAPI_Pnt2d> aStartShapePoint = theStartShapePoint;
737 std::shared_ptr<GeomAPI_Pnt2d> aLastShapePoint = theLastShapePoint;
738 arrangePointsOnLine(aStartPointAttrOfBase, anEndPointAttrOfBase,
739 aStartShapePoint, aLastShapePoint);
741 std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl;
742 if (aStartShapePoint.get())
743 std::cout << "Start point: [" << aStartShapePoint->x() << ", " <<
744 aStartShapePoint->y() << "]" << std::endl;
745 std::cout << "1st point: [" << aStartFeaturePoint->x() << ", " <<
746 aStartFeaturePoint->y() << "]" << std::endl;
747 if (aLastShapePoint.get())
748 std::cout << "2st point: [" << aLastShapePoint->x() << ", " <<
749 aLastShapePoint->y() << "]" << std::endl;
750 std::cout << "End point: [" << aLastFeaturePoint->x() << ", " <<
751 aLastFeaturePoint->y() << "]" << std::endl;
754 bool isStartPoint = !aStartShapePoint.get() || aStartFeaturePoint->isEqual(aStartShapePoint);
755 bool isLastPoint = !aLastShapePoint.get() || aLastFeaturePoint->isEqual(aLastShapePoint);
756 if (isStartPoint || isLastPoint) {
757 // result is one line: changed existing line
758 std::string aModifiedAttribute = isStartPoint ? SketchPlugin_Line::START_ID()
759 : SketchPlugin_Line::END_ID();
760 std::shared_ptr<GeomAPI_Pnt2d> aPoint;
761 if (aStartShapePoint.get() && aLastShapePoint.get())
762 aPoint = isStartPoint ? aLastShapePoint : aStartShapePoint;
764 aPoint = aStartShapePoint.get() ? aStartShapePoint : aLastShapePoint;
766 // it is important to delete references before the feature modification because
767 // if deletion will be after the feature modification, solver returns the feature back
768 removeReferencesToAttribute(aBaseFeature->attribute(aModifiedAttribute),
769 theBaseRefAttributes);
771 fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aPoint);
772 //theModifiedAttributes.insert(
773 // std::make_pair(aBaseFeature->attribute(aModifiedAttribute), AttributePtr()));
775 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
776 (aBaseFeature->attribute(aModifiedAttribute)));
779 // result is two lines: start line point - start shape point,
780 // last shape point - last line point
781 // create second line
782 anNewFeature = SketchPlugin_SegmentationTools::createLineFeature(
783 aBaseFeature, aLastShapePoint, aLastFeaturePoint);
784 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
785 (anNewFeature->attribute(SketchPlugin_Line::START_ID())));
787 std::string aModifiedAttribute = SketchPlugin_Line::END_ID();
788 theModifiedAttributes.insert(
789 std::make_pair(aBaseFeature->attribute(aModifiedAttribute),
790 anNewFeature->attribute(SketchPlugin_Line::END_ID())));
793 fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aStartShapePoint);
795 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
796 (aBaseFeature->attribute(aModifiedAttribute)));
798 // Collinear constraint for lines
799 SketchPlugin_Tools::createConstraintObjectObject(sketch(),
800 SketchPlugin_ConstraintCollinear::ID(),
801 aBaseFeature->lastResult(),
802 anNewFeature->lastResult());
807 FeaturePtr SketchPlugin_Trim::trimArc(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
808 const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
809 std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
810 std::set<AttributePoint2DPtr>& thePoints,
811 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
813 FeaturePtr anNewFeature;
814 // Check the base objects are initialized.
815 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
816 data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
817 ObjectPtr aBaseObject = aBaseObjectAttr->value();
818 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
821 AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
822 SketchPlugin_SegmentationTools::getFeaturePoints(
823 aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
825 std::shared_ptr<GeomAPI_Pnt2d> aStartArcPoint = aStartPointAttrOfBase->pnt();
826 std::shared_ptr<GeomAPI_Pnt2d> aLastArcPoint = anEndPointAttrOfBase->pnt();
828 std::shared_ptr<GeomAPI_Pnt2d> aStartShapePoint = theStartShapePoint;
829 std::shared_ptr<GeomAPI_Pnt2d> aLastShapePoint = theLastShapePoint;
830 arrangePointsOnArc(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase,
831 aStartShapePoint, aLastShapePoint);
833 std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl;
834 if (aStartShapePoint.get())
835 std::cout << "Start shape point: [" << aStartShapePoint->x() << ", " <<
836 aStartShapePoint->y() << "]" << std::endl;
837 std::cout << "Start arc attribute point: [" << aStartArcPoint->x() << ", " <<
838 aStartArcPoint->y() << "]" << std::endl;
839 if (aLastShapePoint.get())
840 std::cout << "Last shape point: [" << aLastShapePoint->x() << ", " <<
841 aLastShapePoint->y() << "]" << std::endl;
842 std::cout << "Last arc attribute point: [" << aLastArcPoint->x() << ", " <<
843 aLastArcPoint->y() << "]" << std::endl;
846 bool isStartPoint = !aStartShapePoint.get() || aStartArcPoint->isEqual(aStartShapePoint);
847 bool isLastPoint = !aLastShapePoint.get() || aLastArcPoint->isEqual(aLastShapePoint);
848 if (isStartPoint || isLastPoint) {
849 // result is one arc: changed existing arc
850 std::string aModifiedAttribute = isStartPoint ? SketchPlugin_Arc::START_ID()
851 : SketchPlugin_Arc::END_ID();
852 std::shared_ptr<GeomAPI_Pnt2d> aPoint;
853 if (aStartShapePoint.get() && aLastShapePoint.get())
854 aPoint = isStartPoint ? aLastShapePoint : aStartShapePoint;
856 aPoint = aStartShapePoint.get() ? aStartShapePoint : aLastShapePoint;
858 removeReferencesToAttribute(aBaseFeature->attribute(aModifiedAttribute),
859 theBaseRefAttributes);
861 fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aPoint);
863 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
864 (aBaseFeature->attribute(aModifiedAttribute)));
867 // result is two arcs: start arc point - start shape point, last shape point - last arc point
869 anNewFeature = SketchPlugin_SegmentationTools::createArcFeature(
870 aBaseFeature, aLastShapePoint, aLastArcPoint);
871 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
872 (anNewFeature->attribute(SketchPlugin_Arc::START_ID())));
874 std::string aModifiedAttribute = SketchPlugin_Arc::END_ID();
875 theModifiedAttributes.insert(
876 std::make_pair(aBaseFeature->attribute(aModifiedAttribute),
877 anNewFeature->attribute(SketchPlugin_Arc::END_ID())));
880 fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aStartShapePoint);
882 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
883 (aBaseFeature->attribute(aModifiedAttribute)));
885 // equal Radius constraint for arcs
886 SketchPlugin_Tools::createConstraintObjectObject(sketch(),
887 SketchPlugin_ConstraintEqual::ID(),
888 aBaseFeature->lastResult(),
889 anNewFeature->lastResult());
890 // coincident centers constraint
891 SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
892 SketchPlugin_ConstraintCoincidence::ID(),
893 aBaseFeature->attribute(SketchPlugin_Arc::CENTER_ID()),
894 anNewFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
897 std::cout << "Created arc on points:" << std::endl;
898 std::cout << "Start shape point: [" << aStartShapePoint->x() << ", " <<
899 aStartShapePoint->y() << "]" << std::endl;
905 FeaturePtr SketchPlugin_Trim::trimEllipticArc(
906 const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
907 const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
908 std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
909 std::set<AttributePoint2DPtr>& thePoints,
910 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
912 FeaturePtr anNewFeature;
913 // Check the base objects are initialized.
914 AttributeReferencePtr aBaseObjectAttr = reference(SELECTED_OBJECT());
915 ObjectPtr aBaseObject = aBaseObjectAttr->value();
916 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
919 AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
920 SketchPlugin_SegmentationTools::getFeaturePoints(
921 aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
923 std::shared_ptr<GeomAPI_Pnt2d> aStartArcPoint = aStartPointAttrOfBase->pnt();
924 std::shared_ptr<GeomAPI_Pnt2d> aLastArcPoint = anEndPointAttrOfBase->pnt();
926 std::shared_ptr<GeomAPI_Pnt2d> aStartShapePoint = theStartShapePoint;
927 std::shared_ptr<GeomAPI_Pnt2d> aLastShapePoint = theLastShapePoint;
928 arrangePointsOnArc(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase,
929 aStartShapePoint, aLastShapePoint);
931 std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl;
932 if (aStartShapePoint.get())
933 std::cout << "Start shape point: [" << aStartShapePoint->x() << ", " <<
934 aStartShapePoint->y() << "]" << std::endl;
935 std::cout << "Start arc attribute point: [" << aStartArcPoint->x() << ", " <<
936 aStartArcPoint->y() << "]" << std::endl;
937 if (aLastShapePoint.get())
938 std::cout << "Last shape point: [" << aLastShapePoint->x() << ", " <<
939 aLastShapePoint->y() << "]" << std::endl;
940 std::cout << "Last arc attribute point: [" << aLastArcPoint->x() << ", " <<
941 aLastArcPoint->y() << "]" << std::endl;
944 bool isStartPoint = !aStartShapePoint.get() || aStartArcPoint->isEqual(aStartShapePoint);
945 bool isLastPoint = !aLastShapePoint.get() || aLastArcPoint->isEqual(aLastShapePoint);
946 if (isStartPoint || isLastPoint) {
947 // result is one arc: changed existing arc
948 std::string aModifiedAttribute = isStartPoint ? SketchPlugin_EllipticArc::START_POINT_ID()
949 : SketchPlugin_EllipticArc::END_POINT_ID();
950 std::shared_ptr<GeomAPI_Pnt2d> aPoint;
951 if (aStartShapePoint.get() && aLastShapePoint.get())
952 aPoint = isStartPoint ? aLastShapePoint : aStartShapePoint;
954 aPoint = aStartShapePoint.get() ? aStartShapePoint : aLastShapePoint;
956 removeReferencesToAttribute(aBaseFeature->attribute(aModifiedAttribute),
957 theBaseRefAttributes);
959 fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aPoint);
961 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
962 (aBaseFeature->attribute(aModifiedAttribute)));
965 // result is two arcs: start arc point - start shape point, last shape point - last arc point
967 anNewFeature = SketchPlugin_SegmentationTools::createArcFeature(
968 aBaseFeature, aLastShapePoint, aLastArcPoint);
969 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
970 anNewFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID())));
972 std::string aModifiedAttribute = SketchPlugin_EllipticArc::END_POINT_ID();
973 theModifiedAttributes.insert(
974 std::make_pair(aBaseFeature->attribute(aModifiedAttribute),
975 anNewFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID())));
978 fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aStartShapePoint);
980 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
981 (aBaseFeature->attribute(aModifiedAttribute)));
983 // make elliptic arcs equal
984 SketchPlugin_Tools::createConstraintObjectObject(sketch(),
985 SketchPlugin_ConstraintEqual::ID(),
986 aBaseFeature->lastResult(),
987 anNewFeature->lastResult());
988 // coincident centers constraint
989 SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
990 SketchPlugin_ConstraintCoincidence::ID(),
991 aBaseFeature->attribute(SketchPlugin_EllipticArc::CENTER_ID()),
992 anNewFeature->attribute(SketchPlugin_EllipticArc::CENTER_ID()));
995 std::cout << "Created arc on points:" << std::endl;
996 std::cout << "Start shape point: [" << aStartShapePoint->x() << ", " <<
997 aStartShapePoint->y() << "]" << std::endl;
1000 return anNewFeature;
1003 FeaturePtr SketchPlugin_Trim::trimClosed(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
1004 const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
1005 std::set<AttributePoint2DPtr>& thePoints,
1006 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
1008 // Check the base objects are initialized.
1009 AttributeReferencePtr aBaseObjectAttr = reference(SELECTED_OBJECT());
1010 ObjectPtr aBaseObject = aBaseObjectAttr->value();
1011 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
1014 FeaturePtr anNewFeature = SketchPlugin_SegmentationTools::createArcFeature(
1015 aBaseFeature, theStartShapePoint, theLastShapePoint);
1016 // arc created by trim of circle is always correct, that means that it is not inversed
1017 const std::string& aReversedAttrName = anNewFeature->getKind() == SketchPlugin_Arc::ID() ?
1018 SketchPlugin_Arc::REVERSED_ID() : SketchPlugin_EllipticArc::REVERSED_ID();
1019 anNewFeature->boolean(aReversedAttrName)->setValue(false);
1021 if (aBaseFeature->getKind() == SketchPlugin_Circle::ID()) {
1022 theModifiedAttributes.insert(
1023 std::make_pair(aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
1024 anNewFeature->attribute(SketchPlugin_Arc::CENTER_ID())));
1026 else if (aBaseFeature->getKind() == SketchPlugin_Ellipse::ID()) {
1027 theModifiedAttributes.insert(std::make_pair(
1028 aBaseFeature->attribute(SketchPlugin_Ellipse::CENTER_ID()),
1029 anNewFeature->attribute(SketchPlugin_EllipticArc::CENTER_ID())));
1030 theModifiedAttributes.insert(std::make_pair(
1031 aBaseFeature->attribute(SketchPlugin_Ellipse::FIRST_FOCUS_ID()),
1032 anNewFeature->attribute(SketchPlugin_EllipticArc::FIRST_FOCUS_ID())));
1033 theModifiedAttributes.insert(std::make_pair(
1034 aBaseFeature->attribute(SketchPlugin_Ellipse::SECOND_FOCUS_ID()),
1035 anNewFeature->attribute(SketchPlugin_EllipticArc::SECOND_FOCUS_ID())));
1036 theModifiedAttributes.insert(std::make_pair(
1037 aBaseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID()),
1038 anNewFeature->attribute(SketchPlugin_EllipticArc::MAJOR_AXIS_START_ID())));
1039 theModifiedAttributes.insert(std::make_pair(
1040 aBaseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()),
1041 anNewFeature->attribute(SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID())));
1042 theModifiedAttributes.insert(std::make_pair(
1043 aBaseFeature->attribute(SketchPlugin_Ellipse::MINOR_AXIS_START_ID()),
1044 anNewFeature->attribute(SketchPlugin_EllipticArc::MINOR_AXIS_START_ID())));
1045 theModifiedAttributes.insert(std::make_pair(
1046 aBaseFeature->attribute(SketchPlugin_Ellipse::MINOR_AXIS_END_ID()),
1047 anNewFeature->attribute(SketchPlugin_EllipticArc::MINOR_AXIS_END_ID())));
1049 // update the PARENT_ID reference for all the features created by the ellipse
1050 const std::set<AttributePtr>& aRefs = aBaseFeature->data()->refsToMe();
1051 std::list<AttributePtr> aRefsToParent;
1052 for (std::set<AttributePtr>::const_iterator aRef = aRefs.begin(); aRef != aRefs.end(); ++aRef) {
1053 if ((*aRef)->id() == SketchPlugin_Line::PARENT_ID() ||
1054 (*aRef)->id() == SketchPlugin_Point::PARENT_ID())
1055 aRefsToParent.push_back(*aRef);
1057 for (std::list<AttributePtr>::iterator aRef = aRefsToParent.begin();
1058 aRef != aRefsToParent.end(); ++aRef)
1059 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(*aRef)->setValue(anNewFeature);
1062 const std::string& aStartAttrName = anNewFeature->getKind() == SketchPlugin_Arc::ID() ?
1063 SketchPlugin_Arc::START_ID() : SketchPlugin_EllipticArc::START_POINT_ID();
1064 const std::string& aEndAttrName = anNewFeature->getKind() == SketchPlugin_Arc::ID() ?
1065 SketchPlugin_Arc::END_ID() : SketchPlugin_EllipticArc::END_POINT_ID();
1067 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1068 (anNewFeature->attribute(aStartAttrName)));
1069 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1070 (anNewFeature->attribute(aEndAttrName)));
1072 return anNewFeature;
1075 void SketchPlugin_Trim::arrangePointsOnLine(const AttributePoint2DPtr& theStartPointAttr,
1076 const AttributePoint2DPtr& theEndPointAttr,
1077 std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
1078 std::shared_ptr<GeomAPI_Pnt2d>& theLastPoint) const
1080 if (!theFirstPoint.get() || !theLastPoint.get())
1083 // if first point is closer to last point, swap first and last values
1084 if (theStartPointAttr->pnt()->distance(theFirstPoint) >
1085 theStartPointAttr->pnt()->distance(theLastPoint)) {
1086 std::shared_ptr<GeomAPI_Pnt2d> aTmpPoint = theFirstPoint;
1087 theFirstPoint = theLastPoint;
1088 theLastPoint = aTmpPoint;
1092 void SketchPlugin_Trim::arrangePointsOnArc(const FeaturePtr& theArc,
1093 const AttributePoint2DPtr& theStartPointAttr,
1094 const AttributePoint2DPtr& theEndPointAttr,
1095 std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
1096 std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint) const
1098 if (!theFirstPoint.get() || !theSecondPoint.get())
1101 static const double anAngleTol = 1.e-12;
1103 const std::string& aCenterAttrName = theArc->getKind() == SketchPlugin_Arc::ID() ?
1104 SketchPlugin_Arc::CENTER_ID() : SketchPlugin_EllipticArc::CENTER_ID();
1105 const std::string& aReversedAttrName = theArc->getKind() == SketchPlugin_Arc::ID() ?
1106 SketchPlugin_Arc::REVERSED_ID() : SketchPlugin_EllipticArc::REVERSED_ID();
1108 std::shared_ptr<GeomAPI_Pnt2d> aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1109 theArc->attribute(aCenterAttrName))->pnt();
1110 bool isReversed = theArc->boolean(aReversedAttrName)->value();
1112 // collect directions to each point
1113 std::shared_ptr<GeomAPI_Dir2d> aStartDir(
1114 new GeomAPI_Dir2d(theStartPointAttr->pnt()->xy()->decreased(aCenter->xy())));
1115 std::shared_ptr<GeomAPI_Dir2d> aFirstPtDir(
1116 new GeomAPI_Dir2d(theFirstPoint->xy()->decreased(aCenter->xy())));
1117 std::shared_ptr<GeomAPI_Dir2d> aSecondPtDir(
1118 new GeomAPI_Dir2d(theSecondPoint->xy()->decreased(aCenter->xy())));
1120 // sort points by their angular values
1121 double aFirstPtAngle = aStartDir->angle(aFirstPtDir);
1122 double aSecondPtAngle = aStartDir->angle(aSecondPtDir);
1123 double aPeriod = isReversed ? -2.0 * PI : 2.0 * PI;
1124 if (fabs(aFirstPtAngle) > anAngleTol && isReversed == (aFirstPtAngle > 0.))
1125 aFirstPtAngle += aPeriod;
1126 if (fabs(aSecondPtAngle) > anAngleTol && isReversed == (aSecondPtAngle > 0.))
1127 aSecondPtAngle += aPeriod;
1129 if (fabs(aFirstPtAngle) > fabs(aSecondPtAngle)) {
1130 std::shared_ptr<GeomAPI_Pnt2d> aTmpPoint = theFirstPoint;
1131 theFirstPoint = theSecondPoint;
1132 theSecondPoint = aTmpPoint;
1136 void SketchPlugin_Trim::fillPointAttribute(const AttributePtr& theModifiedAttribute,
1137 const std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
1139 std::string anAttributeType = theModifiedAttribute->attributeType();
1140 if (anAttributeType == GeomDataAPI_Point2D::typeId()) {
1141 AttributePoint2DPtr aModifiedAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1142 theModifiedAttribute);
1143 aModifiedAttribute->setValue(thePoint);
1146 FeaturePtr aFeature = ModelAPI_Feature::feature(theModifiedAttribute->owner());
1147 std::cout << "<fillPointAttribute[" << aFeature->data()->name() << ": " <<
1148 theModifiedAttribute->id() <<
1149 "]> => Pnt2d - [" << thePoint->x() << ", " << thePoint->y() << "]" << std::endl;
1154 void SketchPlugin_Trim::fillAttribute(const AttributePtr& theModifiedAttribute,
1155 const AttributePtr& theSourceAttribute)
1157 std::string anAttributeType = theModifiedAttribute->attributeType();
1158 if (anAttributeType == GeomDataAPI_Point2D::typeId()) {
1159 AttributePoint2DPtr aModifiedAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1160 theModifiedAttribute);
1161 AttributePoint2DPtr aSourceAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1162 theSourceAttribute);
1164 if (aModifiedAttribute.get() && aSourceAttribute.get())
1165 aModifiedAttribute->setValue(aSourceAttribute->pnt());
1167 else if (anAttributeType == ModelAPI_AttributeBoolean::typeId()) {
1168 AttributeBooleanPtr aModifiedAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(
1169 theModifiedAttribute);
1170 AttributeBooleanPtr aSourceAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(
1171 theSourceAttribute);
1173 if (aModifiedAttribute.get() && aSourceAttribute.get())
1174 aModifiedAttribute->setValue(aSourceAttribute->value());