X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchPlugin%2FSketchPlugin_Tools.cpp;h=710c6fd18d3a6ceedf4b9a5153fabec1b1f9fc5f;hb=06e7f5859095193fc7f498bd89a7d28009794f53;hp=6fc020ddb0143117f5ab56531494b7d12bb6a679;hpb=fec33ea37fbbd369bda3da328abf6171d08a6c42;p=modules%2Fshaper.git diff --git a/src/SketchPlugin/SketchPlugin_Tools.cpp b/src/SketchPlugin/SketchPlugin_Tools.cpp index 6fc020ddb..710c6fd18 100644 --- a/src/SketchPlugin/SketchPlugin_Tools.cpp +++ b/src/SketchPlugin/SketchPlugin_Tools.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 CEA/DEN, EDF R&D +// 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 @@ -12,29 +12,48 @@ // // 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 +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or -// email : webmaster.salome@opencascade.com +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // #include "SketchPlugin_Tools.h" +#include "SketchPlugin_Arc.h" +#include "SketchPlugin_BSpline.h" +#include "SketchPlugin_Circle.h" #include "SketchPlugin_ConstraintCoincidence.h" +#include "SketchPlugin_ConstraintCoincidenceInternal.h" #include "SketchPlugin_ConstraintLength.h" #include "SketchPlugin_ConstraintTangent.h" +#include "SketchPlugin_Ellipse.h" +#include "SketchPlugin_EllipticArc.h" #include "SketchPlugin_Line.h" #include "SketchPlugin_Point.h" +#include "SketchPlugin_Projection.h" #include "SketchPlugin_SketchEntity.h" +#include "SketchPlugin_Split.h" +#include "SketchPlugin_Trim.h" #include +#include + #include +#include +#include + +#include +#include #include +#include #include #include +#include +#include + #include #include @@ -46,17 +65,17 @@ namespace SketchPlugin_Tools { void clearExpressions(AttributeDoublePtr theAttribute) { - theAttribute->setText(std::string()); + theAttribute->setText(std::wstring()); } void clearExpressions(AttributePointPtr theAttribute) { - theAttribute->setText(std::string(), std::string(), std::string()); + theAttribute->setText(std::wstring(), std::wstring(), std::wstring()); } void clearExpressions(AttributePoint2DPtr theAttribute) { - theAttribute->setText(std::string(), std::string()); + theAttribute->setText(std::wstring(), std::wstring()); } void clearExpressions(AttributePtr theAttribute) @@ -99,14 +118,15 @@ std::shared_ptr getCoincidencePoint(const FeaturePtr theStartCoin return aPnt; } -std::set findCoincidentConstraints(const FeaturePtr& theFeature) +std::set findCoincidentConstraints(const ObjectPtr& theObject) { std::set aCoincident; - const std::set& aRefsList = theFeature->data()->refsToMe(); + const std::set& aRefsList = theObject->data()->refsToMe(); std::set::const_iterator aIt; for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) { FeaturePtr aConstrFeature = std::dynamic_pointer_cast((*aIt)->owner()); - if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) + if (aConstrFeature && (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID() || + aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidenceInternal::ID())) aCoincident.insert(aConstrFeature); } return aCoincident; @@ -134,8 +154,8 @@ void findCoincidences(const FeaturePtr theStartCoin, std::set::const_iterator aCIt = aCoincidences.begin(); for (; aCIt != aCoincidences.end(); ++aCIt) { FeaturePtr aConstrFeature = *aCIt; - std::shared_ptr aPnt = getCoincidencePoint(aConstrFeature); - if(aPnt.get() && aOrig->isEqual(aPnt)) { + std::shared_ptr aPnt2d = getCoincidencePoint(aConstrFeature); + if(aPnt2d.get() && aOrig->isEqual(aPnt2d)) { findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A(), theList, theIsAttrOnly); findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B(), @@ -184,26 +204,29 @@ std::set findFeaturesCoincidentToPoint(const AttributePoint2DPtr& th // Useful to find points coincident to a given point. class CoincidentPoints { + static const int THE_DEFAULT_INDEX = -1; + public: - void addCoincidence(const AttributePoint2DPtr& thePoint1, - const AttributePoint2DPtr& thePoint2 = AttributePoint2DPtr()) + void addCoincidence(const AttributePtr& thePoint1, const int theIndex1, + const AttributePtr& thePoint2, const int theIndex2) { - std::list< std::set >::iterator aFound1 = find(thePoint1); - std::list< std::set >::iterator aFound2 = find(thePoint2); + auto aFound1 = find(thePoint1, theIndex1); + auto aFound2 = find(thePoint2, theIndex2); if (aFound1 == myCoincidentPoints.end()) { if (aFound2 == myCoincidentPoints.end()) { - std::set aNewSet; - aNewSet.insert(thePoint1); + std::map > aNewSet; + aNewSet[thePoint1].insert(theIndex1); if (thePoint2) - aNewSet.insert(thePoint2); + aNewSet[thePoint2].insert(theIndex2); myCoincidentPoints.push_back(aNewSet); } else - aFound2->insert(thePoint1); + (*aFound2)[thePoint1].insert(theIndex1); } else if (aFound2 == myCoincidentPoints.end()) { if (thePoint2) - aFound1->insert(thePoint2); + (*aFound1)[thePoint2].insert(theIndex2); } else { - aFound1->insert(aFound2->begin(), aFound2->end()); + for (auto it = aFound2->begin(); it != aFound2->end(); ++it) + (*aFound1)[it->first].insert(it->second.begin(), it->second.end()); myCoincidentPoints.erase(aFound2); } } @@ -212,10 +235,35 @@ public: { collectCoincidentPoints(thePoint); - std::list< std::set >::iterator aFound = find(thePoint); - if (aFound == myCoincidentPoints.end()) - return std::set(); - return *aFound; + std::set aCoincPoints; + auto aFound = find(thePoint, THE_DEFAULT_INDEX); + if (aFound != myCoincidentPoints.end()) { + for (auto it = aFound->begin(); it != aFound->end(); ++it) { + AttributePoint2DPtr aPoint = std::dynamic_pointer_cast(it->first); + if (aPoint) + aCoincPoints.insert(aPoint); + else { + AttributePoint2DArrayPtr aPointArray = + std::dynamic_pointer_cast(it->first); + if (aPointArray) { + // this is a B-spline feature, the connection is possible + // to the first or the last point + FeaturePtr anOwner = ModelAPI_Feature::feature(aPointArray->owner()); + if (it->second.find(0) != it->second.end()) { + AttributePoint2DPtr aFirstPoint = std::dynamic_pointer_cast( + anOwner->attribute(SketchPlugin_BSpline::START_ID())); + aCoincPoints.insert(aFirstPoint); + } + if (it->second.find(aPointArray->size() - 1) != it->second.end()) { + AttributePoint2DPtr aFirstPoint = std::dynamic_pointer_cast( + anOwner->attribute(SketchPlugin_BSpline::END_ID())); + aCoincPoints.insert(aFirstPoint); + } + } + } + } + } + return aCoincPoints; } private: @@ -224,6 +272,11 @@ private: { // iterate through coincideces for the given feature std::set aCoincidences = SketchPlugin_Tools::findCoincidentConstraints(theFeature); + if (theFeature->getKind() == SketchPlugin_Point::ID()) { + std::set aCoincToRes = + SketchPlugin_Tools::findCoincidentConstraints(theFeature->lastResult()); + aCoincidences.insert(aCoincToRes.begin(), aCoincToRes.end()); + } std::set::const_iterator aCIt = aCoincidences.begin(); for (; aCIt != aCoincidences.end(); ++aCIt) { @@ -231,14 +284,20 @@ private: continue; // already processed theCoincidences.insert(*aCIt); // iterate on coincident attributes - for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) { + for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) { AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i)); - if (aRefAttr && !aRefAttr->isObject()) - { - FeaturePtr anOwner = ModelAPI_Feature::feature(aRefAttr->attr()->owner()); - if (anOwner != theFeature) - coincidences(anOwner, theCoincidences); + if (!aRefAttr) + continue; + FeaturePtr anOwner; + if (aRefAttr->isObject()) { + FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object()); + if (aFeature->getKind() == SketchPlugin_Point::ID()) + anOwner = aFeature; } + else + anOwner = ModelAPI_Feature::feature(aRefAttr->attr()->owner()); + if (anOwner && anOwner != theFeature) + coincidences(anOwner, theCoincidences); } } } @@ -247,7 +306,8 @@ private: // (two points may be coincident through the third point) void collectCoincidentPoints(const AttributePoint2DPtr& thePoint) { - AttributePoint2DPtr aPoints[2]; + AttributePtr aPoints[2]; + int anIndicesInArray[2]; FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner()); std::set aCoincidences; @@ -255,30 +315,69 @@ private: std::set::const_iterator aCIt = aCoincidences.begin(); for (; aCIt != aCoincidences.end(); ++aCIt) { - aPoints[0] = AttributePoint2DPtr(); - aPoints[1] = AttributePoint2DPtr(); + aPoints[0] = aPoints[1] = AttributePtr(); + anIndicesInArray[0] = anIndicesInArray[1] = THE_DEFAULT_INDEX; for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) { AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i)); - if (aRefAttr && !aRefAttr->isObject()) - aPoints[aPtInd++] = std::dynamic_pointer_cast(aRefAttr->attr()); + if (!aRefAttr) + continue; + if (aRefAttr->isObject()) { + FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object()); + if (aFeature && aFeature->getKind() == SketchPlugin_Point::ID()) + aPoints[aPtInd++] = aFeature->attribute(SketchPlugin_Point::COORD_ID()); + } + else { + AttributePoint2DPtr aPointAttr = + std::dynamic_pointer_cast(aRefAttr->attr()); + AttributePoint2DArrayPtr aPointArray = + std::dynamic_pointer_cast(aRefAttr->attr()); + if (aPointAttr) + aPoints[aPtInd++] = aPointAttr; + else if (aPointArray) { + AttributeIntegerPtr anIndexAttr = (*aCIt)->integer(i == 0 ? + SketchPlugin_ConstraintCoincidenceInternal::INDEX_ENTITY_A() : + SketchPlugin_ConstraintCoincidenceInternal::INDEX_ENTITY_B()); + aPoints[aPtInd] = aPointArray; + anIndicesInArray[aPtInd++] = anIndexAttr->value(); + } + } } if (aPoints[0] && aPoints[1]) - addCoincidence(aPoints[0], aPoints[1]); + addCoincidence(aPoints[0], anIndicesInArray[0], aPoints[1], anIndicesInArray[1]); } } - std::list< std::set >::iterator find(const AttributePoint2DPtr& thePoint) + std::list< std::map > >::iterator find(const AttributePtr& thePoint, + const int theIndex) { - std::list< std::set >::iterator aSeek = myCoincidentPoints.begin(); - for (; aSeek != myCoincidentPoints.end(); ++aSeek) - if (aSeek->find(thePoint) != aSeek->end()) + auto aSeek = myCoincidentPoints.begin(); + for (; aSeek != myCoincidentPoints.end(); ++aSeek) { + auto aFound = aSeek->find(thePoint); + if (aFound != aSeek->end() && aFound->second.find(theIndex) != aFound->second.end()) return aSeek; + } + // nothing is found, but if the point is a B-spline boundary point, lets check it as poles array + FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner()); + if (anOwner->getKind() == SketchPlugin_BSpline::ID()) { + AttributePtr aPointsArray; + int anIndex = -1; + if (thePoint->id() == SketchPlugin_BSpline::START_ID()) { + aPointsArray = anOwner->attribute(SketchPlugin_BSpline::POLES_ID()); + anIndex = 0; + } + else if (thePoint->id() == SketchPlugin_BSpline::END_ID()) { + aPointsArray = anOwner->attribute(SketchPlugin_BSpline::POLES_ID()); + anIndex = std::dynamic_pointer_cast(aPointsArray)->size() - 1; + } + if (aPointsArray) + return find(aPointsArray, anIndex); + } return myCoincidentPoints.end(); } private: - std::list< std::set > myCoincidentPoints; + std::list< std::map > > myCoincidentPoints; }; std::set findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint) @@ -287,6 +386,7 @@ std::set findPointsCoincidentToPoint(const AttributePoint2D return aCoincidentPoints.coincidentPoints(thePoint); } + void resetAttribute(SketchPlugin_Feature* theFeature, const std::string& theId) { @@ -430,6 +530,69 @@ FeaturePtr createConstraintObjectObject(SketchPlugin_Sketch* theSketch, return aConstraint; } +void createAuxiliaryPointOnEllipse(const FeaturePtr& theEllipseFeature, + const std::string& theEllipsePoint) +{ + SketchPlugin_Sketch* aSketch = + std::dynamic_pointer_cast(theEllipseFeature)->sketch(); + + FeaturePtr aPointFeature = aSketch->addFeature(SketchPlugin_Point::ID()); + aPointFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true); + aPointFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipseFeature); + + AttributePoint2DPtr anElPoint = std::dynamic_pointer_cast( + theEllipseFeature->attribute(theEllipsePoint)); + + AttributePoint2DPtr aCoord = std::dynamic_pointer_cast( + aPointFeature->attribute(SketchPlugin_Point::COORD_ID())); + aCoord->setValue(anElPoint->x(), anElPoint->y()); + + aPointFeature->execute(); + std::wstring aName = theEllipseFeature->name() + L"_" + + Locale::Convert::toWString(theEllipsePoint); + aPointFeature->data()->setName(aName); + aPointFeature->lastResult()->data()->setName(aName); + + createConstraintAttrAttr(aSketch, + SketchPlugin_ConstraintCoincidenceInternal::ID(), anElPoint, aCoord); +} + +void createAuxiliaryAxisOfEllipse(const FeaturePtr& theEllipseFeature, + const std::string& theStartPoint, + const std::string& theEndPoint) +{ + SketchPlugin_Sketch* aSketch = + std::dynamic_pointer_cast(theEllipseFeature)->sketch(); + + FeaturePtr aLineFeature = aSketch->addFeature(SketchPlugin_Line::ID()); + aLineFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true); + aLineFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipseFeature); + + AttributePoint2DPtr aStartPoint = std::dynamic_pointer_cast( + theEllipseFeature->attribute(theStartPoint)); + AttributePoint2DPtr aEndPoint = std::dynamic_pointer_cast( + theEllipseFeature->attribute(theEndPoint)); + + AttributePoint2DPtr aLineStart = std::dynamic_pointer_cast( + aLineFeature->attribute(SketchPlugin_Line::START_ID())); + aLineStart->setValue(aStartPoint->x(), aStartPoint->y()); + + AttributePoint2DPtr aLineEnd = std::dynamic_pointer_cast( + aLineFeature->attribute(SketchPlugin_Line::END_ID())); + aLineEnd->setValue(aEndPoint->x(), aEndPoint->y()); + + aLineFeature->execute(); + std::wstring aName = theEllipseFeature->name() + L"_" + + (theStartPoint == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() ? L"major_axis" : L"minor_axis"); + aLineFeature->data()->setName(aName); + aLineFeature->lastResult()->data()->setName(aName); + + createConstraintAttrAttr(aSketch, + SketchPlugin_ConstraintCoincidenceInternal::ID(), aStartPoint, aLineStart); + createConstraintAttrAttr(aSketch, + SketchPlugin_ConstraintCoincidenceInternal::ID(), aEndPoint, aLineEnd); +} + GeomPnt2dPtr flyoutPointCoordinates(const ConstraintPtr& theConstraint) { // currently process Length constraints only @@ -461,4 +624,468 @@ GeomPnt2dPtr flyoutPointCoordinates(const ConstraintPtr& theConstraint) return GeomPnt2dPtr(new GeomAPI_Pnt2d(X, Y)); } + +void customizeFeaturePrs(const AISObjectPtr& thePrs, bool isAxiliary) +{ + std::vector aColor; + int aWidth = 1; + if (isAxiliary) { + thePrs->setLineStyle(SketchPlugin_SketchEntity::SKETCH_LINE_STYLE_AUXILIARY()); + aColor = Config_PropManager::color("Visualization", "sketch_auxiliary_color"); + aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH_AUXILIARY(); + } + else { + thePrs->setLineStyle(SketchPlugin_SketchEntity::SKETCH_LINE_STYLE()); + aColor = Config_PropManager::color("Visualization", "sketch_entity_color"); + aWidth = Config_PropManager::integer("Visualization", "sketch_line_width"); + } + thePrs->setWidth(aWidth); + thePrs->setColor(aColor[0], aColor[1], aColor[2]); +} + +void setDimensionColor(const AISObjectPtr& theDimPrs) +{ + std::vector aColor = Config_PropManager::color("Visualization", "sketch_dimension_color"); + if (aColor.size() == 3) + theDimPrs->setColor(aColor[0], aColor[1], aColor[2]); +} + +void replaceInName(ObjectPtr theObject, const std::wstring& theSource, const std::wstring& theDest) +{ + std::wstring aName = theObject->data()->name(); + size_t aPos = aName.find(theSource); + if (aPos != std::wstring::npos) { + std::wstring aNewName = aName.substr(0, aPos) + theDest + + aName.substr(aPos + theSource.size()); + theObject->data()->setName(aNewName); + } +} + } // namespace SketchPlugin_Tools + + +// ================================================================================================= +// namespace SketchPlugin_SegmentationTools +// ================================================================================================= + +void SketchPlugin_SegmentationTools::getFeaturePoints(const FeaturePtr& theFeature, + AttributePoint2DPtr& theStartPointAttr, + AttributePoint2DPtr& theEndPointAttr) +{ + 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(); + } + else if (aFeatureKind == SketchPlugin_EllipticArc::ID()) { + aStartAttributeName = SketchPlugin_EllipticArc::START_POINT_ID(); + anEndAttributeName = SketchPlugin_EllipticArc::END_POINT_ID(); + } + else if (aFeatureKind == SketchPlugin_BSpline::ID()) { + aStartAttributeName = SketchPlugin_BSpline::START_ID(); + anEndAttributeName = SketchPlugin_BSpline::END_ID(); + } + if (!aStartAttributeName.empty() && !anEndAttributeName.empty()) { + theStartPointAttr = std::dynamic_pointer_cast( + theFeature->attribute(aStartAttributeName)); + theEndPointAttr = std::dynamic_pointer_cast( + theFeature->attribute(anEndAttributeName)); + } +} + + +void SketchPlugin_SegmentationTools::getRefAttributes( + const FeaturePtr& theFeature, + std::map >& theRefs, + std::list& theRefsToFeature) +{ + theRefs.clear(); + + std::list aPointAttributes = + theFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); + std::set aPointAttributesSet; + + std::list::const_iterator aPIt = + aPointAttributes.begin(), aPLast = aPointAttributes.end(); + for (; aPIt != aPLast; aPIt++) + aPointAttributesSet.insert(*aPIt); + + std::set aRefsAttributes = theFeature->lastResult()->data()->refsToMe(); + std::set aFRefsList = theFeature->data()->refsToMe(); + aRefsAttributes.insert(aFRefsList.begin(), aFRefsList.end()); + + std::set::const_iterator aIt; + for (aIt = aRefsAttributes.cbegin(); aIt != aRefsAttributes.cend(); ++aIt) { + AttributePtr anAttr = (*aIt); + FeaturePtr anAttrFeature = ModelAPI_Feature::feature(anAttr->owner()); + if (!anAttrFeature->isMacro() && // <- skip reference from Trim or Split feature + 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); + } + } + } +} + +GeomShapePtr SketchPlugin_SegmentationTools::getSubShape( + SketchPlugin_Feature* theFeature, + const std::string& theObjectAttributeId, + const std::string& thePointAttributeId, + std::map >& theCashedShapes, + std::map& theObjectToPoints) +{ + GeomShapePtr aBaseShape; + + AttributeReferencePtr anObjectAttr = theFeature->reference(theObjectAttributeId); + ObjectPtr aBaseObject = anObjectAttr->value(); + if (!aBaseObject.get()) + return aBaseShape; + + // point on feature + AttributePoint2DPtr aPointAttr = + std::dynamic_pointer_cast(theFeature->attribute(thePointAttributeId)); + std::shared_ptr anAttributePnt2d = aPointAttr->pnt(); + std::shared_ptr anAttributePnt = + theFeature->sketch()->to3D(anAttributePnt2d->x(), anAttributePnt2d->y()); + + if (theCashedShapes.find(aBaseObject) == theCashedShapes.end()) + fillObjectShapes(theFeature, aBaseObject, theCashedShapes, theObjectToPoints); + + std::shared_ptr aStartPoint; + std::shared_ptr aSecondPoint; + const std::set& aShapes = theCashedShapes[aBaseObject]; + std::set::const_iterator anIt = aShapes.begin(), aLast = aShapes.end(); + for (; anIt != aLast; anIt++) { + GeomShapePtr aCurrentShape = *anIt; + std::shared_ptr aProjectedPoint; + if (ModelGeomAlgo_Point2D::isPointOnEdge(aCurrentShape, anAttributePnt, aProjectedPoint)) { + if (theFeature->getKind() == SketchPlugin_Split::ID()) { + // for Split operation collect start and end points of the shape + if (aCurrentShape->shapeType() == GeomAPI_Shape::EDGE) { + std::shared_ptr anEdge(new GeomAPI_Edge(aCurrentShape)); + aStartPoint = anEdge->firstPoint(); + aSecondPoint = anEdge->lastPoint(); + } + } + else + aBaseShape = aCurrentShape; + break; + } + } + + if (!aStartPoint.get() || !aSecondPoint.get()) + return aBaseShape; + + FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObject); + if (anObjectAttr->isInitialized() && aBaseFeature.get() && aPointAttr->isInitialized()) { + ResultPtr aResult = aBaseFeature->lastResult(); + GeomShapePtr aResultShape = aResult->shape(); + std::list > aPoints; + + aPoints.push_back(aStartPoint); + aPoints.push_back(aSecondPoint); + + std::set > aSplitShapes; + GeomAlgoAPI_ShapeTools::splitShape_p(aResultShape, aPoints, aSplitShapes); + aBaseShape = GeomAlgoAPI_ShapeTools::findShape(aPoints, aSplitShapes); + } + return aBaseShape; +} + +void SketchPlugin_SegmentationTools::fillObjectShapes( + SketchPlugin_Feature* theOpFeature, + const ObjectPtr& theObject, + std::map >& theCashedShapes, + std::map& theObjectToPoints) +{ + SketchPlugin_Sketch* aSketch = theOpFeature->sketch(); + + GeomAlgoAPI_ShapeTools::PointToRefsMap aPoints; + std::set aShapes; + + std::set aRefAttributes; + // current feature + FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); + std::set anEdgeShapes; + // edges on feature + ModelGeomAlgo_Shape::shapesOfType(aFeature, GeomAPI_Shape::EDGE, anEdgeShapes); + if (!anEdgeShapes.empty()) { + GeomShapePtr aFeatureShape = (*anEdgeShapes.begin())->shape(); + + // coincidences to the feature + ModelGeomAlgo_Point2D::getPointsOfReference(aFeature, SketchPlugin_ConstraintCoincidence::ID(), + aRefAttributes, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID()); + // layed on feature coincidences to divide it on several shapes + 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, aPoints); + + if (theOpFeature->getKind() == SketchPlugin_Trim::ID()) { + // collect all intersection points with other edges for Trim operation only + std::list aFeatures; + for (int i = 0; i < aSketch->numberOfSubs(); i++) { + FeaturePtr aSubFeature = aSketch->subFeature(i); + if (aSubFeature.get() && aSubFeature->getKind() != SketchPlugin_Projection::ID()) + aFeatures.push_back(aSubFeature); + } + ModelGeomAlgo_Point2D::getPointsIntersectedShape(aFeature, aFeatures, aPoints); + } + + if (!aPoints.empty()) + GeomAlgoAPI_ShapeTools::splitShape(aFeatureShape, aPoints, aShapes); + } + theObjectToPoints[theObject] = aPoints; + theCashedShapes[theObject] = aShapes; +} + +void SketchPlugin_SegmentationTools::updateRefAttConstraints( + const std::map >& theBaseRefAttributes, + const std::set >& theModifiedAttributes) +{ +#if defined DEBUG_SPLIT || defined DEBUG_TRIM + std::cout << "updateRefAttConstraints" << std::endl; +#endif + + std::set >::const_iterator + anIt = theModifiedAttributes.begin(), aLast = theModifiedAttributes.end(); + for (; anIt != aLast; anIt++) { + AttributePtr anAttribute = anIt->first; + AttributePtr aNewAttribute = anIt->second; + + // not found in references + if (!aNewAttribute.get() || + theBaseRefAttributes.find(anAttribute) == theBaseRefAttributes.end()) + continue; + std::list aRefAttributes = theBaseRefAttributes.at(anAttribute); + std::list::const_iterator aRefIt = aRefAttributes.begin(), + aRLast = aRefAttributes.end(); + + for (; aRefIt != aRLast; aRefIt++) { + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(*aRefIt); + if (aRefAttr.get()) { + aRefAttr->setAttr(aNewAttribute); +#ifdef DEBUG_SPLIT + FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->owner()); + std::cout << " -" << getFeatureInfo(aFeature) << std::endl; +#endif + } + } + } +} + +void SketchPlugin_SegmentationTools::updateFeaturesAfterOperation( + const std::set& theFeaturesToUpdate) +{ + std::set::const_iterator anIt = theFeaturesToUpdate.begin(), + aLast = theFeaturesToUpdate.end(); + for (; anIt != aLast; anIt++) { + FeaturePtr aRefFeature = std::dynamic_pointer_cast(*anIt); + std::string aRefFeatureKind = aRefFeature->getKind(); + if (aRefFeatureKind == SketchPlugin_ConstraintLength::ID()) { + std::shared_ptr aLenghtFeature = + std::dynamic_pointer_cast(*anIt); + if (aLenghtFeature.get()) { + std::shared_ptr aValueAttr = std::dynamic_pointer_cast< + ModelAPI_AttributeDouble>(aLenghtFeature->attribute(SketchPlugin_Constraint::VALUE())); + double aValue; + if (aLenghtFeature->computeLenghtValue(aValue) && aValueAttr.get()) + aValueAttr->setValue(aValue); + } + } + } +} + +AISObjectPtr SketchPlugin_SegmentationTools::getAISObject( + AISObjectPtr thePrevious, + SketchPlugin_Feature* theOpFeature, + const std::string& thePreviewObjectAttrName, + const std::string& thePreviewPointAttrName, + const std::string& theSelectedObjectAttrName, + const std::string& theSelectedPointAttrName) +{ +#if defined DEBUG_SPLIT || defined DEBUG_TRIM_METHODS + std::cout << "getAISObject: " << theOpFeature->data()->name() << std::endl; +#endif + + AISObjectPtr anAIS = thePrevious; + + std::list > aShapes; + std::map > aCashedShapes; + std::map aObjectToPoints; + GeomShapePtr aPreviewShape = getSubShape(theOpFeature, + thePreviewObjectAttrName, thePreviewPointAttrName, aCashedShapes, aObjectToPoints); + if (aPreviewShape.get()) + aShapes.push_back(aPreviewShape); + GeomShapePtr aSelectedShape = getSubShape(theOpFeature, + theSelectedObjectAttrName, theSelectedPointAttrName, aCashedShapes, aObjectToPoints); + if (aSelectedShape.get()) + aShapes.push_back(aSelectedShape); + + if (aShapes.empty()) + return AISObjectPtr(); + + GeomShapePtr aBaseShape = GeomAlgoAPI_CompoundBuilder::compound(aShapes); + if (!aBaseShape.get()) + return AISObjectPtr(); + + if (aBaseShape.get()) { + if (!anAIS) + anAIS = AISObjectPtr(new GeomAPI_AISObject); + anAIS->createShape(aBaseShape); + + std::vector aColor; + aColor = Config_PropManager::color("Visualization", "operation_remove_feature_color"); + double aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH(); + int aLineStyle = SketchPlugin_SketchEntity::SKETCH_LINE_STYLE(); + anAIS->setColor(aColor[0], aColor[1], aColor[2]); + // width when there is not base object should be extened in several points + // in order to see this preview over highlight + anAIS->setWidth(aWidth+4); + anAIS->setLineStyle(aLineStyle); + } + else + anAIS = AISObjectPtr(); + return anAIS; +} + +#define GEOM_DATA_POINT2D(f, a) std::dynamic_pointer_cast((f)->attribute(a)) + +FeaturePtr SketchPlugin_SegmentationTools::createLineFeature( + const FeaturePtr& theBaseFeature, + const std::shared_ptr& theFirstPoint, + const std::shared_ptr& theSecondPoint) +{ + FeaturePtr aFeature; + std::shared_ptr aSketchFeature = + std::dynamic_pointer_cast(theBaseFeature); + SketchPlugin_Sketch* aSketch = aSketchFeature->sketch(); + if (!aSketch || !theBaseFeature.get()) + return aFeature; + + aFeature = aSketch->addFeature(SketchPlugin_Line::ID()); + + GEOM_DATA_POINT2D(aFeature, SketchPlugin_Line::START_ID())->setValue(theFirstPoint); + GEOM_DATA_POINT2D(aFeature, SketchPlugin_Line::END_ID())->setValue(theSecondPoint); + + aFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue( + theBaseFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value()); + aFeature->execute(); // to obtain result + + return aFeature; +} + +struct ArcAttributes +{ + std::string myKind; + std::string myCenter; + std::string myFocus; + std::string myStart; + std::string myEnd; + std::string myReversed; + + ArcAttributes() {} + + ArcAttributes(const std::string& theKind) : myKind(theKind) + { + if (myKind == SketchPlugin_Arc::ID()) { + myCenter = SketchPlugin_Arc::CENTER_ID(); + myStart = SketchPlugin_Arc::START_ID(); + myEnd = SketchPlugin_Arc::END_ID(); + myReversed = SketchPlugin_Arc::REVERSED_ID(); + } + else if (myKind == SketchPlugin_Circle::ID()) { + myCenter = SketchPlugin_Circle::CENTER_ID(); + } + else if (myKind == SketchPlugin_Ellipse::ID()) { + myCenter = SketchPlugin_Ellipse::CENTER_ID(); + myFocus = SketchPlugin_Ellipse::FIRST_FOCUS_ID(); + } + else if (myKind == SketchPlugin_EllipticArc::ID()) { + myCenter = SketchPlugin_EllipticArc::CENTER_ID(); + myFocus = SketchPlugin_EllipticArc::FIRST_FOCUS_ID(); + myStart = SketchPlugin_EllipticArc::START_POINT_ID(); + myEnd = SketchPlugin_EllipticArc::END_POINT_ID(); + myReversed = SketchPlugin_EllipticArc::REVERSED_ID(); + } + } +}; + +FeaturePtr SketchPlugin_SegmentationTools::createArcFeature( + const FeaturePtr& theBaseFeature, + const std::shared_ptr& theFirstPoint, + const std::shared_ptr& theSecondPoint) +{ + FeaturePtr aFeature; + std::shared_ptr aSketchFeature = + std::dynamic_pointer_cast(theBaseFeature); + SketchPlugin_Sketch* aSketch = aSketchFeature->sketch(); + if (!aSketch || !theBaseFeature.get()) + return aFeature; + + ArcAttributes aBaseAttrs(theBaseFeature->getKind()); + ArcAttributes aTargetAttrs; + if (aBaseAttrs.myKind == SketchPlugin_Arc::ID() || + aBaseAttrs.myKind == SketchPlugin_Circle::ID()) + aTargetAttrs = ArcAttributes(SketchPlugin_Arc::ID()); + else if (aBaseAttrs.myKind == SketchPlugin_Ellipse::ID() || + aBaseAttrs.myKind == SketchPlugin_EllipticArc::ID()) + aTargetAttrs = ArcAttributes(SketchPlugin_EllipticArc::ID()); + + if (aTargetAttrs.myKind.empty()) + return aFeature; + + aFeature = aSketch->addFeature(aTargetAttrs.myKind); + // 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); + + GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myCenter)->setValue( + GEOM_DATA_POINT2D(theBaseFeature, aBaseAttrs.myCenter)->pnt()); + if (!aTargetAttrs.myFocus.empty()) { + GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myFocus)->setValue( + GEOM_DATA_POINT2D(theBaseFeature, aBaseAttrs.myFocus)->pnt()); + } + GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myStart)->setValue(theFirstPoint); + GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myEnd)->setValue(theSecondPoint); + + aFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue( + theBaseFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value()); + + /// fill referersed state of created arc as it is on the base arc + bool aReversed = aBaseAttrs.myReversed.empty() ? false : + theBaseFeature->boolean(aBaseAttrs.myReversed)->value(); + aFeature->boolean(aTargetAttrs.myReversed)->setValue(aReversed); + + aFeature->execute(); // to obtain result (need to calculate arc parameters before sending Update) + aFeature->data()->blockSendAttributeUpdated(aWasBlocked); + + return aFeature; +}