From 9d69918c6421ffae24534684847ec8b38741030a Mon Sep 17 00:00:00 2001 From: azv Date: Thu, 24 Jul 2014 16:23:32 +0400 Subject: [PATCH] Crash on constraint creation due to new structure of the Model library --- src/GeomAPI/CMakeLists.txt | 4 +- src/GeomAPI/GeomAPI_Edge.cpp | 52 +++++ src/GeomAPI/GeomAPI_Edge.h | 40 ++++ src/GeomAPI/GeomAPI_Shape.cpp | 14 +- src/GeomAPI/GeomAPI_Shape.h | 6 + src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.cpp | 18 +- src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.h | 8 +- src/SketchSolver/CMakeLists.txt | 1 + src/SketchSolver/SketchSolver_Constraint.cpp | 187 +++++++++--------- .../SketchSolver_ConstraintGroup.cpp | 37 +++- 10 files changed, 250 insertions(+), 117 deletions(-) create mode 100644 src/GeomAPI/GeomAPI_Edge.cpp create mode 100644 src/GeomAPI/GeomAPI_Edge.h diff --git a/src/GeomAPI/CMakeLists.txt b/src/GeomAPI/CMakeLists.txt index e13d4b270..0b2eb9763 100644 --- a/src/GeomAPI/CMakeLists.txt +++ b/src/GeomAPI/CMakeLists.txt @@ -18,8 +18,9 @@ SET(PROJECT_HEADERS GeomAPI_Dir2d.h GeomAPI_Pln.h GeomAPI_Shape.h + GeomAPI_Edge.h GeomAPI_AISObject.h - GeomAPI_IPresentable.h + GeomAPI_IPresentable.h ) SET(PROJECT_SOURCES @@ -36,6 +37,7 @@ SET(PROJECT_SOURCES GeomAPI_Dir2d.cpp GeomAPI_Pln.cpp GeomAPI_Shape.cpp + GeomAPI_Edge.cpp GeomAPI_AISObject.cpp ) diff --git a/src/GeomAPI/GeomAPI_Edge.cpp b/src/GeomAPI/GeomAPI_Edge.cpp new file mode 100644 index 000000000..8d8bf022a --- /dev/null +++ b/src/GeomAPI/GeomAPI_Edge.cpp @@ -0,0 +1,52 @@ +// File: GeomAPI_Edge.cpp +// Created: 24 Jul 2014 +// Author: Artem ZHIDKOV + +#include + +#include +#include +#include +#include +#include +#include + +GeomAPI_Edge::GeomAPI_Edge() + : GeomAPI_Shape() +{} + +bool GeomAPI_Edge::isLine() const +{ + const TopoDS_Shape& aShape = const_cast(this)->impl(); + Handle(BRep_TEdge) anEdge = Handle(BRep_TEdge)::DownCast(aShape.TShape()); + if (anEdge->Curves().Extent() != 1) + return false; // too many curves in the edge + Handle(Geom_Curve) aCurve = anEdge->Curves().First()->Curve3D(); + if (aCurve->IsKind(STANDARD_TYPE(Geom_Line))) + return true; + return false; +} + +bool GeomAPI_Edge::isCircle() const +{ + const TopoDS_Shape& aShape = const_cast(this)->impl(); + Handle(BRep_TEdge) anEdge = Handle(BRep_TEdge)::DownCast(aShape.TShape()); + if (anEdge->Curves().Extent() != 1) + return false; // too many curves in the edge + Handle(Geom_Curve) aCurve = anEdge->Curves().First()->Curve3D(); + if (aCurve->IsKind(STANDARD_TYPE(Geom_Circle)) && aCurve->IsClosed()) + return true; + return false; +} + +bool GeomAPI_Edge::isArc() const +{ + const TopoDS_Shape& aShape = const_cast(this)->impl(); + Handle(BRep_TEdge) anEdge = Handle(BRep_TEdge)::DownCast(aShape.TShape()); + if (anEdge->Curves().Extent() != 1) + return false; // too many curves in the edge + Handle(Geom_Curve) aCurve = anEdge->Curves().First()->Curve3D(); + if (aCurve->IsKind(STANDARD_TYPE(Geom_Circle)) && !aCurve->IsClosed()) + return true; + return false; +} diff --git a/src/GeomAPI/GeomAPI_Edge.h b/src/GeomAPI/GeomAPI_Edge.h new file mode 100644 index 000000000..584e4756c --- /dev/null +++ b/src/GeomAPI/GeomAPI_Edge.h @@ -0,0 +1,40 @@ +// File: GeomAPI_Edge.hxx +// Created: 24 Jul 2014 +// Author: Artem ZHIDKOV + +#ifndef GeomAPI_Edge_HeaderFile +#define GeomAPI_Edge_HeaderFile + +#include + +/**\class GeomAPI_Edge + * \ingroup DataModel + * \brief Interface to the edge object + */ + +class GEOMAPI_EXPORT GeomAPI_Edge: public GeomAPI_Shape +{ +public: + /// Creation of empty (null) shape + GeomAPI_Edge(); + + /// Returns whether the shape is a vertex + virtual bool isVertex() const + { return false; } + + /// Returns whether the shape is an edge + virtual bool isEdge() const + { return true; } + + /// Verifies that the edge is a line + bool isLine() const; + + /// Verifies that the edge is a circle + bool isCircle() const; + + /// Verifies that the edge is an arc of circle + bool isArc() const; +}; + +#endif + diff --git a/src/GeomAPI/GeomAPI_Shape.cpp b/src/GeomAPI/GeomAPI_Shape.cpp index e662ea254..f7f05846a 100644 --- a/src/GeomAPI/GeomAPI_Shape.cpp +++ b/src/GeomAPI/GeomAPI_Shape.cpp @@ -4,10 +4,22 @@ #include -#include +#include #define MY_PNT static_cast(myImpl) GeomAPI_Shape::GeomAPI_Shape() : GeomAPI_Interface(new TopoDS_Shape()) {} + +bool GeomAPI_Shape::isVertex() const +{ + const TopoDS_Shape& aShape = const_cast(this)->impl(); + return aShape.TShape()->ShapeType() == TopAbs_VERTEX; +} + +bool GeomAPI_Shape::isEdge() const +{ + const TopoDS_Shape& aShape = const_cast(this)->impl(); + return aShape.TShape()->ShapeType() == TopAbs_EDGE; +} diff --git a/src/GeomAPI/GeomAPI_Shape.h b/src/GeomAPI/GeomAPI_Shape.h index 8a9d3b26c..7394bee05 100644 --- a/src/GeomAPI/GeomAPI_Shape.h +++ b/src/GeomAPI/GeomAPI_Shape.h @@ -17,6 +17,12 @@ class GEOMAPI_EXPORT GeomAPI_Shape: public GeomAPI_Interface public: /// Creation of empty (null) shape GeomAPI_Shape(); + + /// Returns whether the shape is a vertex + virtual bool isVertex() const; + + /// Returns whether the shape is an edge + virtual bool isEdge() const; }; #endif diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.cpp index 6b8ebd946..0e622ba36 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.cpp @@ -13,24 +13,24 @@ #include #include -boost::shared_ptr GeomAlgoAPI_EdgeBuilder::line( +boost::shared_ptr GeomAlgoAPI_EdgeBuilder::line( boost::shared_ptr theStart, boost::shared_ptr theEnd) { const gp_Pnt& aStart = theStart->impl(); const gp_Pnt& anEnd = theEnd->impl(); if (aStart.IsEqual(anEnd, Precision::Confusion())) - return boost::shared_ptr(); + return boost::shared_ptr(); if (Abs(aStart.SquareDistance(anEnd)) > 1.e+100) - return boost::shared_ptr(); + return boost::shared_ptr(); BRepBuilderAPI_MakeEdge anEdgeBuilder(aStart, anEnd); - boost::shared_ptr aRes(new GeomAPI_Shape); + boost::shared_ptr aRes(new GeomAPI_Edge); TopoDS_Edge anEdge = anEdgeBuilder.Edge(); aRes->setImpl(new TopoDS_Shape(anEdge)); return aRes; } -boost::shared_ptr GeomAlgoAPI_EdgeBuilder::lineCircle( +boost::shared_ptr GeomAlgoAPI_EdgeBuilder::lineCircle( boost::shared_ptr theCenter, boost::shared_ptr theNormal, double theRadius) { @@ -40,13 +40,13 @@ boost::shared_ptr GeomAlgoAPI_EdgeBuilder::lineCircle( gp_Circ aCircle(gp_Ax2(aCenter, aDir), theRadius); BRepBuilderAPI_MakeEdge anEdgeBuilder(aCircle); - boost::shared_ptr aRes(new GeomAPI_Shape); + boost::shared_ptr aRes(new GeomAPI_Edge); TopoDS_Edge anEdge = anEdgeBuilder.Edge(); aRes->setImpl(new TopoDS_Shape(anEdge)); return aRes; } -boost::shared_ptr GeomAlgoAPI_EdgeBuilder::lineCircleArc( +boost::shared_ptr GeomAlgoAPI_EdgeBuilder::lineCircleArc( boost::shared_ptr theCenter, boost::shared_ptr theStartPoint, boost::shared_ptr theEndPoint, @@ -68,12 +68,12 @@ boost::shared_ptr GeomAlgoAPI_EdgeBuilder::lineCircleArc( else anEdgeBuilder = BRepBuilderAPI_MakeEdge(aCircle, aStart, anEnd); - boost::shared_ptr aRes(new GeomAPI_Shape); + boost::shared_ptr aRes(new GeomAPI_Edge); anEdgeBuilder.Build(); if (anEdgeBuilder.IsDone()) aRes->setImpl(new TopoDS_Shape(anEdgeBuilder.Edge())); else - aRes = boost::shared_ptr(); + aRes = boost::shared_ptr(); return aRes; } diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.h b/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.h index de532ea56..bb01b7bf5 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.h @@ -6,7 +6,7 @@ #define GeomAlgoAPI_EdgeBuilder_HeaderFile #include -#include +#include #include #include #include @@ -20,16 +20,16 @@ class GEOMALGOAPI_EXPORT GeomAlgoAPI_EdgeBuilder { public: /// Creates linear edge by two points - static boost::shared_ptr line( + static boost::shared_ptr line( boost::shared_ptr theStart, boost::shared_ptr theEnd); /// Creates linear edge in a form of a circle by a point and a circle radius - static boost::shared_ptr lineCircle( + static boost::shared_ptr lineCircle( boost::shared_ptr theCenter, boost::shared_ptr theNormal, double theRadius); /// Creates linear edge in a form of a circle arc by a three points - static boost::shared_ptr lineCircleArc( + static boost::shared_ptr lineCircleArc( boost::shared_ptr theCenter, boost::shared_ptr theStartPoint, boost::shared_ptr theEndPoint, diff --git a/src/SketchSolver/CMakeLists.txt b/src/SketchSolver/CMakeLists.txt index 8964c31f8..a8525ee70 100644 --- a/src/SketchSolver/CMakeLists.txt +++ b/src/SketchSolver/CMakeLists.txt @@ -20,6 +20,7 @@ SET(PROJECT_LIBRARIES ${SLVS_LIBRARIES} Events ModelAPI + GeomAPI ) INCLUDE_DIRECTORIES( diff --git a/src/SketchSolver/SketchSolver_Constraint.cpp b/src/SketchSolver/SketchSolver_Constraint.cpp index 05f261a69..f831c170b 100644 --- a/src/SketchSolver/SketchSolver_Constraint.cpp +++ b/src/SketchSolver/SketchSolver_Constraint.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -17,9 +18,29 @@ #include #include +#include +#include +#include #include #include +#include +#include + +/// Possible types of attributes (used to determine constraint type) +enum AttrType +{ + UNKNOWN, // Something wrong during type determination + POINT2D, + POINT3D, + LINE, + CIRCLE, + ARC +}; + +/// Calculate type of the attribute +static AttrType typeOfAttribute(boost::shared_ptr theAttribute); + SketchSolver_Constraint::SketchSolver_Constraint() @@ -50,7 +71,7 @@ const int& SketchSolver_Constraint::getType(boost::shared_ptrgetKind(); // Constraint for coincidence of two points - if (aConstraintKind.compare("SketchConstraintCoincidence") == 0) + if (aConstraintKind.compare(SketchPlugin_ConstraintCoincidence::ID()) == 0) { int anAttrPos = 0; // Verify the constraint has only two attributes and they are points @@ -58,31 +79,22 @@ const int& SketchSolver_Constraint::getType(boost::shared_ptr anAttr = - boost::dynamic_pointer_cast( - theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)) - ); - if (!anAttr) continue; - // Verify the attribute is a 2D point - boost::shared_ptr aPoint2D = - boost::dynamic_pointer_cast(anAttr->attr()); - if (aPoint2D) + boost::shared_ptr anAttr = + theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)); + switch (typeOfAttribute(anAttr)) { + case POINT2D: // the attribute is a 2D point aPt2d |= (1 << indAttr); myAttributesList[anAttrPos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); - continue; - } - // Verify the attribute is a 3D point - boost::shared_ptr aPoint3D = - boost::dynamic_pointer_cast(anAttr->attr()); - if (aPoint3D) - { + break; + case POINT3D: // the attribute is a 3D point aPt3d |= (1 << indAttr); myAttributesList[anAttrPos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); - continue; + break; + default: + // Attribute neither 2D nor 3D point is not supported by this type of constraint + return getType(); } - // Attribute neither 2D nor 3D point is not supported by this type of constraint - return getType(); } // The constrained points should be in first and second positions, // so the expected value of aPt2d or aPt3d is 3 @@ -99,52 +111,25 @@ const int& SketchSolver_Constraint::getType(boost::shared_ptr anAttr = - boost::dynamic_pointer_cast( - theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)) - ); - if (!anAttr) continue; - if (anAttr->isObject() && anAttr->object()) - { // verify posiible entities - const std::string& aKind = boost::dynamic_pointer_cast - (anAttr->object())->getKind(); - if (aKind.compare(SketchPlugin_Point::ID()) == 0) - { + boost::shared_ptr anAttr = + theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)); + switch (typeOfAttribute(anAttr)) + { + case POINT2D: + case POINT3D: myAttributesList[aNbPoints++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); - continue; - } - else if(aKind.compare(SketchPlugin_Line::ID()) == 0) - { + break; + case LINE: // entities are placed starting from SketchPlugin_Constraint::ENTITY_C() attribute myAttributesList[2 + aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); myType = SLVS_C_PT_LINE_DISTANCE; - continue; - } - } - else - { // verify points - // Verify the attribute is a 2D point - boost::shared_ptr aPoint2D = - boost::dynamic_pointer_cast(anAttr->attr()); - if (aPoint2D) - { - myAttributesList[aNbPoints++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); - continue; - } - // Verify the attribute is a 3D point - boost::shared_ptr aPoint3D = - boost::dynamic_pointer_cast(anAttr->attr()); - if (aPoint3D) - { - myAttributesList[aNbPoints++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); - continue; - } + break; } } // Verify the correctness of constraint arguments if (aNbPoints == 2 && aNbEntities ==0) myType = SLVS_C_PT_PT_DISTANCE; - else if (aNbPoints == 1 && aNbEntities == 1) + else if (aNbPoints != 1 || aNbEntities != 1) myType = SLVS_C_UNKNOWN; return getType(); } @@ -155,18 +140,10 @@ const int& SketchSolver_Constraint::getType(boost::shared_ptr anAttr = - boost::dynamic_pointer_cast( - theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)) - ); - if (!anAttr) continue; - if (anAttr->isObject() && anAttr->object() && - boost::dynamic_pointer_cast(anAttr->object())->getKind(). - compare(SketchPlugin_Line::ID()) == 0) - { + boost::shared_ptr anAttr = + theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)); + if (typeOfAttribute(anAttr) == LINE) myAttributesList[aNbLines++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); - break; - } } if (aNbLines == 1) myType = SLVS_C_PT_PT_DISTANCE; @@ -178,21 +155,13 @@ const int& SketchSolver_Constraint::getType(boost::shared_ptr anAttr = - boost::dynamic_pointer_cast( - theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)) - ); - if (!anAttr || !anAttr->isObject() || !anAttr->object()) continue; - const std::string& aKind = boost::dynamic_pointer_cast - (anAttr->object())->getKind(); - if (aKind.compare(SketchPlugin_Line::ID()) == 0) - { + boost::shared_ptr anAttr = + theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)); + if (typeOfAttribute(anAttr) == LINE) myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); - continue; - } } if (aNbEntities == 4) myType = isParallel ? SLVS_C_PARALLEL : SLVS_C_PERPENDICULAR; @@ -205,25 +174,59 @@ const int& SketchSolver_Constraint::getType(boost::shared_ptr anAttr = - boost::dynamic_pointer_cast( - theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)) - ); - if (!anAttr || !anAttr->isObject() || !anAttr->object()) continue; - const std::string& aKind = boost::dynamic_pointer_cast - (anAttr->object())->getKind(); - if (aKind.compare(SketchPlugin_Circle::ID()) == 0 || aKind.compare(SketchPlugin_Arc::ID()) == 0) - { + boost::shared_ptr anAttr = + theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)); + AttrType aType = typeOfAttribute(anAttr); + if (aType == CIRCLE || aType == ARC) myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); - continue; - } } if (aNbEntities == 3) myType = SLVS_C_DIAMETER; return getType(); } - /// \todo Implement other kind of constrtaints + /// \todo Implement other kind of constraints return getType(); } + + +// ================= Auxiliary functions ============================== +AttrType typeOfAttribute(boost::shared_ptr theAttribute) +{ + boost::shared_ptr anAttrRef = + boost::dynamic_pointer_cast(theAttribute); + if (!anAttrRef) return UNKNOWN; + + if (anAttrRef->isObject()) + { + ResultConstructionPtr aRC = + boost::dynamic_pointer_cast(anAttrRef->object()); + if (!aRC) return UNKNOWN; + + if (aRC->shape()->isVertex()) + return POINT3D; + else if (aRC->shape()->isEdge()) + { + boost::shared_ptr anEdge = + boost::dynamic_pointer_cast(aRC->shape()); + if (anEdge->isLine()) + return LINE; + else if (anEdge->isCircle()) + return CIRCLE; + else if (anEdge->isArc()) + return ARC; + } + } + else + { + const std::string aType = anAttrRef->attr()->attributeType(); + if (aType == GeomDataAPI_Point2D::type()) + return POINT2D; + if (aType == GeomDataAPI_Point2D::type()) + return POINT2D; + } + + return UNKNOWN; +} + diff --git a/src/SketchSolver/SketchSolver_ConstraintGroup.cpp b/src/SketchSolver/SketchSolver_ConstraintGroup.cpp index 7a06355f4..2640da058 100644 --- a/src/SketchSolver/SketchSolver_ConstraintGroup.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintGroup.cpp @@ -13,7 +13,9 @@ #include #include #include +#include #include +#include #include #include @@ -137,10 +139,16 @@ bool SketchSolver_ConstraintGroup::isInteract( if (!aCAttrRef->isObject() && myEntityAttrMap.find(aCAttrRef->attr()) != myEntityAttrMap.end()) return true; - if (aCAttrRef->isObject() && - myEntityFeatMap.find(boost::dynamic_pointer_cast(aCAttrRef->object())) - != myEntityFeatMap.end()) - return true; + if (aCAttrRef->isObject()) + { // Obtain a base feature for the object + ResultConstructionPtr aRC = + boost::dynamic_pointer_cast(aCAttrRef->object()); + if (!aRC) continue; + boost::shared_ptr aDoc = aRC->document(); + FeaturePtr aFeature = aDoc->feature(aRC); + if (myEntityFeatMap.find(aFeature) != myEntityFeatMap.end()) + return true; + } } // Entities did not found @@ -204,18 +212,29 @@ bool SketchSolver_ConstraintGroup::changeConstraint( ); if (!aConstrAttr) continue; + // Convert the object of the attribute to the feature + FeaturePtr aFeature; + if (aConstrAttr->isObject() && aConstrAttr->object()) + { + ResultConstructionPtr aRC = + boost::dynamic_pointer_cast(aConstrAttr->object()); + if (!aRC) continue; + boost::shared_ptr aDoc = aRC->document(); + aFeature = aDoc->feature(aRC); + } + // For the length constraint the start and end points of the line should be added to the entities list instead of line if (aConstrType == SLVS_C_PT_PT_DISTANCE && theConstraint->getKind().compare(SketchPlugin_ConstraintLength::ID()) == 0) { - boost::shared_ptr aData = aConstrAttr->object()->data(); + boost::shared_ptr aData = aFeature->data(); aConstrEnt[indAttr] = changeEntity(aData->attribute(SketchPlugin_Line::START_ID())); aConstrEnt[indAttr+1] = changeEntity(aData->attribute(SketchPlugin_Line::END_ID())); - // measured object is added into the map of objects to avoid problems with interaction betwee constraint and group - myEntityFeatMap[boost::dynamic_pointer_cast(aConstrAttr->object())] = 0; + // measured object is added into the map of objects to avoid problems with interaction between constraint and group + myEntityFeatMap[aFeature] = 0; break; // there should be no other entities } else if (aConstrAttr->isObject()) - aConstrEnt[indAttr] = changeEntity(boost::dynamic_pointer_cast(aConstrAttr->object())); + aConstrEnt[indAttr] = changeEntity(aFeature); else aConstrEnt[indAttr] = changeEntity(aConstrAttr->attr()); } @@ -227,9 +246,7 @@ bool SketchSolver_ConstraintGroup::changeConstraint( if (aConstrType == SLVS_C_POINTS_COINCIDENT) { if (aConstrEnt[0] == aConstrEnt[1]) // no need to add self coincidence - { return false; - } if (!addCoincidentPoints(aConstrEnt[0], aConstrEnt[1])) { myExtraCoincidence.insert(theConstraint); // the constraint is stored for further purposes -- 2.39.2