From f479bb051a5acfc6315e478b3263160e910952fc Mon Sep 17 00:00:00 2001 From: dbv Date: Tue, 17 Nov 2015 17:22:54 +0300 Subject: [PATCH] Default fillet radius modification. --- src/GeomAPI/GeomAPI_Circ2d.cpp | 19 +++ src/GeomAPI/GeomAPI_Circ2d.h | 21 +++ src/SketchPlugin/SketchPlugin_Arc.cpp | 6 - src/SketchPlugin/SketchPlugin_Arc.h | 7 + .../SketchPlugin_ConstraintFillet.cpp | 137 ++++++++++++++---- 5 files changed, 152 insertions(+), 38 deletions(-) diff --git a/src/GeomAPI/GeomAPI_Circ2d.cpp b/src/GeomAPI/GeomAPI_Circ2d.cpp index 0e0a21a31..c809e567e 100644 --- a/src/GeomAPI/GeomAPI_Circ2d.cpp +++ b/src/GeomAPI/GeomAPI_Circ2d.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -97,3 +98,21 @@ double GeomAPI_Circ2d::radius() const return MY_CIRC2D->Radius(); } +//================================================================================================= +const bool GeomAPI_Circ2d::parameter(const std::shared_ptr thePoint, + const double theTolerance, + double& theParameter) const +{ + Handle(Geom2d_Circle) aCurve = new Geom2d_Circle(*MY_CIRC2D); + return GeomLib_Tool::Parameter(aCurve, thePoint->impl(), theTolerance, theParameter) == Standard_True; +} + +//================================================================================================= +void GeomAPI_Circ2d::D0(const double theU, std::shared_ptr& thePoint) +{ + Handle(Geom2d_Circle) aCurve = new Geom2d_Circle(*MY_CIRC2D); + gp_Pnt2d aPnt; + aCurve->D0(theU, aPnt); + thePoint.reset(new GeomAPI_Pnt2d(aPnt.X(), aPnt.Y())); +} + diff --git a/src/GeomAPI/GeomAPI_Circ2d.h b/src/GeomAPI/GeomAPI_Circ2d.h index 1226a5f78..478c9986a 100644 --- a/src/GeomAPI/GeomAPI_Circ2d.h +++ b/src/GeomAPI/GeomAPI_Circ2d.h @@ -43,6 +43,27 @@ class GeomAPI_Circ2d : public GeomAPI_Interface GEOMAPI_EXPORT const std::shared_ptr project( const std::shared_ptr& thePoint) const; + + /** \brief Computes the parameter of a given point on a circle. The point must be + * located either on the circle itself or relatively to the latter + * at a distance less than the tolerance value. Return FALSE if the point + * is beyond the tolerance limit or if computation fails. + * Max Tolerance value is currently limited to 1.e-4 + * \param[in] thePoint point of origin. + * \param[in] theTolerance tolerance of computation. + * \param[out] theParameter resulting parameter. + */ + GEOMAPI_EXPORT const bool parameter(const std::shared_ptr thePoint, + const double theTolerance, + double& theParameter) const; + + /** \brief Returns in thePoint the point of parameter theU. + * P = C + R * Cos (U) * XDir + R * Sin (U) * YDir where C is the center of the circle, + * XDir the XDirection and YDir the YDirection of the circle's local coordinate system. + * \param[in] theU parameter. + * \param[out] thePoint resulting point. + */ + GEOMAPI_EXPORT void D0(const double theU, std::shared_ptr& thePoint); }; #endif diff --git a/src/SketchPlugin/SketchPlugin_Arc.cpp b/src/SketchPlugin/SketchPlugin_Arc.cpp index 6c8d15b96..e1de89560 100644 --- a/src/SketchPlugin/SketchPlugin_Arc.cpp +++ b/src/SketchPlugin/SketchPlugin_Arc.cpp @@ -29,12 +29,6 @@ const double paramTolerance = 1.e-4; const double PI =3.141592653589793238463; -static const std::string& INVERSED_ID() -{ - static const std::string MY_INVERSED_ID("InversedArc"); - return MY_INVERSED_ID; -} - SketchPlugin_Arc::SketchPlugin_Arc() : SketchPlugin_SketchEntity() { diff --git a/src/SketchPlugin/SketchPlugin_Arc.h b/src/SketchPlugin/SketchPlugin_Arc.h index 121f34916..789d6076a 100644 --- a/src/SketchPlugin/SketchPlugin_Arc.h +++ b/src/SketchPlugin/SketchPlugin_Arc.h @@ -57,6 +57,13 @@ class SketchPlugin_Arc : public SketchPlugin_SketchEntity, public GeomAPI_IPrese return MY_END_ID; } + /// Inversed flag + inline static const std::string& INVERSED_ID() + { + static const std::string MY_INVERSED_ID("InversedArc"); + return MY_INVERSED_ID; + } + /// Returns the kind of a feature SKETCHPLUGIN_EXPORT virtual const std::string& getKind() { diff --git a/src/SketchPlugin/SketchPlugin_ConstraintFillet.cpp b/src/SketchPlugin/SketchPlugin_ConstraintFillet.cpp index 75f1370ca..4a49c2e4b 100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintFillet.cpp +++ b/src/SketchPlugin/SketchPlugin_ConstraintFillet.cpp @@ -6,7 +6,9 @@ #include "SketchPlugin_ConstraintFillet.h" +#include #include +#include #include #include #include @@ -38,6 +40,9 @@ static const std::string PREVIOUS_VALUE("FilletPreviousRadius"); +const double tolerance = 1.e-7; +const double paramTolerance = 1.e-4; + /// \brief Attract specified point on theNewArc to the attribute of theFeature static void recalculateAttributes(FeaturePtr theNewArc, const std::string& theNewArcAttribute, FeaturePtr theFeature, const std::string& theFeatureAttribute); @@ -49,6 +54,15 @@ static void calculateFilletCenter(FeaturePtr theFeatureA, FeaturePtr theFeatureB std::shared_ptr& theTangentA, std::shared_ptr& theTangentB); +/// Get point on 1/3 length of edge from fillet point +static void getPointOnEdge(const FeaturePtr theFeature, + const std::shared_ptr theFilletPoint, + std::shared_ptr& thePoint); + +/// Get distance from point to feature +static double getProjectionDistance(const FeaturePtr theFeature, + const std::shared_ptr thePoint); + SketchPlugin_ConstraintFillet::SketchPlugin_ConstraintFillet() { } @@ -403,14 +417,21 @@ void SketchPlugin_ConstraintFillet::attributeChanged(const std::string& theID) (*aCIt)->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(false); myBaseObjects.clear(); + // Obtain fillet point AttributeRefAttrPtr aBaseA = std::dynamic_pointer_cast( data()->attribute(SketchPlugin_Constraint::ENTITY_A())); if(!aBaseA->isInitialized() || aBaseA->isObject()) { return; } + AttributePtr anAttrBaseA = aBaseA->attr(); + std::shared_ptr aBasePoint = std::dynamic_pointer_cast(anAttrBaseA); + if (!aBasePoint) { + return; + } + std::shared_ptr aFilletPoint = aBasePoint->pnt(); - AttributePtr anAttrBase = aBaseA->attr(); - const std::set& aRefsList = anAttrBase->owner()->data()->refsToMe(); + // Obtain conicident edges + const std::set& aRefsList = anAttrBaseA->owner()->data()->refsToMe(); std::set::const_iterator aIt; FeaturePtr aCoincident; for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) { @@ -423,14 +444,14 @@ void SketchPlugin_ConstraintFillet::attributeChanged(const std::string& theID) aConstrFeature->attribute(SketchPlugin_ConstraintCoincidence::ENTITY_B())); if(anAttrRefA.get() && !anAttrRefA->isObject()) { AttributePtr anAttrA = anAttrRefA->attr(); - if(anAttrBase == anAttrA) { + if(anAttrBaseA == anAttrA) { aCoincident = aConstrFeature; break; } } if(anAttrRefA.get() && !anAttrRefB->isObject()) { AttributePtr anAttrB = anAttrRefB->attr(); - if(anAttrBase == anAttrB) { + if(anAttrBaseA == anAttrB) { aCoincident = aConstrFeature; break; } @@ -462,12 +483,12 @@ void SketchPlugin_ConstraintFillet::attributeChanged(const std::string& theID) aCoinsideLines = aNewLines; } - if(aCoinsideLines.size() != 2) { setError("At selected vertex should be two coincident lines"); return; } + // Store base lines FeaturePtr anOldFeatureA, anOldFeatureB; std::set::iterator aLinesIt = aCoinsideLines.begin(); anOldFeatureA = *aLinesIt++; @@ -475,35 +496,18 @@ void SketchPlugin_ConstraintFillet::attributeChanged(const std::string& theID) aRefListOfBaseLines->append(anOldFeatureA); aRefListOfBaseLines->append(anOldFeatureB); + // Getting points located at 1/3 of edge length from fillet point + std::shared_ptr aPntA, aPntB; + getPointOnEdge(anOldFeatureA, aFilletPoint, aPntA); + getPointOnEdge(anOldFeatureB, aFilletPoint, aPntB); - // Set default value equal to 1/3 of the smallest line sharing the point. - static const int aNbFeatures = 2; - FeaturePtr aFeature[aNbFeatures] = {anOldFeatureA, anOldFeatureB}; - double aLength = 0; + /// Getting distances + double aRadius = 1; + double aDistanceA = getProjectionDistance(anOldFeatureB, aPntA); + double aDistanceB = getProjectionDistance(anOldFeatureA, aPntB); + aRadius = aDistanceA < aDistanceB ? aDistanceA / 2.0 : aDistanceB / 2.0; - double aLengths[aNbFeatures]; - for (int i = 0; i < aNbFeatures; i++) { - std::shared_ptr aStartPnt = std::dynamic_pointer_cast(aFeature[i]->attribute( - aFeature[i]->getKind() == SketchPlugin_Line::ID() ? SketchPlugin_Line::START_ID() : SketchPlugin_Arc::START_ID()))->pnt(); - std::shared_ptr anEndPnt = std::dynamic_pointer_cast(aFeature[i]->attribute( - aFeature[i]->getKind() == SketchPlugin_Line::ID() ? SketchPlugin_Line::END_ID() : SketchPlugin_Arc::END_ID()))->pnt(); - if(aFeature[i]->getKind() == SketchPlugin_Line::ID()) { - aLengths[i] = aStartPnt->distance(anEndPnt); - } else { - std::shared_ptr anArcCenter = std::dynamic_pointer_cast(aFeature[i]->attribute( - SketchPlugin_Arc::CENTER_ID()))->pnt(); - std::shared_ptr aStartDir(new GeomAPI_Dir2d(aStartPnt->xy()->decreased(anArcCenter->xy()))); - std::shared_ptr anEndDir(new GeomAPI_Dir2d(anEndPnt->xy()->decreased(anArcCenter->xy()))); - double aRadius = aStartPnt->distance(anArcCenter); - double anAngle = aStartDir->angle(anEndDir); - aLengths[i] = aRadius * abs(anAngle); - } - } - aLength = aLengths[0]; - for(int i = 1; i < aNbFeatures; i++) { - if(aLengths[i] < aLength) aLength = aLengths[i]; - } - std::dynamic_pointer_cast(data()->attribute(SketchPlugin_Constraint::VALUE()))->setValue(aLength / 3.0); + std::dynamic_pointer_cast(data()->attribute(SketchPlugin_Constraint::VALUE()))->setValue(aRadius); } } @@ -794,3 +798,72 @@ void calculateFilletCenter(FeaturePtr theFeatureA, FeaturePtr theFeatureB, } } } + +void getPointOnEdge(const FeaturePtr theFeature, + const std::shared_ptr theFilletPoint, + std::shared_ptr& thePoint) { + if(theFeature->getKind() == SketchPlugin_Line::ID()) { + std::shared_ptr aPntStart = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Line::START_ID()))->pnt(); + std::shared_ptr aPntEnd = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Line::END_ID()))->pnt(); + if(aPntStart->distance(theFilletPoint) > 1.e-7) { + aPntStart = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Line::END_ID()))->pnt(); + aPntEnd = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Line::START_ID()))->pnt(); + } + thePoint.reset( new GeomAPI_Pnt2d(aPntStart->xy()->added( aPntEnd->xy()->decreased( aPntStart->xy() )->multiplied(1.0 / 3.0) ) ) ); + } else { + std::shared_ptr aPntTemp; + std::shared_ptr aPntStart = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Arc::START_ID()))->pnt(); + std::shared_ptr aPntEnd = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Arc::END_ID()))->pnt(); + if(theFeature->attribute(SketchPlugin_Arc::INVERSED_ID())) { + aPntTemp = aPntStart; + aPntStart = aPntEnd; + aPntEnd = aPntTemp; + } + std::shared_ptr aCenterPnt = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt(); + std::shared_ptr aCirc(new GeomAPI_Circ2d(aCenterPnt, aPntStart)); + double aStartParameter(0), anEndParameter(0); + aCirc->parameter(aPntStart, paramTolerance, aStartParameter); + aCirc->parameter(aPntEnd, paramTolerance, anEndParameter); + if(aPntStart->distance(theFilletPoint) > tolerance) { + double aTmpParameter = aStartParameter; + aStartParameter = anEndParameter; + anEndParameter = aTmpParameter; + } + double aPntParameter = aStartParameter + (anEndParameter - aStartParameter) / 3.0; + aCirc->D0(aPntParameter, thePoint); + } +} + +double getProjectionDistance(const FeaturePtr theFeature, + const std::shared_ptr thePoint) +{ + std::shared_ptr aProjectPnt; + if(theFeature->getKind() == SketchPlugin_Line::ID()) { + std::shared_ptr aPntStart = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Line::START_ID()))->pnt(); + std::shared_ptr aPntEnd = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Line::END_ID()))->pnt(); + std::shared_ptr aLin(new GeomAPI_Lin2d(aPntStart, aPntEnd)); + aProjectPnt = aLin->project(thePoint); + } else { + std::shared_ptr aPntStart = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Arc::START_ID()))->pnt(); + std::shared_ptr aPntEnd = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Arc::END_ID()))->pnt(); + std::shared_ptr aCenterPnt = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt(); + std::shared_ptr aCirc(new GeomAPI_Circ2d(aCenterPnt, aPntStart)); + aProjectPnt = aCirc->project(thePoint); + } + if(aProjectPnt.get()) { + return aProjectPnt->distance(thePoint); + } + return -1; +} -- 2.39.2