X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchPlugin%2FSketchPlugin_Trim.cpp;h=aca80577bee77257e880d75981a9536a60b3d3d1;hb=06e7f5859095193fc7f498bd89a7d28009794f53;hp=6c778e514a200b77a8c7364714ed84c1067058cd;hpb=9168d8e4b881432e80b2a55bfbd4f846516a3bf0;p=modules%2Fshaper.git diff --git a/src/SketchPlugin/SketchPlugin_Trim.cpp b/src/SketchPlugin/SketchPlugin_Trim.cpp index 6c778e514..aca80577b 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-2023 CEA, EDF +// +// 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" @@ -23,21 +36,26 @@ #include #include +#include + #include #include #include #include #include -//#include #include #include #include #include +#include +#include #include #include #include #include +#include + #include #include #include @@ -48,14 +66,15 @@ #include -#define DEBUG_TRIM #ifdef DEBUG_TRIM #include #endif -static const double PI = 3.141592653589793238463; +#ifdef DEBUG_TRIM_METHODS +#include +#endif -static const std::string OPERATION_HIGHLIGHT_COLOR() { return "128, 0, 0"; } +static const double PI = 3.141592653589793238463; SketchPlugin_Trim::SketchPlugin_Trim() { @@ -63,25 +82,39 @@ SketchPlugin_Trim::SketchPlugin_Trim() void SketchPlugin_Trim::initAttributes() { - data()->addAttribute(SketchPlugin_Trim::BASE_OBJECT(), ModelAPI_AttributeReference::typeId()); - data()->addAttribute(ENTITY_POINT(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(SELECTED_OBJECT(), ModelAPI_AttributeReference::typeId()); + data()->addAttribute(SELECTED_POINT(), GeomDataAPI_Point2D::typeId()); + + data()->addAttribute(PREVIEW_POINT(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(PREVIEW_OBJECT(), ModelAPI_AttributeReference::typeId()); + + data()->attribute(PREVIEW_POINT())->setIsArgument(false); + data()->attribute(SELECTED_POINT())->setIsArgument(false); + data()->attribute(PREVIEW_OBJECT())->setIsArgument(false); + + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PREVIEW_POINT()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PREVIEW_OBJECT()); } -void SketchPlugin_Trim::findShapePoints(std::shared_ptr& aStartPoint, +void SketchPlugin_Trim::findShapePoints(const std::string& theObjectAttributeId, + const std::string& thePointAttributeId, + std::shared_ptr& aStartPoint, std::shared_ptr& aLastPoint) { AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast( - data()->attribute(SketchPlugin_Trim::BASE_OBJECT())); + data()->attribute(theObjectAttributeId)); ObjectPtr aBaseObject = aBaseObjectAttr->value(); AttributePoint2DPtr aPoint = std::dynamic_pointer_cast( - data()->attribute(ENTITY_POINT())); + 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); + if (myCashedShapes.find(aBaseObject) == myCashedShapes.end()) { + SketchPlugin_SegmentationTools::fillObjectShapes( + this, aBaseObject, myCashedShapes, myObjectToPoints); + } const std::set& aShapes = myCashedShapes[aBaseObject]; if (!aShapes.empty()) { @@ -93,19 +126,28 @@ void SketchPlugin_Trim::findShapePoints(std::shared_ptr& aStartPoin if (aBaseShape->shapeType() == GeomAPI_Shape::EDGE) { std::shared_ptr anEdge(new GeomAPI_Edge(aBaseShape)); - aStartPoint = anEdge->lastPoint(); - aLastPoint = anEdge->firstPoint(); + //GeomAPI_Shape::Orientation anOrientation = anEdge->orientation(); + //if (anOrientation == GeomAPI_Shape::REVERSED) { + aStartPoint = anEdge->lastPoint(); + aLastPoint = anEdge->firstPoint(); + //} + //else { + //aStartPoint = anEdge->firstPoint(); + //aLastPoint = anEdge->lastPoint(); + //} } } } } #ifdef DEBUG_TRIM std::cout << " => " - << "Start Point: [" - << aStartPoint->x() << ", " << aStartPoint->y() << ", " << aStartPoint->z() << "]" - << "Last Point: [" - << aLastPoint->x() << ", " << aLastPoint->y() << ", " << aLastPoint->z() << "]" - << std::endl; + << std::endl << "Attribute point: " + << anAttributePnt->x() << ", " << anAttributePnt->y() << ", " << anAttributePnt->z() << "]" + << std::endl << "Start Point: [" + << aStartPoint->x() << ", " << aStartPoint->y() << ", " << aStartPoint->z() << "]" + << std::endl << "Last Point: [" + << aLastPoint->x() << ", " << aLastPoint->y() << ", " << aLastPoint->z() << "]" + << std::endl; #endif } @@ -113,16 +155,20 @@ std::shared_ptr SketchPlugin_Trim::convertPoint( const std::shared_ptr& thePoint) { std::shared_ptr aPoint; + if (!thePoint.get()) + return aPoint; AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast( - data()->attribute(SketchPlugin_Trim::BASE_OBJECT())); + data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT())); ObjectPtr aBaseObject = aBaseObjectAttr->value(); - if (myObjectToPoints.find(aBaseObject) == myObjectToPoints.end()) - return aPoint; + 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, @@ -133,245 +179,487 @@ std::shared_ptr SketchPlugin_Trim::convertPoint( aFound = true; } else { - std::shared_ptr aPlane = sketch()->plane(); - aPoint = thePoint->to2D(aPlane); + aPoint = sketch()->to2D(thePoint); aFound = true; } } } if (!aFound) { - // returns an end of the shape to define direction of split if feature's attribute participates - std::shared_ptr aPlane = sketch()->plane(); - aPoint = thePoint->to2D(aPlane); + // returns an end of the shape to define direction of split if feature's attribute + // participates + aPoint = sketch()->to2D(thePoint); } return aPoint; } void SketchPlugin_Trim::execute() { -#ifdef DEBUG_TRIM - std::cout << "SketchPlugin_Trim::execute" << std::endl; +#ifdef DEBUG_TRIM_METHODS + std::cout << "SketchPlugin_Trim::execute: " << data()->name() << std::endl; #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( - data()->attribute(SketchPlugin_Trim::BASE_OBJECT())); + data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT())); if(!aBaseObjectAttr->isInitialized()) { setError("Error: Base object is not initialized."); 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 + /// as trim will be removed after execute + AttributeReferencePtr aPreviewObjectAttr = + std::dynamic_pointer_cast( + data()->attribute(SketchPlugin_Trim::PREVIEW_OBJECT())); + + ObjectPtr aPreviewObject = aPreviewObjectAttr->value(); + AttributePoint2DPtr aPoint = std::dynamic_pointer_cast( + data()->attribute(PREVIEW_POINT())); + std::shared_ptr aPreviewPnt2d = aPoint->pnt(); + // nullify pointer of preview attribute + aPreviewObjectAttr->setValue(ResultPtr()); + + bool anIsEqualPreviewAndSelected = aPreviewObject == aBaseObject; + /// points of trim std::shared_ptr aStartShapePoint, aLastShapePoint; - findShapePoints(aStartShapePoint, aLastShapePoint); - std::shared_ptr aStartShapePoint2d = convertPoint(aStartShapePoint); +#ifdef DEBUG_TRIM + 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); - + /// 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 + aRefIt = aBaseRefAttributes.begin(), aRefLast = aBaseRefAttributes.end(); + std::cout << std::endl << "References to attributes of base feature [" << + aBaseRefAttributes.size() << "]" << std::endl; + for (; aRefIt != aRefLast; aRefIt++) { + AttributePtr aBaseAttr = aRefIt->first; + std::list aRefAttributes = aRefIt->second; + std::string aRefsInfo; + std::list::const_iterator aRefAttrIt = aRefAttributes.begin(), + aRefAttrLast = aRefAttributes.end(); + for (; aRefAttrIt != aRefAttrLast; aRefAttrIt++) { + if (!aRefsInfo.empty()) + aRefsInfo.append(","); + AttributePtr aRAttr = *aRefAttrIt; + aRefsInfo.append(aRAttr->id()); + FeaturePtr aRFeature = ModelAPI_Feature::feature(aRAttr->owner()); + aRefsInfo.append("(" + aRFeature->name() + ") "); + } + std::shared_ptr aPointAttr = + std::dynamic_pointer_cast(aBaseAttr); + std::cout << aPointAttr->id().c_str() << + ": " << "[" << aRefAttributes.size() << "] " << aRefsInfo << std::endl; + } + std::cout << std::endl; + std::cout << std::endl << "References to base feature [" << + aRefsToFeature.size() << "]" << std::endl; + std::list::const_iterator aRefAttrIt = aRefsToFeature.begin(), + aRefAttrLast = aRefsToFeature.end(); + std::string aRefsInfo; + for (; aRefAttrIt != aRefAttrLast; aRefAttrIt++) { + if (!aRefsInfo.empty()) + aRefsInfo.append(","); + AttributePtr aRAttr = *aRefAttrIt; + aRefsInfo.append(aRAttr->id()); + FeaturePtr aRFeature = ModelAPI_Feature::feature(aRAttr->owner()); + aRefsInfo.append("(" + aRFeature->name() + ") "); + } + std::cout << "[" << aRefsToFeature.size() << "] " << aRefsInfo << std::endl; + std::cout << "---- getRefAttributes:end ----" << std::endl; +#endif + + keepCurrentFeature(); std::set aFurtherCoincidences; - std::set aCreatedFeatures; std::set> aModifiedAttributes; const std::string& aKind = aBaseFeature->getKind(); - if (aKind == SketchPlugin_Circle::ID()) { - trimCircle(aStartShapePoint2d, aLastShapePoint2d, - aFurtherCoincidences, aCreatedFeatures, aModifiedAttributes); - updateRefFeatureConstraints(getFeatureResult(aBaseFeature), aRefsToFeature); + FeaturePtr aReplacingFeature, aNewFeature; + if (aKind == SketchPlugin_Circle::ID() || + aKind == SketchPlugin_Ellipse::ID()) { + aReplacingFeature = trimClosed(aStartShapePoint2d, aLastShapePoint2d, + aFurtherCoincidences, aModifiedAttributes); aFeaturesToDelete.insert(aBaseFeature); - // as circle is removed, temporary fill this attribute + // as circle is removed, erase it from dependencies(arguments) of this feature + // otherwise Trim feature will be removed with the circle before + // this operation is finished aBaseObjectAttr->setObject(ResultPtr()); } else if (aKind == SketchPlugin_Line::ID()) { - trimLine(aStartShapePoint2d, aLastShapePoint2d, - aFurtherCoincidences, aCreatedFeatures, aModifiedAttributes); + aNewFeature = trimLine(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes, + aFurtherCoincidences, aModifiedAttributes); } else if (aKind == SketchPlugin_Arc::ID()) { - trimArc(aStartShapePoint2d, aLastShapePoint2d, - aFurtherCoincidences, aCreatedFeatures, aModifiedAttributes); + aNewFeature = trimArc(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes, + aFurtherCoincidences, aModifiedAttributes); } + else if (aKind == SketchPlugin_EllipticArc::ID()) { + aNewFeature = trimEllipticArc(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes, + aFurtherCoincidences, aModifiedAttributes); + } + + restoreCurrentFeature(); - // coincidence to result points - const PointToRefsMap& aRefsMap = myObjectToPoints.at(aBaseObject); - std::set::const_iterator anIt = aFurtherCoincidences.begin(), - aLast = aFurtherCoincidences.end(); - for (; anIt != aLast; anIt++) { + // constraints to end points of trim feature + if (myObjectToPoints.find(aBaseObject) == myObjectToPoints.end()) { + SketchPlugin_SegmentationTools::fillObjectShapes( + this, aBaseObject, myCashedShapes, myObjectToPoints); + } + + // create coincidence to objects, intersected the base object + const GeomAlgoAPI_ShapeTools::PointToRefsMap& aRefsMap = myObjectToPoints.at(aBaseObject); + for (std::set::const_iterator anIt = aFurtherCoincidences.begin(), + aLast = aFurtherCoincidences.end(); + anIt != aLast; anIt++) { AttributePoint2DPtr aPointAttribute = (*anIt); std::shared_ptr aPoint2d = aPointAttribute->pnt(); - std::shared_ptr aPoint; +#ifdef DEBUG_TRIM + std::cout << " => " << std::endl + << "aPoint2d: [" << aPoint2d->x() << ", " << aPoint2d->y() << "]" << std::endl; + if (aStartShapePoint2d.get()) + std::cout << "Start Point: [" << aStartShapePoint2d->x() << ", " << aStartShapePoint2d->y() + << "]" << std::endl; + if (aLastShapePoint2d.get()) + std::cout << "Last Point: [" << aLastShapePoint2d->x() << ", " << aLastShapePoint2d->y() + << "]" << std::endl; +#endif + + std::shared_ptr aExtrPoint; if (aStartShapePoint2d.get() && aPoint2d->isEqual(aStartShapePoint2d)) - aPoint = aStartShapePoint; + aExtrPoint = aStartShapePoint; else if (aLastShapePoint2d.get() && aPoint2d->isEqual(aLastShapePoint2d)) - aPoint = aLastShapePoint; + aExtrPoint = aLastShapePoint; - if (!aPoint.get()) + if (!aExtrPoint.get()) 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)) { + if (aRefIt->first->isEqual(aExtrPoint)) { 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 anInfoIt = anInfo.second.begin(); + anInfoIt != anInfo.second.end() && !isEdge; ++anInfoIt) { + ResultPtr aResult = std::dynamic_pointer_cast(*anInfoIt); + if (aResult) { + GeomShapePtr aShape = aResult->shape(); + isEdge = aShape && aShape->isEdge(); + } + } + if (isEdge) + break; } } - const std::list& anAttributes = anInfo.first; - for (std::list::const_iterator anAttrIt = anAttributes.begin(); - anAttrIt != anAttributes.end(); anAttrIt++) { - createConstraint(SketchPlugin_ConstraintCoincidence::ID(), aPointAttribute, *anAttrIt); - } - const std::list& anObjects = anInfo.second; for (std::list::const_iterator anObjectIt = anObjects.begin(); anObjectIt != anObjects.end(); anObjectIt++) { - createConstraint(SketchPlugin_ConstraintCoincidence::ID(), aPointAttribute, *anObjectIt); + SketchPlugin_Tools::createConstraintAttrObject(sketch(), + SketchPlugin_ConstraintCoincidence::ID(), + aPointAttribute, *anObjectIt); + } + } + + // move constraints from base feature to replacing feature: ignore coincidences to feature + // if attributes of coincidence participated in split + ResultPtr aReplacingResult; + if (aReplacingFeature.get()) { + aReplacingFeature->execute(); // need it to obtain result + aReplacingResult = aReplacingFeature->lastResult(); + } + for(std::list::const_iterator anIt = aRefsToFeature.begin(), + aLast = aRefsToFeature.end(); + anIt != aLast; anIt++) { + AttributePtr anAttribute = *anIt; + + if (setCoincidenceToAttribute(anAttribute, aFurtherCoincidences, aFeaturesToDelete)) + continue; + + // move tangency constraint to the nearest feature if possible + if (aNewFeature.get() && moveTangency(anAttribute, aNewFeature)) + continue; + + if (aReplacingResult.get()) { + AttributeRefAttrPtr aRefAttr = + std::dynamic_pointer_cast(anAttribute); + if (aRefAttr.get()) + aRefAttr->setObject(aReplacingResult); + else { + AttributeReferencePtr aReferenceAttr = + std::dynamic_pointer_cast(anAttribute); + if (aReferenceAttr.get()) + aReferenceAttr->setObject(aReplacingResult); + } } } + SketchPlugin_SegmentationTools::updateRefAttConstraints(aBaseRefAttributes, aModifiedAttributes); + // Wait all constraints being created, then send update events static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent); if (isUpdateFlushed) Events_Loop::loop()->setFlushed(anUpdateEvent, false); - updateRefAttConstraints(aBaseRefAttributes, aModifiedAttributes, aFeaturesToDelete); - // delete constraints #ifdef DEBUG_TRIM - std::cout << "remove features and references:" << std::endl; - std::set::const_iterator aDIt = aFeaturesToDelete.begin(), - aDLast = aFeaturesToDelete.end(); - for (; aDIt != aDLast; aDIt++) { - //std::cout << getFeatureInfo(*aDIt, false) << std::endl; - //std::cout << std::endl; + if (aFeaturesToDelete.size() > 0) { + std::cout << "after SPlit: removeFeaturesAndReferences: " << std::endl; + std::string aValue; + for (std::set::const_iterator anIt = aFeaturesToDelete.begin(); + anIt != aFeaturesToDelete.end(); anIt++) { + FeaturePtr aFeature = *anIt; + std::cout << aFeature->data()->name() << std::endl; + } } #endif 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); } + if (anIsEqualPreviewAndSelected) { + // equal preview and selected objects + // nothing to do if the preview and selected objects are different + if (aReplacingResult.get()) { // base object was removed + aPreviewObject = aReplacingResult; + //aMessage->setSelectedObject(aReplacingResult); +#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 + } + else { + aPreviewObject = ObjectPtr(); + + aBaseFeature->execute(); // should recompute shapes of result to do not check obsolete one + aBaseObject = aBaseFeature->lastResult(); + std::shared_ptr aPreviewPnt = sketch()->to3D(aPreviewPnt2d->x(), + aPreviewPnt2d->y()); + ResultPtr aBaseResult = std::dynamic_pointer_cast(aBaseObject); + if (aBaseResult) { + GeomShapePtr aShape = aBaseResult->shape(); + std::shared_ptr aProjectedPoint; + if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, aPreviewPnt, aProjectedPoint)) + aPreviewObject = aBaseResult; + } + if (!aPreviewObject.get() && aNewFeature.get()) { + ResultPtr aNewFeatureResult = aNewFeature->lastResult(); + if (aNewFeatureResult.get()) { + GeomShapePtr aShape = aNewFeatureResult->shape(); + std::shared_ptr aProjectedPoint; + if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, aPreviewPnt, aProjectedPoint)) + aPreviewObject = aNewFeatureResult; + } + } + } + } + if (aPreviewObject.get()) { + std::shared_ptr aMessage = std::shared_ptr + (new ModelAPI_EventReentrantMessage( + ModelAPI_EventReentrantMessage::eventId(), this)); + aMessage->setSelectedObject(aPreviewObject); + Events_Loop::loop()->send(aMessage); + } #ifdef DEBUG_TRIM std::cout << "SketchPlugin_Trim::done" << std::endl; #endif } -bool SketchPlugin_Trim::isMacro() const +// LCOV_EXCL_START +std::string SketchPlugin_Trim::processEvent(const std::shared_ptr& theMessage) { - return true; +#ifdef DEBUG_TRIM_METHODS + std::cout << "SketchPlugin_Trim::processEvent:" << data()->name() << std::endl; +#endif + std::string aFilledAttributeName; + + std::shared_ptr aMessage = + std::dynamic_pointer_cast(theMessage); + if (aMessage.get()) { + ObjectPtr anObject = aMessage->selectedObject(); + std::shared_ptr aPoint = aMessage->clickedPoint(); + + if (anObject.get() && aPoint.get()) { + 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 -AISObjectPtr SketchPlugin_Trim::getAISObject(AISObjectPtr thePrevious) +bool SketchPlugin_Trim::setCoincidenceToAttribute(const AttributePtr& theAttribute, + const std::set& theFurtherCoincidences, + std::set>& theFeaturesToDelete) { - AISObjectPtr anAIS = thePrevious; - // feature for trim - AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast( - data()->attribute(SketchPlugin_Trim::BASE_OBJECT())); - ObjectPtr aBaseObject = aBaseObjectAttr->value(); - if (!aBaseObject.get()) - return anAIS; - FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value()); - - // point on feature - AttributePoint2DPtr aPoint = std::dynamic_pointer_cast( - data()->attribute(ENTITY_POINT())); - std::shared_ptr anAttributePnt2d = aPoint->pnt(); - std::shared_ptr anAttributePnt = sketch()->to3D(anAttributePnt2d->x(), - anAttributePnt2d->y()); + FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner()); + if (aFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID()) + return false; + + AttributePoint2DPtr aRefPointAttr = SketchPlugin_ConstraintCoincidence::getPoint(aFeature); + if (!aRefPointAttr.get()) + return false; + std::shared_ptr aRefPnt2d = aRefPointAttr->pnt(); + + std::set::const_iterator anIt = theFurtherCoincidences.begin(), + aLast = theFurtherCoincidences.end(); + bool aFoundPoint = false; + for (; anIt != aLast && !aFoundPoint; anIt++) { + AttributePoint2DPtr aPointAttribute = (*anIt); + std::shared_ptr aPoint2d = aPointAttribute->pnt(); + if (aPoint2d->isEqual(aRefPnt2d)) { + // create new coincidence and then remove the old one + SketchPlugin_Tools::createConstraintAttrAttr(sketch(), + SketchPlugin_ConstraintCoincidence::ID(), + aRefPointAttr, aPointAttribute); + theFeaturesToDelete.insert(aFeature); + } + } + return aFoundPoint; +} - if (myCashedShapes.find(aBaseObject) == myCashedShapes.end()) - fillObjectShapes(aBaseObject); +bool SketchPlugin_Trim::moveTangency(const AttributePtr& theAttribute, + const FeaturePtr& theFeature) +{ + FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner()); + if (aFeature->getKind() != SketchPlugin_ConstraintTangent::ID()) + 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 aBaseShape = *anIt; - std::shared_ptr aProjectedPoint; - if (ModelGeomAlgo_Point2D::isPointOnEdge(aBaseShape, anAttributePnt, aProjectedPoint)) { - if (aBaseShape) { - if (!anAIS) - anAIS = AISObjectPtr(new GeomAPI_AISObject); - anAIS->createShape(aBaseShape); - - std::shared_ptr anAuxiliaryAttr = - aBaseFeature->data()->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID()); - - bool isConstruction = anAuxiliaryAttr.get() != NULL && anAuxiliaryAttr->value(); - - std::vector aColor; - aColor = Config_PropManager::color("Visualization", "operation_highlight_color", - OPERATION_HIGHLIGHT_COLOR()); - double aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH(); - int aLineStyle = SketchPlugin_SketchEntity::SKETCH_LINE_STYLE(); - if (isConstruction) { - aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH_AUXILIARY(); - aLineStyle = SketchPlugin_SketchEntity::SKETCH_LINE_STYLE_AUXILIARY(); - } - anAIS->setColor(aColor[0], aColor[1], aColor[2]); - // modification of width should be replaced to value 1 after highlight problem is fixed - anAIS->setWidth(aWidth + 2);//1); - anAIS->setLineStyle(aLineStyle); - break; - } + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( + theAttribute); + if (!aRefAttr.get()) + return false; + + // 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 anAIS; + 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, - std::set& theFeaturesToUpdate) + std::set& theFeaturesToUpdate) { std::shared_ptr aData = data(); // Check the base objects are initialized. AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast( - aData->attribute(SketchPlugin_Trim::BASE_OBJECT())); + 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(); @@ -379,168 +667,76 @@ 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); else if (aRefFeatureKind == SketchPlugin_ConstraintLength::ID()) theFeaturesToUpdate.insert(aRefFeature); - else if (aRefFeatureKind == SketchPlugin_ConstraintTangent::ID()) { - if (aBaseFeature->getKind() == SketchPlugin_Circle::ID()) /// TEMPORARY limitaion - /// until tangency between arc and line is implemented - theFeaturesToDelete.insert(aRefFeature); - else { - std::string anAttributeToBeModified; - AttributePoint2DPtr aTangentPoint; - ObjectPtr aResult1 = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_A())->object(); - ObjectPtr aResult2 = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_B())->object(); - if (aResult1.get() && aResult2.get()) { - FeaturePtr aCoincidenceFeature = - SketchPlugin_ConstraintCoincidence::findCoincidenceFeature - (ModelAPI_Feature::feature(aResult1), - ModelAPI_Feature::feature(aResult2)); - // get the point not lying on the splitting feature - for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) { - AttributeRefAttrPtr aRefAttr = aCoincidenceFeature->refattr( - SketchPlugin_Trim::BASE_OBJECT()); - if (!aRefAttr || aRefAttr->isObject()) - continue; - AttributePoint2DPtr aPoint = - std::dynamic_pointer_cast(aRefAttr->attr()); - if (!aPoint) - continue; - if (aPoint->owner() != aBaseFeature) { - aTangentPoint = aPoint; - break; - } - } - } - if (aTangentPoint.get()) { - // collect tangent feaures - } - else /// there is not coincident point between tangent constraint - theFeaturesToDelete.insert(aRefFeature); - } - } } } -void SketchPlugin_Trim::getRefAttributes(const FeaturePtr& theFeature, - std::map >& theRefs, - std::list& theRefsToFeature) +void SketchPlugin_Trim::removeReferencesToAttribute(const AttributePtr& theAttribute, + std::map >& theBaseRefAttributes) { - 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); + /// not found in references + if (theBaseRefAttributes.find(theAttribute) == theBaseRefAttributes.end()) + return; - std::set aRefsAttributes = getFeatureResult(theFeature)->data()->refsToMe(); - std::set aFRefsList = theFeature->data()->refsToMe(); - aRefsAttributes.insert(aFRefsList.begin(), aFRefsList.end()); + std::list aRefAttributes = theBaseRefAttributes.at(theAttribute); + std::list::const_iterator aRefIt = aRefAttributes.begin(), + aRLast = aRefAttributes.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); - } + std::set aFeaturesToDelete; + for (; aRefIt != aRLast; aRefIt++) { + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(*aRefIt); + if (aRefAttr.get()) { + aFeaturesToDelete.insert(ModelAPI_Feature::feature(aRefAttr->owner())); } } -} -void SketchPlugin_Trim::updateRefFeatureConstraints( - const ResultPtr& theFeatureBaseResult, - const std::list& theRefsToFeature) -{ - std::list::const_iterator anIt = theRefsToFeature.begin(), - aLast = theRefsToFeature.end(); - for (; anIt != aLast; anIt++) { - AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(*anIt); - if (aRefAttr.get()) - aRefAttr->setObject(theFeatureBaseResult); - } -} - -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; - for (; aRefIt != aRLast; aRefIt++) { - AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(*aRefIt); - if (aRefAttr.get()) { - if (aNewAttribute.get()) - aRefAttr->setAttr(aNewAttribute); - else - theFeaturesToDelete.insert(ModelAPI_Feature::feature(aRefAttr->owner())); -#ifdef DEBUG_TRIM - //FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->owner()); - //std::cout << " -" << getFeatureInfo(aFeature) << std::endl; -#endif - } + // delete constraints + if (aFeaturesToDelete.size() > 0) { + std::cout << "removeReferencesToAttribute: " << std::endl; + std::string aValue; + for (std::set::const_iterator anIt = aFeaturesToDelete.begin(); + anIt != aFeaturesToDelete.end(); anIt++) { + FeaturePtr aFeature = *anIt; + std::cout << aFeature->data()->name() << std::endl; } } +#endif + ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToDelete); + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED)); } -void SketchPlugin_Trim::trimLine(const std::shared_ptr& theStartShapePoint, - const std::shared_ptr& theLastShapePoint, - std::set& thePoints, - std::set& theCreatedFeatures, +FeaturePtr SketchPlugin_Trim::trimLine(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::BASE_OBJECT())); + data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT())); ObjectPtr aBaseObject = aBaseObjectAttr->value(); FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value()); /// 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(); @@ -575,17 +771,24 @@ void SketchPlugin_Trim::trimLine(const std::shared_ptr& theStartS else aPoint = aStartShapePoint.get() ? aStartShapePoint : aLastShapePoint; + // it is important to delete references before the feature modification because + // if deletion will be after the feature modification, solver returns the feature back + removeReferencesToAttribute(aBaseFeature->attribute(aModifiedAttribute), + theBaseRefAttributes); + fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aPoint); - theModifiedAttributes.insert( - std::make_pair(aBaseFeature->attribute(aModifiedAttribute), AttributePtr())); + //theModifiedAttributes.insert( + // std::make_pair(aBaseFeature->attribute(aModifiedAttribute), AttributePtr())); thePoints.insert(std::dynamic_pointer_cast (aBaseFeature->attribute(aModifiedAttribute))); } else { - // result is two lines: start line point - start shape point, last shape point - last line point + // result is two lines: start line point - start shape point, + // last shape point - last line point // create second line - FeaturePtr anNewFeature = createLineFeature(aBaseFeature, aLastShapePoint, aLastFeaturePoint); + anNewFeature = SketchPlugin_SegmentationTools::createLineFeature( + aBaseFeature, aLastShapePoint, aLastFeaturePoint); thePoints.insert(std::dynamic_pointer_cast (anNewFeature->attribute(SketchPlugin_Line::START_ID()))); @@ -601,28 +804,31 @@ void SketchPlugin_Trim::trimLine(const std::shared_ptr& theStartS (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; } -void SketchPlugin_Trim::trimArc(const std::shared_ptr& theStartShapePoint, - const std::shared_ptr& theLastShapePoint, - std::set& thePoints, - std::set& theCreatedFeatures, +FeaturePtr SketchPlugin_Trim::trimArc(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::BASE_OBJECT())); + data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT())); ObjectPtr aBaseObject = aBaseObjectAttr->value(); FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value()); /// 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(); @@ -634,14 +840,14 @@ void SketchPlugin_Trim::trimArc(const std::shared_ptr& theStartSh #ifdef DEBUG_TRIM std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl; if (aStartShapePoint.get()) - std::cout << "Start point: [" << aStartShapePoint->x() << ", " << + std::cout << "Start shape point: [" << aStartShapePoint->x() << ", " << aStartShapePoint->y() << "]" << std::endl; - std::cout << "1st point: [" << aStartArcPoint->x() << ", " << + std::cout << "Start arc attribute point: [" << aStartArcPoint->x() << ", " << aStartArcPoint->y() << "]" << std::endl; if (aLastShapePoint.get()) - std::cout << "2st point: [" << aLastShapePoint->x() << ", " << + std::cout << "Last shape point: [" << aLastShapePoint->x() << ", " << aLastShapePoint->y() << "]" << std::endl; - std::cout << "End point: [" << aLastArcPoint->x() << ", " << + std::cout << "Last arc attribute point: [" << aLastArcPoint->x() << ", " << aLastArcPoint->y() << "]" << std::endl; #endif @@ -657,9 +863,10 @@ void SketchPlugin_Trim::trimArc(const std::shared_ptr& theStartSh else aPoint = aStartShapePoint.get() ? aStartShapePoint : aLastShapePoint; + removeReferencesToAttribute(aBaseFeature->attribute(aModifiedAttribute), + theBaseRefAttributes); + fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aPoint); - theModifiedAttributes.insert( - std::make_pair(aBaseFeature->attribute(aModifiedAttribute), AttributePtr())); thePoints.insert(std::dynamic_pointer_cast (aBaseFeature->attribute(aModifiedAttribute))); @@ -667,14 +874,15 @@ void SketchPlugin_Trim::trimArc(const std::shared_ptr& theStartSh else { // result is two arcs: start arc point - start shape point, last shape point - last arc point // create second arc - FeaturePtr anArcFeature = createArcFeature(aBaseFeature, aLastShapePoint, aLastArcPoint); + anNewFeature = SketchPlugin_SegmentationTools::createArcFeature( + aBaseFeature, aLastShapePoint, aLastArcPoint); thePoints.insert(std::dynamic_pointer_cast - (anArcFeature->attribute(SketchPlugin_Arc::START_ID()))); + (anNewFeature->attribute(SketchPlugin_Arc::START_ID()))); std::string aModifiedAttribute = SketchPlugin_Arc::END_ID(); theModifiedAttributes.insert( std::make_pair(aBaseFeature->attribute(aModifiedAttribute), - anArcFeature->attribute(SketchPlugin_Arc::END_ID()))); + anNewFeature->attribute(SketchPlugin_Arc::END_ID()))); // modify base arc fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aStartShapePoint); @@ -683,47 +891,202 @@ void SketchPlugin_Trim::trimArc(const std::shared_ptr& theStartSh (aBaseFeature->attribute(aModifiedAttribute))); // equal Radius constraint for arcs - createConstraintForObjects(SketchPlugin_ConstraintEqual::ID(), - getFeatureResult(aBaseFeature), - getFeatureResult(anArcFeature)); + SketchPlugin_Tools::createConstraintObjectObject(sketch(), + SketchPlugin_ConstraintEqual::ID(), + aBaseFeature->lastResult(), + anNewFeature->lastResult()); // coincident centers constraint - createConstraint(SketchPlugin_ConstraintCoincidence::ID(), - aBaseFeature->attribute(SketchPlugin_Arc::CENTER_ID()), - anArcFeature->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; + std::cout << "Start shape point: [" << aStartShapePoint->x() << ", " << + aStartShapePoint->y() << "]" << std::endl; +#endif } + return anNewFeature; } -void SketchPlugin_Trim::trimCircle(const std::shared_ptr& theStartShapePoint, - const std::shared_ptr& theLastShapePoint, - std::set& thePoints, - std::set& theCreatedFeatures, +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::BASE_OBJECT())); + AttributeReferencePtr aBaseObjectAttr = reference(SELECTED_OBJECT()); ObjectPtr aBaseObject = aBaseObjectAttr->value(); FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value()); - /// points of trim + // 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(); + + 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; +} - /// trim feature - FeaturePtr anArcFeature = createArcFeature(aBaseFeature, theStartShapePoint, theLastShapePoint); +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()); - theModifiedAttributes.insert( - std::make_pair(aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()), - anArcFeature->attribute(SketchPlugin_Arc::CENTER_ID()))); + // 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 + const std::string& aReversedAttrName = anNewFeature->getKind() == SketchPlugin_Arc::ID() ? + SketchPlugin_Arc::REVERSED_ID() : SketchPlugin_EllipticArc::REVERSED_ID(); + anNewFeature->boolean(aReversedAttrName)->setValue(false); + + 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 - (anArcFeature->attribute(SketchPlugin_Arc::START_ID()))); + (anNewFeature->attribute(aStartAttrName))); thePoints.insert(std::dynamic_pointer_cast - (anArcFeature->attribute(SketchPlugin_Arc::END_ID()))); + (anNewFeature->attribute(aEndAttrName))); + + return anNewFeature; } void SketchPlugin_Trim::arrangePointsOnLine(const AttributePoint2DPtr& theStartPointAttr, - const AttributePoint2DPtr& theEndPointAttr, + const AttributePoint2DPtr& /*theEndPointAttr*/, std::shared_ptr& theFirstPoint, std::shared_ptr& theLastPoint) const { @@ -741,7 +1104,7 @@ void SketchPlugin_Trim::arrangePointsOnLine(const AttributePoint2DPtr& theStartP void SketchPlugin_Trim::arrangePointsOnArc(const FeaturePtr& theArc, const AttributePoint2DPtr& theStartPointAttr, - const AttributePoint2DPtr& theEndPointAttr, + const AttributePoint2DPtr& /*theEndPointAttr*/, std::shared_ptr& theFirstPoint, std::shared_ptr& theSecondPoint) const { @@ -750,9 +1113,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::INVERSED_ID())->value(); + theArc->attribute(aCenterAttrName))->pnt(); + bool isReversed = theArc->boolean(aReversedAttrName)->value(); // collect directions to each point std::shared_ptr aStartDir( @@ -788,13 +1156,14 @@ void SketchPlugin_Trim::fillPointAttribute(const AttributePtr& theModifiedAttrib aModifiedAttribute->setValue(thePoint); #ifdef DEBUG_TRIM - std::cout << " => Pnt2d - [" << thePoint->x() << ", " - << thePoint->y() << "]" << std::endl; + FeaturePtr aFeature = ModelAPI_Feature::feature(theModifiedAttribute->owner()); + std::cout << "data()->name() << ": " << + theModifiedAttribute->id() << + "]> => Pnt2d - [" << thePoint->x() << ", " << thePoint->y() << "]" << std::endl; #endif } } - void SketchPlugin_Trim::fillAttribute(const AttributePtr& theModifiedAttribute, const AttributePtr& theSourceAttribute) { @@ -817,259 +1186,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) -{ - 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 - - 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; - - 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); - - aFeature->string(SketchPlugin_Arc::ARC_TYPE())->setValue( - SketchPlugin_Arc::ARC_TYPE_CENTER_START_END()); - - 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::INVERSED_ID())->value(); - aFeature->boolean(SketchPlugin_Arc::INVERSED_ID())->setValue(aReversed); - } - aFeature->execute(); // to obtain result - aFeature->data()->blockSendAttributeUpdated(aWasBlocked); - - 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::createConstraint(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; -} - -//******************************************************************** -bool SketchPlugin_Trim::useGraphicIntersection() const -{ - return true; -} - -//******************************************************************** -void SketchPlugin_Trim::fillObjectShapes(const ObjectPtr& theObject) -{ - 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 - ModelAPI_Tools::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 = aSketch->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); - - // intersection points - if (useGraphicIntersection()) { - std::list aFeatures; - for (int i = 0; i < aSketch->numberOfSubs(); i++) { - FeaturePtr aFeature = aSketch->subFeature(i); - if (aFeature.get()) - aFeatures.push_back(aFeature); - } - ModelGeomAlgo_Point2D::getPointsIntersectedShape(aFeature, aFeatures, aPointsInfo); - } - GeomAlgoAPI_ShapeTools::splitShape(aFeatureShape, aPointsInfo, aShapes); - } - myObjectToPoints[theObject] = aPointsInfo; - myCashedShapes[theObject] = aShapes; -} - -//******************************************************************** -void SketchPlugin_Trim::attributeChanged(const std::string& theID) -{ - //data()->addAttribute(SketchPlugin_Trim::BASE_OBJECT(), ModelAPI_AttributeReference::typeId()); - if (theID == SketchPlugin_Trim::BASE_OBJECT()) { - bool isValidAttribute = false; - // feature for trim - AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast( - data()->attribute(SketchPlugin_Trim::BASE_OBJECT())); - ObjectPtr aBaseObject = aBaseObjectAttr->value(); - if (aBaseObject.get()) { - FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value()); - // point on feature - AttributePoint2DPtr aPoint = std::dynamic_pointer_cast( - data()->attribute(ENTITY_POINT())); - std::shared_ptr anAttributePnt2d = aPoint->pnt(); - std::shared_ptr anAttributePnt = sketch()->to3D(anAttributePnt2d->x(), - anAttributePnt2d->y()); - - if (myCashedShapes.find(aBaseObject) == myCashedShapes.end()) - fillObjectShapes(aBaseObject); - - const std::set& aShapes = myCashedShapes[aBaseObject]; - isValidAttribute = !aShapes.empty(); - - if (!isValidAttribute) { - bool aWasBlocked = data()->blockSendAttributeUpdated(true); - aBaseObjectAttr->setValue(ObjectPtr()); - data()->blockSendAttributeUpdated(aWasBlocked); - } - } - } }