From c90afd8fc02390be22cc8cef7ea570df148201b6 Mon Sep 17 00:00:00 2001 From: dbv Date: Wed, 13 Jul 2016 18:49:17 +0300 Subject: [PATCH] Issue #1649: Added options to create plane by coincident point; --- .../ConstructionPlugin_Plane.cpp | 108 ++++++++++++------ .../ConstructionPlugin_Plane.h | 8 ++ src/ConstructionPlugin/plane_widget.xml | 6 + src/GeomAlgoAPI/GeomAlgoAPI_FaceBuilder.cpp | 20 ++++ src/GeomAlgoAPI/GeomAlgoAPI_FaceBuilder.h | 4 + 5 files changed, 113 insertions(+), 33 deletions(-) diff --git a/src/ConstructionPlugin/ConstructionPlugin_Plane.cpp b/src/ConstructionPlugin/ConstructionPlugin_Plane.cpp index 40529c0c9..368bc3236 100644 --- a/src/ConstructionPlugin/ConstructionPlugin_Plane.cpp +++ b/src/ConstructionPlugin/ConstructionPlugin_Plane.cpp @@ -28,6 +28,8 @@ static GeomShapePtr faceByThreeVertices(const std::shared_ptr theV1, const std::shared_ptr theV2, const std::shared_ptr theV3); +static std::shared_ptr makeRectangularFace(const std::shared_ptr theFace, + const std::shared_ptr thePln); //================================================================================================== ConstructionPlugin_Plane::ConstructionPlugin_Plane() @@ -62,6 +64,7 @@ void ConstructionPlugin_Plane::initAttributes() data()->addAttribute(CREATION_METHOD_BY_OTHER_PLANE_OPTION(), ModelAPI_AttributeString::typeId()); data()->addAttribute(PLANE(), ModelAPI_AttributeSelection::typeId()); data()->addAttribute(DISTANCE(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(COINCIDENT_POINT(), ModelAPI_AttributeSelection::typeId()); } //================================================================================================== @@ -80,14 +83,17 @@ void ConstructionPlugin_Plane::execute() std::string aCreationMethodOption = string(CREATION_METHOD_BY_OTHER_PLANE_OPTION())->value(); if(aCreationMethodOption == CREATION_METHOD_BY_DISTANCE_FROM_OTHER()) { aShape = createByDistanceFromOther(); + } else if(aCreationMethodOption == CREATION_METHOD_BY_COINCIDENT_TO_POINT()) { + aShape = createByCoincidentPoint(); } } - if(!aShape.get()) { + setError("Error: Could not create a plane."); return; } + removeResults(0); ResultConstructionPtr aConstr = document()->createConstruction(data()); aConstr->setInfinite(true); aConstr->setShape(aShape); @@ -205,7 +211,7 @@ std::shared_ptr ConstructionPlugin_Plane::createByLineAndPoint() } //================================================================================================== -std::shared_ptr ConstructionPlugin_Plane::createByDistanceFromOther() +std::shared_ptr ConstructionPlugin_Plane::createByDistanceFromOther() { AttributeSelectionPtr aFaceAttr = data()->selection(ConstructionPlugin_Plane::PLANE()); AttributeDoublePtr aDistAttr = data()->real(ConstructionPlugin_Plane::DISTANCE()); @@ -233,41 +239,39 @@ std::shared_ptr ConstructionPlugin_Plane::createByDistanceFromOt aOrig->translate(aDir, aDist); std::shared_ptr aNewPln(new GeomAPI_Pln(aOrig, aDir)); - // Create rectangular face close to the selected - double aXmin, aYmin, Zmin, aXmax, aYmax, Zmax; - aFace->computeSize(aXmin, aYmin, Zmin, aXmax, aYmax, Zmax); - - // use all 8 points of the bounding box to find the 2D bounds - bool isFirst = true; - double aMinX2d, aMaxX2d, aMinY2d, aMaxY2d; - for(int aXIsMin = 0; aXIsMin < 2; aXIsMin++) { - for(int aYIsMin = 0; aYIsMin < 2; aYIsMin++) { - for(int aZIsMin = 0; aZIsMin < 2; aZIsMin++) { - std::shared_ptr aPnt(new GeomAPI_Pnt( - aXIsMin ? aXmin : aXmax, aYIsMin ? aYmin : aYmax, aZIsMin ? Zmin : Zmax)); - std::shared_ptr aPnt2d = aPnt->to2D(aNewPln); - if (isFirst || aPnt2d->x() < aMinX2d) - aMinX2d = aPnt2d->x(); - if (isFirst || aPnt2d->y() < aMinY2d) - aMinY2d = aPnt2d->y(); - if (isFirst || aPnt2d->x() > aMaxX2d) - aMaxX2d = aPnt2d->x(); - if (isFirst || aPnt2d->y() > aMaxY2d) - aMaxY2d = aPnt2d->y(); - if (isFirst) - isFirst = !isFirst; - } - } - } - double aWgap = (aMaxX2d - aMinX2d) * 0.1; - double aHgap = (aMaxY2d - aMinY2d) * 0.1; - aPlane = GeomAlgoAPI_FaceBuilder::planarFace(aNewPln, - aMinX2d - aWgap, aMinY2d - aHgap, aMaxX2d - aMinX2d + 2. * aWgap, aMaxY2d - aMinY2d + 2. * aHgap); - + aPlane = makeRectangularFace(aFace, aNewPln); } return aPlane; } +//================================================================================================== +std::shared_ptr ConstructionPlugin_Plane::createByCoincidentPoint() +{ + // Get face. + AttributeSelectionPtr aFaceSelection = selection(PLANE()); + GeomShapePtr aFaceShape = aFaceSelection->value(); + if(!aFaceShape.get()) { + aFaceShape = aFaceSelection->context()->shape(); + } + std::shared_ptr aFace(new GeomAPI_Face(aFaceShape)); + + // Get point. + AttributeSelectionPtr aPointSelection = selection(COINCIDENT_POINT()); + GeomShapePtr aPointShape = aPointSelection->value(); + if(!aPointShape.get()) { + aPointShape = aPointSelection->context()->shape(); + } + std::shared_ptr aVertex(new GeomAPI_Vertex(aPointShape)); + + std::shared_ptr anOrig = aVertex->point(); + std::shared_ptr aPln = aFace->getPlane(); + std::shared_ptr aDir = aPln->direction(); + + std::shared_ptr aNewPln(new GeomAPI_Pln(anOrig, aDir)); + + return makeRectangularFace(aFace, aNewPln); +} + //================================================================================================== GeomShapePtr faceByThreeVertices(const std::shared_ptr theV1, const std::shared_ptr theV2, @@ -284,3 +288,41 @@ GeomShapePtr faceByThreeVertices(const std::shared_ptr theV1, return aRes; } + +//================================================================================================== +std::shared_ptr makeRectangularFace(const std::shared_ptr theFace, + const std::shared_ptr thePln) +{ + // Create rectangular face close to the selected + double aXmin, aYmin, Zmin, aXmax, aYmax, Zmax; + theFace->computeSize(aXmin, aYmin, Zmin, aXmax, aYmax, Zmax); + + // use all 8 points of the bounding box to find the 2D bounds + bool isFirst = true; + double aMinX2d, aMaxX2d, aMinY2d, aMaxY2d; + for(int aXIsMin = 0; aXIsMin < 2; aXIsMin++) { + for(int aYIsMin = 0; aYIsMin < 2; aYIsMin++) { + for(int aZIsMin = 0; aZIsMin < 2; aZIsMin++) { + std::shared_ptr aPnt(new GeomAPI_Pnt( + aXIsMin ? aXmin : aXmax, aYIsMin ? aYmin : aYmax, aZIsMin ? Zmin : Zmax)); + std::shared_ptr aPnt2d = aPnt->to2D(thePln); + if (isFirst || aPnt2d->x() < aMinX2d) + aMinX2d = aPnt2d->x(); + if (isFirst || aPnt2d->y() < aMinY2d) + aMinY2d = aPnt2d->y(); + if (isFirst || aPnt2d->x() > aMaxX2d) + aMaxX2d = aPnt2d->x(); + if (isFirst || aPnt2d->y() > aMaxY2d) + aMaxY2d = aPnt2d->y(); + if (isFirst) + isFirst = !isFirst; + } + } + } + double aWgap = (aMaxX2d - aMinX2d) * 0.1; + double aHgap = (aMaxY2d - aMinY2d) * 0.1; + std::shared_ptr aResFace = GeomAlgoAPI_FaceBuilder::planarFace(thePln, + aMinX2d - aWgap, aMinY2d - aHgap, aMaxX2d - aMinX2d + 2. * aWgap, aMaxY2d - aMinY2d + 2. * aHgap); + + return aResFace; +} diff --git a/src/ConstructionPlugin/ConstructionPlugin_Plane.h b/src/ConstructionPlugin/ConstructionPlugin_Plane.h index 3bfecc7a7..d92f00811 100644 --- a/src/ConstructionPlugin/ConstructionPlugin_Plane.h +++ b/src/ConstructionPlugin/ConstructionPlugin_Plane.h @@ -159,6 +159,13 @@ public: return ATTR_ID; } + /// Attribute name for coincident point. + inline static const std::string& COINCIDENT_POINT() + { + static const std::string ATTR_ID("coincident_point"); + return ATTR_ID; + } + /// Attribute name for a parameter for the general equation of a plane (ax+by+cz+d=0) inline static const std::string& A() { @@ -205,6 +212,7 @@ protected: std::shared_ptr createByGeneralEquation(); std::shared_ptr createByThreePoints(); std::shared_ptr createByLineAndPoint(); + std::shared_ptr createByCoincidentPoint(); /// Creates a new plane by copy of face plane with translation along the normal /// to the specified distance. std::shared_ptr createByDistanceFromOther(); diff --git a/src/ConstructionPlugin/plane_widget.xml b/src/ConstructionPlugin/plane_widget.xml index 299e6ae35..6c8e2f966 100644 --- a/src/ConstructionPlugin/plane_widget.xml +++ b/src/ConstructionPlugin/plane_widget.xml @@ -74,6 +74,12 @@ title="By coincident to point" tooltip="Plane by coincident to point." icon="icons/Construction/plane_by_coincident_to_point_32x32.png"> + + GeomAlgoAPI_FaceBuilder::planarFaceByThreeVertices return aFace; } +//================================================================================================== +std::shared_ptr GeomAlgoAPI_FaceBuilder::planarFaceByFaceAndVertex( + const std::shared_ptr theFace, + const std::shared_ptr theVertex) +{ + gp_Pln aPln = theFace->getPlane()->impl(); + gp_Pnt aPnt = theVertex->point()->impl(); + + std::shared_ptr aFace; + GC_MakePlane aMakePlane(aPln, aPnt); + if(!aMakePlane.IsDone()) { + return aFace; + } + + BRepBuilderAPI_MakeFace aMakeFace(aMakePlane.Value()->Pln()); + aFace.reset(new GeomAPI_Face()); + aFace->setImpl(new TopoDS_Face(aMakeFace.Face())); + return aFace; +} + //================================================================================================== std::shared_ptr GeomAlgoAPI_FaceBuilder::plane(const std::shared_ptr theFace) { diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_FaceBuilder.h b/src/GeomAlgoAPI/GeomAlgoAPI_FaceBuilder.h index 603ed4620..c33013f02 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_FaceBuilder.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_FaceBuilder.h @@ -47,6 +47,10 @@ class GEOMALGOAPI_EXPORT GeomAlgoAPI_FaceBuilder const std::shared_ptr theVertex2, const std::shared_ptr theVertex3); + /// Creates a planar face parallel to theFace and passing through theVertex. + static std::shared_ptr planarFaceByFaceAndVertex(const std::shared_ptr theFace, + const std::shared_ptr theVertex); + /// Returns the plane of the planar face. If it is not planar, returns empty ptr. static std::shared_ptr plane(const std::shared_ptr theFace); }; -- 2.39.2