From ed85a646b6e504a93705b1a08af06674ec75c9e7 Mon Sep 17 00:00:00 2001 From: mpv Date: Thu, 7 Sep 2017 16:55:25 +0300 Subject: [PATCH] Issue #2209 : New option of creation of construction points --- src/ConstructionAPI/ConstructionAPI_Point.cpp | 64 +++++++++++++------ src/ConstructionAPI/ConstructionAPI_Point.h | 40 +++++++++--- src/ConstructionPlugin/CMakeLists.txt | 3 +- .../ConstructionPlugin_Plugin.cpp | 4 +- .../ConstructionPlugin_Point.cpp | 46 +++++++++---- .../ConstructionPlugin_Point.h | 36 +++++++++-- .../ConstructionPlugin_Validators.cpp | 32 +++++++--- .../ConstructionPlugin_Validators.h | 6 +- .../Test/TestAxisCreation.py | 2 + src/ConstructionPlugin/Test/TestPointName.py | 1 + .../Test/TestPoint_LineAndPlane.py | 55 ++++++++++++++++ .../Test/{TestPoint.py => TestPoint_XYZ.py} | 41 +----------- src/ConstructionPlugin/point_widget.xml | 19 +++--- src/GeomAPI/GeomAPI_Pln.cpp | 12 ---- src/GeomAPI/GeomAPI_Pln.h | 4 -- src/GeomAPI/GeomAPI_Shape.cpp | 10 +++ src/GeomAPI/GeomAPI_Shape.h | 6 ++ src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp | 47 ++++++++++++++ src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h | 6 ++ .../InitializationPlugin_Plugin.cpp | 1 + src/ModelAPI/Test/TestUndoRedo.py | 1 + .../Test/TestConstraintCoincidence.py | 1 + .../Test/TestConstraintMiddlePoint.py | 1 + 23 files changed, 309 insertions(+), 129 deletions(-) create mode 100644 src/ConstructionPlugin/Test/TestPoint_LineAndPlane.py rename src/ConstructionPlugin/Test/{TestPoint.py => TestPoint_XYZ.py} (50%) diff --git a/src/ConstructionAPI/ConstructionAPI_Point.cpp b/src/ConstructionAPI/ConstructionAPI_Point.cpp index 2656c55dc..48222cfc4 100644 --- a/src/ConstructionAPI/ConstructionAPI_Point.cpp +++ b/src/ConstructionAPI/ConstructionAPI_Point.cpp @@ -56,7 +56,7 @@ ConstructionAPI_Point::ConstructionAPI_Point(const std::shared_ptr& theFeature, @@ -67,19 +67,19 @@ ConstructionAPI_Point::ConstructionAPI_Point(const std::shared_ptrdocument()); - - AttributeDoublePtr anAttrX = aBase->real(ConstructionPlugin_Point::X()); - AttributeDoublePtr anAttrY = aBase->real(ConstructionPlugin_Point::Y()); - AttributeDoublePtr anAttrZ = aBase->real(ConstructionPlugin_Point::Z()); - theDumper << aBase << " = model.addPoint(" << aDocName << ", " - << anAttrX << ", " << anAttrY << ", " << anAttrZ << ")" << std::endl; + const std::string& aMeth = creationMethod()->value(); + + // common part + theDumper << aBase << " = model.addPoint(" << aDocName << ", "; + + if (aMeth == "" || // default is XYZ + aMeth == ConstructionPlugin_Point::CREATION_METHOD_BY_XYZ()) { + theDumper << x() << ", " << y() << ", " << z() << ")" << std::endl; + } else if (aMeth == ConstructionPlugin_Point::CREATION_METHOD_BY_LINE_AND_PLANE_INTERSECTION()) { + theDumper << intersectionLine() << ", " <value().empty()) { // call method with defined offset + theDumper << ", " << offset() << ", " << reverseOffset(); + } + theDumper << ")" << std::endl; + } } //================================================================================================== @@ -180,17 +189,32 @@ PointPtr addPoint(const std::shared_ptr & thePart, const bool theDistancePercent, const bool theReverse) { - // TODO(spo): check that thePart is not empty std::shared_ptr aFeature = thePart->addFeature(ConstructionAPI_Point::ID()); return PointPtr(new ConstructionAPI_Point(aFeature, theEdge, theDistanceValue, theDistancePercent, theReverse)); -} +}*/ //================================================================================================== PointPtr addPoint(const std::shared_ptr & thePart, const ModelHighAPI_Selection& theObject1, const ModelHighAPI_Selection& theObject2) { - // TODO(spo): check that thePart is not empty std::shared_ptr aFeature = thePart->addFeature(ConstructionAPI_Point::ID()); return PointPtr(new ConstructionAPI_Point(aFeature, theObject1, theObject2)); -}*/ +} + +//================================================================================================== +PointPtr addPoint(const std::shared_ptr & thePart, + const ModelHighAPI_Selection& theObject1, + const ModelHighAPI_Selection& theObject2, + const ModelHighAPI_Double& theDistanceValue, + const bool theReverse) +{ + std::shared_ptr aFeature = thePart->addFeature(ConstructionAPI_Point::ID()); + PointPtr anAPI(new ConstructionAPI_Point(aFeature, theObject1, theObject2)); + + fillAttribute(ConstructionPlugin_Point::USE_OFFSET(), anAPI->useOffset()); + fillAttribute(theDistanceValue, anAPI->offset()); + fillAttribute(theReverse, anAPI->reverseOffset()); + + return anAPI; +} diff --git a/src/ConstructionAPI/ConstructionAPI_Point.h b/src/ConstructionAPI/ConstructionAPI_Point.h index eb5f06719..322176c4a 100644 --- a/src/ConstructionAPI/ConstructionAPI_Point.h +++ b/src/ConstructionAPI/ConstructionAPI_Point.h @@ -56,21 +56,33 @@ public: const ModelHighAPI_Double& theDistanceValue, const bool theDistancePercent = false, const bool theReverse = false); - - /// Constructor with values. + */ + /// Constructor with values: intersected objects. CONSTRUCTIONAPI_EXPORT ConstructionAPI_Point(const std::shared_ptr& theFeature, const ModelHighAPI_Selection& theObject1, - const ModelHighAPI_Selection& theObject2);*/ + const ModelHighAPI_Selection& theObject2); /// Destructor. CONSTRUCTIONAPI_EXPORT virtual ~ConstructionAPI_Point(); - INTERFACE_3(ConstructionPlugin_Point::ID(), + INTERFACE_9(ConstructionPlugin_Point::ID(), x, ConstructionPlugin_Point::X(), ModelAPI_AttributeDouble, /** X attribute */, y, ConstructionPlugin_Point::Y(), ModelAPI_AttributeDouble, /** Y attribute */, - z, ConstructionPlugin_Point::Z(), ModelAPI_AttributeDouble, /** Z attribute */) + z, ConstructionPlugin_Point::Z(), ModelAPI_AttributeDouble, /** Z attribute */, + creationMethod, ConstructionPlugin_Point::CREATION_METHOD(), + ModelAPI_AttributeString, /** Creation method */, + intersectionLine, ConstructionPlugin_Point::INTERSECTION_LINE(), + ModelAPI_AttributeSelection, /** Line for intersection */, + intersectionPlane, ConstructionPlugin_Point::INTERSECTION_PLANE(), + ModelAPI_AttributeSelection, /** Plane for intersection */, + useOffset, ConstructionPlugin_Point::USE_OFFSET(), + ModelAPI_AttributeString, /** Use offset */, + offset, ConstructionPlugin_Point::OFFSET(), + ModelAPI_AttributeDouble, /** Offset */, + reverseOffset, ConstructionPlugin_Point::REVERSE_OFFSET(), + ModelAPI_AttributeBoolean, /** Reverse offset */) /// Set point values. @@ -95,11 +107,11 @@ public: CONSTRUCTIONAPI_EXPORT void setByLinesIntersection(const ModelHighAPI_Selection& theEdge1, const ModelHighAPI_Selection& theEdge2); - + */ /// Set line and plane for intersections. CONSTRUCTIONAPI_EXPORT void setByLineAndPlaneIntersection(const ModelHighAPI_Selection& theEdge, - const ModelHighAPI_Selection& theFace);*/ + const ModelHighAPI_Selection& theFace); /// Dump wrapped feature CONSTRUCTIONAPI_EXPORT @@ -125,12 +137,22 @@ PointPtr addPoint(const std::shared_ptr & thePart, const ModelHighAPI_Double& theDistanceValue, const bool theDistancePercent = false, const bool theReverse = false); +*/ +/// \ingroup CPPHighAPI +/// \brief Create Point feature as an intersection of selected plane (or planar face) and edge +CONSTRUCTIONAPI_EXPORT +PointPtr addPoint(const std::shared_ptr & thePart, + const ModelHighAPI_Selection& theObject1, + const ModelHighAPI_Selection& theObject2); /// \ingroup CPPHighAPI -/// \brief Create Point feature +/// \brief Create Point feature as an intersection of selected plane (or planar face) and edge +/// with positive distance from the plane and flag to reverse the offset direction. CONSTRUCTIONAPI_EXPORT PointPtr addPoint(const std::shared_ptr & thePart, const ModelHighAPI_Selection& theObject1, - const ModelHighAPI_Selection& theObject2);*/ + const ModelHighAPI_Selection& theObject2, + const ModelHighAPI_Double& theDistanceValue, + const bool theReverse = false); #endif /* SRC_CONSTRUCTIONAPI_CONSTRUCTIONAPI_POINT_H_ */ diff --git a/src/ConstructionPlugin/CMakeLists.txt b/src/ConstructionPlugin/CMakeLists.txt index 96e79ceda..0cbcec049 100644 --- a/src/ConstructionPlugin/CMakeLists.txt +++ b/src/ConstructionPlugin/CMakeLists.txt @@ -77,6 +77,7 @@ INCLUDE_DIRECTORIES( ADD_UNIT_TESTS(TestAxisCreation.py UnitTestAxis.py - TestPoint.py + TestPoint_XYZ.py + TestPoint_LineAndPlane.py TestPointName.py TestPlane.py) diff --git a/src/ConstructionPlugin/ConstructionPlugin_Plugin.cpp b/src/ConstructionPlugin/ConstructionPlugin_Plugin.cpp index 04864cfb6..9f18a3318 100644 --- a/src/ConstructionPlugin/ConstructionPlugin_Plugin.cpp +++ b/src/ConstructionPlugin/ConstructionPlugin_Plugin.cpp @@ -42,8 +42,8 @@ ConstructionPlugin_Plugin::ConstructionPlugin_Plugin() ModelAPI_ValidatorsFactory* aFactory = aMgr->validators(); aFactory->registerValidator("ConstructionPlugin_ValidatorPointLines", new ConstructionPlugin_ValidatorPointLines()); - aFactory->registerValidator("ConstructionPlugin_ValidatorPointLineAndPlaneNotParallel", - new ConstructionPlugin_ValidatorPointLineAndPlaneNotParallel()); + aFactory->registerValidator("ConstructionPlugin_ValidatorPointEdgeAndPlaneNotParallel", + new ConstructionPlugin_ValidatorPointEdgeAndPlaneNotParallel()); aFactory->registerValidator("ConstructionPlugin_ValidatorPlaneThreePoints", new ConstructionPlugin_ValidatorPlaneThreePoints()); aFactory->registerValidator("ConstructionPlugin_ValidatorPlaneLinePoint", diff --git a/src/ConstructionPlugin/ConstructionPlugin_Point.cpp b/src/ConstructionPlugin/ConstructionPlugin_Point.cpp index 43f2e78e2..f08cd5fa4 100644 --- a/src/ConstructionPlugin/ConstructionPlugin_Point.cpp +++ b/src/ConstructionPlugin/ConstructionPlugin_Point.cpp @@ -27,10 +27,12 @@ #include #include +#include #include #include #include +#include //================================================================================================== ConstructionPlugin_Point::ConstructionPlugin_Point() @@ -47,12 +49,12 @@ const std::string& ConstructionPlugin_Point::getKind() //================================================================================================== void ConstructionPlugin_Point::initAttributes() { - //data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId()); - data()->addAttribute(X(), ModelAPI_AttributeDouble::typeId()); data()->addAttribute(Y(), ModelAPI_AttributeDouble::typeId()); data()->addAttribute(Z(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId()); + /*data()->addAttribute(EDGE(), ModelAPI_AttributeSelection::typeId()); data()->addAttribute(DISTANCE_VALUE(), ModelAPI_AttributeDouble::typeId()); data()->addAttribute(DISTANCE_PERCENT(), ModelAPI_AttributeBoolean::typeId()); @@ -63,32 +65,38 @@ void ConstructionPlugin_Point::initAttributes() data()->addAttribute(FIRST_LINE(), ModelAPI_AttributeSelection::typeId()); data()->addAttribute(SECOND_LINE(), ModelAPI_AttributeSelection::typeId()); - +*/ data()->addAttribute(INTERSECTION_LINE(), ModelAPI_AttributeSelection::typeId()); - data()->addAttribute(INTERSECTION_PLANE(), ModelAPI_AttributeSelection::typeId());*/ + data()->addAttribute(INTERSECTION_PLANE(), ModelAPI_AttributeSelection::typeId()); + + data()->addAttribute(USE_OFFSET(), ModelAPI_AttributeString::typeId()); + data()->addAttribute(OFFSET(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(REVERSE_OFFSET(), ModelAPI_AttributeBoolean::typeId()); } //================================================================================================== void ConstructionPlugin_Point::execute() { - GeomShapePtr aShape = createByXYZ(); - - /*GeomShapePtr aShape; + GeomShapePtr aShape; - std::string aCreationMethod = string(CREATION_METHOD())->value(); + // to support compatibility with old documents where aCreationMethod did not exist + std::string aCreationMethod = + string(CREATION_METHOD()).get() && !string(CREATION_METHOD())->value().empty() ? + string(CREATION_METHOD())->value() : CREATION_METHOD_BY_XYZ(); if(aCreationMethod == CREATION_METHOD_BY_XYZ()) { aShape = createByXYZ(); - } else if(aCreationMethod == CREATION_METHOD_BY_DISTANCE_ON_EDGE()) { + }/* else if(aCreationMethod == CREATION_METHOD_BY_DISTANCE_ON_EDGE()) { aShape = createByDistanceOnEdge(); } else if(aCreationMethod == CREATION_METHOD_BY_PROJECTION()) { aShape = createByProjection(); } else if(aCreationMethod == CREATION_METHOD_BY_LINES_INTERSECTION()) { aShape = createByLinesIntersection(); - } else if(aCreationMethod == CREATION_METHOD_BY_LINE_AND_PLANE_INTERSECTION()) { + }*/ else if(aCreationMethod == CREATION_METHOD_BY_LINE_AND_PLANE_INTERSECTION()) { aShape = createByLineAndPlaneIntersection(); - }*/ + } if(!aShape.get()) { + setError("Error: intersection not found."); return; } @@ -180,12 +188,13 @@ std::shared_ptr ConstructionPlugin_Point::createByLinesIntersect return GeomAlgoAPI_PointBuilder::vertexByIntersection(aFirstEdge, aSecondEdge); } +*/ //================================================================================================== std::shared_ptr ConstructionPlugin_Point::createByLineAndPlaneIntersection() { // Get line. - AttributeSelectionPtr aLineSelection= selection(INTERSECTION_LINE()); + AttributeSelectionPtr aLineSelection = selection(INTERSECTION_LINE()); GeomShapePtr aLineShape = aLineSelection->value(); if(!aLineShape.get()) { aLineShape = aLineSelection->context()->shape(); @@ -200,5 +209,14 @@ std::shared_ptr ConstructionPlugin_Point::createByLineAndPlaneIn } std::shared_ptr aFace(new GeomAPI_Face(aPlaneShape)); - return GeomAlgoAPI_PointBuilder::vertexByIntersection(anEdge, aFace); -}*/ + if (!string(USE_OFFSET())->value().empty()) { + double anOffset = real(OFFSET())->value(); + if (boolean(REVERSE_OFFSET())->value()) + anOffset = -anOffset; + if (fabs(anOffset) > 1.e-9) { // move face + aFace->translate(aFace->getPlane()->direction(), anOffset); + } + } + + return GeomAlgoAPI_ShapeTools::intersect(anEdge, aFace); +} diff --git a/src/ConstructionPlugin/ConstructionPlugin_Point.h b/src/ConstructionPlugin/ConstructionPlugin_Point.h index e9efd6ab0..346fe8022 100644 --- a/src/ConstructionPlugin/ConstructionPlugin_Point.h +++ b/src/ConstructionPlugin/ConstructionPlugin_Point.h @@ -45,7 +45,7 @@ public: return CONSTRUCTION_POINT_KIND; } - /*/// Attribute name for creation method. + /// Attribute name for creation method. inline static const std::string& CREATION_METHOD() { static const std::string MY_CREATION_METHOD_ID("creation_method"); @@ -58,7 +58,7 @@ public: static const std::string MY_CREATION_METHOD_ID("by_xyz"); return MY_CREATION_METHOD_ID; } - + /* /// Attribute name for creation method. inline static const std::string& CREATION_METHOD_BY_DISTANCE_ON_EDGE() { @@ -79,13 +79,13 @@ public: static const std::string MY_CREATION_METHOD_ID("by_lines_intersection"); return MY_CREATION_METHOD_ID; } - + */ /// Attribute name for creation method. inline static const std::string& CREATION_METHOD_BY_LINE_AND_PLANE_INTERSECTION() { static const std::string MY_CREATION_METHOD_ID("by_line_and_plane_intersection"); return MY_CREATION_METHOD_ID; - }*/ + } /// Attribute name for X coordinate. inline static const std::string& X() @@ -163,6 +163,7 @@ public: static const std::string ATTR_ID("second_line"); return ATTR_ID; } + */ /// Attribute name for selected intersection line. inline static const std::string& INTERSECTION_LINE() @@ -176,7 +177,28 @@ public: { static const std::string ATTR_ID("intersection_plane"); return ATTR_ID; - }*/ + } + + /// Attribute name for use offset for the intersection plane. + inline static const std::string& USE_OFFSET() + { + static const std::string ATTR_ID("use_offset"); + return ATTR_ID; + } + + /// Attribute name for offset for the intersection plane. + inline static const std::string& OFFSET() + { + static const std::string ATTR_ID("offset"); + return ATTR_ID; + } + + /// Attribute name for reverse offset for the intersection plane. + inline static const std::string& REVERSE_OFFSET() + { + static const std::string ATTR_ID("reverse_offset"); + return ATTR_ID; + } /// Creates a new part document if needed. CONSTRUCTIONPLUGIN_EXPORT virtual void execute(); @@ -198,8 +220,8 @@ private: std::shared_ptr createByXYZ(); /*std::shared_ptr createByDistanceOnEdge(); std::shared_ptr createByProjection(); - std::shared_ptr createByLinesIntersection(); - std::shared_ptr createByLineAndPlaneIntersection();*/ + std::shared_ptr createByLinesIntersection();*/ + std::shared_ptr createByLineAndPlaneIntersection(); }; diff --git a/src/ConstructionPlugin/ConstructionPlugin_Validators.cpp b/src/ConstructionPlugin/ConstructionPlugin_Validators.cpp index 33d98d704..a3bd2bd53 100644 --- a/src/ConstructionPlugin/ConstructionPlugin_Validators.cpp +++ b/src/ConstructionPlugin/ConstructionPlugin_Validators.cpp @@ -26,12 +26,14 @@ #include #include #include +#include #include #include #include +static std::shared_ptr getEdge(const GeomShapePtr theShape); static std::shared_ptr getLin(const GeomShapePtr theShape); static std::shared_ptr getPln(const GeomShapePtr theShape); static std::shared_ptr getPnt(const GeomShapePtr theShape); @@ -94,7 +96,7 @@ bool ConstructionPlugin_ValidatorPointLines::isValid(const AttributePtr& theAttr } //================================================================================================== -bool ConstructionPlugin_ValidatorPointLineAndPlaneNotParallel::isValid( +bool ConstructionPlugin_ValidatorPointEdgeAndPlaneNotParallel::isValid( const AttributePtr& theAttribute, const std::list& theArguments, Events_InfoMessage& theError) const @@ -105,7 +107,7 @@ bool ConstructionPlugin_ValidatorPointLineAndPlaneNotParallel::isValid( std::dynamic_pointer_cast(theAttribute); AttributeSelectionPtr anAttribute2 = aFeature->selection(theArguments.front()); - std::shared_ptr aLin; + std::shared_ptr anEdge; std::shared_ptr aPln; GeomShapePtr aShape1 = anAttribute1->value(); @@ -127,20 +129,23 @@ bool ConstructionPlugin_ValidatorPointLineAndPlaneNotParallel::isValid( aShape2 = aContext2->shape(); } - aLin = getLin(aShape1); + bool isPlaneFirst = false; + anEdge = getEdge(aShape1); aPln = getPln(aShape2); - if(!aLin.get() || !aPln.get()) { - aLin = getLin(aShape2); + if(!anEdge.get() || !aPln.get()) { + anEdge = getEdge(aShape2); aPln = getPln(aShape1); + isPlaneFirst = true; } - if(!aLin.get() || !aPln.get()) { + if(!anEdge.get() || !aPln.get()) { theError = "Wrong shape types selected."; return false; } - if(aPln->isParallel(aLin)) { - theError = "Plane and line are parallel."; + std::shared_ptr aPlaneFace(new GeomAPI_Face(isPlaneFirst ? aShape1 : aShape2)); + if(GeomAlgoAPI_ShapeTools::isParallel(anEdge, aPlaneFace)) { + theError = "Plane and edge are parallel."; return false; } @@ -381,6 +386,17 @@ bool ConstructionPlugin_ValidatorAxisTwoNotParallelPlanes::isValid( return true; } +std::shared_ptr getEdge(const GeomShapePtr theShape) +{ + if(!theShape->isEdge()) { + return std::shared_ptr(); + } + + std::shared_ptr anEdge(new GeomAPI_Edge(theShape)); + + return anEdge; +} + std::shared_ptr getLin(const GeomShapePtr theShape) { std::shared_ptr aLin; diff --git a/src/ConstructionPlugin/ConstructionPlugin_Validators.h b/src/ConstructionPlugin/ConstructionPlugin_Validators.h index cb13f6abb..3254672de 100644 --- a/src/ConstructionPlugin/ConstructionPlugin_Validators.h +++ b/src/ConstructionPlugin/ConstructionPlugin_Validators.h @@ -38,10 +38,10 @@ public: Events_InfoMessage& theError) const; }; -/// \class ConstructionPlugin_ValidatorPointLineAndPlaneNotParallel +/// \class ConstructionPlugin_ValidatorPointEdgeAndPlaneNotParallel /// \ingroup Validators -/// \brief A validator for selection line and plane for point by intersection. -class ConstructionPlugin_ValidatorPointLineAndPlaneNotParallel: public ModelAPI_AttributeValidator +/// \brief A validator for selection edge and plane for point by intersection. +class ConstructionPlugin_ValidatorPointEdgeAndPlaneNotParallel: public ModelAPI_AttributeValidator { public: //! \return True if the attribute is valid. diff --git a/src/ConstructionPlugin/Test/TestAxisCreation.py b/src/ConstructionPlugin/Test/TestAxisCreation.py index 80db16361..a645c548e 100644 --- a/src/ConstructionPlugin/Test/TestAxisCreation.py +++ b/src/ConstructionPlugin/Test/TestAxisCreation.py @@ -52,6 +52,7 @@ assert(aPointFeatureData is not None) aPointFeatureData.real("x").setValue(0.) aPointFeatureData.real("y").setValue(0.) aPointFeatureData.real("z").setValue(0.) +aPointFeatureData.string("creation_method").setValue("by_xyz") aPointFeature.execute() aSession.finishOperation() aPoint1Result = aPointFeature.firstResult(); @@ -67,6 +68,7 @@ assert(aPointFeatureData is not None) aPointFeatureData.real("x").setValue(0.) aPointFeatureData.real("y").setValue(0.) aPointFeatureData.real("z").setValue(100.) +aPointFeatureData.string("creation_method").setValue("by_xyz") aPointFeature.execute() aSession.finishOperation() aPoint2Result = aPointFeature.firstResult(); diff --git a/src/ConstructionPlugin/Test/TestPointName.py b/src/ConstructionPlugin/Test/TestPointName.py index 33ff527c4..557970091 100644 --- a/src/ConstructionPlugin/Test/TestPointName.py +++ b/src/ConstructionPlugin/Test/TestPointName.py @@ -31,6 +31,7 @@ assert(aFeatureData is not None) aFeatureData.real("x").setValue(0.) aFeatureData.real("y").setValue(0.) aFeatureData.real("z").setValue(0.) +aFeatureData.string("creation_method").setValue("by_xyz") aFeatureName = aFeature.name() aFeature.execute() aSession.finishOperation() diff --git a/src/ConstructionPlugin/Test/TestPoint_LineAndPlane.py b/src/ConstructionPlugin/Test/TestPoint_LineAndPlane.py new file mode 100644 index 000000000..635ab8102 --- /dev/null +++ b/src/ConstructionPlugin/Test/TestPoint_LineAndPlane.py @@ -0,0 +1,55 @@ +## Copyright (C) 2014-2017 CEA/DEN, EDF R&D +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## +## See http:##www.salome-platform.org/ or +## email : webmaster.salome@opencascade.com +## + +""" +Test case for Construction Point feature as intersection of line and plane. +""" + +from salome.shaper import model +from GeomAPI import * + +model.begin() +partSet = model.moduleDocument() +Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY")) +SketchPoint_1 = Sketch_1.addPoint(model.selection("VERTEX", "Origin")) +SketchCircle_1 = Sketch_1.addCircle(0, 0, 60) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center()) +model.do() +Sketch_2 = model.addSketch(partSet, model.defaultPlane("XOZ")) +SketchLine_1 = Sketch_2.addLine(60, 100, 0, 20) +SketchArc_1 = Sketch_2.addArc(0, 0, -65.89631323066888, 61.2998850129882, -90, 0, False) +model.do() + +# point by sketch face and a line +Point_1 = model.addPoint(partSet, model.selection("EDGE", "Sketch_2/Edge-SketchLine_1"), model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")) +model.do() +# check the point position +rightPosition = GeomAPI_Vertex(-15, 0, 0) +assert(rightPosition.isEqual(Point_1.results()[0].resultSubShapePair()[0].shape())) + +# point by sketch face and an arc, intersection outside of the face, offset is defined +Point_2 = model.addPoint(partSet, model.selection("EDGE", "Sketch_2/Edge-SketchArc_1"), model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f"), 10, True) +# check the point position +rightPosition = GeomAPI_Vertex(-89.442719099991606, 0, -10) +assert(rightPosition.isEqual(Point_2.results()[0].resultSubShapePair()[0].shape())) + + +model.end() +assert(model.checkPythonDump()) diff --git a/src/ConstructionPlugin/Test/TestPoint.py b/src/ConstructionPlugin/Test/TestPoint_XYZ.py similarity index 50% rename from src/ConstructionPlugin/Test/TestPoint.py rename to src/ConstructionPlugin/Test/TestPoint_XYZ.py index 4241bc5f1..df73e5fd1 100644 --- a/src/ConstructionPlugin/Test/TestPoint.py +++ b/src/ConstructionPlugin/Test/TestPoint_XYZ.py @@ -19,7 +19,7 @@ ## """ -Test case for Construction Point feature. Written on High API. +Test case for Construction Point feature by coordinates. """ from ModelAPI import * from GeomAPI import * @@ -42,43 +42,4 @@ aPoint = model.addPoint(aDocument, 50, 50, 50) aSession.finishOperation() assert (len(aPoint.results()) > 0) -# # Create a sketch with lines -# aSession.startOperation() -# anOrigin = GeomAPI_Pnt(0, 0, 0) -# aDirX = GeomAPI_Dir(1, 0, 0) -# aNorm = GeomAPI_Dir(0, 0, 1) -# aSketch = model.addSketch(aDocument, GeomAPI_Ax3(anOrigin, aDirX, aNorm)) -# aSketchLine1 = aSketch.addLine(0, 0, 100, 100) -# aSketchLine2 = aSketch.addLine(0, 100, 100, 0) -# aSession.finishOperation() -# -# # Create a point on line -# aSession.startOperation() -# aPoint = model.addPoint(aDocument, aSketchLine1.result()[0], 25, True, False) -# aSession.finishOperation() -# assert (len(aPoint.result()) > 0) -# -# # Create plane -# aSession.startOperation() -# aPlane = model.addPlane(aDocument, 1, 1, 1, 1) -# aSession.finishOperation() -# -# # Create a point by projection -# aSession.startOperation() -# aPoint = model.addPoint(aDocument, aPoint.result()[0], aPlane.result()[0]) -# aSession.finishOperation() -# assert (len(aPoint.result()) > 0) -# -# # Create a point by lines intersection -# aSession.startOperation() -# aPoint = model.addPoint(aDocument, aSketchLine1.result()[0], aSketchLine2.result()[0]) -# aSession.finishOperation() -# assert (len(aPoint.result()) > 0) -# -# # Create a point by line and plane intersection -# aSession.startOperation() -# aPoint = model.addPoint(aDocument, aSketchLine1.result()[0], aPlane.result()[0]) -# aSession.finishOperation() -# assert (len(aPoint.result()) > 0) - assert(model.checkPythonDump()) diff --git a/src/ConstructionPlugin/point_widget.xml b/src/ConstructionPlugin/point_widget.xml index 42368daf2..20f2f3cb9 100644 --- a/src/ConstructionPlugin/point_widget.xml +++ b/src/ConstructionPlugin/point_widget.xml @@ -20,11 +20,7 @@ email : webmaster.salome@opencascade.com - - - - - - - + - + + + + + - --> + diff --git a/src/GeomAPI/GeomAPI_Pln.cpp b/src/GeomAPI/GeomAPI_Pln.cpp index f7950f6f1..60e417c7c 100644 --- a/src/GeomAPI/GeomAPI_Pln.cpp +++ b/src/GeomAPI/GeomAPI_Pln.cpp @@ -81,18 +81,6 @@ bool GeomAPI_Pln::isCoincident(const std::shared_ptr thePlane, aMyPln.Axis().IsParallel(anOtherPln.Axis(), theTolerance)); } -bool GeomAPI_Pln::isParallel(const std::shared_ptr theLine) -{ - 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); - return Abs(aDot) < Precision::SquareConfusion(); -} - std::shared_ptr GeomAPI_Pln::intersect(const std::shared_ptr& theLine) const { diff --git a/src/GeomAPI/GeomAPI_Pln.h b/src/GeomAPI/GeomAPI_Pln.h index 14d886ee3..863a72f61 100644 --- a/src/GeomAPI/GeomAPI_Pln.h +++ b/src/GeomAPI/GeomAPI_Pln.h @@ -70,10 +70,6 @@ class GeomAPI_Pln : public GeomAPI_Interface GEOMAPI_EXPORT bool isCoincident(const std::shared_ptr thePlane, const double theTolerance = 1.e-7); - /// Returns true if plane is parallel to theLine. - GEOMAPI_EXPORT - bool isParallel(const std::shared_ptr theLine); - /// Returns intersection point or empty if no intersections GEOMAPI_EXPORT std::shared_ptr intersect(const std::shared_ptr& theLine) const; diff --git a/src/GeomAPI/GeomAPI_Shape.cpp b/src/GeomAPI/GeomAPI_Shape.cpp index fd1d6adeb..c1df33555 100644 --- a/src/GeomAPI/GeomAPI_Shape.cpp +++ b/src/GeomAPI/GeomAPI_Shape.cpp @@ -490,3 +490,13 @@ bool GeomAPI_Shape::isIntersect(const GeomShapePtr theShape) const return false; } + +void GeomAPI_Shape::translate(const std::shared_ptr theDir, const double theOffset) +{ + gp_Dir aDir = theDir->impl(); + gp_Vec aTrsfVec(aDir.XYZ() * theOffset); + gp_Trsf aTranslation; + aTranslation.SetTranslation(aTrsfVec); + TopoDS_Shape aResult = MY_SHAPE->Moved(aTranslation); + setImpl(new TopoDS_Shape(aResult)); +} diff --git a/src/GeomAPI/GeomAPI_Shape.h b/src/GeomAPI/GeomAPI_Shape.h index c7345461b..4e148978c 100644 --- a/src/GeomAPI/GeomAPI_Shape.h +++ b/src/GeomAPI/GeomAPI_Shape.h @@ -21,6 +21,8 @@ #ifndef GeomAPI_Shape_H_ #define GeomAPI_Shape_H_ +#include "GeomAPI_Dir.h" + #include #include #include @@ -142,6 +144,10 @@ public: /// Returns true if min distance between shapes < tolerance. GEOMAPI_EXPORT bool isIntersect(const std::shared_ptr theShape) const; + + // Translates the shape along the direction for the given offset + GEOMAPI_EXPORT + void translate(const std::shared_ptr theDir, const double theOffset); }; //! Pointer on list of shapes diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp index da5fa0ac0..2886fa7b4 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -50,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -67,6 +69,7 @@ #include #include + #include #include #include @@ -707,6 +710,50 @@ bool GeomAlgoAPI_ShapeTools::isParallel(const std::shared_ptr theE return anExt.IsParallel() == Standard_True; } +//================================================================================================== +std::shared_ptr GeomAlgoAPI_ShapeTools::intersect( + const std::shared_ptr theEdge, const std::shared_ptr theFace) +{ + if(!theEdge.get() || !theFace.get()) { + return false; + } + + TopoDS_Edge anEdge = TopoDS::Edge(theEdge->impl()); + double aFirstOnCurve, aLastOnCurve; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirstOnCurve, aLastOnCurve); + + TopoDS_Face aFace = TopoDS::Face(theFace->impl()); + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace); + + GeomAPI_ExtremaCurveSurface anExt(aCurve, aSurf); + // searching for the best point-intersection + int aMaxLevel = 0; + gp_Pnt aResult; + for(int anIntNum = 1; anIntNum <= anExt.NbExtrema(); anIntNum++) { + if (anExt.Distance(anIntNum) > Precision::Confusion()) + continue; + Standard_Real aW, aU, aV; + anExt.Parameters(anIntNum, aW, aU, aV); + gp_Pnt2d aPointOfSurf(aU, aV); + // level of the intersection: if it is inside of edge and/or face the level is higher + int aIntLevel = aW > aFirstOnCurve && aW < aLastOnCurve ? 2 : 1; + BRepClass_FaceClassifier aFClass(aFace, aPointOfSurf, Precision::Confusion()); + if (aFClass.State() == TopAbs_IN) // "in" is better than "on" + aIntLevel += 2; + else if (aFClass.State() == TopAbs_ON) + aIntLevel += 1; + if (aMaxLevel < aIntLevel) { + aMaxLevel = anIntNum; + anExt.Points(anIntNum, aResult, aResult); + } + } + if (aMaxLevel > 0) { // intersection found + return std::shared_ptr( + new GeomAPI_Vertex(aResult.X(), aResult.Y(), aResult.Z())); + } + return std::shared_ptr(); // no intersection found +} + //================================================================================================== void GeomAlgoAPI_ShapeTools::splitShape(const std::shared_ptr& theBaseShape, const GeomAlgoAPI_ShapeTools::PointToRefsMap& thePointsInfo, diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h index ba530ebd5..2e48c96bb 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h @@ -133,6 +133,12 @@ public: GEOMALGOAPI_EXPORT static bool isParallel(const std::shared_ptr theEdge, const std::shared_ptr theFace); + // Computes intersection point between the edge curve and a face surface (only one point, with + // preferences to point that belongs to edge and face boundaries. + /// \returns null if there is no intersection + GEOMALGOAPI_EXPORT static std::shared_ptr intersect( + const std::shared_ptr theEdge, const std::shared_ptr theFace); + typedef std::map, std::pair >, std::list > > > PointToRefsMap; diff --git a/src/InitializationPlugin/InitializationPlugin_Plugin.cpp b/src/InitializationPlugin/InitializationPlugin_Plugin.cpp index 0d10a4b15..5d4781494 100644 --- a/src/InitializationPlugin/InitializationPlugin_Plugin.cpp +++ b/src/InitializationPlugin/InitializationPlugin_Plugin.cpp @@ -141,6 +141,7 @@ FeaturePtr InitializationPlugin_Plugin::createPoint(DocumentPtr theDoc, const st aPoint->real("x")->setValue(theX); aPoint->real("y")->setValue(theY); aPoint->real("z")->setValue(theZ); + aPoint->string("creation_method")->setValue("by_xyz"); aPoint->data()->setName(theName); // don't show automatically created feature in the features history aPoint->setInHistory(aPoint, false); diff --git a/src/ModelAPI/Test/TestUndoRedo.py b/src/ModelAPI/Test/TestUndoRedo.py index 34aa535eb..5f748b665 100644 --- a/src/ModelAPI/Test/TestUndoRedo.py +++ b/src/ModelAPI/Test/TestUndoRedo.py @@ -32,6 +32,7 @@ aFeature = aDoc.addFeature("Point") aFeature.real("x").setValue(1.) aFeature.real("y").setValue(-1.) aFeature.real("z").setValue(0.) +aFeature.string("creation_method").setValue("by_xyz") aFeatureName = aFeature.name() # "2" is because Origin is the first point assert(aFeatureName == "Point_2") diff --git a/src/SketchPlugin/Test/TestConstraintCoincidence.py b/src/SketchPlugin/Test/TestConstraintCoincidence.py index 082de9f9a..4ce25cd89 100644 --- a/src/SketchPlugin/Test/TestConstraintCoincidence.py +++ b/src/SketchPlugin/Test/TestConstraintCoincidence.py @@ -87,6 +87,7 @@ aFeature = aDocument.addFeature("Point") aFeature.real("x").setValue(0.) aFeature.real("y").setValue(0.) aFeature.real("z").setValue(0.) +aFeature.string("creation_method").setValue("by_xyz") anOriginName = aFeature.name() aSession.finishOperation() #========================================================================= diff --git a/src/SketchPlugin/Test/TestConstraintMiddlePoint.py b/src/SketchPlugin/Test/TestConstraintMiddlePoint.py index e7e8a5c12..c5aaa01a8 100644 --- a/src/SketchPlugin/Test/TestConstraintMiddlePoint.py +++ b/src/SketchPlugin/Test/TestConstraintMiddlePoint.py @@ -71,6 +71,7 @@ aFeature = aDocument.addFeature("Point") aFeature.real("x").setValue(0.) aFeature.real("y").setValue(0.) aFeature.real("z").setValue(0.) +aFeature.string("creation_method").setValue("by_xyz") anOriginName = aFeature.name() aSession.finishOperation() #========================================================================= -- 2.39.2