X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchPlugin%2FSketchPlugin_Trim.cpp;h=1b56a1884172e56678eabd384099c077a0090e54;hb=645e2cb70c0e40290725f28fdc5fec8a93338d28;hp=986b99b30d941314868403303847a83dfcf26bc0;hpb=205dad6e3d828218e87f8dc050a41cb1af7eaa65;p=modules%2Fshaper.git diff --git a/src/SketchPlugin/SketchPlugin_Trim.cpp b/src/SketchPlugin/SketchPlugin_Trim.cpp index 986b99b30..1b56a1884 100644 --- a/src/SketchPlugin/SketchPlugin_Trim.cpp +++ b/src/SketchPlugin/SketchPlugin_Trim.cpp @@ -1,8 +1,21 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> - -// File: SketchPlugin_Trim.cpp -// Created: 22 Feb 2017 -// Author: Natalia ERMOLAEVA +// Copyright (C) 2014-2019 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// #include "SketchPlugin_Trim.h" @@ -12,7 +25,6 @@ #include #include #include -#include #include #include @@ -31,11 +43,12 @@ #include #include #include -//#include #include #include #include #include +#include +#include #include #include #include @@ -53,9 +66,6 @@ #include -//#define DEBUG_TRIM_METHODS -//#define DEBUG_TRIM - #ifdef DEBUG_TRIM #include #endif @@ -75,8 +85,7 @@ SketchPlugin_Trim::SketchPlugin_Trim() void SketchPlugin_Trim::initAttributes() { - data()->addAttribute(SketchPlugin_Trim::SELECTED_OBJECT(), - ModelAPI_AttributeReference::typeId()); + data()->addAttribute(SELECTED_OBJECT(), ModelAPI_AttributeReference::typeId()); data()->addAttribute(SELECTED_POINT(), GeomDataAPI_Point2D::typeId()); data()->addAttribute(PREVIEW_POINT(), GeomDataAPI_Point2D::typeId()); @@ -105,8 +114,10 @@ void SketchPlugin_Trim::findShapePoints(const std::string& theObjectAttributeId, std::shared_ptr anAttributePnt = sketch()->to3D(anAttributePnt2d->x(), anAttributePnt2d->y()); - if (myCashedShapes.find(aBaseObject) == myCashedShapes.end()) - fillObjectShapes(aBaseObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints); + if (myCashedShapes.find(aBaseObject) == myCashedShapes.end()) { + SketchPlugin_SegmentationTools::fillObjectShapes( + this, aBaseObject, myCashedShapes, myObjectToPoints); + } const std::set& aShapes = myCashedShapes[aBaseObject]; if (!aShapes.empty()) { @@ -153,12 +164,14 @@ std::shared_ptr SketchPlugin_Trim::convertPoint( AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast( data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT())); ObjectPtr aBaseObject = aBaseObjectAttr->value(); - if (myObjectToPoints.find(aBaseObject) == myObjectToPoints.end()) - fillObjectShapes(aBaseObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints); + if (myObjectToPoints.find(aBaseObject) == myObjectToPoints.end()) { + SketchPlugin_SegmentationTools::fillObjectShapes( + this, aBaseObject, myCashedShapes, myObjectToPoints); + } bool aFound = false; - const PointToRefsMap& aRefsMap = myObjectToPoints.at(aBaseObject); - for (PointToRefsMap::const_iterator aPointIt = aRefsMap.begin(); + const GeomAlgoAPI_ShapeTools::PointToRefsMap& aRefsMap = myObjectToPoints.at(aBaseObject); + for (GeomAlgoAPI_ShapeTools::PointToRefsMap::const_iterator aPointIt = aRefsMap.begin(); aPointIt != aRefsMap.end() && !aFound; aPointIt++) { if (aPointIt->first->isEqual(thePoint)) { const std::pair, @@ -189,8 +202,10 @@ void SketchPlugin_Trim::execute() #endif SketchPlugin_Sketch* aSketch = sketch(); - if (!aSketch) + if (!aSketch) { + setError("Error: Sketch object is empty."); return; + } // Check the base objects are initialized. AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast( @@ -200,8 +215,10 @@ void SketchPlugin_Trim::execute() return; } ObjectPtr aBaseObject = aBaseObjectAttr->value(); - if (!aBaseObject.get()) + if (!aBaseObject.get()) { + setError("Error: Base object is not initialized."); return; + } FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value()); /// Remove reference of this feature to feature used in preview, it is not necessary anymore @@ -225,16 +242,21 @@ void SketchPlugin_Trim::execute() std::cout << " Base Feature: " << aBaseFeature->data()->name() << std::endl; #endif findShapePoints(SELECTED_OBJECT(), SELECTED_POINT(), aStartShapePoint, aLastShapePoint); + if (!aStartShapePoint || !aLastShapePoint) { + setError("Error: Selected point is not placed on any edge"); + return; + } std::shared_ptr aStartShapePoint2d = convertPoint(aStartShapePoint); std::shared_ptr aLastShapePoint2d = convertPoint(aLastShapePoint); - - std::set aFeaturesToDelete; - getConstraints(aFeaturesToDelete); - + /// find features that should be deleted (e.g. Middle Point) or updated (e.g. Length) + std::set aFeaturesToDelete, aFeaturesToUpdate; + getConstraints(aFeaturesToDelete, aFeaturesToUpdate); + // find references(attributes and features) to the base feature std::map > aBaseRefAttributes; std::list aRefsToFeature; - getRefAttributes(aBaseFeature, aBaseRefAttributes, aRefsToFeature); + SketchPlugin_SegmentationTools::getRefAttributes( + aBaseFeature, aBaseRefAttributes, aRefsToFeature); #ifdef DEBUG_TRIM std::cout << "---- getRefAttributes ----" << std::endl; std::map >::const_iterator @@ -277,18 +299,16 @@ void SketchPlugin_Trim::execute() std::cout << "[" << aRefsToFeature.size() << "] " << aRefsInfo << std::endl; std::cout << "---- getRefAttributes:end ----" << std::endl; #endif - // coincidence to result points - // find coincidences to the base object, it should be used when attribute is found - // in myObjectToPoints - //std::map aCoincidencesToBaseFeature; - //getCoincidencesToObject(aBaseObject, aCoincidencesToBaseFeature); + + keepCurrentFeature(); std::set aFurtherCoincidences; std::set> aModifiedAttributes; const std::string& aKind = aBaseFeature->getKind(); FeaturePtr aReplacingFeature, aNewFeature; - if (aKind == SketchPlugin_Circle::ID()) { - aReplacingFeature = trimCircle(aStartShapePoint2d, aLastShapePoint2d, + if (aKind == SketchPlugin_Circle::ID() || + aKind == SketchPlugin_Ellipse::ID()) { + aReplacingFeature = trimClosed(aStartShapePoint2d, aLastShapePoint2d, aFurtherCoincidences, aModifiedAttributes); aFeaturesToDelete.insert(aBaseFeature); @@ -305,13 +325,21 @@ void SketchPlugin_Trim::execute() aNewFeature = trimArc(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes, aFurtherCoincidences, aModifiedAttributes); } + else if (aKind == SketchPlugin_EllipticArc::ID()) { + aNewFeature = trimEllipticArc(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes, + aFurtherCoincidences, aModifiedAttributes); + } + + restoreCurrentFeature(); // constraints to end points of trim feature - if (myObjectToPoints.find(aBaseObject) == myObjectToPoints.end()) - fillObjectShapes(aBaseObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints); + if (myObjectToPoints.find(aBaseObject) == myObjectToPoints.end()) { + SketchPlugin_SegmentationTools::fillObjectShapes( + this, aBaseObject, myCashedShapes, myObjectToPoints); + } // create coincidence to objects, intersected the base object - const PointToRefsMap& aRefsMap = myObjectToPoints.at(aBaseObject); + const GeomAlgoAPI_ShapeTools::PointToRefsMap& aRefsMap = myObjectToPoints.at(aBaseObject); for (std::set::const_iterator anIt = aFurtherCoincidences.begin(), aLast = aFurtherCoincidences.end(); anIt != aLast; anIt++) { @@ -339,19 +367,32 @@ void SketchPlugin_Trim::execute() continue; std::pair, std::list > anInfo; - for (PointToRefsMap::const_iterator aRefIt = aRefsMap.begin(); aRefIt != aRefsMap.end(); - aRefIt++) + for (GeomAlgoAPI_ShapeTools::PointToRefsMap::const_iterator aRefIt = aRefsMap.begin(); + aRefIt != aRefsMap.end(); aRefIt++) { if (aRefIt->first->isEqual(aPoint)) { anInfo = aRefIt->second; - break; + // prefer a segment instead of a point, because further coincidence with a segment + // decreases only 1 DoF (instead of 2 for point) and prevents an overconstraint situation. + bool isEdge = false; + for (std::list::const_iterator anIt = anInfo.second.begin(); + anIt != anInfo.second.end() && !isEdge; ++anIt) { + ResultPtr aResult = std::dynamic_pointer_cast(*anIt); + if (aResult) { + GeomShapePtr aShape = aResult->shape(); + isEdge = aShape && aShape->isEdge(); + } + } + if (isEdge) + break; } } const std::list& anObjects = anInfo.second; for (std::list::const_iterator anObjectIt = anObjects.begin(); anObjectIt != anObjects.end(); anObjectIt++) { - createConstraintToObject(SketchPlugin_ConstraintCoincidence::ID(), aPointAttribute, - *anObjectIt); + SketchPlugin_Tools::createConstraintAttrObject(sketch(), + SketchPlugin_ConstraintCoincidence::ID(), + aPointAttribute, *anObjectIt); } } @@ -360,17 +401,18 @@ void SketchPlugin_Trim::execute() ResultPtr aReplacingResult; if (aReplacingFeature.get()) { aReplacingFeature->execute(); // need it to obtain result - aReplacingResult = getFeatureResult(aReplacingFeature); + aReplacingResult = aReplacingFeature->lastResult(); } for(std::list::const_iterator anIt = aRefsToFeature.begin(), aLast = aRefsToFeature.end(); anIt != aLast; anIt++) { AttributePtr anAttribute = *anIt; - //if (replaceCoincidenceAttribute(anAttribute, aModifiedAttributes)) - // continue; + if (setCoincidenceToAttribute(anAttribute, aFurtherCoincidences, aFeaturesToDelete)) + continue; - if (setCoincidenceToAttribute(anAttribute, aFurtherCoincidences)) + // move tangency constraint to the nearest feature if possible + if (aNewFeature.get() && moveTangency(anAttribute, aNewFeature)) continue; if (aReplacingResult.get()) { @@ -387,7 +429,7 @@ void SketchPlugin_Trim::execute() } } - updateRefAttConstraints(aBaseRefAttributes, aModifiedAttributes, aFeaturesToDelete); + SketchPlugin_SegmentationTools::updateRefAttConstraints(aBaseRefAttributes, aModifiedAttributes); // Wait all constraints being created, then send update events static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); @@ -410,6 +452,8 @@ void SketchPlugin_Trim::execute() ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToDelete); Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED)); + SketchPlugin_SegmentationTools::updateFeaturesAfterOperation(aFeaturesToUpdate); + // Send events to update the sub-features by the solver. if(isUpdateFlushed) { Events_Loop::loop()->setFlushed(anUpdateEvent, true); @@ -421,29 +465,18 @@ void SketchPlugin_Trim::execute() if (aReplacingResult.get()) { // base object was removed aPreviewObject = aReplacingResult; //aMessage->setSelectedObject(aReplacingResult); - - GeomShapePtr aSelectedShape = aReplacingResult->shape(); - std::shared_ptr aPreviewPnt = sketch()->to3D(aPreviewPnt2d->x(), - aPreviewPnt2d->y()); - std::shared_ptr aProjectedPoint; - if (ModelGeomAlgo_Point2D::isPointOnEdge(aSelectedShape, aPreviewPnt, aProjectedPoint)) { - bool aValue = true; - } - //aBaseShape = aShape; - #ifdef DEBUG_TRIM_METHODS if (!aSelectedShape.get()) std::cout << "Set empty selected object" << std::endl; else std::cout << "Set shape with ShapeType: " << aSelectedShape->shapeTypeStr() << std::endl; #endif - bool aValue = true; } else { aPreviewObject = ObjectPtr(); aBaseFeature->execute(); // should recompute shapes of result to do not check obsolete one - aBaseObject = getFeatureResult(aBaseFeature); + aBaseObject = aBaseFeature->lastResult(); std::shared_ptr aPreviewPnt = sketch()->to3D(aPreviewPnt2d->x(), aPreviewPnt2d->y()); ResultPtr aBaseResult = std::dynamic_pointer_cast(aBaseObject); @@ -454,7 +487,7 @@ void SketchPlugin_Trim::execute() aPreviewObject = aBaseResult; } if (!aPreviewObject.get() && aNewFeature.get()) { - ResultPtr aNewFeatureResult = getFeatureResult(aNewFeature); + ResultPtr aNewFeatureResult = aNewFeature->lastResult(); if (aNewFeatureResult.get()) { GeomShapePtr aShape = aNewFeatureResult->shape(); std::shared_ptr aProjectedPoint; @@ -467,7 +500,7 @@ void SketchPlugin_Trim::execute() if (aPreviewObject.get()) { std::shared_ptr aMessage = std::shared_ptr (new ModelAPI_EventReentrantMessage( - ModelAPI_EventReentrantMessage::eventId(), 0)); + ModelAPI_EventReentrantMessage::eventId(), this)); aMessage->setSelectedObject(aPreviewObject); Events_Loop::loop()->send(aMessage); } @@ -476,12 +509,12 @@ void SketchPlugin_Trim::execute() #endif } +// LCOV_EXCL_START std::string SketchPlugin_Trim::processEvent(const std::shared_ptr& theMessage) { #ifdef DEBUG_TRIM_METHODS std::cout << "SketchPlugin_Trim::processEvent:" << data()->name() << std::endl; #endif - std::string aFilledAttributeName; std::shared_ptr aMessage = @@ -491,41 +524,51 @@ std::string SketchPlugin_Trim::processEvent(const std::shared_ptr aPoint = aMessage->clickedPoint(); if (anObject.get() && aPoint.get()) { - std::shared_ptr aRefSelectedAttr = - std::dynamic_pointer_cast( - data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT())); - std::shared_ptr aRefPreviewAttr = - std::dynamic_pointer_cast( - data()->attribute(SketchPlugin_Trim::PREVIEW_OBJECT())); - aRefSelectedAttr->setValue(anObject); - aRefPreviewAttr->setValue(anObject); - - std::shared_ptr aPointSelectedAttr = - std::dynamic_pointer_cast( - data()->attribute(SketchPlugin_Trim::SELECTED_POINT())); - std::shared_ptr aPointPreviewAttr = - std::dynamic_pointer_cast( - data()->attribute(SketchPlugin_Trim::PREVIEW_POINT())); - aPointSelectedAttr->setValue(aPoint); - aPointPreviewAttr->setValue(aPoint); - - Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); - - GeomShapePtr aSelectedShape = getSubShape(SELECTED_OBJECT(), SELECTED_POINT()); -#ifdef DEBUG_TRIM_METHODS - if (!aSelectedShape.get()) - std::cout << "Set empty selected object" << std::endl; - else - std::cout << "Set shape with ShapeType: " << aSelectedShape->shapeTypeStr() << std::endl; -#endif - aFilledAttributeName = SketchPlugin_Trim::SELECTED_OBJECT(); + if (myCashedShapes.find(anObject) == myCashedShapes.end()) { + SketchPlugin_SegmentationTools::fillObjectShapes( + this, anObject, myCashedShapes, myObjectToPoints); + } + const std::set& aShapes = myCashedShapes[anObject]; + if (aShapes.size() > 1) { + std::shared_ptr aRefSelectedAttr = + std::dynamic_pointer_cast( + data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT())); + std::shared_ptr aRefPreviewAttr = + std::dynamic_pointer_cast( + data()->attribute(SketchPlugin_Trim::PREVIEW_OBJECT())); + aRefSelectedAttr->setValue(anObject); + aRefPreviewAttr->setValue(anObject); + + std::shared_ptr aPointSelectedAttr = + std::dynamic_pointer_cast( + data()->attribute(SketchPlugin_Trim::SELECTED_POINT())); + std::shared_ptr aPointPreviewAttr = + std::dynamic_pointer_cast( + data()->attribute(SketchPlugin_Trim::PREVIEW_POINT())); + aPointSelectedAttr->setValue(aPoint); + aPointPreviewAttr->setValue(aPoint); + + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); + + GeomShapePtr aSelectedShape = SketchPlugin_SegmentationTools::getSubShape(this, + SELECTED_OBJECT(), SELECTED_POINT(), myCashedShapes, myObjectToPoints); + #ifdef DEBUG_TRIM_METHODS + if (!aSelectedShape.get()) + std::cout << "Set empty selected object" << std::endl; + else + std::cout << "Set shape with ShapeType: " << aSelectedShape->shapeTypeStr() << std::endl; + #endif + aFilledAttributeName = SketchPlugin_Trim::SELECTED_OBJECT(); + } } } return aFilledAttributeName; } +// LCOV_EXCL_STOP bool SketchPlugin_Trim::setCoincidenceToAttribute(const AttributePtr& theAttribute, - const std::set& theFurtherCoincidences) + const std::set& theFurtherCoincidences, + std::set>& theFeaturesToDelete) { FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner()); if (aFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID()) @@ -543,153 +586,75 @@ bool SketchPlugin_Trim::setCoincidenceToAttribute(const AttributePtr& theAttribu AttributePoint2DPtr aPointAttribute = (*anIt); std::shared_ptr aPoint2d = aPointAttribute->pnt(); if (aPoint2d->isEqual(aRefPnt2d)) { - AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( - theAttribute); - if (aRefAttr.get()) { - aRefAttr->setAttr(aPointAttribute); - aFoundPoint = true; - } + // create new coincidence and then remove the old one + SketchPlugin_Tools::createConstraintAttrAttr(sketch(), + SketchPlugin_ConstraintCoincidence::ID(), + aRefPointAttr, aPointAttribute); + theFeaturesToDelete.insert(aFeature); } } return aFoundPoint; } -bool SketchPlugin_Trim::replaceCoincidenceAttribute(const AttributePtr& theCoincidenceAttribute, - const std::set>& theModifiedAttributes) +bool SketchPlugin_Trim::moveTangency(const AttributePtr& theAttribute, + const FeaturePtr& theFeature) { - FeaturePtr aCoincidenceFeature = ModelAPI_Feature::feature(theCoincidenceAttribute->owner()); - if (aCoincidenceFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID()) + FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner()); + if (aFeature->getKind() != SketchPlugin_ConstraintTangent::ID()) return false; - AttributeRefAttrPtr aCAttrA = std::dynamic_pointer_cast( - aCoincidenceFeature->attribute(SketchPlugin_Constraint::ENTITY_A())); - AttributeRefAttrPtr aCAttrB = std::dynamic_pointer_cast( - aCoincidenceFeature->attribute(SketchPlugin_Constraint::ENTITY_B())); - AttributePtr aCAttrRefA = aCAttrA->attr(); - AttributePtr aCAttrRefB = aCAttrB->attr(); - - bool isProcessed = false; - for (std::set>::const_iterator - anIt = theModifiedAttributes.begin(); anIt != theModifiedAttributes.end(); anIt++) { - AttributePtr anAttributeBefore = anIt->first; - if (anAttributeBefore == aCAttrRefA) { - aCAttrA->setAttr(anIt->second); - isProcessed = true; - } - if (anAttributeBefore == aCAttrRefB) { - aCAttrB->setAttr(anIt->second); - isProcessed = true; - } - } - return isProcessed; -} - -bool SketchPlugin_Trim::isMacro() const -{ - return true; -} - -AISObjectPtr SketchPlugin_Trim::getAISObject(AISObjectPtr thePrevious) -{ -#ifdef DEBUG_TRIM_METHODS - std::cout << "SketchPlugin_Trim::getAISObject: " << data()->name() << std::endl; -#endif - - AISObjectPtr anAIS = thePrevious; - - std::list > aShapes; - GeomShapePtr aPreviewShape = getSubShape(PREVIEW_OBJECT(), PREVIEW_POINT()); - if (aPreviewShape.get()) - aShapes.push_back(aPreviewShape); - GeomShapePtr aSelectedShape = getSubShape(SELECTED_OBJECT(), SELECTED_POINT()); - if (aSelectedShape.get()) - aShapes.push_back(aSelectedShape); - - if (aShapes.empty()) - return AISObjectPtr(); - - GeomShapePtr aBaseShape = GeomAlgoAPI_CompoundBuilder::compound(aShapes); - if (!aBaseShape.get()) - return AISObjectPtr(); - - if (aBaseShape.get()) { - if (!anAIS) - anAIS = AISObjectPtr(new GeomAPI_AISObject); - anAIS->createShape(aBaseShape); - - std::vector aColor; - aColor = Config_PropManager::color("Visualization", "operation_remove_feature_color"); - double aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH(); - int aLineStyle = SketchPlugin_SketchEntity::SKETCH_LINE_STYLE(); - anAIS->setColor(aColor[0], aColor[1], aColor[2]); - // width when there is not base object should be extened in several points - // in order to see this preview over highlight - anAIS->setWidth(aWidth+4); - anAIS->setLineStyle(aLineStyle); - } - else - anAIS = AISObjectPtr(); - - return anAIS; -} - -GeomShapePtr SketchPlugin_Trim::getSubShape(const std::string& theObjectAttributeId, - const std::string& thePointAttributeId) -{ - GeomShapePtr aBaseShape; - - AttributeReferencePtr anObjectAttr = std::dynamic_pointer_cast( - data()->attribute(theObjectAttributeId)); - ObjectPtr aBaseObject = anObjectAttr->value(); - if (!aBaseObject.get()) - return aBaseShape; - - // point on feature - AttributePoint2DPtr aPoint = std::dynamic_pointer_cast( - data()->attribute(thePointAttributeId)); - std::shared_ptr anAttributePnt2d = aPoint->pnt(); - std::shared_ptr anAttributePnt = sketch()->to3D(anAttributePnt2d->x(), - anAttributePnt2d->y()); - - if (myCashedShapes.find(aBaseObject) == myCashedShapes.end()) - fillObjectShapes(aBaseObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints); + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( + theAttribute); + if (!aRefAttr.get()) + return false; - const std::set& aShapes = myCashedShapes[aBaseObject]; - if (!aShapes.empty()) { - std::set::const_iterator anIt = aShapes.begin(), aLast = aShapes.end(); - for (; anIt != aLast; anIt++) { - GeomShapePtr aShape = *anIt; - std::shared_ptr aProjectedPoint; - if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, anAttributePnt, aProjectedPoint)) - aBaseShape = aShape; + // get shape of tangent object to the current + std::string aTangentAttr = SketchPlugin_Constraint::ENTITY_A(); + if (aRefAttr->id() == SketchPlugin_Constraint::ENTITY_A()) + aTangentAttr = SketchPlugin_Constraint::ENTITY_B(); + AttributeRefAttrPtr aTangentRefAttr = std::dynamic_pointer_cast( + aFeature->attribute(aTangentAttr)); + FeaturePtr aTangentFeature = ModelAPI_Feature::feature(aTangentRefAttr->object()); + + // get shape of the feature of the attribute + FeaturePtr anAttributeFeature = ModelAPI_Feature::feature(aRefAttr->object()); + anAttributeFeature->execute(); // the modified value should be applyed to recompute shape + GeomAlgoAPI_ShapeTools::PointToRefsMap aPointToAttributeOrObject; + std::list aFeatures; + aFeatures.push_back(anAttributeFeature); + ModelGeomAlgo_Point2D::getPointsIntersectedShape(aTangentFeature, aFeatures, + aPointToAttributeOrObject); + if (!aPointToAttributeOrObject.empty()) + return true; // the attribute feature has a point of intersection, so we do not replace it + + // get shape of the feature + aPointToAttributeOrObject.clear(); + aFeatures.clear(); + aFeatures.push_back(theFeature); + ModelGeomAlgo_Point2D::getPointsIntersectedShape(aTangentFeature, aFeatures, + aPointToAttributeOrObject); + if (!aPointToAttributeOrObject.empty()) { + std::set anEdgeShapes; + ModelGeomAlgo_Shape::shapesOfType(theFeature, GeomAPI_Shape::EDGE, anEdgeShapes); + if (!anEdgeShapes.empty()) { + ResultPtr aResult = *anEdgeShapes.begin(); + if (aResult.get()) { + aRefAttr->setObject(aResult); + return true; // the attribute feature has a point of intersection, so we do not replace it + } } } - return aBaseShape; + return false; } -void SketchPlugin_Trim::getFeaturePoints(const FeaturePtr& theFeature, - AttributePoint2DPtr& theStartPointAttr, - AttributePoint2DPtr& theEndPointAttr) +AISObjectPtr SketchPlugin_Trim::getAISObject(AISObjectPtr thePrevious) { - std::string aFeatureKind = theFeature->getKind(); - std::string aStartAttributeName, anEndAttributeName; - if (aFeatureKind == SketchPlugin_Line::ID()) { - aStartAttributeName = SketchPlugin_Line::START_ID(); - anEndAttributeName = SketchPlugin_Line::END_ID(); - } - else if (aFeatureKind == SketchPlugin_Arc::ID()) { - aStartAttributeName = SketchPlugin_Arc::START_ID(); - anEndAttributeName = SketchPlugin_Arc::END_ID(); - } - if (!aStartAttributeName.empty() && !anEndAttributeName.empty()) { - theStartPointAttr = std::dynamic_pointer_cast( - theFeature->attribute(aStartAttributeName)); - theEndPointAttr = std::dynamic_pointer_cast( - theFeature->attribute(anEndAttributeName)); - } + return SketchPlugin_SegmentationTools::getAISObject(thePrevious, + this, PREVIEW_OBJECT(), PREVIEW_POINT(), SELECTED_OBJECT(), SELECTED_POINT()); } -void SketchPlugin_Trim::getConstraints(std::set& theFeaturesToDelete) +void SketchPlugin_Trim::getConstraints(std::set& theFeaturesToDelete, + std::set& theFeaturesToUpdate) { std::shared_ptr aData = data(); @@ -697,7 +662,7 @@ void SketchPlugin_Trim::getConstraints(std::set& theFeaturesToDelete AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast( aData->attribute(SketchPlugin_Trim::SELECTED_OBJECT())); FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value()); - ResultPtr aBaseFeatureResult = getFeatureResult(aBaseFeature); + ResultPtr aBaseFeatureResult = aBaseFeature->lastResult(); std::set aRefsList = aBaseFeatureResult->data()->refsToMe(); std::set aFRefsList = aBaseFeature->data()->refsToMe(); @@ -705,132 +670,20 @@ void SketchPlugin_Trim::getConstraints(std::set& theFeaturesToDelete std::set::const_iterator aIt; for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) { - std::shared_ptr aAttr = (*aIt); - FeaturePtr aRefFeature = std::dynamic_pointer_cast(aAttr->owner()); + std::shared_ptr anAttr = (*aIt); + FeaturePtr aRefFeature = std::dynamic_pointer_cast(anAttr->owner()); std::string aRefFeatureKind = aRefFeature->getKind(); - if (aRefFeatureKind == SketchPlugin_ConstraintMirror::ID() || - aRefFeatureKind == SketchPlugin_MultiRotation::ID() || - aRefFeatureKind == SketchPlugin_MultiTranslation::ID() || + std::string anAttributeId = anAttr->id(); + if ((aRefFeatureKind == SketchPlugin_ConstraintMirror::ID() && + anAttributeId == SketchPlugin_ConstraintMirror::MIRROR_LIST_ID()) || + (aRefFeatureKind == SketchPlugin_MultiRotation::ID() && + anAttributeId == SketchPlugin_MultiRotation::ROTATION_LIST_ID()) || + (aRefFeatureKind == SketchPlugin_MultiTranslation::ID() && + anAttributeId == SketchPlugin_MultiTranslation::TRANSLATION_LIST_ID()) || aRefFeatureKind == SketchPlugin_ConstraintMiddle::ID()) theFeaturesToDelete.insert(aRefFeature); - } -} - -void SketchPlugin_Trim::getRefAttributes(const FeaturePtr& theFeature, - std::map >& theRefs, - std::list& theRefsToFeature) -{ - theRefs.clear(); - - std::list aPointAttributes = - theFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); - std::set aPointAttributesSet; - - std::list::const_iterator aPIt = - aPointAttributes.begin(), aPLast = aPointAttributes.end(); - for (; aPIt != aPLast; aPIt++) - aPointAttributesSet.insert(*aPIt); - - std::set aRefsAttributes = getFeatureResult(theFeature)->data()->refsToMe(); - std::set aFRefsList = theFeature->data()->refsToMe(); - aRefsAttributes.insert(aFRefsList.begin(), aFRefsList.end()); - - std::set::const_iterator aIt; - for (aIt = aRefsAttributes.cbegin(); aIt != aRefsAttributes.cend(); ++aIt) { - AttributePtr anAttr = (*aIt); - FeaturePtr anAttrFeature = ModelAPI_Feature::feature(anAttr->owner()); - if (anAttrFeature.get() != this && - anAttr.get() && anAttr->attributeType() == ModelAPI_AttributeRefAttr::typeId()) { - AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(anAttr); - if (!aRefAttr->isObject()) { /// find attributes referenced to feature point attributes - AttributePtr anAttrInRef = aRefAttr->attr(); - if (anAttrInRef.get() && - aPointAttributesSet.find(anAttrInRef) != aPointAttributesSet.end()) { - if (theRefs.find(anAttrInRef) != theRefs.end()) - theRefs[anAttrInRef].push_back(aRefAttr); - else { - std::list anAttrList; - anAttrList.push_back(aRefAttr); - theRefs[anAttrInRef] = anAttrList; - } - } - } - else { /// find attributes referenced to feature itself - theRefsToFeature.push_back(anAttr); - } - } - } -} - -/*void SketchPlugin_Trim::getCoincidencesToObject(const ObjectPtr& theObject, - std::map& theCoincidencesToBaseFeature) -{ - const std::set& aRefsList = theObject->data()->refsToMe(); - std::set::const_iterator aIt; - for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) { - std::shared_ptr aAttr = (*aIt); - FeaturePtr aRefFeature = std::dynamic_pointer_cast(aAttr->owner()); - if (aRefFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID()) - continue; - AttributePtr anAttribute; - AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast - (aRefFeature->attribute(SketchPlugin_Constraint::ENTITY_A())); - if (aRefAttr->isObject() && aRefAttr->object() == theObject) - { - anAttribute = aRefFeature->attribute(SketchPlugin_Constraint::ENTITY_B()); - } - else { - AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast - (aRefFeature->attribute(SketchPlugin_Constraint::ENTITY_B())); - if (aRefAttr->isObject() && aRefAttr->object() == theObject) - anAttribute = aRefFeature->attribute(SketchPlugin_Constraint::ENTITY_A()); - } - if (!anAttribute.get()) - continue; - - aRefAttr = std::dynamic_pointer_cast(anAttribute); - if (aRefAttr->isObject()) - continue; // one of attributes of coincidence contains link to an attribute - - anAttribute = aRefAttr->attr(); - if (anAttribute.get()) - { - theCoincidencesToBaseFeature[anAttribute] = aRefFeature; - } - } -}*/ - -void SketchPlugin_Trim::updateRefAttConstraints( - const std::map >& theBaseRefAttributes, - const std::set >& theModifiedAttributes, - std::set& theFeaturesToDelete) -{ -#ifdef DEBUG_TRIM - std::cout << "SketchPlugin_Trim::updateRefAttConstraints" << std::endl; -#endif - - std::set >::const_iterator - anIt = theModifiedAttributes.begin(), aLast = theModifiedAttributes.end(); - for (; anIt != aLast; anIt++) { - AttributePtr anAttribute = anIt->first; - - /// not found in references - if (theBaseRefAttributes.find(anAttribute) == theBaseRefAttributes.end()) - continue; - std::list aRefAttributes = theBaseRefAttributes.at(anAttribute); - std::list::const_iterator aRefIt = aRefAttributes.begin(), - aRLast = aRefAttributes.end(); - - AttributePtr aNewAttribute = anIt->second; - if (aNewAttribute.get()) { - for (; aRefIt != aRLast; aRefIt++) { - AttributeRefAttrPtr aRefAttr = - std::dynamic_pointer_cast(*aRefIt); - if (aRefAttr.get()) { - aRefAttr->setAttr(aNewAttribute); - } - } - } + else if (aRefFeatureKind == SketchPlugin_ConstraintLength::ID()) + theFeaturesToUpdate.insert(aRefFeature); } } @@ -885,7 +738,8 @@ FeaturePtr SketchPlugin_Trim::trimLine(const std::shared_ptr& the /// points of trim AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase; - getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase); + SketchPlugin_SegmentationTools::getFeaturePoints( + aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase); std::shared_ptr aStartFeaturePoint = aStartPointAttrOfBase->pnt(); std::shared_ptr aLastFeaturePoint = anEndPointAttrOfBase->pnt(); @@ -936,7 +790,8 @@ FeaturePtr SketchPlugin_Trim::trimLine(const std::shared_ptr& the // result is two lines: start line point - start shape point, // last shape point - last line point // create second line - anNewFeature = createLineFeature(aBaseFeature, aLastShapePoint, aLastFeaturePoint); + anNewFeature = SketchPlugin_SegmentationTools::createLineFeature( + aBaseFeature, aLastShapePoint, aLastFeaturePoint); thePoints.insert(std::dynamic_pointer_cast (anNewFeature->attribute(SketchPlugin_Line::START_ID()))); @@ -952,10 +807,10 @@ FeaturePtr SketchPlugin_Trim::trimLine(const std::shared_ptr& the (aBaseFeature->attribute(aModifiedAttribute))); // Collinear constraint for lines - createConstraintForObjects(SketchPlugin_ConstraintCollinear::ID(), - getFeatureResult(aBaseFeature), - getFeatureResult(anNewFeature)); - + SketchPlugin_Tools::createConstraintObjectObject(sketch(), + SketchPlugin_ConstraintCollinear::ID(), + aBaseFeature->lastResult(), + anNewFeature->lastResult()); } return anNewFeature; } @@ -975,7 +830,8 @@ FeaturePtr SketchPlugin_Trim::trimArc(const std::shared_ptr& theS /// points of trim AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase; - getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase); + SketchPlugin_SegmentationTools::getFeaturePoints( + aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase); std::shared_ptr aStartArcPoint = aStartPointAttrOfBase->pnt(); std::shared_ptr aLastArcPoint = anEndPointAttrOfBase->pnt(); @@ -1021,7 +877,8 @@ FeaturePtr SketchPlugin_Trim::trimArc(const std::shared_ptr& theS else { // result is two arcs: start arc point - start shape point, last shape point - last arc point // create second arc - anNewFeature = createArcFeature(aBaseFeature, aLastShapePoint, aLastArcPoint); + anNewFeature = SketchPlugin_SegmentationTools::createArcFeature( + aBaseFeature, aLastShapePoint, aLastArcPoint); thePoints.insert(std::dynamic_pointer_cast (anNewFeature->attribute(SketchPlugin_Arc::START_ID()))); @@ -1037,14 +894,15 @@ FeaturePtr SketchPlugin_Trim::trimArc(const std::shared_ptr& theS (aBaseFeature->attribute(aModifiedAttribute))); // equal Radius constraint for arcs - anNewFeature->execute(); // we need the created arc result to set equal constraint - createConstraintForObjects(SketchPlugin_ConstraintEqual::ID(), - getFeatureResult(aBaseFeature), - getFeatureResult(anNewFeature)); + SketchPlugin_Tools::createConstraintObjectObject(sketch(), + SketchPlugin_ConstraintEqual::ID(), + aBaseFeature->lastResult(), + anNewFeature->lastResult()); // coincident centers constraint - createConstraint(SketchPlugin_ConstraintCoincidence::ID(), - aBaseFeature->attribute(SketchPlugin_Arc::CENTER_ID()), - anNewFeature->attribute(SketchPlugin_Arc::CENTER_ID())); + SketchPlugin_Tools::createConstraintAttrAttr(sketch(), + SketchPlugin_ConstraintCoincidence::ID(), + aBaseFeature->attribute(SketchPlugin_Arc::CENTER_ID()), + anNewFeature->attribute(SketchPlugin_Arc::CENTER_ID())); #ifdef DEBUG_TRIM std::cout << "Created arc on points:" << std::endl; @@ -1055,34 +913,177 @@ FeaturePtr SketchPlugin_Trim::trimArc(const std::shared_ptr& theS return anNewFeature; } -FeaturePtr SketchPlugin_Trim::trimCircle(const std::shared_ptr& theStartShapePoint, - const std::shared_ptr& theLastShapePoint, - std::set& thePoints, +FeaturePtr SketchPlugin_Trim::trimEllipticArc( + const std::shared_ptr& theStartShapePoint, + const std::shared_ptr& theLastShapePoint, + std::map >& theBaseRefAttributes, + std::set& thePoints, std::set>& theModifiedAttributes) { + FeaturePtr anNewFeature; // Check the base objects are initialized. - AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast( - data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT())); + AttributeReferencePtr aBaseObjectAttr = reference(SELECTED_OBJECT()); ObjectPtr aBaseObject = aBaseObjectAttr->value(); FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value()); - /// points of trim - //AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase; - //getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase); + // points of trim + AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase; + SketchPlugin_SegmentationTools::getFeaturePoints( + aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase); - /// trim feature - FeaturePtr anNewFeature = createArcFeature(aBaseFeature, theStartShapePoint, theLastShapePoint); + std::shared_ptr aStartArcPoint = aStartPointAttrOfBase->pnt(); + std::shared_ptr aLastArcPoint = anEndPointAttrOfBase->pnt(); + + std::shared_ptr aStartShapePoint = theStartShapePoint; + std::shared_ptr aLastShapePoint = theLastShapePoint; + arrangePointsOnArc(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase, + aStartShapePoint, aLastShapePoint); +#ifdef DEBUG_TRIM + std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl; + if (aStartShapePoint.get()) + std::cout << "Start shape point: [" << aStartShapePoint->x() << ", " << + aStartShapePoint->y() << "]" << std::endl; + std::cout << "Start arc attribute point: [" << aStartArcPoint->x() << ", " << + aStartArcPoint->y() << "]" << std::endl; + if (aLastShapePoint.get()) + std::cout << "Last shape point: [" << aLastShapePoint->x() << ", " << + aLastShapePoint->y() << "]" << std::endl; + std::cout << "Last arc attribute point: [" << aLastArcPoint->x() << ", " << + aLastArcPoint->y() << "]" << std::endl; +#endif + + bool isStartPoint = !aStartShapePoint.get() || aStartArcPoint->isEqual(aStartShapePoint); + bool isLastPoint = !aLastShapePoint.get() || aLastArcPoint->isEqual(aLastShapePoint); + if (isStartPoint || isLastPoint) { + // result is one arc: changed existing arc + std::string aModifiedAttribute = isStartPoint ? SketchPlugin_EllipticArc::START_POINT_ID() + : SketchPlugin_EllipticArc::END_POINT_ID(); + std::shared_ptr aPoint; + if (aStartShapePoint.get() && aLastShapePoint.get()) + aPoint = isStartPoint ? aLastShapePoint : aStartShapePoint; + else + aPoint = aStartShapePoint.get() ? aStartShapePoint : aLastShapePoint; + + removeReferencesToAttribute(aBaseFeature->attribute(aModifiedAttribute), + theBaseRefAttributes); + + fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aPoint); + + thePoints.insert(std::dynamic_pointer_cast + (aBaseFeature->attribute(aModifiedAttribute))); + } + else { + // result is two arcs: start arc point - start shape point, last shape point - last arc point + // create second arc + anNewFeature = SketchPlugin_SegmentationTools::createArcFeature( + aBaseFeature, aLastShapePoint, aLastArcPoint); + thePoints.insert(std::dynamic_pointer_cast( + anNewFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID()))); + + std::string aModifiedAttribute = SketchPlugin_EllipticArc::END_POINT_ID(); + theModifiedAttributes.insert( + std::make_pair(aBaseFeature->attribute(aModifiedAttribute), + anNewFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID()))); + + // modify base arc + fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aStartShapePoint); + + thePoints.insert(std::dynamic_pointer_cast + (aBaseFeature->attribute(aModifiedAttribute))); + + // make elliptic arcs equal + SketchPlugin_Tools::createConstraintObjectObject(sketch(), + SketchPlugin_ConstraintEqual::ID(), + aBaseFeature->lastResult(), + anNewFeature->lastResult()); + // coincident centers constraint + SketchPlugin_Tools::createConstraintAttrAttr(sketch(), + SketchPlugin_ConstraintCoincidence::ID(), + aBaseFeature->attribute(SketchPlugin_EllipticArc::CENTER_ID()), + anNewFeature->attribute(SketchPlugin_EllipticArc::CENTER_ID())); + +#ifdef DEBUG_TRIM + std::cout << "Created arc on points:" << std::endl; + std::cout << "Start shape point: [" << aStartShapePoint->x() << ", " << + aStartShapePoint->y() << "]" << std::endl; +#endif + } + return anNewFeature; +} + +FeaturePtr SketchPlugin_Trim::trimClosed(const std::shared_ptr& theStartShapePoint, + const std::shared_ptr& theLastShapePoint, + std::set& thePoints, + std::set>& theModifiedAttributes) +{ + // Check the base objects are initialized. + AttributeReferencePtr aBaseObjectAttr = reference(SELECTED_OBJECT()); + ObjectPtr aBaseObject = aBaseObjectAttr->value(); + FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value()); + + // trim feature + FeaturePtr anNewFeature = SketchPlugin_SegmentationTools::createArcFeature( + aBaseFeature, theStartShapePoint, theLastShapePoint); // arc created by trim of circle is always correct, that means that it is not inversed - anNewFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(false); + const std::string& aReversedAttrName = anNewFeature->getKind() == SketchPlugin_Arc::ID() ? + SketchPlugin_Arc::REVERSED_ID() : SketchPlugin_EllipticArc::REVERSED_ID(); + anNewFeature->boolean(aReversedAttrName)->setValue(false); - theModifiedAttributes.insert( - std::make_pair(aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()), - anNewFeature->attribute(SketchPlugin_Arc::CENTER_ID()))); + if (aBaseFeature->getKind() == SketchPlugin_Circle::ID()) { + theModifiedAttributes.insert( + std::make_pair(aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()), + anNewFeature->attribute(SketchPlugin_Arc::CENTER_ID()))); + } + else if (aBaseFeature->getKind() == SketchPlugin_Ellipse::ID()) { + theModifiedAttributes.insert(std::make_pair( + aBaseFeature->attribute(SketchPlugin_Ellipse::CENTER_ID()), + anNewFeature->attribute(SketchPlugin_EllipticArc::CENTER_ID()))); + theModifiedAttributes.insert(std::make_pair( + aBaseFeature->attribute(SketchPlugin_Ellipse::FIRST_FOCUS_ID()), + anNewFeature->attribute(SketchPlugin_EllipticArc::FIRST_FOCUS_ID()))); + theModifiedAttributes.insert(std::make_pair( + aBaseFeature->attribute(SketchPlugin_Ellipse::SECOND_FOCUS_ID()), + anNewFeature->attribute(SketchPlugin_EllipticArc::SECOND_FOCUS_ID()))); + theModifiedAttributes.insert(std::make_pair( + aBaseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID()), + anNewFeature->attribute(SketchPlugin_EllipticArc::MAJOR_AXIS_START_ID()))); + theModifiedAttributes.insert(std::make_pair( + aBaseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()), + anNewFeature->attribute(SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID()))); + theModifiedAttributes.insert(std::make_pair( + aBaseFeature->attribute(SketchPlugin_Ellipse::MINOR_AXIS_START_ID()), + anNewFeature->attribute(SketchPlugin_EllipticArc::MINOR_AXIS_START_ID()))); + theModifiedAttributes.insert(std::make_pair( + aBaseFeature->attribute(SketchPlugin_Ellipse::MINOR_AXIS_END_ID()), + anNewFeature->attribute(SketchPlugin_EllipticArc::MINOR_AXIS_END_ID()))); + + // update the PARENT_ID reference for all the features created by the ellipse + const std::set& aRefs = aBaseFeature->data()->refsToMe(); + std::list aRefsToParent; + for (std::set::const_iterator aRef = aRefs.begin(); aRef != aRefs.end(); ++aRef) { + if ((*aRef)->id() == SketchPlugin_SketchEntity::PARENT_ID()) + aRefsToParent.push_back(*aRef); + } + for (std::list::iterator aRef = aRefsToParent.begin(); + aRef != aRefsToParent.end(); ++aRef) { + std::dynamic_pointer_cast(*aRef)->setValue(anNewFeature); + + FeaturePtr anOwner = ModelAPI_Feature::feature((*aRef)->owner()); + SketchPlugin_Tools::replaceInName(anOwner, aBaseFeature->name(), anNewFeature->name()); + SketchPlugin_Tools::replaceInName(anOwner->lastResult(), + aBaseFeature->name(), anNewFeature->name()); + } + } + + const std::string& aStartAttrName = anNewFeature->getKind() == SketchPlugin_Arc::ID() ? + SketchPlugin_Arc::START_ID() : SketchPlugin_EllipticArc::START_POINT_ID(); + const std::string& aEndAttrName = anNewFeature->getKind() == SketchPlugin_Arc::ID() ? + SketchPlugin_Arc::END_ID() : SketchPlugin_EllipticArc::END_POINT_ID(); thePoints.insert(std::dynamic_pointer_cast - (anNewFeature->attribute(SketchPlugin_Arc::START_ID()))); + (anNewFeature->attribute(aStartAttrName))); thePoints.insert(std::dynamic_pointer_cast - (anNewFeature->attribute(SketchPlugin_Arc::END_ID()))); + (anNewFeature->attribute(aEndAttrName))); return anNewFeature; } @@ -1115,9 +1116,14 @@ void SketchPlugin_Trim::arrangePointsOnArc(const FeaturePtr& theArc, static const double anAngleTol = 1.e-12; + const std::string& aCenterAttrName = theArc->getKind() == SketchPlugin_Arc::ID() ? + SketchPlugin_Arc::CENTER_ID() : SketchPlugin_EllipticArc::CENTER_ID(); + const std::string& aReversedAttrName = theArc->getKind() == SketchPlugin_Arc::ID() ? + SketchPlugin_Arc::REVERSED_ID() : SketchPlugin_EllipticArc::REVERSED_ID(); + std::shared_ptr aCenter = std::dynamic_pointer_cast( - theArc->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt(); - bool isReversed = theArc->boolean(SketchPlugin_Arc::REVERSED_ID())->value(); + theArc->attribute(aCenterAttrName))->pnt(); + bool isReversed = theArc->boolean(aReversedAttrName)->value(); // collect directions to each point std::shared_ptr aStartDir( @@ -1161,7 +1167,6 @@ void SketchPlugin_Trim::fillPointAttribute(const AttributePtr& theModifiedAttrib } } - void SketchPlugin_Trim::fillAttribute(const AttributePtr& theModifiedAttribute, const AttributePtr& theSourceAttribute) { @@ -1184,234 +1189,4 @@ void SketchPlugin_Trim::fillAttribute(const AttributePtr& theModifiedAttribute, if (aModifiedAttribute.get() && aSourceAttribute.get()) aModifiedAttribute->setValue(aSourceAttribute->value()); } - else if (anAttributeType == ModelAPI_AttributeRefAttr::typeId()) { - AttributeRefAttrPtr aRefAttributeToFill = std::dynamic_pointer_cast( - theModifiedAttribute); - AttributeRefAttrPtr aSourceRefAttr = std::dynamic_pointer_cast( - theSourceAttribute); - if (!aSourceRefAttr.get()) - aRefAttributeToFill->setAttr(theSourceAttribute); - else { - if (aSourceRefAttr->isObject()) - aRefAttributeToFill->setObject(aSourceRefAttr->object()); - else - aRefAttributeToFill->setAttr(aSourceRefAttr->attr()); - } - } -} - -FeaturePtr SketchPlugin_Trim::createLineFeature(const FeaturePtr& theBaseFeature, - const std::shared_ptr& theFirstPoint, - const std::shared_ptr& theSecondPoint) -{ -#ifdef DEBUG_TRIM - std::cout << "---- createLineFeature ---" << std::endl; -#endif - - FeaturePtr aFeature; - SketchPlugin_Sketch* aSketch = sketch(); - if (!aSketch || !theBaseFeature.get()) - return aFeature; - - aFeature = aSketch->addFeature(SketchPlugin_Line::ID()); - - fillPointAttribute(aFeature->attribute(SketchPlugin_Line::START_ID()), theFirstPoint); - fillPointAttribute(aFeature->attribute(SketchPlugin_Line::END_ID()), theSecondPoint); - - fillAttribute(aFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()), - theBaseFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID())); - - aFeature->execute(); // to obtain result - -#ifdef DEBUG_TRIM - std::cout << "---- createLineFeature:end ---" << std::endl; -#endif - - return aFeature; -} - -FeaturePtr SketchPlugin_Trim::createArcFeature(const FeaturePtr& theBaseFeature, - const std::shared_ptr& theFirstPoint, - const std::shared_ptr& theSecondPoint) -{ - FeaturePtr aFeature; - SketchPlugin_Sketch* aSketch = sketch(); - if (!aSketch || !theBaseFeature.get()) - return aFeature; - - std::string aCenterAttributeId; - if (theBaseFeature->getKind() == SketchPlugin_Arc::ID()) - aCenterAttributeId = SketchPlugin_Arc::CENTER_ID(); - else if (theBaseFeature->getKind() == SketchPlugin_Circle::ID()) - aCenterAttributeId = SketchPlugin_Circle::CENTER_ID(); - - if (aCenterAttributeId.empty()) - return aFeature; - -#ifdef DEBUG_TRIM - std::cout << "---- createArcFeature ---" << std::endl; -#endif - - aFeature = aSketch->addFeature(SketchPlugin_Arc::ID()); - // update fillet arc: make the arc correct for sure, so, it is not needed to process - // the "attribute updated" - // by arc; moreover, it may cause cyclicity in hte mechanism of updater - bool aWasBlocked = aFeature->data()->blockSendAttributeUpdated(true); - - fillAttribute(aFeature->attribute(SketchPlugin_Arc::CENTER_ID()), - theBaseFeature->attribute(aCenterAttributeId)); - fillPointAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), theFirstPoint); - fillPointAttribute(aFeature->attribute(SketchPlugin_Arc::END_ID()), theSecondPoint); - - fillAttribute(aFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()), - theBaseFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID())); - - /// fill referersed state of created arc as it is on the base arc - if (theBaseFeature->getKind() == SketchPlugin_Arc::ID()) { - bool aReversed = theBaseFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->value(); - aFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(aReversed); - } - //aFeature->execute(); // to obtain result - aFeature->data()->blockSendAttributeUpdated(aWasBlocked); - - #ifdef DEBUG_TRIM - std::cout << "---- createArcFeature:end ---" << std::endl; - #endif - - return aFeature; -} - -FeaturePtr SketchPlugin_Trim::createConstraint(const std::string& theConstraintId, - const AttributePtr& theFirstAttribute, - const AttributePtr& theSecondAttribute) -{ - FeaturePtr aConstraint = sketch()->addFeature(theConstraintId); - AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( - aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A())); - aRefAttr->setAttr(theFirstAttribute); - - aRefAttr = std::dynamic_pointer_cast( - aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B())); - aRefAttr->setAttr(theSecondAttribute); - -#ifdef DEBUG_TRIM - std::cout << " :" - << "first attribute - " << theFirstAttribute->id() - << "second attribute - " << theSecondAttribute->id() - << std::endl; -#endif - - return aConstraint; -} - -FeaturePtr SketchPlugin_Trim::createConstraintToObject(const std::string& theConstraintId, - const AttributePtr& theFirstAttribute, - const ObjectPtr& theSecondObject) -{ - FeaturePtr aConstraint = sketch()->addFeature(theConstraintId); - AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( - aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A())); - aRefAttr->setAttr(theFirstAttribute); - - aRefAttr = std::dynamic_pointer_cast( - aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B())); - aRefAttr->setObject(theSecondObject); - -#ifdef DEBUG_TRIM - std::cout << " :" - << "first attribute - " << theFirstAttribute->id() - << "second object - " << ModelAPI_Feature::feature(theSecondObject)->getKind() - << std::endl; -#endif - - return aConstraint; -} - -FeaturePtr SketchPlugin_Trim::createConstraintForObjects( - const std::string& theConstraintId, - const ObjectPtr& theFirstObject, - const ObjectPtr& theSecondObject) -{ - FeaturePtr aConstraint = sketch()->addFeature(theConstraintId); - AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( - aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A())); - aRefAttr->setObject(theFirstObject); - - aRefAttr = std::dynamic_pointer_cast( - aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B())); - aRefAttr->setObject(theSecondObject); - - return aConstraint; -} - -std::shared_ptr SketchPlugin_Trim::getFeatureResult( - const std::shared_ptr& theFeature) -{ - std::shared_ptr aResult; - - std::string aFeatureKind = theFeature->getKind(); - if (aFeatureKind == SketchPlugin_Line::ID()) - aResult = theFeature->firstResult(); - else if (aFeatureKind == SketchPlugin_Arc::ID()) - aResult = theFeature->lastResult(); - else if (aFeatureKind == SketchPlugin_Circle::ID()) - aResult = theFeature->lastResult(); - - return aResult; -} - -//******************************************************************** -void SketchPlugin_Trim::fillObjectShapes(const ObjectPtr& theObject, - const ObjectPtr& theSketch, - std::map >& theCashedShapes, - std::map& theObjectToPoints) -{ - PointToRefsMap aPointsInfo; - - std::set > aShapes; - std::map, - std::list< AttributePoint2DPtr > > aPointToAttributes; - std::map, - std::list< ObjectPtr > > aPointToObjects; - - std::set aRefAttributes; - // current feature - FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); - std::set anEdgeShapes; - // edges on feature - ModelGeomAlgo_Shape::shapesOfType(aFeature, GeomAPI_Shape::EDGE, anEdgeShapes); - if (!anEdgeShapes.empty()) { - GeomShapePtr aFeatureShape = (*anEdgeShapes.begin())->shape(); - - // coincidences to the feature - ModelGeomAlgo_Point2D::getPointsOfReference(aFeature, SketchPlugin_ConstraintCoincidence::ID(), - aRefAttributes, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID()); - // layed on feature coincidences to divide it on several shapes - //SketchPlugin_Sketch* aSketch = sketch(); - std::shared_ptr aData = theSketch->data(); - std::shared_ptr aC = std::dynamic_pointer_cast( - aData->attribute(SketchPlugin_Sketch::ORIGIN_ID())); - std::shared_ptr aX = std::dynamic_pointer_cast( - aData->attribute(SketchPlugin_Sketch::DIRX_ID())); - std::shared_ptr aNorm = std::dynamic_pointer_cast( - aData->attribute(SketchPlugin_Sketch::NORM_ID())); - std::shared_ptr aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir()))); - - ModelGeomAlgo_Point2D::getPointsInsideShape(aFeatureShape, aRefAttributes, aC->pnt(), - aX->dir(), aY, aPointsInfo); - - std::list aFeatures; - CompositeFeaturePtr aSketchComposite = - std::dynamic_pointer_cast(theSketch); - for (int i = 0; i < aSketchComposite->numberOfSubs(); i++) { - FeaturePtr aFeature = aSketchComposite->subFeature(i); - if (aFeature.get()) - aFeatures.push_back(aFeature); - } - ModelGeomAlgo_Point2D::getPointsIntersectedShape(aFeature, aFeatures, aPointsInfo); - - GeomAlgoAPI_ShapeTools::splitShape(aFeatureShape, aPointsInfo, aShapes); - } - theObjectToPoints[theObject] = aPointsInfo; - theCashedShapes[theObject] = aShapes; }