X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchPlugin%2FSketchPlugin_Trim.cpp;h=f2d2c4da8bc856f4ef3492a3152cf05b32eece81;hb=21a0c85b52bb93f94680e2342370764e6510e387;hp=5a6f4e1eed7b1b6b989ebce2f6e6521edced8cc3;hpb=17d8a9be9ff8975e7551160a82116a65e1203128;p=modules%2Fshaper.git diff --git a/src/SketchPlugin/SketchPlugin_Trim.cpp b/src/SketchPlugin/SketchPlugin_Trim.cpp index 5a6f4e1ee..f2d2c4da8 100644 --- a/src/SketchPlugin/SketchPlugin_Trim.cpp +++ b/src/SketchPlugin/SketchPlugin_Trim.cpp @@ -41,6 +41,8 @@ #include #include +#include + #include #include #include @@ -51,11 +53,17 @@ #include -#define DEBUG_TRIM +//#define DEBUG_TRIM_METHODS +//#define DEBUG_TRIM + #ifdef DEBUG_TRIM #include #endif +#ifdef DEBUG_TRIM_METHODS +#include +#endif + static const double PI = 3.141592653589793238463; static const std::string OPERATION_HIGHLIGHT_COLOR() { return "128, 0, 0"; } @@ -110,19 +118,28 @@ void SketchPlugin_Trim::findShapePoints(const std::string& theObjectAttributeId, 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 } @@ -130,6 +147,8 @@ 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::SELECTED_OBJECT())); @@ -150,8 +169,7 @@ 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; } } @@ -159,21 +177,22 @@ std::shared_ptr SketchPlugin_Trim::convertPoint( 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); + 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( @@ -183,15 +202,35 @@ 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 + /// 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; +#ifdef DEBUG_TRIM + std::cout << " Base Feature: " << aBaseFeature->data()->name() << std::endl; +#endif findShapePoints(SELECTED_OBJECT(), SELECTED_POINT(), aStartShapePoint, aLastShapePoint); - std::shared_ptr aStartShapePoint2d = convertPoint(aStartShapePoint); + std::shared_ptr aStartShapePoint2d = convertPoint(aStartShapePoint); std::shared_ptr aLastShapePoint2d = convertPoint(aLastShapePoint); std::set aFeaturesToDelete; @@ -200,18 +239,58 @@ void SketchPlugin_Trim::execute() std::map > aBaseRefAttributes; std::list aRefsToFeature; 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 // 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); + //std::map aCoincidencesToBaseFeature; + //getCoincidencesToObject(aBaseObject, aCoincidencesToBaseFeature); std::set aFurtherCoincidences; std::set> aModifiedAttributes; const std::string& aKind = aBaseFeature->getKind(); - FeaturePtr aReplacingFeature; + FeaturePtr aReplacingFeature, aNewFeature; if (aKind == SketchPlugin_Circle::ID()) { aReplacingFeature = trimCircle(aStartShapePoint2d, aLastShapePoint2d, aFurtherCoincidences, aModifiedAttributes); @@ -221,33 +300,39 @@ void SketchPlugin_Trim::execute() // otherwise Trim feature will be removed with the circle before // this operation is finished aBaseObjectAttr->setObject(ResultPtr()); - - AttributeReferencePtr aPreviewObjectAttr = - std::dynamic_pointer_cast( - data()->attribute(SketchPlugin_Trim::PREVIEW_OBJECT())); - aPreviewObjectAttr->setObject(ResultPtr()); - } else if (aKind == SketchPlugin_Line::ID()) { - trimLine(aStartShapePoint2d, aLastShapePoint2d, - aFurtherCoincidences, aModifiedAttributes); + aNewFeature = trimLine(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes, + aFurtherCoincidences, aModifiedAttributes); } else if (aKind == SketchPlugin_Arc::ID()) { - trimArc(aStartShapePoint2d, aLastShapePoint2d, - aFurtherCoincidences, aModifiedAttributes); + aNewFeature = trimArc(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes, + aFurtherCoincidences, aModifiedAttributes); } - // + // constraints to end points of trim feature if (myObjectToPoints.find(aBaseObject) == myObjectToPoints.end()) fillObjectShapes(aBaseObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints); + // create coincidence to objects, intersected the base object const PointToRefsMap& aRefsMap = myObjectToPoints.at(aBaseObject); - std::set::const_iterator anIt = aFurtherCoincidences.begin(), - aLast = aFurtherCoincidences.end(); - for (; anIt != aLast; anIt++) { + for (std::set::const_iterator anIt = aFurtherCoincidences.begin(), + aLast = aFurtherCoincidences.end(); + anIt != aLast; anIt++) { AttributePoint2DPtr aPointAttribute = (*anIt); std::shared_ptr aPoint2d = aPointAttribute->pnt(); +#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 aPoint; if (aStartShapePoint2d.get() && aPoint2d->isEqual(aStartShapePoint2d)) aPoint = aStartShapePoint; @@ -266,29 +351,6 @@ void SketchPlugin_Trim::execute() break; } } - const std::list& anAttributes = anInfo.first; - for (std::list::const_iterator anAttrIt = anAttributes.begin(); - anAttrIt != anAttributes.end(); anAttrIt++) { - AttributePtr anAttribute = *anAttrIt; - if (aCoincidencesToBaseFeature.find(anAttribute) != aCoincidencesToBaseFeature.end()) - { - FeaturePtr anAttrFeature = aCoincidencesToBaseFeature.at(anAttribute); - AttributePtr anOtherAttribute; - if (std::dynamic_pointer_cast - (anAttrFeature->attribute(SketchPlugin_Constraint::ENTITY_A()))->attr() == anAttribute) - anOtherAttribute = anAttrFeature->attribute(SketchPlugin_Constraint::ENTITY_B()); - else if (std::dynamic_pointer_cast - (anAttrFeature->attribute(SketchPlugin_Constraint::ENTITY_B()))->attr() == anAttribute) - anOtherAttribute = anAttrFeature->attribute(SketchPlugin_Constraint::ENTITY_A()); - else - continue; - AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast - (anOtherAttribute); - if (aRefAttr.get()) - aRefAttr->setAttr(aPointAttribute); - } - } - const std::list& anObjects = anInfo.second; for (std::list::const_iterator anObjectIt = anObjects.begin(); anObjectIt != anObjects.end(); anObjectIt++) { @@ -299,42 +361,54 @@ void SketchPlugin_Trim::execute() // move constraints from base feature to replacing feature: ignore coincidences to feature // if attributes of coincidence participated in split + ResultPtr aReplacingResult; if (aReplacingFeature.get()) { - ResultPtr aReplacingResult = getFeatureResult(aReplacingFeature); - std::list::const_iterator anIt = aRefsToFeature.begin(), - aLast = aRefsToFeature.end(); - for (; anIt != aLast; anIt++) { - AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(*anIt); - if (!aRefAttr.get()) - continue; - FeaturePtr anAttrFeature = ModelAPI_Feature::feature(aRefAttr->owner()); - if (anAttrFeature.get() && - anAttrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) - { - if (anAttrFeature->attribute(SketchPlugin_Constraint::ENTITY_A()) == aRefAttr || - anAttrFeature->attribute(SketchPlugin_Constraint::ENTITY_B()) == aRefAttr) - continue; + aReplacingFeature->execute(); // need it to obtain result + aReplacingResult = getFeatureResult(aReplacingFeature); + } + 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)) + 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); } - aRefAttr->setObject(aReplacingResult); } } + updateRefAttConstraints(aBaseRefAttributes, aModifiedAttributes, aFeaturesToDelete); + // 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); @@ -345,11 +419,179 @@ void SketchPlugin_Trim::execute() 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); + + 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); + 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 = getFeatureResult(aNewFeature); + 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 } +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 = + 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()) + fillObjectShapes(anObject, sketch()->data()->owner(), 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 = 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(); + } + } + } + return aFilledAttributeName; +} + +bool SketchPlugin_Trim::setCoincidenceToAttribute(const AttributePtr& theAttribute, + const std::set& theFurtherCoincidences) +{ + 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)) { + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( + theAttribute); + if (aRefAttr.get()) { + aRefAttr->setAttr(aPointAttribute); + aFoundPoint = true; + } + } + } + return aFoundPoint; +} + +bool SketchPlugin_Trim::replaceCoincidenceAttribute(const AttributePtr& theCoincidenceAttribute, + const std::set>& theModifiedAttributes) +{ + FeaturePtr aCoincidenceFeature = ModelAPI_Feature::feature(theCoincidenceAttribute->owner()); + if (aCoincidenceFeature->getKind() != SketchPlugin_ConstraintCoincidence::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; @@ -357,6 +599,10 @@ bool SketchPlugin_Trim::isMacro() const 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; @@ -524,7 +770,7 @@ void SketchPlugin_Trim::getRefAttributes(const FeaturePtr& theFeature, } } -void SketchPlugin_Trim::getCoincidencesToObject(const ObjectPtr& theObject, +/*void SketchPlugin_Trim::getCoincidencesToObject(const ObjectPtr& theObject, std::map& theCoincidencesToBaseFeature) { const std::set& aRefsList = theObject->data()->refsToMe(); @@ -542,23 +788,25 @@ void SketchPlugin_Trim::getCoincidencesToObject(const ObjectPtr& theObject, anAttribute = aRefFeature->attribute(SketchPlugin_Constraint::ENTITY_B()); } else { - aRefAttr = std::dynamic_pointer_cast + 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()) - { - aRefAttr = std::dynamic_pointer_cast - (anAttribute); - anAttribute = aRefAttr->attr(); - if (anAttribute.get()) - theCoincidencesToBaseFeature[anAttribute] = aRefFeature; - } + } + 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, @@ -582,27 +830,61 @@ void SketchPlugin_Trim::updateRefAttConstraints( 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 + if (aNewAttribute.get()) { + for (; aRefIt != aRLast; aRefIt++) { + AttributeRefAttrPtr aRefAttr = + std::dynamic_pointer_cast(*aRefIt); + if (aRefAttr.get()) { + aRefAttr->setAttr(aNewAttribute); + } } } } } -void SketchPlugin_Trim::trimLine(const std::shared_ptr& theStartShapePoint, - const std::shared_ptr& theLastShapePoint, - std::set& thePoints, +void SketchPlugin_Trim::removeReferencesToAttribute(const AttributePtr& theAttribute, + std::map >& theBaseRefAttributes) +{ + /// not found in references + if (theBaseRefAttributes.find(theAttribute) == theBaseRefAttributes.end()) + return; + + std::list aRefAttributes = theBaseRefAttributes.at(theAttribute); + std::list::const_iterator aRefIt = aRefAttributes.begin(), + aRLast = aRefAttributes.end(); + + std::set aFeaturesToDelete; + for (; aRefIt != aRLast; aRefIt++) { + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(*aRefIt); + if (aRefAttr.get()) { + aFeaturesToDelete.insert(ModelAPI_Feature::feature(aRefAttr->owner())); + } + } + +#ifdef DEBUG_TRIM + // 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)); +} + +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::SELECTED_OBJECT())); @@ -646,9 +928,14 @@ 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))); @@ -657,7 +944,7 @@ void SketchPlugin_Trim::trimLine(const std::shared_ptr& theStartS // 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 = createLineFeature(aBaseFeature, aLastShapePoint, aLastFeaturePoint); thePoints.insert(std::dynamic_pointer_cast (anNewFeature->attribute(SketchPlugin_Line::START_ID()))); @@ -678,13 +965,16 @@ void SketchPlugin_Trim::trimLine(const std::shared_ptr& theStartS getFeatureResult(anNewFeature)); } + return anNewFeature; } -void SketchPlugin_Trim::trimArc(const std::shared_ptr& theStartShapePoint, - const std::shared_ptr& theLastShapePoint, - std::set& thePoints, +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::SELECTED_OBJECT())); @@ -705,14 +995,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 @@ -728,9 +1018,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))); @@ -738,14 +1029,14 @@ 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 = 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); @@ -756,12 +1047,19 @@ void SketchPlugin_Trim::trimArc(const std::shared_ptr& theStartSh // equal Radius constraint for arcs createConstraintForObjects(SketchPlugin_ConstraintEqual::ID(), getFeatureResult(aBaseFeature), - getFeatureResult(anArcFeature)); + getFeatureResult(anNewFeature)); // coincident centers constraint createConstraint(SketchPlugin_ConstraintCoincidence::ID(), aBaseFeature->attribute(SketchPlugin_Arc::CENTER_ID()), - anArcFeature->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; } FeaturePtr SketchPlugin_Trim::trimCircle(const std::shared_ptr& theStartShapePoint, @@ -780,18 +1078,20 @@ FeaturePtr SketchPlugin_Trim::trimCircle(const std::shared_ptr& t //getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase); /// trim feature - FeaturePtr anArcFeature = createArcFeature(aBaseFeature, theStartShapePoint, theLastShapePoint); + FeaturePtr anNewFeature = 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); theModifiedAttributes.insert( std::make_pair(aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()), - anArcFeature->attribute(SketchPlugin_Arc::CENTER_ID()))); + anNewFeature->attribute(SketchPlugin_Arc::CENTER_ID()))); thePoints.insert(std::dynamic_pointer_cast - (anArcFeature->attribute(SketchPlugin_Arc::START_ID()))); + (anNewFeature->attribute(SketchPlugin_Arc::START_ID()))); thePoints.insert(std::dynamic_pointer_cast - (anArcFeature->attribute(SketchPlugin_Arc::END_ID()))); + (anNewFeature->attribute(SketchPlugin_Arc::END_ID()))); - return anArcFeature; + return anNewFeature; } void SketchPlugin_Trim::arrangePointsOnLine(const AttributePoint2DPtr& theStartPointAttr, @@ -860,8 +1160,10 @@ 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 } } @@ -909,6 +1211,10 @@ 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()) @@ -924,10 +1230,13 @@ FeaturePtr SketchPlugin_Trim::createLineFeature(const FeaturePtr& theBaseFeature 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) @@ -946,6 +1255,10 @@ FeaturePtr SketchPlugin_Trim::createArcFeature(const FeaturePtr& theBaseFeature, 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" @@ -965,9 +1278,13 @@ FeaturePtr SketchPlugin_Trim::createArcFeature(const FeaturePtr& theBaseFeature, bool aReversed = theBaseFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->value(); aFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(aReversed); } - aFeature->execute(); // to obtain result + aFeature->execute(); // to obtain result (need to calculate arc parameters before sending Update) aFeature->data()->blockSendAttributeUpdated(aWasBlocked); + #ifdef DEBUG_TRIM + std::cout << "---- createArcFeature:end ---" << std::endl; + #endif + return aFeature; }