From 7e614d73ed89a98e3cb83f373fbffaab9797795e Mon Sep 17 00:00:00 2001 From: azv Date: Fri, 12 Feb 2016 14:19:31 +0300 Subject: [PATCH] Intersection point feature implementation --- src/GeomAPI/GeomAPI_Pln.cpp | 26 +++++-- src/GeomAPI/GeomAPI_Pln.h | 9 ++- src/SketchPlugin/CMakeLists.txt | 2 + .../SketchPlugin_IntersectionPoint.cpp | 71 +++++++++++++++++++ .../SketchPlugin_IntersectionPoint.h | 66 +++++++++++++++++ src/SketchPlugin/SketchPlugin_Plugin.cpp | 6 ++ src/SketchPlugin/SketchPlugin_Validators.cpp | 49 +++++++++++++ src/SketchPlugin/SketchPlugin_Validators.h | 16 +++++ src/SketchPlugin/plugin-Sketch.xml | 22 +++++- .../PlaneGCSSolver/PlaneGCSSolver_Builder.cpp | 4 +- .../PlaneGCSSolver_EntityWrapper.cpp | 4 +- .../SketchSolver_ConstraintMulti.cpp | 4 +- src/SketchSolver/SketchSolver_Storage.cpp | 4 +- .../SolveSpaceSolver_Builder.cpp | 4 +- 14 files changed, 275 insertions(+), 12 deletions(-) create mode 100644 src/SketchPlugin/SketchPlugin_IntersectionPoint.cpp create mode 100644 src/SketchPlugin/SketchPlugin_IntersectionPoint.h diff --git a/src/GeomAPI/GeomAPI_Pln.cpp b/src/GeomAPI/GeomAPI_Pln.cpp index dfb7e9bd7..4ba715898 100644 --- a/src/GeomAPI/GeomAPI_Pln.cpp +++ b/src/GeomAPI/GeomAPI_Pln.cpp @@ -4,12 +4,14 @@ // Created: 23 Apr 2014 // Author: Mikhail PONIKAROV -#include +#include #include #include #include +#include +#include -#include +#include using namespace std; @@ -29,13 +31,13 @@ GeomAPI_Pln::GeomAPI_Pln(const double theA, const double theB, const double theC { } -std::shared_ptr GeomAPI_Pln::location() +std::shared_ptr GeomAPI_Pln::location() const { gp_Pnt aLoc = impl().Location(); return std::shared_ptr(new GeomAPI_Pnt(aLoc.X(), aLoc.Y(), aLoc.Z())); } -std::shared_ptr GeomAPI_Pln::direction() +std::shared_ptr GeomAPI_Pln::direction() const { const gp_Dir& aDir = impl().Axis().Direction(); return std::shared_ptr(new GeomAPI_Dir(aDir.X(), aDir.Y(), aDir.Z())); @@ -56,3 +58,19 @@ bool GeomAPI_Pln::isCoincident(const std::shared_ptr thePlane, cons const gp_Pln& anOtherPln = thePlane->impl(); return (aMyPln.Contains(anOtherPln.Location(), theTolerance) && aMyPln.Axis().IsParallel(anOtherPln.Axis(), theTolerance)); } + +std::shared_ptr GeomAPI_Pln::intersect(const std::shared_ptr& theLine) const +{ + std::shared_ptr aLineDir = theLine->direction()->xyz(); + std::shared_ptr aLineLoc = theLine->location()->xyz(); + + std::shared_ptr aNormal = direction()->xyz(); + std::shared_ptr aLocation = location()->xyz(); + + double aDot = aNormal->dot(aLineDir); + if (Abs(aDot) < Precision::SquareConfusion()) + return std::shared_ptr(); + + double aParam = aNormal->dot(aLocation->decreased(aLineLoc)) / aDot; + return std::shared_ptr(new GeomAPI_Pnt(aLineLoc->added(aLineDir->multiplied(aParam)))); +} diff --git a/src/GeomAPI/GeomAPI_Pln.h b/src/GeomAPI/GeomAPI_Pln.h index e0564557e..81bc519a0 100644 --- a/src/GeomAPI/GeomAPI_Pln.h +++ b/src/GeomAPI/GeomAPI_Pln.h @@ -13,6 +13,7 @@ class GeomAPI_Ax3; class GeomAPI_Pnt; class GeomAPI_Dir; +class GeomAPI_Lin; /**\class GeomAPI_Pln * \ingroup DataModel @@ -37,11 +38,11 @@ class GeomAPI_Pln : public GeomAPI_Interface /// Returns a point of this plane GEOMAPI_EXPORT - std::shared_ptr location(); + std::shared_ptr location() const; /// Returns a plane normal GEOMAPI_EXPORT - std::shared_ptr direction(); + std::shared_ptr direction() const; /// Returns the plane coefficients (Ax+By+Cz+D=0) GEOMAPI_EXPORT @@ -50,6 +51,10 @@ class GeomAPI_Pln : public GeomAPI_Interface /// Returns true if planes are coincident. GEOMAPI_EXPORT bool isCoincident(const std::shared_ptr thePlane, const double theTolerance = 1.e-7); + + /// Returns intersection point or empty if no intersections + GEOMAPI_EXPORT + std::shared_ptr intersect(const std::shared_ptr& theLine) const; }; #endif diff --git a/src/SketchPlugin/CMakeLists.txt b/src/SketchPlugin/CMakeLists.txt index d92bfba14..ecb1cb269 100644 --- a/src/SketchPlugin/CMakeLists.txt +++ b/src/SketchPlugin/CMakeLists.txt @@ -11,6 +11,7 @@ SET(PROJECT_HEADERS SketchPlugin_SketchEntity.h SketchPlugin_Line.h SketchPlugin_Point.h + SketchPlugin_IntersectionPoint.h SketchPlugin_Circle.h SketchPlugin_Arc.h SketchPlugin_Constraint.h @@ -45,6 +46,7 @@ SET(PROJECT_SOURCES SketchPlugin_SketchEntity.cpp SketchPlugin_Line.cpp SketchPlugin_Point.cpp + SketchPlugin_IntersectionPoint.cpp SketchPlugin_Circle.cpp SketchPlugin_Arc.cpp SketchPlugin_Constraint.cpp diff --git a/src/SketchPlugin/SketchPlugin_IntersectionPoint.cpp b/src/SketchPlugin/SketchPlugin_IntersectionPoint.cpp new file mode 100644 index 000000000..5c411427c --- /dev/null +++ b/src/SketchPlugin/SketchPlugin_IntersectionPoint.cpp @@ -0,0 +1,71 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: SketchPlugin_IntersectionPoint.cpp +// Created: 07 May 2014 +// Author: Artem ZHIDKOV + +#include "SketchPlugin_IntersectionPoint.h" + +#include + +#include +#include +#include + +SketchPlugin_IntersectionPoint::SketchPlugin_IntersectionPoint() + : SketchPlugin_Point() +{ +} + +void SketchPlugin_IntersectionPoint::initDerivedClassAttributes() +{ + data()->addAttribute(EXTERNAL_LINE_ID(), ModelAPI_AttributeRefAttr::typeId()); + + SketchPlugin_Point::initDerivedClassAttributes(); +} + +void SketchPlugin_IntersectionPoint::execute() +{ + SketchPlugin_Sketch* aSketch = sketch(); + if (aSketch) { + computePoint(); + SketchPlugin_Point::execute(); + + // set this feature as external + data()->selection(EXTERNAL_ID())->setValue(lastResult(), lastResult()->shape()); + } +} + +void SketchPlugin_IntersectionPoint::move(double theDeltaX, double theDeltaY) +{ +} + +void SketchPlugin_IntersectionPoint::attributeChanged(const std::string& theID) +{ + if (theID == EXTERNAL_LINE_ID()) { + // compute intersection between line and sketch plane + computePoint(); + } +} + +void SketchPlugin_IntersectionPoint::computePoint() +{ + AttributeRefAttrPtr aLineRefAttr = + std::dynamic_pointer_cast(attribute(EXTERNAL_LINE_ID())); + ResultPtr aLineResult = std::dynamic_pointer_cast(aLineRefAttr->object()); + if (!aLineResult) + return; + + std::shared_ptr aLinearEdge = + std::dynamic_pointer_cast(aLineResult->shape()); + std::shared_ptr aLine = aLinearEdge->line(); + std::shared_ptr aSketchPlane = sketch()->plane(); + + std::shared_ptr anIntersection = aSketchPlane->intersect(aLine); + if (!anIntersection) + return; + + std::shared_ptr aCoordAttr = + std::dynamic_pointer_cast(attribute(COORD_ID())); + aCoordAttr->setValue(sketch()->to2D(anIntersection)); +} diff --git a/src/SketchPlugin/SketchPlugin_IntersectionPoint.h b/src/SketchPlugin/SketchPlugin_IntersectionPoint.h new file mode 100644 index 000000000..c088bc6f0 --- /dev/null +++ b/src/SketchPlugin/SketchPlugin_IntersectionPoint.h @@ -0,0 +1,66 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: SketchPlugin_IntersectionPoint.h +// Created: 07 May 2014 +// Author: Artem ZHIDKOV + +#ifndef SketchPlugin_IntersectionPoint_H_ +#define SketchPlugin_IntersectionPoint_H_ + +#include "SketchPlugin_Point.h" + +/**\class SketchPlugin_IntersectionPoint + * \ingroup Plugins + * \brief Feature for creation of external point as an intersection + * between external edge and a plane of the sketch. + */ +class SketchPlugin_IntersectionPoint : public SketchPlugin_Point +{ +public: + /// Point feature kind + inline static const std::string& ID() + { + static const std::string MY_POINT_ID("SketchIntersectionPoint"); + return MY_POINT_ID; + } + /// Returns the kind of a feature + virtual const std::string& getKind() + { + static std::string MY_KIND = SketchPlugin_IntersectionPoint::ID(); + return MY_KIND; + } + + static const std::string& EXTERNAL_LINE_ID() + { + static std::string MY_LINE_ID("ExternalLine"); + return MY_LINE_ID; + } + + /// Returns true because intersection point is always external + virtual bool isFixed() + { return true; } + + /// Creates a new part document if needed + SKETCHPLUGIN_EXPORT virtual void execute(); + + /// Moves the feature + /// \param theDeltaX the delta for X coordinate is moved + /// \param theDeltaY the delta for Y coordinate is moved + SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY); + + /// Called on change of any argument-attribute of this object: for external point + SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID); + + /// Use plugin manager for features creation + SketchPlugin_IntersectionPoint(); + +protected: + /// \brief Initializes attributes of derived class. + virtual void initDerivedClassAttributes(); + +private: + /// \brief Find intersection between a line and a sketch plane + void computePoint(); +}; + +#endif diff --git a/src/SketchPlugin/SketchPlugin_Plugin.cpp b/src/SketchPlugin/SketchPlugin_Plugin.cpp index 0d3c66fd5..b0f84cc79 100644 --- a/src/SketchPlugin/SketchPlugin_Plugin.cpp +++ b/src/SketchPlugin/SketchPlugin_Plugin.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -78,6 +79,8 @@ SketchPlugin_Plugin::SketchPlugin_Plugin() new SketchPlugin_MiddlePointAttrValidator); aFactory->registerValidator("SketchPlugin_ArcTangentPoint", new SketchPlugin_ArcTangentPointValidator); + aFactory->registerValidator("SketchPlugin_IntersectionValidator", + new SketchPlugin_IntersectionValidator); // register this plugin ModelAPI_Session::get()->registerPlugin(this); @@ -115,6 +118,8 @@ FeaturePtr SketchPlugin_Plugin::createFeature(string theFeatureID) return FeaturePtr(new SketchPlugin_Sketch); } else if (theFeatureID == SketchPlugin_Point::ID()) { return FeaturePtr(new SketchPlugin_Point); + } else if (theFeatureID == SketchPlugin_IntersectionPoint::ID()) { + return FeaturePtr(new SketchPlugin_IntersectionPoint); } else if (theFeatureID == SketchPlugin_Line::ID()) { return FeaturePtr(new SketchPlugin_Line); } else if (theFeatureID == SketchPlugin_Circle::ID()) { @@ -194,6 +199,7 @@ std::shared_ptr SketchPlugin_Plugin !(aNormal->x() == 0 && aNormal->y() == 0 && aNormal->z() == 0); aMsg->setState(SketchPlugin_Point::ID(), aHasSketchPlane); + aMsg->setState(SketchPlugin_IntersectionPoint::ID(), aHasSketchPlane); aMsg->setState(SketchPlugin_Line::ID(), aHasSketchPlane); aMsg->setState(SketchPlugin_Circle::ID(), aHasSketchPlane); aMsg->setState(SketchPlugin_Arc::ID(), aHasSketchPlane); diff --git a/src/SketchPlugin/SketchPlugin_Validators.cpp b/src/SketchPlugin/SketchPlugin_Validators.cpp index 26c965dec..13d7138e1 100755 --- a/src/SketchPlugin/SketchPlugin_Validators.cpp +++ b/src/SketchPlugin/SketchPlugin_Validators.cpp @@ -30,9 +30,13 @@ #include #include +#include +#include #include #include +#include + const double tolerance = 1.e-7; bool SketchPlugin_DistanceAttrValidator::isValid(const AttributePtr& theAttribute, @@ -683,3 +687,48 @@ bool SketchPlugin_ArcTangentPointValidator::isValid(const AttributePtr& theAttri return true; } + +bool SketchPlugin_IntersectionValidator::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + std::string& theError) const +{ + if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) { + theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed"; + return false; + } + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(theAttribute); + ResultPtr aResult = std::dynamic_pointer_cast(aRefAttr->object()); + if (!aResult) { + theError = "The attribute " + theAttribute->id() + " should be an object"; + return false; + } + + std::shared_ptr anEdge = std::dynamic_pointer_cast(aResult->shape()); + if (!anEdge || !anEdge->isLine()) { + theError = "The attribute " + theAttribute->id() + " should be a line"; + return false; + } + + std::shared_ptr aLineDir = anEdge->line()->direction(); + + // find a sketch + std::shared_ptr aSketch; + std::set aRefs = aRefAttr->owner()->data()->refsToMe(); + std::set::const_iterator anIt = aRefs.begin(); + for (; anIt != aRefs.end(); ++anIt) { + CompositeFeaturePtr aComp = + std::dynamic_pointer_cast((*anIt)->owner()); + if (aComp && aComp->getKind() == SketchPlugin_Sketch::ID()) { + aSketch = std::dynamic_pointer_cast(aComp); + break; + } + } + if (!aSketch) { + theError = "There is no sketch referring to the current feature"; + return false; + } + + std::shared_ptr aPlane = aSketch->plane(); + std::shared_ptr aNormal = aPlane->direction(); + return fabs(aNormal->dot(aLineDir)) > tolerance * tolerance; +} diff --git a/src/SketchPlugin/SketchPlugin_Validators.h b/src/SketchPlugin/SketchPlugin_Validators.h index ef5e77aba..49854af5e 100644 --- a/src/SketchPlugin/SketchPlugin_Validators.h +++ b/src/SketchPlugin/SketchPlugin_Validators.h @@ -218,4 +218,20 @@ class SketchPlugin_ArcTangentPointValidator : public ModelAPI_AttributeValidator std::string& theError) const; }; +/**\class SketchPlugin_IntersectionValidator + * \ingroup Validators + * \brief Validator for the attribute to be intersected with the sketch plane. + */ +class SketchPlugin_IntersectionValidator : public ModelAPI_AttributeValidator +{ + public: + //! returns true if attribute is valid + //! \param theAttribute the checked attribute + //! \param theArguments arguments of the attribute + //! \param theError error message + virtual bool isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + std::string& theError) const; +}; + #endif diff --git a/src/SketchPlugin/plugin-Sketch.xml b/src/SketchPlugin/plugin-Sketch.xml index 6b3ba5c8b..cdcef0155 100644 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@ -5,7 +5,7 @@ + + + + + + + + + + + + diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Builder.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Builder.cpp index e5002f130..583c65401 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Builder.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Builder.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -499,7 +500,8 @@ EntityWrapperPtr PlaneGCSSolver_Builder::createFeature( else if (aFeatureKind == SketchPlugin_Arc::ID()) return createArc(theFeature, theAttributes, theGroupID); // Point (it has low probability to be an attribute of constraint, so it is checked at the end) - else if (aFeatureKind == SketchPlugin_Point::ID()) { + else if (aFeatureKind == SketchPlugin_Point::ID() || + aFeatureKind == SketchPlugin_IntersectionPoint::ID()) { EntityWrapperPtr aSub; if (theAttributes.size() == 1) aSub = theAttributes.front(); diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityWrapper.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityWrapper.cpp index 45bee0ed5..e1dbad9be 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityWrapper.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityWrapper.cpp @@ -6,6 +6,7 @@ #include #include +#include #include PlaneGCSSolver_EntityWrapper::PlaneGCSSolver_EntityWrapper( @@ -27,7 +28,8 @@ PlaneGCSSolver_EntityWrapper::PlaneGCSSolver_EntityWrapper( } // empty entity, probably this is a SketchPlugin_Point or SketchPlugin_Sketch - if (theFeature->getKind() == SketchPlugin_Point::ID()) + if (theFeature->getKind() == SketchPlugin_Point::ID() || + theFeature->getKind() == SketchPlugin_IntersectionPoint::ID()) myType = ENTITY_POINT; else if (theFeature->getKind() == SketchPlugin_Sketch::ID()) myType = ENTITY_SKETCH; diff --git a/src/SketchSolver/SketchSolver_ConstraintMulti.cpp b/src/SketchSolver/SketchSolver_ConstraintMulti.cpp index 404c5df7f..d9e246cc9 100644 --- a/src/SketchSolver/SketchSolver_ConstraintMulti.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintMulti.cpp @@ -10,6 +10,7 @@ #include #include #include +#include void SketchSolver_ConstraintMulti::getEntities(std::list& theEntities) { @@ -159,7 +160,8 @@ void SketchSolver_ConstraintMulti::adjustConstraint() aPoints.push_back(aFeature->attribute(SketchPlugin_Line::END_ID())); } else if (aFeature->getKind() == SketchPlugin_Circle::ID()) aPoints.push_back(aFeature->attribute(SketchPlugin_Circle::CENTER_ID())); - else if (aFeature->getKind() == SketchPlugin_Point::ID()) + else if (aFeature->getKind() == SketchPlugin_Point::ID() || + aFeature->getKind() == SketchPlugin_IntersectionPoint::ID()) aPoints.push_back(aFeature->attribute(SketchPlugin_Point::COORD_ID())); std::list::iterator aPtIt = aPoints.begin(); diff --git a/src/SketchSolver/SketchSolver_Storage.cpp b/src/SketchSolver/SketchSolver_Storage.cpp index 809bef132..c63d28e43 100644 --- a/src/SketchSolver/SketchSolver_Storage.cpp +++ b/src/SketchSolver/SketchSolver_Storage.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -96,7 +97,8 @@ static std::list pointAttributes(FeaturePtr theFeature) aPoints.push_back(theFeature->attribute(SketchPlugin_Line::START_ID())); aPoints.push_back(theFeature->attribute(SketchPlugin_Line::END_ID())); } - else if (theFeature->getKind() == SketchPlugin_Point::ID()) + else if (theFeature->getKind() == SketchPlugin_Point::ID() || + theFeature->getKind() == SketchPlugin_IntersectionPoint::ID()) aPoints.push_back(theFeature->attribute(SketchPlugin_Point::COORD_ID())); return aPoints; } diff --git a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Builder.cpp b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Builder.cpp index 01b747804..f080a9fca 100644 --- a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Builder.cpp +++ b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Builder.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -331,7 +332,8 @@ EntityWrapperPtr SolveSpaceSolver_Builder::createFeature( else if (aFeatureKind == SketchPlugin_Arc::ID()) return createArc(theFeature, theAttributes, theGroupID, theSketchID); // Point (it has low probability to be an attribute of constraint, so it is checked at the end) - else if (aFeatureKind == SketchPlugin_Point::ID()) { + else if (aFeatureKind == SketchPlugin_Point::ID() || + aFeatureKind == SketchPlugin_IntersectionPoint::ID()) { AttributePtr aPoint = theFeature->attribute(SketchPlugin_Point::COORD_ID()); if (!aPoint->isInitialized()) return aDummy; -- 2.39.2