From 5716015fe7c4240cec04bd64bef46192af53db1d Mon Sep 17 00:00:00 2001 From: mpv Date: Wed, 18 Jan 2017 16:03:01 +0300 Subject: [PATCH] Additional fix for the issue #1876 : now compsolid result is also splitted when selection list requires solids. --- src/GeomAPI/GeomAPI_Angle.cpp | 140 ------------------------- src/GeomAPI/GeomAPI_Angle.h | 56 ---------- src/Model/Model_AttributeSelection.cpp | 64 +++++++---- src/Model/Model_AttributeSelection.h | 4 + 4 files changed, 46 insertions(+), 218 deletions(-) delete mode 100644 src/GeomAPI/GeomAPI_Angle.cpp delete mode 100644 src/GeomAPI/GeomAPI_Angle.h diff --git a/src/GeomAPI/GeomAPI_Angle.cpp b/src/GeomAPI/GeomAPI_Angle.cpp deleted file mode 100644 index 9849b9e9d..000000000 --- a/src/GeomAPI/GeomAPI_Angle.cpp +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (C) 2016-20xx CEA/DEN, EDF R&D - -// File: GeomAPI_Angle.cpp -// Created: 19 April 2016 -// Author: Artem ZHIDKOV - -#include -#include -#include -#include -#include - -#include -#include -#include - -/// \struct ThreePoints -/// \brief Used to store info about angle point and state. -struct ThreePoints { - gp_Pnt myCenter; - gp_Pnt myFirst; - gp_Pnt mySecond; - bool myReversed[2]; -}; - -#define MY_ANGLE implPtr() -#define PI 3.1415926535897932 - -static ThreePoints* newAngle(const std::shared_ptr& theCenter, - const std::shared_ptr& theFirst, - const std::shared_ptr& theSecond) -{ - ThreePoints* aResult = new ThreePoints; - aResult->myCenter = gp_Pnt(theCenter->x(), theCenter->y(), theCenter->z()); - aResult->myFirst = gp_Pnt(theFirst->x(), theFirst->y(), theFirst->z()); - aResult->mySecond = gp_Pnt(theSecond->x(), theSecond->y(), theSecond->z()); - aResult->myReversed[0] = aResult->myReversed[1] = false; - return aResult; -} - -static ThreePoints* newAngle(const std::shared_ptr& theStart1, - const std::shared_ptr& theEnd1, - const std::shared_ptr& theStart2, - const std::shared_ptr& theEnd2) -{ - std::shared_ptr aLine1(new GeomAPI_Lin(theStart1, theEnd1)); - std::shared_ptr aLine2(new GeomAPI_Lin(theStart2, theEnd2)); - std::shared_ptr aCenter = aLine1->intersect(aLine2); - bool isParallel = !aCenter; - if (isParallel) - aCenter = theStart1; - std::shared_ptr aPoint1, aPoint2; - if (isParallel) - aPoint1 = aPoint2 = theEnd1; - else { - aPoint1 = theStart1->distance(aCenter) < theEnd1->distance(aCenter) ? theEnd1 : theStart1; - aPoint2 = theStart2->distance(aCenter) < theEnd2->distance(aCenter) ? theEnd2 : theStart2; - } - ThreePoints* anAngle = newAngle(aCenter, aPoint1, aPoint2); - anAngle->myReversed[0] = aPoint1 == theStart1; - anAngle->myReversed[1] = !isParallel && aPoint2 == theStart2; - return anAngle; -} - -static ThreePoints* newAngle(const std::shared_ptr& theLine1, bool theReversed1, - const std::shared_ptr& theLine2, bool theReversed2) -{ - std::shared_ptr aCenter = theLine1->intersect(theLine2); - if (!aCenter) - aCenter = theLine1->location(); - double aCoeff = theReversed1 ? -1.0 : 1.0; - std::shared_ptr aPoint1(new GeomAPI_Pnt( - aCenter->xyz()->added(theLine1->direction()->xyz()->multiplied(aCoeff)))); - aCoeff = theReversed2 ? -1.0 : 1.0; - std::shared_ptr aPoint2(new GeomAPI_Pnt( - aCenter->xyz()->added(theLine2->direction()->xyz()->multiplied(aCoeff)))); - ThreePoints* anAngle = newAngle(aCenter, aPoint1, aPoint2); - anAngle->myReversed[0] = theReversed1; - anAngle->myReversed[1] = theReversed2; - return anAngle; -} - - - -GeomAPI_Angle::GeomAPI_Angle(const std::shared_ptr& theStartLine1, - const std::shared_ptr& theEndLine1, - const std::shared_ptr& theStartLine2, - const std::shared_ptr& theEndLine2) - : GeomAPI_Interface(newAngle(theStartLine1, theEndLine1, theStartLine2, theEndLine2)) -{ -} - -GeomAPI_Angle::GeomAPI_Angle(const std::shared_ptr& theLine1, bool theReversed1, - const std::shared_ptr& theLine2, bool theReversed2) - : GeomAPI_Interface(newAngle(theLine1, theReversed1, theLine2, theReversed2)) -{ -} - -GeomAPI_Angle::GeomAPI_Angle(const std::shared_ptr& theCenter, - const std::shared_ptr& thePoint1, - const std::shared_ptr& thePoint2) - : GeomAPI_Interface(newAngle(theCenter, thePoint1, thePoint2)) -{ -} - -std::shared_ptr GeomAPI_Angle::center() -{ - gp_Pnt aPnt = MY_ANGLE->myCenter; - return std::shared_ptr(new GeomAPI_Pnt(aPnt.X(), aPnt.Y(), aPnt.Z())); -} - -std::shared_ptr GeomAPI_Angle::firstPoint() -{ - gp_Pnt aPnt = MY_ANGLE->myFirst; - return std::shared_ptr(new GeomAPI_Pnt(aPnt.X(), aPnt.Y(), aPnt.Z())); -} - -std::shared_ptr GeomAPI_Angle::secondPoint() -{ - gp_Pnt aPnt = MY_ANGLE->mySecond; - return std::shared_ptr(new GeomAPI_Pnt(aPnt.X(), aPnt.Y(), aPnt.Z())); -} - -double GeomAPI_Angle::angleDegree() -{ - return angleRadian() * 180.0 / PI; -} - -double GeomAPI_Angle::angleRadian() -{ - ThreePoints* anAngle = MY_ANGLE; - gp_Dir aDir1(anAngle->myFirst.XYZ() - anAngle->myCenter.XYZ()); - gp_Dir aDir2(anAngle->mySecond.XYZ() - anAngle->myCenter.XYZ()); - return aDir1.Angle(aDir2); -} - -bool GeomAPI_Angle::isReversed(int theIndex) -{ - return MY_ANGLE->myReversed[theIndex & 0x1]; -} diff --git a/src/GeomAPI/GeomAPI_Angle.h b/src/GeomAPI/GeomAPI_Angle.h deleted file mode 100644 index 8d8743351..000000000 --- a/src/GeomAPI/GeomAPI_Angle.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (C) 2016-20xx CEA/DEN, EDF R&D - -// File: GeomAPI_Angle.h -// Created: 19 April 2016 -// Author: Artem ZHIDKOV - -#ifndef GeomAPI_Angle_H_ -#define GeomAPI_Angle_H_ - -#include - -class GeomAPI_Lin; -class GeomAPI_Pnt; - -/// \class GeomAPI_Angle -/// \ingroup DataModel -/// \brief Build an angle in 3D -class GeomAPI_Angle : public GeomAPI_Interface -{ -public: - /// Creation of an angle defined by two lines' start, end points - GEOMAPI_EXPORT - GeomAPI_Angle(const std::shared_ptr& theStartLine1, - const std::shared_ptr& theEndLine1, - const std::shared_ptr& theStartLine2, - const std::shared_ptr& theEndLine2); - /// Creation of an angle defined by two lines taking into account their orientation - GEOMAPI_EXPORT - GeomAPI_Angle(const std::shared_ptr& theLine1, bool theReversed1, - const std::shared_ptr& theLine2, bool theReversed2); - /// Creation of an angle defined by three points - GEOMAPI_EXPORT - GeomAPI_Angle(const std::shared_ptr& theCenter, - const std::shared_ptr& thePoint1, - const std::shared_ptr& thePoint2); - - /// Returns central point of the angle - GEOMAPI_EXPORT std::shared_ptr center(); - /// Returns point on the first edge - GEOMAPI_EXPORT std::shared_ptr firstPoint(); - /// Returns point on the second edge - GEOMAPI_EXPORT std::shared_ptr secondPoint(); - - /// Returns value of the angle in degrees - GEOMAPI_EXPORT double angleDegree(); - /// Returns value of the angle in radians - GEOMAPI_EXPORT double angleRadian(); - - /// Returns \c true if the line is reversed during angle calculation. - /// If theIndex = 0, the result corresponds to the first line, - /// if theIndex = 1, the to the second line - GEOMAPI_EXPORT bool isReversed(int theIndex); -}; - -#endif - diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index 8fc2d5e77..af701cb26 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -399,6 +399,32 @@ static bool setInvalidIfFalse(TDF_Label& theLab, const bool theFlag) { return theFlag; } +void Model_AttributeSelection::split( + ResultPtr theContext, TopoDS_Shape theNewShape, TopAbs_ShapeEnum theType) +{ + TopTools_ListOfShape aSubs; + for(TopoDS_Iterator anExplorer(theNewShape); anExplorer.More(); anExplorer.Next()) { + if (!anExplorer.Value().IsNull() && + anExplorer.Value().ShapeType() == theType) { + aSubs.Append(anExplorer.Value()); + } else { // invalid case; bad result shape, so, impossible to split easily + aSubs.Clear(); + break; + } + } + if (aSubs.Extent() > 1) { // ok to split + TopTools_ListIteratorOfListOfShape aSub(aSubs); + GeomShapePtr aSubSh(new GeomAPI_Shape); + aSubSh->setImpl(new TopoDS_Shape(aSub.Value())); + setValue(theContext, aSubSh); + for(aSub.Next(); aSub.More(); aSub.Next()) { + GeomShapePtr aSubSh(new GeomAPI_Shape); + aSubSh->setImpl(new TopoDS_Shape(aSub.Value())); + myParent->append(theContext, aSubSh); + } + } +} + bool Model_AttributeSelection::update() { TDF_Label aSelLab = selectionLabel(); @@ -464,28 +490,9 @@ bool Model_AttributeSelection::update() // shape type shoud not not changed: if shape becomes compound of such shapes, then split if (myParent && !anOldShape.IsNull() && !aNewShape.IsNull() && anOldShape.ShapeType() != aNewShape.ShapeType() && - aNewShape.ShapeType() == TopAbs_COMPOUND) { - TopTools_ListOfShape aSubs; - for(TopoDS_Iterator anExplorer(aNewShape); anExplorer.More(); anExplorer.Next()) { - if (!anExplorer.Value().IsNull() && - anExplorer.Value().ShapeType() == anOldShape.ShapeType()) { - aSubs.Append(anExplorer.Value()); - } else { // invalid case; bad result shape, so, impossible to split easily - aSubs.Clear(); - break; - } - } - if (aSubs.Extent() > 1) { // ok to split - TopTools_ListIteratorOfListOfShape aSub(aSubs); - GeomShapePtr aSubSh(new GeomAPI_Shape); - aSubSh->setImpl(new TopoDS_Shape(aSub.Value())); - setValue(aContext, aSubSh); - for(aSub.Next(); aSub.More(); aSub.Next()) { - GeomShapePtr aSubSh(new GeomAPI_Shape); - aSubSh->setImpl(new TopoDS_Shape(aSub.Value())); - myParent->append(aContext, aSubSh); - } - } + (aNewShape.ShapeType() == TopAbs_COMPOUND || aNewShape.ShapeType() == TopAbs_COMPSOLID)) + { + split(aContext, aNewShape, anOldShape.ShapeType()); } owner()->data()->sendAttributeUpdated(this); // send updated if shape is changed } @@ -1202,6 +1209,19 @@ void Model_AttributeSelection::updateInHistory() // update scope to reset to a new one myScope.Clear(); myRef.setValue(aModifierResFound); + // if context shape type is changed to more complicated and this context is selected, split + if (myParent &&!aSubShape.get() && aModifierResFound->shape().get() && aContext->shape().get()) + { + TopoDS_Shape anOldShape = aContext->shape()->impl(); + TopoDS_Shape aNewShape = aModifierResFound->shape()->impl(); + if (!anOldShape.IsNull() && !aNewShape.IsNull() && + anOldShape.ShapeType() != aNewShape.ShapeType() && + (aNewShape.ShapeType() == TopAbs_COMPOUND || aNewShape.ShapeType() == TopAbs_COMPSOLID)) { + // prepare for split in "update" + TDF_Label aSelLab = selectionLabel(); + split(aContext, aNewShape, anOldShape.ShapeType()); + } + } update(); // it must recompute a new sub-shape automatically } } diff --git a/src/Model/Model_AttributeSelection.h b/src/Model/Model_AttributeSelection.h index a24ca2d81..93fb9876e 100644 --- a/src/Model/Model_AttributeSelection.h +++ b/src/Model/Model_AttributeSelection.h @@ -11,6 +11,7 @@ #include "Model_AttributeReference.h" #include #include +#include class Model_AttributeSelectionList; @@ -121,6 +122,9 @@ protected: /// Sets the parent attribute void setParent(Model_AttributeSelectionList* theParent); + /// Splits theNewShape into sub-shapes of theType type (for the list parent of this attribute) + void split(ResultPtr theContext, TopoDS_Shape theNewShape, TopAbs_ShapeEnum theType); + friend class Model_Data; friend class Model_AttributeSelectionList; }; -- 2.39.2