From: azv Date: Thu, 22 Jun 2017 05:08:46 +0000 (+0300) Subject: Merge branch 'Pre_2.8.0_development' X-Git-Tag: V_2.7.1.1~3 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=a94fc319f2aa64b43c9a73b5ff7063923648faec;p=modules%2Fshaper.git Merge branch 'Pre_2.8.0_development' # Conflicts: # src/PartSet/CMakeLists.txt # src/SketchSolver/SketchSolver_ConstraintFixed.cpp # src/SketchSolver/SketchSolver_Group.cpp --- a94fc319f2aa64b43c9a73b5ff7063923648faec diff --cc src/GeomAPI/GeomAPI_Ellipse.cpp index 000000000,2d47a5a6f..9c0926a13 mode 000000,100644..100644 --- a/src/GeomAPI/GeomAPI_Ellipse.cpp +++ b/src/GeomAPI/GeomAPI_Ellipse.cpp @@@ -1,0 -1,47 +1,65 @@@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D ++// Copyright (C) 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 ++// + + // File: GeomAPI_Ellipse.cpp + // Created: 25 April 2017 + // Author: Vitaly Smetannikov + + #include "GeomAPI_Ellipse.h" + #include "GeomAPI_Ax2.h" + #include "GeomAPI_Pnt.h" + + #include + + #define MY_ELIPS implPtr() + + GeomAPI_Ellipse::GeomAPI_Ellipse(const std::shared_ptr& theAx2, + double theMajorRadius, double theMinorRadius) + : GeomAPI_Interface(new gp_Elips(theAx2->impl(), theMajorRadius, theMinorRadius)) + { + } + + std::shared_ptr GeomAPI_Ellipse::center() const + { + const gp_Pnt& aCenter = MY_ELIPS->Location(); + return std::shared_ptr(new GeomAPI_Pnt(aCenter.X(), aCenter.Y(), aCenter.Z())); + } + + GeomPointPtr GeomAPI_Ellipse::firstFocus() const + { + const gp_Pnt& aFirst = MY_ELIPS->Focus1(); + return std::shared_ptr(new GeomAPI_Pnt(aFirst.X(), aFirst.Y(), aFirst.Z())); + } + + GeomPointPtr GeomAPI_Ellipse::secondFocus() const + { + const gp_Pnt& aSecond = MY_ELIPS->Focus2(); + return std::shared_ptr(new GeomAPI_Pnt(aSecond.X(), aSecond.Y(), aSecond.Z())); + } + + double GeomAPI_Ellipse::minorRadius() const + { + return MY_ELIPS->MinorRadius(); + } + + double GeomAPI_Ellipse::majorRadius() const + { + return MY_ELIPS->MajorRadius(); + } diff --cc src/GeomAPI/GeomAPI_Ellipse.h index 000000000,d201d127a..02536b240 mode 000000,100644..100644 --- a/src/GeomAPI/GeomAPI_Ellipse.h +++ b/src/GeomAPI/GeomAPI_Ellipse.h @@@ -1,0 -1,58 +1,76 @@@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D ++// Copyright (C) 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 ++// + + // File: GeomAPI_Ellipse.h + // Created: 25 April 2017 + // Author: Vitaly Smetannikov + + #ifndef GeomAPI_Ellipse_H_ + #define GeomAPI_Ellipse_H_ + + #include + #include + + class GeomAPI_Pnt; + class GeomAPI_Ax2; + + + /**\class GeomAPI_Ellipse + * \ingroup DataModel + * \brief Ellipse in 3D + */ + class GeomAPI_Ellipse : public GeomAPI_Interface + { + public: + + /// \brief Constructs an epty ellipse + GEOMAPI_EXPORT GeomAPI_Ellipse() : GeomAPI_Interface() {} + + /** \brief Constructs an ellipse with major and minor radiuses, + * where theAx2 locates the ellipse and defines its orientation in 3D space such that:\n + * - the center of the circle is the origin of theAx2;\n + * - the origin, "X Direction" and "Y Direction" of theAx2 define the plane of the circle;\n + * - theAx2 is the local coordinate system of the circle.\n + * Note: It is possible to create a circle where Radius is equal to 0.0. raised if Radius < 0. + */ + GEOMAPI_EXPORT GeomAPI_Ellipse(const std::shared_ptr& theAx2, + double theMajorRadius, double theMinorRadius); + + /// Returns center of the ellipse + GEOMAPI_EXPORT std::shared_ptr center() const; + + /// Returns first focus of the ellipse + GEOMAPI_EXPORT std::shared_ptr firstFocus() const; + + /// Returns second focus of the ellipse + GEOMAPI_EXPORT std::shared_ptr secondFocus() const; + + /// Returns minor radius of the ellipse + GEOMAPI_EXPORT double minorRadius() const; + + /// Returns major radius of the ellipse + GEOMAPI_EXPORT double majorRadius() const; + + }; + + //! Pointer on the object + typedef std::shared_ptr GeomEllipsePtr; + + #endif diff --cc src/GeomAPI/GeomAPI_Ellipse2d.cpp index 000000000,eca8f4a8e..d789f717f mode 000000,100644..100644 --- a/src/GeomAPI/GeomAPI_Ellipse2d.cpp +++ b/src/GeomAPI/GeomAPI_Ellipse2d.cpp @@@ -1,0 -1,97 +1,115 @@@ -// Copyright (C) 2017-20xx CEA/DEN, EDF R&D ++// Copyright (C) 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 ++// + + // File: GeomAPI_Ellipse2d.cpp + // Created: 26 April 2017 + // Author: Artem ZHIDKOV + + #include + #include + #include + + #include + #include + #include + + #define MY_ELLIPSE implPtr() + + static gp_Elips2d* newEllipse(const gp_Pnt2d& theCenter, + const gp_Dir2d& theXAxis, + const double theMajorRadius, + const double theMinorRadius) + { + if (theMajorRadius < theMinorRadius - Precision::Confusion()) { + return newEllipse(theCenter, gp_Dir2d(-theXAxis.Y(), theXAxis.X()), + theMinorRadius, theMajorRadius); + } + + gp_Ax22d anAxis(theCenter, theXAxis); + return new gp_Elips2d(anAxis, theMajorRadius, theMinorRadius); + } + + static gp_Elips2d* newEllipse(const std::shared_ptr& theCenter, + const std::shared_ptr& theAxisPoint, + const std::shared_ptr& thePassingPoint) + { + const gp_Pnt2d& aCenter = theCenter->impl(); + const gp_Pnt2d& anAxisPnt = theAxisPoint->impl(); + const gp_Pnt2d& aPassedPnt = thePassingPoint->impl(); + + gp_Dir2d aXAxis(anAxisPnt.XY() - aCenter.XY()); + double aMajorRadius = anAxisPnt.Distance(aCenter); + + gp_XY aPassedDir = aPassedPnt.XY() - aCenter.XY(); + + double X = aPassedDir.Dot(aXAxis.XY()) / aMajorRadius; + if (Abs(X) > 1.0 - Precision::Confusion()) + return 0; // ellipse cannot be created for such parameters + + double Y = aPassedDir.CrossMagnitude(aXAxis.XY()); + double aMinorRadius = Y / Sqrt(1. - X * X); + + return newEllipse(aCenter, aXAxis, aMajorRadius, aMinorRadius); + } + + + GeomAPI_Ellipse2d::GeomAPI_Ellipse2d(const std::shared_ptr& theCenter, + const std::shared_ptr& theXAxis, + const double theMajorRadius, + const double theMinorRadius) + : GeomAPI_Interface(newEllipse(theCenter->impl(), theXAxis->impl(), + theMajorRadius, theMinorRadius)) + { + } + + GeomAPI_Ellipse2d::GeomAPI_Ellipse2d(const std::shared_ptr& theCenter, + const std::shared_ptr& theAxisPoint, + const std::shared_ptr& thePassingPoint) + : GeomAPI_Interface(newEllipse(theCenter, theAxisPoint, thePassingPoint)) + { + } + + std::shared_ptr GeomAPI_Ellipse2d::center() const + { + const gp_Pnt2d& aCenter = MY_ELLIPSE->Location(); + return std::shared_ptr(new GeomAPI_Pnt2d(aCenter.X(), aCenter.Y())); + } + + std::shared_ptr GeomAPI_Ellipse2d::firstFocus() const + { + const gp_Pnt2d& aFirst = MY_ELLIPSE->Focus1(); + return std::shared_ptr(new GeomAPI_Pnt2d(aFirst.X(), aFirst.Y())); + } + + std::shared_ptr GeomAPI_Ellipse2d::secondFocus() const + { + const gp_Pnt2d& aSecond = MY_ELLIPSE->Focus2(); + return std::shared_ptr(new GeomAPI_Pnt2d(aSecond.X(), aSecond.Y())); + } + + double GeomAPI_Ellipse2d::minorRadius() const + { + return MY_ELLIPSE->MinorRadius(); + } + + double GeomAPI_Ellipse2d::majorRadius() const + { + return MY_ELLIPSE->MajorRadius(); + } diff --cc src/GeomAPI/GeomAPI_Ellipse2d.h index 000000000,293c95649..ef8840d4a mode 000000,100644..100644 --- a/src/GeomAPI/GeomAPI_Ellipse2d.h +++ b/src/GeomAPI/GeomAPI_Ellipse2d.h @@@ -1,0 -1,51 +1,69 @@@ -// Copyright (C) 2017-20xx CEA/DEN, EDF R&D ++// Copyright (C) 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 ++// + + // File: GeomAPI_Ellipse2d.h + // Created: 26 April 2017 + // Author: Artem ZHIDKOV + + #ifndef GeomAPI_Ellipse2d_H_ + #define GeomAPI_Ellipse2d_H_ + + #include + + class GeomAPI_Pnt2d; + class GeomAPI_Dir2d; + + /**\class GeomAPI_Ellipse2d + * \ingroup DataModel + * \brief Ellipse in 2D + */ + class GeomAPI_Ellipse2d : public GeomAPI_Interface + { + public: + /// \brief Constructs ellipse by center, X-axis and given radii + GEOMAPI_EXPORT GeomAPI_Ellipse2d(const std::shared_ptr& theCenter, + const std::shared_ptr& theXAxis, + const double theMajorRadius, + const double theMinorRadius); + + /// \brief Constructs ellipse by center and two points lying on the ellipse: + /// first of them defines an axis of the ellipse + /// and another is just placed on the ellipse. + GEOMAPI_EXPORT GeomAPI_Ellipse2d(const std::shared_ptr& theCenter, + const std::shared_ptr& theAxisPoint, + const std::shared_ptr& thePassingPoint); + + /// Returns center of the ellipse + GEOMAPI_EXPORT std::shared_ptr center() const; + + /// Returns first focus of the ellipse + GEOMAPI_EXPORT std::shared_ptr firstFocus() const; + + /// Returns second focus of the ellipse + GEOMAPI_EXPORT std::shared_ptr secondFocus() const; + + /// Returns minor radius of the ellipse + GEOMAPI_EXPORT double minorRadius() const; + + /// Returns major radius of the ellipse + GEOMAPI_EXPORT double majorRadius() const; + }; + + #endif diff --cc src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.cpp index c292ee482,b10bbf736..2e9c9c18e --- a/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.cpp @@@ -1,38 -1,25 +1,39 @@@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: GeomAlgoAPI_EdgeBuilder.cpp -// Created: 23 Apr 2014 -// Author: Mikhail PONIKAROV +// 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 +// #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include #include + #include #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include std::shared_ptr GeomAlgoAPI_EdgeBuilder::line( std::shared_ptr theStart, std::shared_ptr theEnd) diff --cc src/PartSet/CMakeLists.txt index b04c31716,3ab77b28b..37575cf72 --- a/src/PartSet/CMakeLists.txt +++ b/src/PartSet/CMakeLists.txt @@@ -56,6 -38,9 +56,8 @@@ SET(PROJECT_HEADER PartSet_WidgetShapeSelector.h PartSet_WidgetSketchCreator.h PartSet_WidgetSketchLabel.h - PartSet_WidgetSubShapeSelector.h - PartSet_CenterPrs.h - PartSet_ExternalPointsMgr.h ++ PartSet_CenterPrs.h ++ PartSet_ExternalPointsMgr.h ) SET(PROJECT_MOC_HEADERS @@@ -74,6 -59,8 +76,7 @@@ PartSet_WidgetShapeSelector.h PartSet_WidgetSketchCreator.h PartSet_WidgetSketchLabel.h - PartSet_WidgetSubShapeSelector.h - PartSet_ExternalPointsMgr.h ++ PartSet_ExternalPointsMgr.h ) SET(PROJECT_SOURCES @@@ -101,6 -88,9 +104,8 @@@ PartSet_WidgetShapeSelector.cpp PartSet_WidgetSketchCreator.cpp PartSet_WidgetSketchLabel.cpp - PartSet_WidgetSubShapeSelector.cpp - PartSet_CenterPrs.cpp - PartSet_ExternalPointsMgr.cpp ++ PartSet_CenterPrs.cpp ++ PartSet_ExternalPointsMgr.cpp ) SET(PROJECT_RESOURCES diff --cc src/PartSet/PartSet_CenterPrs.cpp index 000000000,9f7f66249..065c7971c mode 000000,100644..100644 --- a/src/PartSet/PartSet_CenterPrs.cpp +++ b/src/PartSet/PartSet_CenterPrs.cpp @@@ -1,0 -1,23 +1,41 @@@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D ++// Copyright (C) 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 ++// + + // File: PartSet_CenterPrs.cpp + // Created: 25 April 2017 + // Author: Vitaly SMETANNIKOV + + #include "PartSet_CenterPrs.h" + + #include + + + IMPLEMENT_STANDARD_RTTIEXT(PartSet_CenterPrs, AIS_Point) + + PartSet_CenterPrs::PartSet_CenterPrs(const ObjectPtr& theObject, + const GeomEdgePtr& theEdge, + const gp_Pnt& theCenter, + ModelAPI_AttributeSelection::CenterType theType) + : AIS_Point(new Geom_CartesianPoint(theCenter)), + myObject(theObject), + myEdge(theEdge), + myCenterType(theType) + { + } diff --cc src/PartSet/PartSet_CenterPrs.h index 000000000,f9cf9232f..86e54b24f mode 000000,100644..100644 --- a/src/PartSet/PartSet_CenterPrs.h +++ b/src/PartSet/PartSet_CenterPrs.h @@@ -1,0 -1,54 +1,72 @@@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D ++// Copyright (C) 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 ++// + + // File: PartSet_CenterPrs.h + // Created: 25 April 2017 + // Author: Vitaly SMETANNIKOV + + #ifndef PartSet_CenterPrs_H + #define PartSet_CenterPrs_H + + #include + #include + #include + + #include + #include + #include + + DEFINE_STANDARD_HANDLE(PartSet_CenterPrs, AIS_Point) + + /** + * \ingroup GUI + * A presentation class for displaying of centers of external curcular objects in a sketch + */ + class PartSet_CenterPrs: public AIS_Point + { + public: + /// Constructor + /// \param theObject an object with circular edge + /// \param theEdge a circular edge + /// \param theCenter a center point of the circular edge + /// \param theType a type of the center + Standard_EXPORT PartSet_CenterPrs(const ObjectPtr& theObject, + const GeomEdgePtr& theEdge, + const gp_Pnt& theCenter, + ModelAPI_AttributeSelection::CenterType theType); + + /// Returns an Object which contains the circular edge + ObjectPtr object() const { return myObject; } + + /// Returns a circular edge shape + GeomEdgePtr edge() const { return myEdge; } + + /// Returns type of the center + ModelAPI_AttributeSelection::CenterType centerType() const { return myCenterType; } + + DEFINE_STANDARD_RTTIEXT(PartSet_CenterPrs, AIS_Point) + + private: + ObjectPtr myObject; + GeomEdgePtr myEdge; + ModelAPI_AttributeSelection::CenterType myCenterType; + }; + + #endif diff --cc src/PartSet/PartSet_ExternalPointsMgr.cpp index 000000000,b0faeb447..0f9babdae mode 000000,100644..100644 --- a/src/PartSet/PartSet_ExternalPointsMgr.cpp +++ b/src/PartSet/PartSet_ExternalPointsMgr.cpp @@@ -1,0 -1,211 +1,229 @@@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D ++// Copyright (C) 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 ++// + + // File: PartSet_ExternalPointsMgr.cpp + // Created: 26 April 2017 + // Author: Vitaly SMETANNIKOV + + #include "PartSet_ExternalPointsMgr.h" + #include "PartSet_CenterPrs.h" + #include "PartSet_Tools.h" + + #include + + #include + #include + + #include + #include + #include + #include + #include + + #include + #include + #include + #include + + PartSet_ExternalPointsMgr::PartSet_ExternalPointsMgr(ModuleBase_IWorkshop* theWorkshop, + const CompositeFeaturePtr& theSketch) + : QObject(theWorkshop), myWorkshop(theWorkshop), mySketch(theSketch) + { + XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop); + XGUI_Displayer* aDisplayer = aWorkshop->displayer(); + connect(aDisplayer, SIGNAL(objectDisplayed(ObjectPtr, AISObjectPtr)), + SLOT(onDisplayObject(ObjectPtr, AISObjectPtr))); + + connect(aDisplayer, SIGNAL(beforeObjectErase(ObjectPtr, AISObjectPtr)), + SLOT(onEraseObject(ObjectPtr, AISObjectPtr))); + + updateCenterPresentations(); + } + + + PartSet_ExternalPointsMgr::~PartSet_ExternalPointsMgr() + { + if (myPresentations.isEmpty()) + return; + XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop); + if (!aWorkshop) + return; + + XGUI_Displayer* aDisplayer = aWorkshop->displayer(); + QMapIterator aIt(myPresentations); + while (aIt.hasNext()) { + aIt.next(); + ListOfAIS aAISList = aIt.value(); + foreach (AISObjectPtr aAIS, aAISList) { + aDisplayer->eraseAIS(aAIS, false); + } + } + } + + + //****************************************************** + QList> PartSet_ExternalPointsMgr::findCircularEdgesInPlane() + { + QList> aResult; + XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop); + XGUI_Displayer* aDisplayer = aWorkshop->displayer(); + QObjectPtrList aDispObjects = aDisplayer->displayedObjects(); + + std::shared_ptr aPlane = plane(); + foreach(ObjectPtr aObj, aDispObjects) { + if (myPresentations.contains(aObj)) + continue; + + // Do not process objects of the current sketch + if (isSketchObject(aObj)) + continue; + + ResultPtr aResObj = std::dynamic_pointer_cast(aObj); + if (aResObj.get()) { + GeomShapePtr aShape = aResObj->shape(); + if (aShape.get()) { + GeomAPI_ShapeExplorer aExplorer(aShape, GeomAPI_Shape::EDGE); + for(; aExplorer.more(); aExplorer.next()) { + GeomShapePtr aEdgeShape = aExplorer.current(); + GeomAPI_Edge anEdge(aEdgeShape); + if ((anEdge.isCircle() || anEdge.isArc() || anEdge.isEllipse()) && + anEdge.isInPlane(aPlane)) { + bool isContains = false; + // Check that edge is not already used. + // It is possible that the same edge will be taken from different faces + foreach(std::shared_ptr aPrs, aResult) { + GeomAPI_Edge aUsedEdge(aPrs->shape()); + if (aUsedEdge.isEqual(aEdgeShape)) { + isContains = true; + break; + } + } + if (!isContains) { + std::shared_ptr + aPrs(new ModuleBase_ViewerPrs(aResObj, aEdgeShape)); + aResult.append(aPrs); + } + } + } + } + } + } + return aResult; + } + + + void PartSet_ExternalPointsMgr::updateCenterPresentations() + { + XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop); + // Return if there is no plane defined + if (!plane().get()) { + connect(aWorkshop->selector(), SIGNAL(selectionChanged()), + SLOT(onSelectionChanged())); + return; + } + XGUI_Displayer* aDisplayer = aWorkshop->displayer(); + + QList> aEdgesPrs = findCircularEdgesInPlane(); + foreach(std::shared_ptr aPrs, aEdgesPrs) { + GeomEdgePtr aEdge(new GeomAPI_Edge(aPrs->shape())); + ListOfAIS aList; + if (aEdge->isArc() || aEdge->isCircle()) { + GeomCirclePtr aCircle = aEdge->circle(); + GeomPointPtr aCenter = aCircle->center(); + Handle(PartSet_CenterPrs) aCentPrs = + new PartSet_CenterPrs(aPrs->object(), aEdge, aCenter->impl(), + ModelAPI_AttributeSelection::CIRCLE_CENTER); + + AISObjectPtr anAIS(new GeomAPI_AISObject()); + anAIS->setImpl(new Handle(AIS_InteractiveObject)(aCentPrs)); + aList.append(anAIS); + } else if (aEdge->isEllipse()) { + GeomEllipsePtr aEllipse = aEdge->ellipse(); + GeomPointPtr aF1 = aEllipse->firstFocus(); + GeomPointPtr aF2 = aEllipse->secondFocus(); + Handle(PartSet_CenterPrs) aF1Prs = + new PartSet_CenterPrs(aPrs->object(), aEdge, aF1->impl(), + ModelAPI_AttributeSelection::ELLIPSE_FIRST_FOCUS); + Handle(PartSet_CenterPrs) aF2Prs = + new PartSet_CenterPrs(aPrs->object(), aEdge, aF2->impl(), + ModelAPI_AttributeSelection::ELLIPSE_SECOND_FOCUS); + + AISObjectPtr anAIS1(new GeomAPI_AISObject()); + anAIS1->setImpl(new Handle(AIS_InteractiveObject)(aF1Prs)); + aList.append(anAIS1); + + AISObjectPtr anAIS2(new GeomAPI_AISObject()); + anAIS2->setImpl(new Handle(AIS_InteractiveObject)(aF2Prs)); + aList.append(anAIS2); + } + if (myPresentations.contains(aPrs->object())) + myPresentations[aPrs->object()].append(aList); + else + myPresentations[aPrs->object()] = aList; + foreach(AISObjectPtr anAIS, aList) { + aDisplayer->displayAIS(anAIS, false); + aDisplayer->activateAIS(anAIS->impl(), TopAbs_VERTEX, false); + } + } + } + + std::shared_ptr PartSet_ExternalPointsMgr::plane() const + { + return PartSet_Tools::sketchPlane(mySketch); + } + + void PartSet_ExternalPointsMgr::onDisplayObject(ObjectPtr theObj, AISObjectPtr theAIS) + { + updateCenterPresentations(); + } + + void PartSet_ExternalPointsMgr::onEraseObject(ObjectPtr theObj, AISObjectPtr theAIS) + { + if (myPresentations.contains(theObj)) { + XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop); + XGUI_Displayer* aDisplayer = aWorkshop->displayer(); + ListOfAIS aList = myPresentations[theObj]; + foreach(AISObjectPtr aAIS, aList) { + aDisplayer->eraseAIS(aAIS, false); + } + myPresentations.remove(theObj); + aDisplayer->updateViewer(); + } + } + + + bool PartSet_ExternalPointsMgr::isSketchObject(const ObjectPtr& theRes) const + { + FeaturePtr aFeature = ModelAPI_Feature::feature(theRes); + if (!aFeature.get()) + return false; + CompositeFeaturePtr aComp = ModelAPI_Tools::compositeOwner(aFeature); + return aComp == mySketch; + } + + void PartSet_ExternalPointsMgr::onSelectionChanged() + { + if (plane().get()) { + XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop); + disconnect(aWorkshop->selector(), SIGNAL(selectionChanged()), + this, SLOT(onSelectionChanged())); + updateCenterPresentations(); + } + } diff --cc src/PartSet/PartSet_ExternalPointsMgr.h index 000000000,a053bcd1a..4f13f09e8 mode 000000,100644..100644 --- a/src/PartSet/PartSet_ExternalPointsMgr.h +++ b/src/PartSet/PartSet_ExternalPointsMgr.h @@@ -1,0 -1,90 +1,108 @@@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D ++// Copyright (C) 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 ++// + + // File: PartSet_ExternalPointsMgr.h + // Created: 26 April 2017 + // Author: Vitaly SMETANNIKOV + + #ifndef PartSet_ExternalPointsMgr_H + #define PartSet_ExternalPointsMgr_H + + + #include + #include + #include + #include + + #include + #include + + class ModuleBase_ViewerPrs; + class ModuleBase_IWorkshop; + + + /** + * \ingroup Modules + * A class to manage display of presentations of center points of circular + * edges outside of a current sketcher + */ + class PartSet_ExternalPointsMgr: public QObject + { + Q_OBJECT + public: + PartSet_ExternalPointsMgr(ModuleBase_IWorkshop* theWorkshop, + const CompositeFeaturePtr& theSketch); + + virtual ~PartSet_ExternalPointsMgr(); + + public slots: + /** + * A slot which processes display of object + * \param theObj the displayed object + * \param theAIS its presentation + */ + void onDisplayObject(ObjectPtr theObj, AISObjectPtr theAIS); + + /** + * A slot which processes erase of object + * \param theObj the displayed object + * \param theAIS its presentation + */ + void onEraseObject(ObjectPtr theObj, AISObjectPtr theAIS); + + // Called on selection changed + void onSelectionChanged(); + + private: + /** + * Returns list of presentations which have displayed shapes with circular edges + * (circles, arcs) which are in pane of of the given sketch + * \param theSketch - the sketch + */ + QList> findCircularEdgesInPlane(); + + /// Creates presentations of centers + void updateCenterPresentations(); + + /// Returns plane of the current sketch + GeomPlanePtr plane() const; + + /** + * Checks that the given object is an object of the current sketch + * \param theRes an object to check + * \return True if the given object is a sub-object of the current sketch + */ + bool isSketchObject(const ObjectPtr& theRes) const; + + private: + /// Workshop + ModuleBase_IWorkshop* myWorkshop; + + /// Current sketch + CompositeFeaturePtr mySketch; + + /// Type for list of created AIS objects + typedef QList ListOfAIS; + + /// Map of created AIS objects + QMap myPresentations; + }; + + #endif diff --cc src/PythonAPI/model/sketcher/tests.py index 000000000,18984008c..ea690813d mode 000000,100644..100644 --- a/src/PythonAPI/model/sketcher/tests.py +++ b/src/PythonAPI/model/sketcher/tests.py @@@ -1,0 -1,76 +1,93 @@@ -# Author: Artem Zhidkov -# Copyright (C) 2017-20xx CEA/DEN, EDF R&D ++## Copyright (C) 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 ++## + + from ModelAPI import * + from GeomDataAPI import * + import ModelHighAPI + import math + from salome.shaper.model.sketcher import tools + + TOLERANCE = 1.e-7 + + def assertPoint(thePoint, theCoords): + """ Verifies coordinates of the point + """ + aPoint = tools.toList(thePoint) + assert aPoint[0] == theCoords[0] and aPoint[1] == theCoords[1], "Wrong '{}' point {}, expected {}".format(thePoint.id(), aPoint, theCoords) + + + def assertLine(theLine, theStart, theEnd): + """ Verifies coordinates of line extremities + """ + aLine = tools.toSketchFeature(theLine) + + aStartPnt = geomDataAPI_Point2D(aLine.attribute("StartPoint")) + aEndPnt = geomDataAPI_Point2D(aLine.attribute("EndPoint")) + if len(theStart): + assertPoint(aStartPnt, theStart) + if len(theEnd): + assertPoint(aEndPnt, theEnd) + + + def assertCircle(theCircle, theCenter, theRadius): + """ Verifies attributes of circle + """ + aCircle = tools.toSketchFeature(theCircle) + + aCenter = geomDataAPI_Point2D(aCircle.attribute("circle_center")) + if len(theCenter): + assertPoint(aCenter, theCenter) + + aRadius = aCircle.real("circle_radius") + assert aRadius.value() == theRadius, "Wrong circle radius {}, expected {}".format(aRadius.value(), theRadius) + + + def assertArc(theArc, theCenter, theStart, theEnd): + """ Verifies coordinates of arc points and the consistency of the arc. + Some of points may be empty lists. + """ + anArc = tools.toSketchFeature(theArc) + + aCenterPnt = geomDataAPI_Point2D(anArc.attribute("center_point")) + aStartPnt = geomDataAPI_Point2D(anArc.attribute("start_point")) + aEndPnt = geomDataAPI_Point2D(anArc.attribute("end_point")) + if len(theCenter): + assertPoint(aCenterPnt, theCenter) + if len(theStart): + assertPoint(aStartPnt, theStart) + if len(theEnd): + assertPoint(aEndPnt, theEnd) + + assertArcValidity(anArc) + + + def assertArcValidity(theArc): + """ Tests whether the arc is correctly defined + """ + anArc = tools.toSketchFeature(theArc) + + aCenterPnt = geomDataAPI_Point2D(anArc.attribute("center_point")) + aStartPnt = geomDataAPI_Point2D(anArc.attribute("start_point")) + aEndPnt = geomDataAPI_Point2D(anArc.attribute("end_point")) + aRadius = anArc.real("radius") + aDistCS = tools.distancePointPoint(aCenterPnt, aStartPnt) + aDistCE = tools.distancePointPoint(aCenterPnt, aEndPnt) + assert math.fabs(aDistCS - aDistCE) < TOLERANCE, "Wrong arc: center-start distance {}, center-end distance {}".format(aDistCS, aDistCE) + assert math.fabs(aRadius.value() - aDistCS) < TOLERANCE, "Wrong arc: radius is {}, expected {}".format(aRadius.value(), aDistCS) diff --cc src/PythonAPI/model/sketcher/tools.py index de3032f54,49a73bfbd..e93fec49c --- a/src/PythonAPI/model/sketcher/tools.py +++ b/src/PythonAPI/model/sketcher/tools.py @@@ -1,25 -1,10 +1,27 @@@ -# Author: Sergey Pokhodenko -# Copyright (C) 2014-20xx CEA/DEN, EDF R&D +## 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 +## import ModelHighAPI - import GeomDataAPI + from GeomDataAPI import * + from ModelAPI import * + import math def addPolyline(sketch, *coords): """Add a poly-line to sketch. diff --cc src/SketchPlugin/CMakeLists.txt index 82e27cd77,6f4b3a09c..bacf4249a --- a/src/SketchPlugin/CMakeLists.txt +++ b/src/SketchPlugin/CMakeLists.txt @@@ -41,10 -24,13 +42,12 @@@ SET(PROJECT_HEADER SketchPlugin_ConstraintPerpendicular.h SketchPlugin_ConstraintRadius.h SketchPlugin_ConstraintRigid.h - SketchPlugin_ConstraintSplit.h SketchPlugin_ConstraintTangent.h SketchPlugin_ConstraintVertical.h + SketchPlugin_Ellipse.h SketchPlugin_ExternalValidator.h SketchPlugin_Feature.h + SketchPlugin_Fillet.h SketchPlugin_IntersectionPoint.h SketchPlugin_Line.h SketchPlugin_MacroArc.h @@@ -82,10 -69,13 +87,12 @@@ SET(PROJECT_SOURCE SketchPlugin_ConstraintPerpendicular.cpp SketchPlugin_ConstraintRadius.cpp SketchPlugin_ConstraintRigid.cpp - SketchPlugin_ConstraintSplit.cpp SketchPlugin_ConstraintTangent.cpp SketchPlugin_ConstraintVertical.cpp + SketchPlugin_Ellipse.cpp SketchPlugin_ExternalValidator.cpp SketchPlugin_Feature.cpp + SketchPlugin_Fillet.cpp SketchPlugin_IntersectionPoint.cpp SketchPlugin_Line.cpp SketchPlugin_MacroArc.cpp diff --cc src/SketchPlugin/SketchPlugin_ConstraintDistanceHorizontal.cpp index 000000000,29c8ce222..4d9216477 mode 000000,100644..100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintDistanceHorizontal.cpp +++ b/src/SketchPlugin/SketchPlugin_ConstraintDistanceHorizontal.cpp @@@ -1,0 -1,149 +1,167 @@@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> ++// Copyright (C) 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 ++// + + // File: SketchPlugin_ConstraintDistanceHorizontal.cpp + // Created: 2 May 2017 + // Author: Artem ZHIDKOV + + #include + + #include + #include + + #include + #include + #include + + #include + + const double tolerance = 1e-7; + + + SketchPlugin_ConstraintDistanceHorizontal::SketchPlugin_ConstraintDistanceHorizontal() + : SketchPlugin_ConstraintDistance() + { + } + + //************************************************************************************* + void SketchPlugin_ConstraintDistanceHorizontal::initAttributes() + { + data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId()); + data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId()); + } + + //************************************************************************************* + void SketchPlugin_ConstraintDistanceHorizontal::execute() + { + AttributeDoublePtr anAttrValue = real(SketchPlugin_Constraint::VALUE()); + if (anAttrValue->isInitialized() || !areAttributesInitialized()) + return; + + double aDistance = calculateCurrentDistance(); + anAttrValue->setValue(aDistance); + } + + //************************************************************************************* + AISObjectPtr SketchPlugin_ConstraintDistanceHorizontal::getAISObject(AISObjectPtr thePrevious) + { + if (!sketch()) + return thePrevious; + + AISObjectPtr anAIS = SketcherPrs_Factory::lengthDimensionConstraint(this, + sketch()->coordinatePlane(), + thePrevious); + return anAIS; + } + + //************************************************************************************* + void SketchPlugin_ConstraintDistanceHorizontal::move(double theDeltaX, double theDeltaY) + { + std::shared_ptr aData = data(); + if (!aData->isValid()) + return; + + // Recalculate a shift of flyout point in terms of local coordinates + std::shared_ptr aDir(new GeomAPI_XY(theDeltaX, theDeltaY)); + std::shared_ptr aPlane = SketchPlugin_Sketch::plane(sketch()); + std::shared_ptr aPointA = SketcherPrs_Tools::getFeaturePoint( + data(), SketchPlugin_Constraint::ENTITY_A(), aPlane); + std::shared_ptr aPointB = SketcherPrs_Tools::getFeaturePoint( + data(), SketchPlugin_Constraint::ENTITY_B(), aPlane); + + if (!aPointA || !aPointB) + return; + + std::shared_ptr aStartPnt = aPointA->pnt()->xy(); + std::shared_ptr aEndPnt = aPointB->pnt()->xy(); + + std::shared_ptr aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt))); + double dX = aDir->dot(aLineDir->xy()); + double dY = -aDir->cross(aLineDir->xy()); + + std::shared_ptr aPoint = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT())); + myFlyoutUpdate = true; + if (aPoint->isInitialized()) { + aPoint->setValue(aPoint->x() + dX, aPoint->y() + dY); + } else { + aPoint->setValue(dX, dY); + } + myFlyoutUpdate = false; + } + + double SketchPlugin_ConstraintDistanceHorizontal::calculateCurrentDistance() + { + std::shared_ptr aData = data(); + std::shared_ptr aPlane = SketchPlugin_Sketch::plane(sketch()); + std::shared_ptr aPointA = + SketcherPrs_Tools::getFeaturePoint(aData, SketchPlugin_Constraint::ENTITY_A(), aPlane); + std::shared_ptr aPointB = + SketcherPrs_Tools::getFeaturePoint(aData, SketchPlugin_Constraint::ENTITY_B(), aPlane); + + return aPointB->x() - aPointA->x(); + } + + void SketchPlugin_ConstraintDistanceHorizontal::attributeChanged(const std::string& theID) + { + if (theID == SketchPlugin_Constraint::ENTITY_A() || + theID == SketchPlugin_Constraint::ENTITY_B()) + { + AttributeDoublePtr aValueAttr = real(SketchPlugin_Constraint::VALUE()); + if (!aValueAttr->isInitialized() && areAttributesInitialized()) { + // only if it is not initialized, try to compute the current value + double aDistance = calculateCurrentDistance(); + aValueAttr->setValue(aDistance); + } + } else if (theID == SketchPlugin_Constraint::FLYOUT_VALUE_PNT() && !myFlyoutUpdate) { + myFlyoutUpdate = true; + // Recalculate flyout point in local coordinates of the distance constraint: + // the X coordinate is a length of projection of the flyout point on the + // line binding two distanced points + // or a line of projection of the distanced point onto the distanced segment + // the Y coordinate is a distance from the flyout point to the line + std::shared_ptr aFlyoutAttr = + std::dynamic_pointer_cast( + attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT())); + std::shared_ptr aFlyoutPnt = aFlyoutAttr->pnt(); + + std::shared_ptr aPlane = SketchPlugin_Sketch::plane(sketch()); + std::shared_ptr aPointA = SketcherPrs_Tools::getFeaturePoint( + data(), SketchPlugin_Constraint::ENTITY_A(), aPlane); + std::shared_ptr aPointB = SketcherPrs_Tools::getFeaturePoint( + data(), SketchPlugin_Constraint::ENTITY_B(), aPlane); + + std::shared_ptr aStartPnt = aPointA->pnt()->xy(); + std::shared_ptr aEndPnt = aPointB->pnt()->xy(); + + if (aEndPnt->distance(aStartPnt) < tolerance) + return; + + std::shared_ptr aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt))); + std::shared_ptr aFlyoutDir = aFlyoutPnt->xy()->decreased(aStartPnt); + + double X = aFlyoutDir->dot(aLineDir->xy()); + double Y = -aFlyoutDir->cross(aLineDir->xy()); + aFlyoutAttr->setValue(X, Y); + myFlyoutUpdate = false; + } + } diff --cc src/SketchPlugin/SketchPlugin_ConstraintDistanceHorizontal.h index 000000000,948fe13e2..98ef11796 mode 000000,100644..100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintDistanceHorizontal.h +++ b/src/SketchPlugin/SketchPlugin_ConstraintDistanceHorizontal.h @@@ -1,0 -1,66 +1,84 @@@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> ++// Copyright (C) 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 ++// + + // File: SketchPlugin_ConstraintDistanceHorizontal.h + // Created: 2 May 2017 + // Author: Artem ZHIDKOV + + #ifndef SketchPlugin_ConstraintDistanceHorizontal_H_ + #define SketchPlugin_ConstraintDistanceHorizontal_H_ + + #include + #include + + /** \class SketchPlugin_ConstraintDistanceHorizontal + * \ingroup Plugins + * \brief Feature for creation of a new constraint which defines a horizontal distance between two points. + * + * This constraint has three attributes: + * SketchPlugin_Constraint::VALUE(), SketchPlugin_Constraint::ENTITY_A() and SketchPlugin_Constraint::ENTITY_B() + */ + class SketchPlugin_ConstraintDistanceHorizontal : public SketchPlugin_ConstraintDistance + { + public: + /// Distance constraint kind + inline static const std::string& ID() + { + static const std::string MY_CONSTRAINT_DISTANCE_ID("SketchConstraintDistanceHorizontal"); + return MY_CONSTRAINT_DISTANCE_ID; + } + + /// \brief Returns the kind of a feature + SKETCHPLUGIN_EXPORT virtual const std::string& getKind() + { + static std::string MY_KIND = SketchPlugin_ConstraintDistanceHorizontal::ID(); + return MY_KIND; + } + + /// \brief Creates a new part document if needed + SKETCHPLUGIN_EXPORT virtual void execute(); + + /// \brief Request for initialization of data model of the feature: adding all attributes + SKETCHPLUGIN_EXPORT virtual void initAttributes(); + + /// Returns the AIS preview + SKETCHPLUGIN_EXPORT virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious); + + /// 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 + /// \param theID identifier of changed attribute + SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID); + + /// \brief Use plugin manager for features creation + SketchPlugin_ConstraintDistanceHorizontal(); + + protected: + /// Returns the current distance between the feature attributes + virtual double calculateCurrentDistance(); + + private: + bool myFlyoutUpdate; ///< to avoid cyclic dependencies on automatic updates of flyout point + }; + + #endif diff --cc src/SketchPlugin/SketchPlugin_ConstraintDistanceVertical.cpp index 000000000,49db91f59..6691ee51b mode 000000,100644..100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintDistanceVertical.cpp +++ b/src/SketchPlugin/SketchPlugin_ConstraintDistanceVertical.cpp @@@ -1,0 -1,149 +1,167 @@@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> ++// Copyright (C) 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 ++// + + // File: SketchPlugin_ConstraintDistanceVertical.cpp + // Created: 10 May 2017 + // Author: Artem ZHIDKOV + + #include + + #include + #include + + #include + #include + #include + + #include + + const double tolerance = 1e-7; + + + SketchPlugin_ConstraintDistanceVertical::SketchPlugin_ConstraintDistanceVertical() + : SketchPlugin_ConstraintDistance() + { + } + + //************************************************************************************* + void SketchPlugin_ConstraintDistanceVertical::initAttributes() + { + data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId()); + data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId()); + } + + //************************************************************************************* + void SketchPlugin_ConstraintDistanceVertical::execute() + { + AttributeDoublePtr anAttrValue = real(SketchPlugin_Constraint::VALUE()); + if (anAttrValue->isInitialized() || !areAttributesInitialized()) + return; + + double aDistance = calculateCurrentDistance(); + anAttrValue->setValue(aDistance); + } + + //************************************************************************************* + AISObjectPtr SketchPlugin_ConstraintDistanceVertical::getAISObject(AISObjectPtr thePrevious) + { + if (!sketch()) + return thePrevious; + + AISObjectPtr anAIS = SketcherPrs_Factory::lengthDimensionConstraint(this, + sketch()->coordinatePlane(), + thePrevious); + return anAIS; + } + + //************************************************************************************* + void SketchPlugin_ConstraintDistanceVertical::move(double theDeltaX, double theDeltaY) + { + std::shared_ptr aData = data(); + if (!aData->isValid()) + return; + + // Recalculate a shift of flyout point in terms of local coordinates + std::shared_ptr aDir(new GeomAPI_XY(theDeltaX, theDeltaY)); + std::shared_ptr aPlane = SketchPlugin_Sketch::plane(sketch()); + std::shared_ptr aPointA = SketcherPrs_Tools::getFeaturePoint( + data(), SketchPlugin_Constraint::ENTITY_A(), aPlane); + std::shared_ptr aPointB = SketcherPrs_Tools::getFeaturePoint( + data(), SketchPlugin_Constraint::ENTITY_B(), aPlane); + + if (!aPointA || !aPointB) + return; + + std::shared_ptr aStartPnt = aPointA->pnt()->xy(); + std::shared_ptr aEndPnt = aPointB->pnt()->xy(); + + std::shared_ptr aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt))); + double dX = aDir->dot(aLineDir->xy()); + double dY = -aDir->cross(aLineDir->xy()); + + std::shared_ptr aPoint = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT())); + myFlyoutUpdate = true; + if (aPoint->isInitialized()) { + aPoint->setValue(aPoint->x() + dX, aPoint->y() + dY); + } else { + aPoint->setValue(dX, dY); + } + myFlyoutUpdate = false; + } + + double SketchPlugin_ConstraintDistanceVertical::calculateCurrentDistance() + { + std::shared_ptr aData = data(); + std::shared_ptr aPlane = SketchPlugin_Sketch::plane(sketch()); + std::shared_ptr aPointA = + SketcherPrs_Tools::getFeaturePoint(aData, SketchPlugin_Constraint::ENTITY_A(), aPlane); + std::shared_ptr aPointB = + SketcherPrs_Tools::getFeaturePoint(aData, SketchPlugin_Constraint::ENTITY_B(), aPlane); + + return aPointB->y() - aPointA->y(); + } + + void SketchPlugin_ConstraintDistanceVertical::attributeChanged(const std::string& theID) + { + if (theID == SketchPlugin_Constraint::ENTITY_A() || + theID == SketchPlugin_Constraint::ENTITY_B()) + { + AttributeDoublePtr aValueAttr = real(SketchPlugin_Constraint::VALUE()); + if (!aValueAttr->isInitialized() && areAttributesInitialized()) { + // only if it is not initialized, try to compute the current value + double aDistance = calculateCurrentDistance(); + aValueAttr->setValue(aDistance); + } + } else if (theID == SketchPlugin_Constraint::FLYOUT_VALUE_PNT() && !myFlyoutUpdate) { + myFlyoutUpdate = true; + // Recalculate flyout point in local coordinates of the distance constraint: + // the X coordinate is a length of projection of the flyout point on the + // line binding two distanced points + // or a line of projection of the distanced point onto the distanced segment + // the Y coordinate is a distance from the flyout point to the line + std::shared_ptr aFlyoutAttr = + std::dynamic_pointer_cast( + attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT())); + std::shared_ptr aFlyoutPnt = aFlyoutAttr->pnt(); + + std::shared_ptr aPlane = SketchPlugin_Sketch::plane(sketch()); + std::shared_ptr aPointA = SketcherPrs_Tools::getFeaturePoint( + data(), SketchPlugin_Constraint::ENTITY_A(), aPlane); + std::shared_ptr aPointB = SketcherPrs_Tools::getFeaturePoint( + data(), SketchPlugin_Constraint::ENTITY_B(), aPlane); + + std::shared_ptr aStartPnt = aPointA->pnt()->xy(); + std::shared_ptr aEndPnt = aPointB->pnt()->xy(); + + if (aEndPnt->distance(aStartPnt) < tolerance) + return; + + std::shared_ptr aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt))); + std::shared_ptr aFlyoutDir = aFlyoutPnt->xy()->decreased(aStartPnt); + + double X = aFlyoutDir->dot(aLineDir->xy()); + double Y = -aFlyoutDir->cross(aLineDir->xy()); + aFlyoutAttr->setValue(X, Y); + myFlyoutUpdate = false; + } + } diff --cc src/SketchPlugin/SketchPlugin_ConstraintDistanceVertical.h index 000000000,e5f14d83e..784770061 mode 000000,100644..100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintDistanceVertical.h +++ b/src/SketchPlugin/SketchPlugin_ConstraintDistanceVertical.h @@@ -1,0 -1,66 +1,84 @@@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> ++// Copyright (C) 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 ++// + + // File: SketchPlugin_ConstraintDistanceVertical.h + // Created: 10 May 2017 + // Author: Artem ZHIDKOV + + #ifndef SketchPlugin_ConstraintDistanceVertical_H_ + #define SketchPlugin_ConstraintDistanceVertical_H_ + + #include + #include + + /** \class SketchPlugin_ConstraintDistanceVertical + * \ingroup Plugins + * \brief Feature for creation of a new constraint which defines a vertical distance between two points. + * + * This constraint has three attributes: + * SketchPlugin_Constraint::VALUE(), SketchPlugin_Constraint::ENTITY_A() and SketchPlugin_Constraint::ENTITY_B() + */ + class SketchPlugin_ConstraintDistanceVertical : public SketchPlugin_ConstraintDistance + { + public: + /// Distance constraint kind + inline static const std::string& ID() + { + static const std::string MY_CONSTRAINT_DISTANCE_ID("SketchConstraintDistanceVertical"); + return MY_CONSTRAINT_DISTANCE_ID; + } + + /// \brief Returns the kind of a feature + SKETCHPLUGIN_EXPORT virtual const std::string& getKind() + { + static std::string MY_KIND = SketchPlugin_ConstraintDistanceVertical::ID(); + return MY_KIND; + } + + /// \brief Creates a new part document if needed + SKETCHPLUGIN_EXPORT virtual void execute(); + + /// \brief Request for initialization of data model of the feature: adding all attributes + SKETCHPLUGIN_EXPORT virtual void initAttributes(); + + /// Returns the AIS preview + SKETCHPLUGIN_EXPORT virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious); + + /// 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 + /// \param theID identifier of changed attribute + SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID); + + /// \brief Use plugin manager for features creation + SketchPlugin_ConstraintDistanceVertical(); + + protected: + /// Returns the current distance between the feature attributes + virtual double calculateCurrentDistance(); + + private: + bool myFlyoutUpdate; ///< to avoid cyclic dependencies on automatic updates of flyout point + }; + + #endif diff --cc src/SketchPlugin/SketchPlugin_Ellipse.cpp index 000000000,2317e0575..d9f61e165 mode 000000,100644..100644 --- a/src/SketchPlugin/SketchPlugin_Ellipse.cpp +++ b/src/SketchPlugin/SketchPlugin_Ellipse.cpp @@@ -1,0 -1,132 +1,150 @@@ -// Copyright (C) 2017-20xx CEA/DEN, EDF R&D --> ++// Copyright (C) 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 ++// + + // File: SketchPlugin_Ellipse.cpp + // Created: 26 April 2017 + // Author: Artem ZHIDKOV + + #include + #include + + #include + #include + #include + #include + #include + #include + #include + #include + + static const double tolerance = 1e-7; + + + SketchPlugin_Ellipse::SketchPlugin_Ellipse() + : SketchPlugin_SketchEntity() + { + } + + void SketchPlugin_Ellipse::initDerivedClassAttributes() + { + data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(FOCUS_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(MAJOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(MINOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId()); + + data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID()); + } + + void SketchPlugin_Ellipse::execute() + { + SketchPlugin_Sketch* aSketch = sketch(); + if(!aSketch) { + return; + } + + // Compute a ellipse in 3D view. + std::shared_ptr aCenterAttr = + std::dynamic_pointer_cast(data()->attribute(CENTER_ID())); + std::shared_ptr aFocusAttr = + std::dynamic_pointer_cast(data()->attribute(FOCUS_ID())); + AttributeDoublePtr aMajorRadiusAttr = real(MAJOR_RADIUS_ID()); + AttributeDoublePtr aMinorRadiusAttr = real(MINOR_RADIUS_ID()); + if (!aCenterAttr->isInitialized() || + !aFocusAttr->isInitialized() || + !aMajorRadiusAttr->isInitialized() || + !aMinorRadiusAttr->isInitialized()) { + return; + } + + double aMajorRadius = aMajorRadiusAttr->value(); + double aMinorRadius = aMinorRadiusAttr->value(); + if(aMajorRadius < tolerance || aMinorRadius < tolerance) { + return; + } + + // Make a visible point. + SketchPlugin_Sketch::createPoint2DResult(this, aSketch, CENTER_ID(), 0); + + std::shared_ptr aNDir = std::dynamic_pointer_cast( + aSketch->attribute(SketchPlugin_Sketch::NORM_ID())); + + // Make a visible ellipse. + std::shared_ptr aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y())); + std::shared_ptr aFocus(aSketch->to3D(aFocusAttr->x(), aFocusAttr->y())); + std::shared_ptr aNormal = aNDir->dir(); + std::shared_ptr aMajorAxis(new GeomAPI_Dir(aFocus->x() - aCenter->x(), + aFocus->y() - aCenter->y(), aFocus->z() - aCenter->z())); + + std::shared_ptr anEllipseShape = + GeomAlgoAPI_EdgeBuilder::ellipse(aCenter, aNormal, aMajorAxis, aMajorRadius, aMinorRadius); + + std::shared_ptr aResult = document()->createConstruction(data(), 1); + aResult->setShape(anEllipseShape); + aResult->setIsInHistory(false); + setResult(aResult, 1); + } + + void SketchPlugin_Ellipse::move(double theDeltaX, double theDeltaY) + { + std::shared_ptr aData = data(); + if(!aData->isValid()) { + return; + } + + std::shared_ptr aPoint = std::dynamic_pointer_cast( + aData->attribute(CENTER_ID())); + if(aPoint->isInitialized()) { + aPoint->move(theDeltaX, theDeltaY); + } + } + + bool SketchPlugin_Ellipse::isFixed() { + return data()->selection(EXTERNAL_ID())->context().get() != NULL; + } + + void SketchPlugin_Ellipse::attributeChanged(const std::string& theID) { + // the second condition for unability to move external segments anywhere + if (theID == EXTERNAL_ID() || isFixed()) { + std::shared_ptr aSelection = data()->selection(EXTERNAL_ID())->value(); + if (!aSelection) { + // empty shape in selection shows that the shape is equal to context + ResultPtr anExtRes = selection(EXTERNAL_ID())->context(); + if (anExtRes) + aSelection = anExtRes->shape(); + } + // update arguments due to the selection value + if (aSelection && !aSelection->isNull() && aSelection->isEdge()) { + std::shared_ptr anEdge( new GeomAPI_Edge(aSelection)); + std::shared_ptr anEllipse = anEdge->ellipse(); + + std::shared_ptr aCenterAttr = + std::dynamic_pointer_cast(attribute(CENTER_ID())); + aCenterAttr->setValue(sketch()->to2D(anEllipse->center())); + + std::shared_ptr aFocusAttr = + std::dynamic_pointer_cast(attribute(FOCUS_ID())); + aFocusAttr->setValue(sketch()->to2D(anEllipse->firstFocus())); + + real(MAJOR_RADIUS_ID())->setValue(anEllipse->majorRadius()); + real(MINOR_RADIUS_ID())->setValue(anEllipse->minorRadius()); + } + } + } diff --cc src/SketchPlugin/SketchPlugin_Ellipse.h index 000000000,287a1a54a..fc4b77c64 mode 000000,100644..100644 --- a/src/SketchPlugin/SketchPlugin_Ellipse.h +++ b/src/SketchPlugin/SketchPlugin_Ellipse.h @@@ -1,0 -1,84 +1,102 @@@ -// Copyright (C) 2017-20xx CEA/DEN, EDF R&D --> ++// Copyright (C) 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 ++// + + // File: SketchPlugin_Ellipse.h + // Created: 26 April 2017 + // Author: Artem ZHIDKOV + + #ifndef SketchPlugin_Ellipse_H_ + #define SketchPlugin_Ellipse_H_ + + #include + #include + + /**\class SketchPlugin_Ellipse + * \ingroup Plugins + * \brief Feature for creation of the new ellipse in Sketch. + */ + class SketchPlugin_Ellipse: public SketchPlugin_SketchEntity + { + public: + /// Ellipse feature kind + inline static const std::string& ID() + { + static const std::string ID("SketchEllipse"); + return ID; + } + + /// 2D point - center of the ellipse + inline static const std::string& CENTER_ID() + { + static const std::string ID("ellipse_center"); + return ID; + } + + /// 2D point - focus of the ellipse + inline static const std::string& FOCUS_ID() + { + static const std::string ID("ellipse_focus"); + return ID; + } + + /// Major radius of the ellipse + inline static const std::string& MAJOR_RADIUS_ID() + { + static const std::string ID("ellipse_major_radius"); + return ID; + } + + /// Minor radius of the ellipse + inline static const std::string& MINOR_RADIUS_ID() + { + static const std::string ID("ellipse_minor_radius"); + return ID; + } + + /// Returns the kind of a feature + SKETCHPLUGIN_EXPORT virtual const std::string& getKind() + { + static std::string MY_KIND = SketchPlugin_Ellipse::ID(); + return MY_KIND; + } + + /// Returns true is sketch element is under the rigid constraint + SKETCHPLUGIN_EXPORT virtual bool isFixed(); + + /// Called on change of any argument-attribute of this object + SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID); + + /// 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); + + /// Use plugin manager for features creation + SketchPlugin_Ellipse(); + + protected: + /// \brief Initializes attributes of derived class. + virtual void initDerivedClassAttributes(); + }; + + #endif diff --cc src/SketchPlugin/SketchPlugin_MacroEllipse.cpp index 000000000,1376384ea..37ea7aa31 mode 000000,100644..100644 --- a/src/SketchPlugin/SketchPlugin_MacroEllipse.cpp +++ b/src/SketchPlugin/SketchPlugin_MacroEllipse.cpp @@@ -1,0 -1,244 +1,262 @@@ -// Copyright (C) 2017-20xx CEA/DEN, EDF R&D --> ++// Copyright (C) 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 ++// + + // File: SketchPlugin_MacroEllipse.cpp + // Created: 26 April 2017 + // Author: Artem ZHIDKOV + + #include + + #include + #include + #include + + #include + #include + #include + #include + #include + #include + + #include + + #include + #include + #include + #include + + #include + #include + #include + + + SketchPlugin_MacroEllipse::SketchPlugin_MacroEllipse() + : SketchPlugin_SketchEntity(), + myMajorRadius(0.0), + myMinorRadius(0.0) + { + } + + void SketchPlugin_MacroEllipse::initAttributes() + { + data()->addAttribute(CENTER_POINT_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(CENTER_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId()); + data()->addAttribute(MAJOR_AXIS_POINT_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(MAJOR_AXIS_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId()); + data()->addAttribute(PASSED_POINT_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(PASSED_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId()); + + data()->addAttribute(MAJOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(MINOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId()); + + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_POINT_REF_ID()); + ModelAPI_Session::get()->validators()-> + registerNotObligatory(getKind(), MAJOR_AXIS_POINT_REF_ID()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PASSED_POINT_REF_ID()); + } + + void SketchPlugin_MacroEllipse::execute() + { + FeaturePtr anEllipse = createEllipseFeature(); + constraintsForEllipse(anEllipse); + + // message to init reentrant operation + static Events_ID anId = ModelAPI_EventReentrantMessage::eventId(); + ReentrantMessagePtr aMessage(new ModelAPI_EventReentrantMessage(anId, this)); + aMessage->setCreatedFeature(anEllipse); + Events_Loop::loop()->send(aMessage); + } + + void SketchPlugin_MacroEllipse::attributeChanged(const std::string& theID) + { + static const int NB_POINTS = 3; + std::string aPointAttrName[NB_POINTS] = { CENTER_POINT_ID(), + MAJOR_AXIS_POINT_ID(), + PASSED_POINT_ID() }; + std::string aPointRefName[NB_POINTS] = { CENTER_POINT_REF_ID(), + MAJOR_AXIS_POINT_REF_ID(), + PASSED_POINT_REF_ID() }; + + int aNbInitialized = 0; + std::shared_ptr anEllipsePoints[NB_POINTS]; + + for (int aPntIndex = 0; aPntIndex < NB_POINTS; ++aPntIndex) { + AttributePtr aPointAttr = attribute(aPointAttrName[aPntIndex]); + if (!aPointAttr->isInitialized()) + continue; + + AttributeRefAttrPtr aPointRef = refattr(aPointRefName[aPntIndex]); + // calculate ellipse parameters + std::shared_ptr aPassedPoint; + std::shared_ptr aTangentCurve; + SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve( + aPointRef, aPointAttr, aTangentCurve, aPassedPoint); + + anEllipsePoints[aNbInitialized++] = aPassedPoint; + } + + std::shared_ptr anEllipse; + if (aNbInitialized == 2) { + std::shared_ptr aXDir(new GeomAPI_Dir2d( + anEllipsePoints[1]->x() - anEllipsePoints[0]->x(), + anEllipsePoints[1]->y() - anEllipsePoints[0]->y())); + double aMajorRad = anEllipsePoints[1]->distance(anEllipsePoints[0]); + anEllipse = std::shared_ptr( + new GeomAPI_Ellipse2d(anEllipsePoints[0], aXDir, aMajorRad, 0.5 * aMajorRad)); + } else if (aNbInitialized == 3) { + anEllipse = std::shared_ptr( + new GeomAPI_Ellipse2d(anEllipsePoints[0], anEllipsePoints[1], anEllipsePoints[2])); + } + + if (!anEllipse || anEllipse->implPtr() == 0) + return; + + myCenter = anEllipse->center(); + myFocus = anEllipse->firstFocus(); + myMajorRadius = anEllipse->majorRadius(); + myMinorRadius = anEllipse->minorRadius(); + + AttributeDoublePtr aMajorRadiusAttr = real(MAJOR_RADIUS_ID()); + AttributeDoublePtr aMinorRadiusAttr = real(MINOR_RADIUS_ID()); + + bool aWasBlocked = data()->blockSendAttributeUpdated(true); + // center attribute is used in processEvent() to set reference to reentrant arc + std::dynamic_pointer_cast(attribute(CENTER_POINT_ID()))->setValue(myCenter); + aMajorRadiusAttr->setValue(myMajorRadius); + aMinorRadiusAttr->setValue(myMinorRadius); + data()->blockSendAttributeUpdated(aWasBlocked, false); + } + + std::string SketchPlugin_MacroEllipse::processEvent( + const std::shared_ptr& theMessage) + { + std::string aFilledAttributeName; + + ReentrantMessagePtr aReentrantMessage = + std::dynamic_pointer_cast(theMessage); + if (aReentrantMessage) { + FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature(); + ObjectPtr anObject = aReentrantMessage->selectedObject(); + AttributePtr anAttribute = aReentrantMessage->selectedAttribute(); + std::shared_ptr aClickedPoint = aReentrantMessage->clickedPoint(); + + if (aClickedPoint && (anObject || anAttribute)) { + aFilledAttributeName = CENTER_POINT_ID(); + std::string aReferenceAttributeName = CENTER_POINT_REF_ID(); + + // fill 2d point attribute + AttributePoint2DPtr aPointAttr = + std::dynamic_pointer_cast(attribute(aFilledAttributeName)); + aPointAttr->setValue(aClickedPoint); + + // fill reference attribute + AttributeRefAttrPtr aRefAttr = + std::dynamic_pointer_cast(attribute(aReferenceAttributeName)); + if (anAttribute) { + if (!anAttribute->owner() || !anAttribute->owner()->data()->isValid()) { + if (aCreatedFeature && anAttribute->id() == CENTER_POINT_ID()) + anAttribute = aCreatedFeature->attribute(SketchPlugin_Ellipse::CENTER_ID()); + } + aRefAttr->setAttr(anAttribute); + } + else if (anObject.get()) { + // if presentation of previous reentrant macro arc is used, the object is invalid, + // we should use result of previous feature of the message(Arc) + if (!anObject->data()->isValid()) + anObject = aCreatedFeature->lastResult(); + aRefAttr->setObject(anObject); + } + } + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); + } + return aFilledAttributeName; + } + + void SketchPlugin_MacroEllipse::constraintsForEllipse(FeaturePtr theEllipseFeature) + { + // Create constraints. + SketchPlugin_Tools::createConstraint( + this, CENTER_POINT_REF_ID(), + theEllipseFeature->attribute(SketchPlugin_Ellipse::CENTER_ID()), + ObjectPtr(), false); + SketchPlugin_Tools::createConstraint( + this, MAJOR_AXIS_POINT_REF_ID(), AttributePtr(), + theEllipseFeature->lastResult(), true); + SketchPlugin_Tools::createConstraint( + this, PASSED_POINT_REF_ID(), AttributePtr(), + theEllipseFeature->lastResult(), true); + } + + FeaturePtr SketchPlugin_MacroEllipse::createEllipseFeature() + { + FeaturePtr aEllipseFeature = sketch()->addFeature(SketchPlugin_Ellipse::ID()); + + AttributePoint2DPtr aCenterAttr = std::dynamic_pointer_cast( + aEllipseFeature->attribute(SketchPlugin_Ellipse::CENTER_ID())); + aCenterAttr->setValue(myCenter->x(), myCenter->y()); + + AttributePoint2DPtr aFocusAttr = std::dynamic_pointer_cast( + aEllipseFeature->attribute(SketchPlugin_Ellipse::FOCUS_ID())); + aFocusAttr->setValue(myFocus->x(), myFocus->y()); + + aEllipseFeature->real(SketchPlugin_Ellipse::MAJOR_RADIUS_ID())->setValue(myMajorRadius); + aEllipseFeature->real(SketchPlugin_Ellipse::MINOR_RADIUS_ID())->setValue(myMinorRadius); + + aEllipseFeature->boolean(SketchPlugin_Ellipse::AUXILIARY_ID())->setValue( + boolean(AUXILIARY_ID())->value()); + + aEllipseFeature->execute(); + return aEllipseFeature; + } + + AISObjectPtr SketchPlugin_MacroEllipse::getAISObject(AISObjectPtr thePrevious) + { + SketchPlugin_Sketch* aSketch = sketch(); + if (!aSketch || !myCenter || myMajorRadius == 0) + return AISObjectPtr(); + + std::shared_ptr aNDir = std::dynamic_pointer_cast( + aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID())); + + // Compute a ellipse in 3D view. + std::shared_ptr aCenter(aSketch->to3D(myCenter->x(), myCenter->y())); + std::shared_ptr aFocus(aSketch->to3D(myFocus->x(), myFocus->y())); + std::shared_ptr aNormal = aNDir->dir(); + std::shared_ptr aMajorAxis(new GeomAPI_Dir(aFocus->x() - aCenter->x(), + aFocus->y() - aCenter->y(), aFocus->z() - aCenter->z())); + + std::shared_ptr anEllipseShape = + GeomAlgoAPI_EdgeBuilder::ellipse(aCenter, aNormal, aMajorAxis, myMajorRadius, myMinorRadius); + GeomShapePtr aCenterPointShape = GeomAlgoAPI_PointBuilder::vertex(aCenter); + if (!anEllipseShape.get() || !aCenterPointShape.get()) + return AISObjectPtr(); + + std::list > aShapes; + aShapes.push_back(anEllipseShape); + aShapes.push_back(aCenterPointShape); + + std::shared_ptr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes); + AISObjectPtr anAIS = thePrevious; + if (!anAIS) + anAIS.reset(new GeomAPI_AISObject()); + anAIS->createShape(aCompound); + return anAIS; + } diff --cc src/SketchPlugin/SketchPlugin_MacroEllipse.h index 000000000,29ae08978..d31d0d55f mode 000000,100644..100644 --- a/src/SketchPlugin/SketchPlugin_MacroEllipse.h +++ b/src/SketchPlugin/SketchPlugin_MacroEllipse.h @@@ -1,0 -1,142 +1,160 @@@ -// Copyright (C) 2017-20xx CEA/DEN, EDF R&D --> ++// Copyright (C) 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 ++// + + // File: SketchPlugin_MacroEllipse.h + // Created: 26 April 2017 + // Author: Artem ZHIDKOV + + #ifndef SketchPlugin_MacroEllipse_H_ + #define SketchPlugin_MacroEllipse_H_ + + #include + #include + #include + #include + + ////class GeomAPI_Circ2d; + class GeomAPI_Pnt2d; + + /**\class SketchPlugin_MacroEllipse + * \ingroup Plugins + * \brief Feature for creation of the new ellipse in Sketch. + */ + class SketchPlugin_MacroEllipse: public SketchPlugin_SketchEntity, + public GeomAPI_IPresentable, + public ModelAPI_IReentrant + { + public: + /// Ellipse feature kind + inline static const std::string& ID() + { + static const std::string ID("SketchMacroEllipse"); + return ID; + } + + /// 2D point - center of the ellipse. + inline static const std::string& CENTER_POINT_ID() + { + static const std::string ID("center_point"); + return ID; + } + + /// Reference for center point selection. + inline static const std::string& CENTER_POINT_REF_ID() + { + static const std::string ID("center_point_ref"); + return ID; + } + + /// 2D point - major axis point of the ellipse. + inline static const std::string& MAJOR_AXIS_POINT_ID() + { + static const std::string ID("major_axis_point"); + return ID; + } + + /// Reference for major axis point selection. + inline static const std::string& MAJOR_AXIS_POINT_REF_ID() + { + static const std::string ID("major_axis_point_ref"); + return ID; + } + + /// 2D point - passed point of the ellipse + inline static const std::string& PASSED_POINT_ID() + { + static const std::string ID("passed_point"); + return ID; + } + + /// Reference for passed point selection. + inline static const std::string& PASSED_POINT_REF_ID() + { + static const std::string ID("passed_point_ref"); + return ID; + } + + /// Major radius of the ellipse + inline static const std::string& MAJOR_RADIUS_ID() + { + static const std::string ID("ellipse_major_radius"); + return ID; + } + + /// Minor radius of the ellipse + inline static const std::string& MINOR_RADIUS_ID() + { + static const std::string ID("ellipse_minor_radius"); + return ID; + } + + /// Returns the kind of a feature + SKETCHPLUGIN_EXPORT virtual const std::string& getKind() + { + static std::string MY_KIND = SketchPlugin_MacroEllipse::ID(); + return MY_KIND; + } + + /// \brief Request for initialization of data model of the feature: adding all attributes. + SKETCHPLUGIN_EXPORT virtual void initAttributes(); + + /// Called on change of any argument-attribute of this object + SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID); + + /// Returns the AIS preview + virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious); + + /// 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) + {} + + /// Reimplemented from ModelAPI_Feature::isMacro(). + /// \returns true + SKETCHPLUGIN_EXPORT virtual bool isMacro() const + {return true;} + + SKETCHPLUGIN_EXPORT virtual bool isPreviewNeeded() const + {return false;} + + /// Apply information of the message to current object. It fills reference object, + /// tangent type and tangent point refence in case of tangent arc + virtual std::string processEvent(const std::shared_ptr& theMessage); + + /// Use plugin manager for features creation + SketchPlugin_MacroEllipse(); + + private: + void constraintsForEllipse(FeaturePtr theEllipseFeature); + + FeaturePtr createEllipseFeature(); + + private: + std::shared_ptr myCenter; + std::shared_ptr myFocus; + double myMajorRadius; + double myMinorRadius; + }; + + #endif diff --cc src/SketchPlugin/SketchPlugin_Plugin.cpp index 515cc685d,4776e5e3a..0a1c02678 --- a/src/SketchPlugin/SketchPlugin_Plugin.cpp +++ b/src/SketchPlugin/SketchPlugin_Plugin.cpp @@@ -30,8 -12,11 +30,10 @@@ #include #include #include + #include + #include #include #include -#include #include #include #include @@@ -47,9 -32,10 +49,11 @@@ #include #include #include +#include #include #include + #include + #include #include #include diff --cc src/SketchPlugin/Test/TestConstraintDistanceBehavior.py index 000000000,37c0458e4..35ab1496c mode 000000,100644..100644 --- a/src/SketchPlugin/Test/TestConstraintDistanceBehavior.py +++ b/src/SketchPlugin/Test/TestConstraintDistanceBehavior.py @@@ -1,0 -1,82 +1,102 @@@ ++## Copyright (C) 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 ++## ++ + from salome.shaper import model + from SketchAPI import * + import math + + TOLERANCE = 1.e-7 + + model.begin() + partSet = model.moduleDocument() + Part_1 = model.addPart(partSet) + Part_1_doc = Part_1.document() + DistanceParam = model.addParameter(Part_1_doc, "distance", "10.") + Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) + SketchRectangle_1 = Sketch_1.addRectangle(20., 20., 70., 50.) + [SketchLine_1, SketchLine_2, SketchLine_3, SketchLine_4] = SketchRectangle_1.lines() + firstPoint = SketchAPI_Line(SketchLine_2).startPoint() + secondPoint = SketchAPI_Line(SketchLine_3).endPoint() + model.do() + + # ============================================================================= + # Test 1. + # ============================================================================= + # horizontal distance constraint + SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(firstPoint, secondPoint, "distance") + model.do() + + # changing the parameter + for param in range(-30, 31, 2): + DistanceParam.setValue(param) + model.do() + dist = secondPoint.x() - firstPoint.x() + assert math.fabs(dist - param) < TOLERANCE, "Incorrect horizontal distance {}, expected {}".format(dist, param) + + model.testNbSubFeatures(Sketch_1, "SketchLine", 4) + model.testNbSubFeatures(Sketch_1, "SketchConstraintDistanceHorizontal", 1) + + # remove horizontal distance constraint + Part_1_doc.removeFeature(SketchConstraintDistanceHorizontal_1.feature()) + model.do() + + # ============================================================================= + # Test 2. + # ============================================================================= + # Vertical distance constraint + SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(firstPoint, secondPoint, "distance") + model.do() + + # changing the parameter + for param in range(-30, 31, 2): + DistanceParam.setValue(param) + model.do() + dist = secondPoint.y() - firstPoint.y() + assert math.fabs(dist - param) < TOLERANCE, "Incorrect vertical distance {}, expected {}".format(dist, param) + + model.testNbSubFeatures(Sketch_1, "SketchLine", 4) + model.testNbSubFeatures(Sketch_1, "SketchConstraintDistanceVertical", 1) + + # remove verticel distance constraint + Part_1_doc.removeFeature(SketchConstraintDistanceVertical_1.feature()) + model.do() + + # ============================================================================= + # Test 3. + # ============================================================================= + # distance constraint + SketchConstraintDistance_1 = Sketch_1.setDistance(firstPoint, secondPoint, "distance") + model.do() + + # changing the parameter + for param in range(-30, 31, 2): + DistanceParam.setValue(param) + model.do() + if param <= 0: + assert SketchConstraintDistance_1.feature().error() != '', "ERROR: Sketch should not be valid due to negative distance value" + else: + dist = model.distancePointPoint(firstPoint, secondPoint) + assert math.fabs(dist - math.fabs(param)) < TOLERANCE, "Incorrect distance {}, expected {}".format(dist, math.fabs(param)) + + model.testNbSubFeatures(Sketch_1, "SketchLine", 4) + model.testNbSubFeatures(Sketch_1, "SketchConstraintDistance", 1) + # leave distance constraint alive + + model.end() diff --cc src/SketchPlugin/Test/TestConstraintDistanceHorizontal.py index 000000000,dedb8d685..242787471 mode 000000,100644..100644 --- a/src/SketchPlugin/Test/TestConstraintDistanceHorizontal.py +++ b/src/SketchPlugin/Test/TestConstraintDistanceHorizontal.py @@@ -1,0 -1,208 +1,228 @@@ ++## Copyright (C) 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 ++## ++ + """ + TestConstraintDistanceHorizontal.py + Unit test of SketchPlugin_ConstraintDistanceHorizontal class + + SketchPlugin_ConstraintDistanceHorizontal + static const std::string MY_CONSTRAINT_DISTANCE_ID("SketchConstraintDistance"); + data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId()); + data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId()); + """ + + from GeomDataAPI import * + from ModelAPI import * + import math + from salome.shaper import model + + #========================================================================= + # Initialization of the test + #========================================================================= + + __updated__ = "2017-05-10" + + + def horizontalDistance(point1, point2): + """ + subroutine to calculate signed distance between two points + """ + return point2.x() - point1.x() + + aSession = ModelAPI_Session.get() + aDocument = aSession.moduleDocument() + #========================================================================= + # Creation of a sketch + #========================================================================= + aSession.startOperation() + aSketchCommonFeature = aDocument.addFeature("Sketch") + aSketchFeature = featureToCompositeFeature(aSketchCommonFeature) + origin = geomDataAPI_Point(aSketchFeature.attribute("Origin")) + origin.setValue(0, 0, 0) + dirx = geomDataAPI_Dir(aSketchFeature.attribute("DirX")) + dirx.setValue(1, 0, 0) + norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm")) + norm.setValue(0, 0, 1) + aSession.finishOperation() + #========================================================================= + # Create two movable and one fixed point + #========================================================================= + aSession.startOperation() + aPoint1 = aSketchFeature.addFeature("SketchPoint") + aPoint1Coords = geomDataAPI_Point2D(aPoint1.attribute("PointCoordinates")) + aPoint1Coords.setValue(50., 50.) + aSession.finishOperation() + aSession.startOperation() + aPoint2 = aSketchFeature.addFeature("SketchPoint") + aPoint2Coords = geomDataAPI_Point2D(aPoint2.attribute("PointCoordinates")) + aPoint2Coords.setValue(70., 70.) + aSession.finishOperation() + aSession.startOperation() + anOriginResult = modelAPI_Result(aDocument.objectByName("Construction", "Origin")) + anOriginShape = anOriginResult.shape() + anExtPoint = aSketchFeature.addFeature("SketchPoint") + anExtCoords = geomDataAPI_Point2D(anExtPoint.attribute("PointCoordinates")) + anExtCoords.setValue(0., 0.) + anExtPoint.selection("External").setValue(anOriginResult, anOriginShape) + aSession.finishOperation() + assert (model.dof(aSketchFeature) == 4) + + #========================================================================= + # Create a constraint to keep horizontal distance between movable points + #========================================================================= + DISTANCE1 = 25. + aSession.startOperation() + aHDist1 = aSketchFeature.addFeature("SketchConstraintDistanceHorizontal") + aDistance = aHDist1.real("ConstraintValue") + refattrA = aHDist1.refattr("ConstraintEntityA") + refattrB = aHDist1.refattr("ConstraintEntityB") + assert (not aDistance.isInitialized()) + assert (not refattrA.isInitialized()) + assert (not refattrB.isInitialized()) + refattrA.setObject(aPoint1.lastResult()) + refattrB.setObject(aPoint2.lastResult()) + aSession.finishOperation() + assert (model.dof(aSketchFeature) == 3) + # set flyout point then abort operation, after that check the Distance is correct + aSession.startOperation() + aFlyoutPoint = geomDataAPI_Point2D(aHDist1.attribute("ConstraintFlyoutValuePnt")) + aFlyoutPoint.setValue(50.0, 100.0) + aSession.abortOperation() + assert (refattrA.isInitialized()) + assert (refattrB.isInitialized()) + assert (aDistance.isInitialized()) + aSession.startOperation() + aDistance.setValue(DISTANCE1) + aSession.finishOperation() + assert math.fabs(horizontalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1) + assert (model.dof(aSketchFeature) == 3) + #========================================================================= + # Change a distance value + #========================================================================= + d = DISTANCE1 + 20. + dStep = -5. + while d >= -30.: + aSession.startOperation() + DISTANCE1 = d + aDistance.setValue(DISTANCE1) + aSession.finishOperation() + assert math.fabs(horizontalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1) + d += dStep + assert (model.dof(aSketchFeature) == 3) + + #========================================================================= + # Create a constraint to keep horizontal distance between fixed and movable points + #========================================================================= + DISTANCE2 = 50. + aSession.startOperation() + aHDist2 = aSketchFeature.addFeature("SketchConstraintDistanceHorizontal") + aDistance = aHDist2.real("ConstraintValue") + refattrA = aHDist2.refattr("ConstraintEntityA") + refattrB = aHDist2.refattr("ConstraintEntityB") + assert (not aDistance.isInitialized()) + assert (not refattrA.isInitialized()) + assert (not refattrB.isInitialized()) + refattrA.setObject(anExtPoint.lastResult()) + refattrB.setAttr(aPoint1Coords) + aDistance.setValue(DISTANCE2) + aSession.finishOperation() + assert math.fabs(horizontalDistance(anExtCoords, aPoint1Coords) - DISTANCE2) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(anExtCoords, aPoint1Coords), DISTANCE2) + assert math.fabs(aPoint1Coords.x() - DISTANCE2) < 1.e-5, "Wrong point coordinates ({}, {}), expected x = {}".format(aPoint1Coords.x(), aPoint1Coords.y(), DISTANCE2) + assert (model.dof(aSketchFeature) == 2) + #========================================================================= + # Change a distance value (check previous constraint is applied too) + #========================================================================= + d = DISTANCE2 + dStep = -5. + while d >= -50.: + aSession.startOperation() + DISTANCE2 = d + aDistance.setValue(DISTANCE2) + aSession.finishOperation() + assert math.fabs(horizontalDistance(anExtCoords, aPoint1Coords) - DISTANCE2) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(anExtCoords, aPoint1Coords), DISTANCE2) + assert math.fabs(aPoint1Coords.x() - DISTANCE2) < 1.e-5, "Wrong point coordinates ({}, {}), expected x = {}".format(aPoint1Coords.x(), aPoint1Coords.y(), DISTANCE2) + assert math.fabs(horizontalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1) + d += dStep + assert (model.dof(aSketchFeature) == 2) + + #========================================================================= + # Remove first distance + #========================================================================= + aStoredCoords = [aPoint2Coords.x(), aPoint2Coords.y()] + aSession.startOperation() + aDocument.removeFeature(aHDist1) + aSession.finishOperation() + assert (model.dof(aSketchFeature) == 3) + aSession.startOperation() + DISTANCE2 = 20. + aDistance.setValue(DISTANCE2) + aSession.finishOperation() + assert math.fabs(horizontalDistance(anExtCoords, aPoint1Coords) - DISTANCE2) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(anExtCoords, aPoint1Coords), DISTANCE2) + assert math.fabs(aPoint1Coords.x() - DISTANCE2) < 1.e-5, "Wrong point coordinates ({}, {}), expected x = {}".format(aPoint1Coords.x(), aPoint1Coords.y(), DISTANCE2) + assert aPoint2Coords.x() == aStoredCoords[0] and aPoint2Coords.y() == aStoredCoords[1] + + #========================================================================= + # Create line and set horizontal distance between line boundaries + #========================================================================= + aSession.startOperation() + aLine = aSketchFeature.addFeature("SketchLine") + aStartPoint = geomDataAPI_Point2D(aLine.attribute("StartPoint")) + aEndPoint = geomDataAPI_Point2D(aLine.attribute("EndPoint")) + aStartPoint.setValue(50., 0.) + aEndPoint.setValue(100., 20.) + aSession.finishOperation() + assert (model.dof(aSketchFeature) == 7) + + DISTANCE3 = 50. + aSession.startOperation() + aHDist3 = aSketchFeature.addFeature("SketchConstraintDistanceHorizontal") + aDistance = aHDist3.real("ConstraintValue") + refattrA = aHDist3.refattr("ConstraintEntityA") + refattrB = aHDist3.refattr("ConstraintEntityB") + assert (not aDistance.isInitialized()) + assert (not refattrA.isInitialized()) + assert (not refattrB.isInitialized()) + refattrA.setAttr(aStartPoint) + refattrB.setAttr(aEndPoint) + aDistance.setValue(DISTANCE3) + aSession.finishOperation() + assert math.fabs(horizontalDistance(aStartPoint, aEndPoint) - DISTANCE3) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(aStartPoint, aEndPoint), DISTANCE3) + assert (model.dof(aSketchFeature) == 6) + #========================================================================= + # Change a distance value + #========================================================================= + d = DISTANCE3 + dStep = -5. + while d >= -50.: + aSession.startOperation() + DISTANCE3 = d + aDistance.setValue(DISTANCE3) + aSession.finishOperation() + assert math.fabs(horizontalDistance(aStartPoint, aEndPoint) - DISTANCE3) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(aStartPoint, aEndPoint), DISTANCE3) + d += dStep + assert (model.dof(aSketchFeature) == 6) + + #========================================================================= + # End of test + #========================================================================= + + assert(model.checkPythonDump()) diff --cc src/SketchPlugin/Test/TestConstraintDistanceVertical.py index 000000000,09ba21142..8910edcbf mode 000000,100644..100644 --- a/src/SketchPlugin/Test/TestConstraintDistanceVertical.py +++ b/src/SketchPlugin/Test/TestConstraintDistanceVertical.py @@@ -1,0 -1,208 +1,228 @@@ ++## Copyright (C) 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 ++## ++ + """ + TestConstraintDistanceVertical.py + Unit test of SketchPlugin_ConstraintDistanceVertical class + + SketchPlugin_ConstraintDistanceVertical + static const std::string MY_CONSTRAINT_DISTANCE_ID("SketchConstraintDistance"); + data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId()); + data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId()); + """ + + from GeomDataAPI import * + from ModelAPI import * + import math + from salome.shaper import model + + #========================================================================= + # Initialization of the test + #========================================================================= + + __updated__ = "2017-05-10" + + + def verticalDistance(point1, point2): + """ + subroutine to calculate signed distance between two points + """ + return point2.y() - point1.y() + + aSession = ModelAPI_Session.get() + aDocument = aSession.moduleDocument() + #========================================================================= + # Creation of a sketch + #========================================================================= + aSession.startOperation() + aSketchCommonFeature = aDocument.addFeature("Sketch") + aSketchFeature = featureToCompositeFeature(aSketchCommonFeature) + origin = geomDataAPI_Point(aSketchFeature.attribute("Origin")) + origin.setValue(0, 0, 0) + dirx = geomDataAPI_Dir(aSketchFeature.attribute("DirX")) + dirx.setValue(1, 0, 0) + norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm")) + norm.setValue(0, 0, 1) + aSession.finishOperation() + #========================================================================= + # Create two movable and one fixed point + #========================================================================= + aSession.startOperation() + aPoint1 = aSketchFeature.addFeature("SketchPoint") + aPoint1Coords = geomDataAPI_Point2D(aPoint1.attribute("PointCoordinates")) + aPoint1Coords.setValue(50., 50.) + aSession.finishOperation() + aSession.startOperation() + aPoint2 = aSketchFeature.addFeature("SketchPoint") + aPoint2Coords = geomDataAPI_Point2D(aPoint2.attribute("PointCoordinates")) + aPoint2Coords.setValue(70., 70.) + aSession.finishOperation() + aSession.startOperation() + anOriginResult = modelAPI_Result(aDocument.objectByName("Construction", "Origin")) + anOriginShape = anOriginResult.shape() + anExtPoint = aSketchFeature.addFeature("SketchPoint") + anExtCoords = geomDataAPI_Point2D(anExtPoint.attribute("PointCoordinates")) + anExtCoords.setValue(0., 0.) + anExtPoint.selection("External").setValue(anOriginResult, anOriginShape) + aSession.finishOperation() + assert (model.dof(aSketchFeature) == 4) + + #========================================================================= + # Create a constraint to keep vertical distance between movable points + #========================================================================= + DISTANCE1 = 25. + aSession.startOperation() + aVDist1 = aSketchFeature.addFeature("SketchConstraintDistanceVertical") + aDistance = aVDist1.real("ConstraintValue") + refattrA = aVDist1.refattr("ConstraintEntityA") + refattrB = aVDist1.refattr("ConstraintEntityB") + assert (not aDistance.isInitialized()) + assert (not refattrA.isInitialized()) + assert (not refattrB.isInitialized()) + refattrA.setObject(aPoint1.lastResult()) + refattrB.setObject(aPoint2.lastResult()) + aSession.finishOperation() + assert (model.dof(aSketchFeature) == 3) + # set flyout point then abort operation, after that check the Distance is correct + aSession.startOperation() + aFlyoutPoint = geomDataAPI_Point2D(aVDist1.attribute("ConstraintFlyoutValuePnt")) + aFlyoutPoint.setValue(50.0, 100.0) + aSession.abortOperation() + assert (refattrA.isInitialized()) + assert (refattrB.isInitialized()) + assert (aDistance.isInitialized()) + aSession.startOperation() + aDistance.setValue(DISTANCE1) + aSession.finishOperation() + assert math.fabs(verticalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1) + assert (model.dof(aSketchFeature) == 3) + #========================================================================= + # Change a distance value + #========================================================================= + d = DISTANCE1 + 20. + dStep = -5. + while d >= -30.: + aSession.startOperation() + DISTANCE1 = d + aDistance.setValue(DISTANCE1) + aSession.finishOperation() + assert math.fabs(verticalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1) + d += dStep + assert (model.dof(aSketchFeature) == 3) + + #========================================================================= + # Create a constraint to keep vertical distance between fixed and movable points + #========================================================================= + DISTANCE2 = 50. + aSession.startOperation() + aVDist2 = aSketchFeature.addFeature("SketchConstraintDistanceVertical") + aDistance = aVDist2.real("ConstraintValue") + refattrA = aVDist2.refattr("ConstraintEntityA") + refattrB = aVDist2.refattr("ConstraintEntityB") + assert (not aDistance.isInitialized()) + assert (not refattrA.isInitialized()) + assert (not refattrB.isInitialized()) + refattrA.setObject(anExtPoint.lastResult()) + refattrB.setAttr(aPoint1Coords) + aDistance.setValue(DISTANCE2) + aSession.finishOperation() + assert math.fabs(verticalDistance(anExtCoords, aPoint1Coords) - DISTANCE2) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(anExtCoords, aPoint1Coords), DISTANCE2) + assert math.fabs(aPoint1Coords.y() - DISTANCE2) < 1.e-5, "Wrong point coordinates ({}, {}), expected y = {}".format(aPoint1Coords.x(), aPoint1Coords.y(), DISTANCE2) + assert (model.dof(aSketchFeature) == 2) + #========================================================================= + # Change a distance value (check previous constraint is applied too) + #========================================================================= + d = DISTANCE2 + dStep = -5. + while d >= -50.: + aSession.startOperation() + DISTANCE2 = d + aDistance.setValue(DISTANCE2) + aSession.finishOperation() + assert math.fabs(verticalDistance(anExtCoords, aPoint1Coords) - DISTANCE2) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(anExtCoords, aPoint1Coords), DISTANCE2) + assert math.fabs(aPoint1Coords.y() - DISTANCE2) < 1.e-5, "Wrong point coordinates ({}, {}), expected y = {}".format(aPoint1Coords.x(), aPoint1Coords.y(), DISTANCE2) + assert math.fabs(verticalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1) + d += dStep + assert (model.dof(aSketchFeature) == 2) + + #========================================================================= + # Remove first distance + #========================================================================= + aStoredCoords = [aPoint2Coords.x(), aPoint2Coords.y()] + aSession.startOperation() + aDocument.removeFeature(aVDist1) + aSession.finishOperation() + assert (model.dof(aSketchFeature) == 3) + aSession.startOperation() + DISTANCE2 = 20. + aDistance.setValue(DISTANCE2) + aSession.finishOperation() + assert math.fabs(verticalDistance(anExtCoords, aPoint1Coords) - DISTANCE2) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(anExtCoords, aPoint1Coords), DISTANCE2) + assert math.fabs(aPoint1Coords.y() - DISTANCE2) < 1.e-5, "Wrong point coordinates ({}, {}), expected y = {}".format(aPoint1Coords.x(), aPoint1Coords.y(), DISTANCE2) + assert aPoint2Coords.x() == aStoredCoords[0] and aPoint2Coords.y() == aStoredCoords[1] + + #========================================================================= + # Create line and set vertical distance between line boundaries + #========================================================================= + aSession.startOperation() + aLine = aSketchFeature.addFeature("SketchLine") + aStartPoint = geomDataAPI_Point2D(aLine.attribute("StartPoint")) + aEndPoint = geomDataAPI_Point2D(aLine.attribute("EndPoint")) + aStartPoint.setValue(50., 0.) + aEndPoint.setValue(100., 20.) + aSession.finishOperation() + assert (model.dof(aSketchFeature) == 7) + + DISTANCE3 = 50. + aSession.startOperation() + aVDist3 = aSketchFeature.addFeature("SketchConstraintDistanceVertical") + aDistance = aVDist3.real("ConstraintValue") + refattrA = aVDist3.refattr("ConstraintEntityA") + refattrB = aVDist3.refattr("ConstraintEntityB") + assert (not aDistance.isInitialized()) + assert (not refattrA.isInitialized()) + assert (not refattrB.isInitialized()) + refattrA.setAttr(aStartPoint) + refattrB.setAttr(aEndPoint) + aDistance.setValue(DISTANCE3) + aSession.finishOperation() + assert math.fabs(verticalDistance(aStartPoint, aEndPoint) - DISTANCE3) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(aStartPoint, aEndPoint), DISTANCE3) + assert (model.dof(aSketchFeature) == 6) + #========================================================================= + # Change a distance value + #========================================================================= + d = DISTANCE3 + dStep = -5. + while d >= -50.: + aSession.startOperation() + DISTANCE3 = d + aDistance.setValue(DISTANCE3) + aSession.finishOperation() + assert math.fabs(verticalDistance(aStartPoint, aEndPoint) - DISTANCE3) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(aStartPoint, aEndPoint), DISTANCE3) + d += dStep + assert (model.dof(aSketchFeature) == 6) + + #========================================================================= + # End of test + #========================================================================= + + assert(model.checkPythonDump()) diff --cc src/SketchPlugin/Test/TestConstraintHorizontalValidator.py index 000000000,caf2f1a49..103d7db80 mode 000000,100644..100644 --- a/src/SketchPlugin/Test/TestConstraintHorizontalValidator.py +++ b/src/SketchPlugin/Test/TestConstraintHorizontalValidator.py @@@ -1,0 -1,50 +1,70 @@@ ++## Copyright (C) 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 ++## ++ + """ + TestConstraintHorizontalValidator.py + It tests validation of horizontal and vertical segments in H and V constraints to avoid + selection segments that already have one of these constraint" + """ + + #========================================================================= + # of the test + #========================================================================= + from salome.shaper import model + from ModelAPI import * + import math + #========================================================================= + # Creation of a part + #========================================================================= + model.begin() + partSet = model.moduleDocument() + Part_1 = model.addPart(partSet) + Part_1_doc = Part_1.document() + #========================================================================= + # Creation of a sketch + #========================================================================= + Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ")) + SketchLine_1 = Sketch_1.addLine(20, 20, 40, 80) + SketchLine_2 = Sketch_1.addLine(40, 80, 60, 40) + SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) + SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result()) + SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_1.result()) + model.do() + #========================================================================= + # Checking that sketch and constraints become invalid when to one line + # two horizontal/vertical constraints are applied in any combination + #========================================================================= + aFactory = ModelAPI_Session.get().validators() + assert(aFactory.validate(Sketch_1.feature())) + assert(Sketch_1.feature().error() != '') + #========================================================================= + # Remove duplicated Vertical constraints + #========================================================================= + Part_1_doc.removeFeature(SketchConstraintVertical_1.feature()) + assert(aFactory.validate(Sketch_1.feature())) + model.do() + #========================================================================= + # Checking that after excess constraints are removed or undone, + # sketch becomes valid. + #========================================================================= + assert(aFactory.validate(Sketch_1.feature())) + assert(Sketch_1.feature().error() == '') + + assert(model.checkPythonDump()) diff --cc src/SketchPlugin/Test/TestMoveArc.py index 000000000,10f4ec06a..4419d85e1 mode 000000,100644..100644 --- a/src/SketchPlugin/Test/TestMoveArc.py +++ b/src/SketchPlugin/Test/TestMoveArc.py @@@ -1,0 -1,329 +1,349 @@@ ++## Copyright (C) 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 movement of the sketch arc of circle + """ + + import unittest + from GeomDataAPI import geomDataAPI_Point2D + from salome.shaper import model + + __updated__ = "2017-05-11" + + class TestMoveArc(unittest.TestCase): + def setUp(self): + model.begin() + self.myDocument = model.moduleDocument() + self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY")) + self.myCenter = [50., 50.] + self.myStart = [70., 50.] + self.myEnd = [50., 70.] + self.myArc = self.mySketch.addArc(self.myCenter[0], self.myCenter[1], self.myStart[0], self.myStart[1], self.myEnd[0], self.myEnd[1], False) + self.myDOF = 5 + model.do() + self.checkDOF() + + def tearDown(self): + model.assertArcValidity(self.myArc) + self.checkDOF() + model.end() + assert(model.checkPythonDump()) + + def checkDOF(self): + self.assertEqual(model.dof(self.mySketch), self.myDOF) + + def checkPointCoordinates(self, thePoint, theCoordinates): + self.assertAlmostEqual(thePoint.x(), theCoordinates[0]) + self.assertAlmostEqual(thePoint.y(), theCoordinates[1]) + + def checkPointOnArc(self, theCoordinates): + distPC = model.distancePointPoint(self.myArc.center(), theCoordinates) + radius = model.distancePointPoint(self.myArc.center(), self.myArc.startPoint()) + self.assertAlmostEqual(distPC, radius) + + def checkArcRadius(self): + radius = model.distancePointPoint(self.myArc.center(), self.myArc.startPoint()) + self.assertAlmostEqual(radius, self.myRadius) + + def fixArcRadius(self): + self.myRadius = 20. + self.mySketch.setRadius(self.myArc.results()[1], self.myRadius) + self.myDOF -= 1 + model.do() + self.checkDOF() + + def fixPoint(self, thePoint): + self.mySketch.setFixed(thePoint) + self.myDOF -= 2 + model.do() + self.checkDOF() + + def fixArc(self): + self.mySketch.setFixed(self.myArc.results()[1]) + self.myDOF -= 5 + model.do() + self.checkDOF() + + + def test_move_center_of_free_arc(self): + """ Test 1. Movement of center of a free arc + """ + newPosition = [self.myCenter[0] + 10., self.myCenter[1] - 15.] + self.mySketch.move(self.myArc.center(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myArc.center(), newPosition) + + def test_move_start_of_free_arc(self): + """ Test 2. Movement of start point of a free arc + """ + newPosition = [self.myStart[0] - 10., self.myStart[1] + 5.] + self.mySketch.move(self.myArc.startPoint(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myArc.center(), self.myCenter) + self.checkPointCoordinates(self.myArc.startPoint(), newPosition) + + def test_move_end_of_free_arc(self): + """ Test 3. Movement of end point of a free arc + """ + newPosition = [self.myEnd[0] + 10., self.myEnd[1] + 5.] + self.mySketch.move(self.myArc.endPoint(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myArc.center(), self.myCenter) + self.checkPointCoordinates(self.myArc.endPoint(), newPosition) + + def test_move_free_arc(self): + """ Test 4. Movement of a free arc dragging the edge + """ + newPosition = [100., 80.] + self.mySketch.move(self.myArc.defaultResult(), newPosition[0], newPosition[1]) + model.do() + self.checkPointOnArc(newPosition) + self.checkPointCoordinates(self.myArc.center(), self.myCenter) + + def test_move_center_of_arc_fixed_center(self): + """ Test 5. Movement of center of the arc with fixed center (nothing should be changed) + """ + self.fixPoint(self.myArc.center()) + + newPosition = [self.myCenter[0] + 10., self.myCenter[1] - 15.] + self.mySketch.move(self.myArc.center(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myArc.center(), self.myCenter) + + def test_move_start_of_arc_fixed_center(self): + """ Test 6. Movement of start point of the arc with fixed center + """ + self.fixPoint(self.myArc.center()) + + newPosition = [self.myStart[0] - 10., self.myStart[1] + 5.] + self.mySketch.move(self.myArc.startPoint(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myArc.center(), self.myCenter) + self.checkPointCoordinates(self.myArc.startPoint(), newPosition) + + def test_move_end_of_arc_fixed_center(self): + """ Test 7. Movement of end point of the arc with fixed center + """ + self.fixPoint(self.myArc.center()) + + newPosition = [self.myEnd[0] + 10., self.myEnd[1] + 5.] + self.mySketch.move(self.myArc.endPoint(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myArc.center(), self.myCenter) + self.checkPointCoordinates(self.myArc.endPoint(), newPosition) + + def test_move_arc_fixed_center(self): + """ Test 8. Movement of the arc with fixed center dragging the edge + """ + self.fixPoint(self.myArc.center()) + + newPosition = [100., 80.] + self.mySketch.move(self.myArc.defaultResult(), newPosition[0], newPosition[1]) + model.do() + self.checkPointOnArc(newPosition) + self.checkPointCoordinates(self.myArc.center(), self.myCenter) + + def test_move_center_of_arc_fixed_start(self): + """ Test 9. Movement of center of the arc with fixed start point + """ + self.fixPoint(self.myArc.startPoint()) + + newPosition = [self.myCenter[0] + 10., self.myCenter[1] - 15.] + self.mySketch.move(self.myArc.center(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myArc.center(), newPosition) + self.checkPointCoordinates(self.myArc.startPoint(), self.myStart) + + def test_move_start_of_arc_fixed_start(self): + """ Test 10. Movement of start point of the arc with fixed start point (nothing should be changed) + """ + self.fixPoint(self.myArc.startPoint()) + + newPosition = [self.myStart[0] - 10., self.myStart[1] + 5.] + self.mySketch.move(self.myArc.startPoint(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myArc.center(), self.myCenter) + self.checkPointCoordinates(self.myArc.startPoint(), self.myStart) + self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd) + + def test_move_end_of_arc_fixed_start(self): + """ Test 11. Movement of end point of the arc with fixed start point + """ + self.fixPoint(self.myArc.startPoint()) + + newPosition = [self.myEnd[0] + 10., self.myEnd[1] + 5.] + self.mySketch.move(self.myArc.endPoint(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myArc.startPoint(), self.myStart) + self.assertNotEqual(self.myArc.center().x(), self.myCenter[0]) + self.assertNotEqual(self.myArc.center().y(), self.myCenter[1]) + + def test_move_arc_fixed_start(self): + """ Test 12. Movement of the arc with fixed start point dragging the edge + """ + self.fixPoint(self.myArc.startPoint()) + + newPosition = [100., 80.] + self.mySketch.move(self.myArc.defaultResult(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myArc.startPoint(), self.myStart) + self.assertNotEqual(self.myArc.center().x(), self.myCenter[0]) + self.assertNotEqual(self.myArc.center().y(), self.myCenter[1]) + + def test_move_center_of_arc_fixed_end(self): + """ Test 13. Movement of center of the arc with fixed end point + """ + self.fixPoint(self.myArc.endPoint()) + + newPosition = [self.myCenter[0] + 10., self.myCenter[1] - 15.] + self.mySketch.move(self.myArc.center(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myArc.center(), newPosition) + self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd) + + def test_move_start_of_arc_fixed_end(self): + """ Test 14. Movement of start point of the arc with fixed end point + """ + self.fixPoint(self.myArc.endPoint()) + + newPosition = [self.myStart[0] - 10., self.myStart[1] + 5.] + self.mySketch.move(self.myArc.startPoint(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd) + self.assertNotEqual(self.myArc.center().x(), self.myCenter[0]) + self.assertNotEqual(self.myArc.center().y(), self.myCenter[1]) + + def test_move_end_of_arc_fixed_end(self): + """ Test 15. Movement of end point of the arc with fixed end point (nothing should be changed) + """ + self.fixPoint(self.myArc.endPoint()) + + newPosition = [self.myEnd[0] + 10., self.myEnd[1] + 5.] + self.mySketch.move(self.myArc.endPoint(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myArc.center(), self.myCenter) + self.checkPointCoordinates(self.myArc.startPoint(), self.myStart) + self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd) + + def test_move_arc_fixed_end(self): + """ Test 16. Movement of the arc with fixed end point dragging the edge + """ + self.fixPoint(self.myArc.endPoint()) + + newPosition = [100., 80.] + self.mySketch.move(self.myArc.defaultResult(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd) + self.assertNotEqual(self.myArc.center().x(), self.myCenter[0]) + self.assertNotEqual(self.myArc.center().y(), self.myCenter[1]) + + def test_move_center_of_arc_fixed_radius(self): + """ Test 17. Movement of center of the arc with fixed radius + """ + self.fixArcRadius() + + newPosition = [self.myCenter[0] + 10., self.myCenter[1] - 15.] + self.mySketch.move(self.myArc.center(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myArc.center(), newPosition) + self.checkArcRadius() + + def test_move_start_of_arc_fixed_radius(self): + """ Test 18. Movement of start point of the arc with fixed radius + """ + self.fixArcRadius() + + newPosition = [self.myStart[0] - 10., self.myStart[1] + 5.] + self.mySketch.move(self.myArc.startPoint(), newPosition[0], newPosition[1]) + model.do() + self.checkArcRadius() + + def test_move_end_of_arc_fixed_radius(self): + """ Test 19. Movement of end point of the arc with fixed radius + """ + self.fixArcRadius() + + newPosition = [self.myEnd[0] + 10., self.myEnd[1] + 5.] + self.mySketch.move(self.myArc.endPoint(), newPosition[0], newPosition[1]) + model.do() + self.checkArcRadius() + + def test_move_arc_fixed_radius(self): + """ Test 20. Movement of the arc with fixed radius dragging the edge + """ + self.fixArcRadius() + + newPosition = [100., 80.] + self.mySketch.move(self.myArc.defaultResult(), newPosition[0], newPosition[1]) + model.do() + self.checkArcRadius() + + def test_move_center_of_fixed_arc(self): + """ Test 21. Movement of center of fully fixed arc (nothing should be changed) + """ + self.fixArc() + + newPosition = [self.myCenter[0] + 10., self.myCenter[1] - 15.] + self.mySketch.move(self.myArc.center(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myArc.center(), self.myCenter) + self.checkPointCoordinates(self.myArc.startPoint(), self.myStart) + self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd) + + def test_move_start_of_fixed_arc(self): + """ Test 22. Movement of start point of fully fixed arc (nothing should be changed) + """ + self.fixArc() + + newPosition = [self.myStart[0] - 10., self.myStart[1] + 5.] + self.mySketch.move(self.myArc.startPoint(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myArc.center(), self.myCenter) + self.checkPointCoordinates(self.myArc.startPoint(), self.myStart) + self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd) + + def test_move_end_of_fixed_arc(self): + """ Test 23. Movement of end point of fully fixed arc (nothing should be changed) + """ + self.fixArc() + + newPosition = [self.myEnd[0] + 10., self.myEnd[1] + 5.] + self.mySketch.move(self.myArc.endPoint(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myArc.center(), self.myCenter) + self.checkPointCoordinates(self.myArc.startPoint(), self.myStart) + self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd) + + def test_move_fixed_arc(self): + """ Test 24. Movement of fully fixed arc (nothing should be changed) + """ + self.fixArc() + + newPosition = [100., 80.] + self.mySketch.move(self.myArc.defaultResult(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myArc.center(), self.myCenter) + self.checkPointCoordinates(self.myArc.startPoint(), self.myStart) + self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd) + + + if __name__ == '__main__': + unittest.main() diff --cc src/SketchPlugin/Test/TestMoveCircle.py index 000000000,fdccca617..54a9b580e mode 000000,100644..100644 --- a/src/SketchPlugin/Test/TestMoveCircle.py +++ b/src/SketchPlugin/Test/TestMoveCircle.py @@@ -1,0 -1,129 +1,149 @@@ ++## Copyright (C) 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 movement of the sketch circle + """ + + import unittest + from GeomDataAPI import geomDataAPI_Point2D + from salome.shaper import model + + __updated__ = "2017-05-11" + + class TestMoveCircle(unittest.TestCase): + def setUp(self): + model.begin() + self.myDocument = model.moduleDocument() + self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY")) + self.myCenter = [70., 50.] + self.myRadius = 20. + self.myCircle = self.mySketch.addCircle(self.myCenter[0], self.myCenter[1], self.myRadius) + self.myDOF = 3 + model.do() + self.checkDOF() + + def tearDown(self): + self.checkDOF() + model.end() + assert(model.checkPythonDump()) + + def checkDOF(self): + self.assertEqual(model.dof(self.mySketch), self.myDOF) + + def checkPointCoordinates(self, thePoint, theCoordinates): + self.assertAlmostEqual(thePoint.x(), theCoordinates[0]) + self.assertAlmostEqual(thePoint.y(), theCoordinates[1]) + + def checkPointOnCircle(self, theCoordinates): + self.assertAlmostEqual(model.distancePointPoint(self.myCircle.center(), theCoordinates), self.myCircle.radius().value()) + + def fixCircleRadius(self): + self.mySketch.setRadius(self.myCircle.results()[1], self.myRadius) + self.myDOF -= 1 + model.do() + self.checkDOF() + + def fixCircleCenter(self): + self.mySketch.setFixed(self.myCircle.center()) + self.myDOF -= 2 + model.do() + self.checkDOF() + + + def test_move_center_free_circle(self): + """ Test 1. Movement of central point of a free circle + """ + newPosition = [self.myCenter[0] + 20., self.myCenter[1] + 10.] + self.mySketch.move(self.myCircle.center(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myCircle.center(), newPosition) + self.assertAlmostEqual(self.myCircle.radius().value(), self.myRadius) + + def test_move_free_circle(self): + """ Test 2. Movement of a free circle dragging the edge + """ + newPosition = [120., 90.] + self.mySketch.move(self.myCircle.defaultResult(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myCircle.center(), self.myCenter) + self.checkPointOnCircle(newPosition) + self.assertNotEqual(self.myCircle.radius().value(), self.myRadius) + + def test_move_center_circle_fixed_radius(self): + """ Test 3. Movement of central point of a circle with fixed radius + """ + self.fixCircleRadius() + + newPosition = [self.myCenter[0] + 20., self.myCenter[1] + 10.] + self.mySketch.move(self.myCircle.center(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myCircle.center(), newPosition) + self.assertAlmostEqual(self.myCircle.radius().value(), self.myRadius) + + def test_move_circle_fixed_radius(self): + """ Test 4. Movement of a circle with fixed radius + """ + self.fixCircleRadius() + + newPosition = [120., 90.] + self.mySketch.move(self.myCircle.defaultResult(), newPosition[0], newPosition[1]) + model.do() + self.assertAlmostEqual(self.myCircle.radius().value(), self.myRadius) + self.assertNotEqual(self.myCircle.center().x(), self.myCenter[0]) + self.assertNotEqual(self.myCircle.center().y(), self.myCenter[1]) + + def test_move_center_circle_fixed_center(self): + """ Test 5. Movement of central point of a circle with fixed center (nothing should be changed) + """ + self.fixCircleCenter() + + newPosition = [self.myCenter[0] + 20., self.myCenter[1] + 10.] + self.mySketch.move(self.myCircle.center(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myCircle.center(), self.myCenter) + self.assertAlmostEqual(self.myCircle.radius().value(), self.myRadius) + + def test_move_circle_fixed_center(self): + """ Test 6. Movement of a circle with fixed center + """ + self.fixCircleCenter() + + newPosition = [120., 90.] + self.mySketch.move(self.myCircle.defaultResult(), newPosition[0], newPosition[1]) + model.do() + self.checkPointOnCircle(newPosition) + self.assertNotEqual(self.myCircle.radius().value(), self.myRadius) + + def test_move_fixed_circle(self): + """ Test 7. Trying to move fully fixed circle + """ + self.fixCircleCenter() + self.fixCircleRadius() + + newPosition = [120., 90.] + self.mySketch.move(self.myCircle.defaultResult(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myCircle.center(), self.myCenter) + self.assertAlmostEqual(self.myCircle.radius().value(), self.myRadius) + + + if __name__ == '__main__': + unittest.main() diff --cc src/SketchPlugin/Test/TestMoveLine.py index 000000000,89c6f7fec..3d4efa1dc mode 000000,100644..100644 --- a/src/SketchPlugin/Test/TestMoveLine.py +++ b/src/SketchPlugin/Test/TestMoveLine.py @@@ -1,0 -1,116 +1,136 @@@ ++## Copyright (C) 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 movement of the sketch line + """ + + import unittest + from GeomDataAPI import geomDataAPI_Point2D + from salome.shaper import model + + __updated__ = "2017-05-11" + + class TestMoveLine(unittest.TestCase): + def setUp(self): + model.begin() + self.myDocument = model.moduleDocument() + self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY")) + self.myStart = [70., 50.] + self.myEnd = [100., 20.] + self.myLine = self.mySketch.addLine(self.myStart[0], self.myStart[1], self.myEnd[0], self.myEnd[1]) + self.myDOF = 4 + model.do() + self.checkDOF() + + def tearDown(self): + self.checkDOF() + model.end() + assert(model.checkPythonDump()) + + def checkDOF(self): + self.assertEqual(model.dof(self.mySketch), self.myDOF) + + def checkPointCoordinates(self, thePoint, theCoordinates): + self.assertAlmostEqual(thePoint.x(), theCoordinates[0]) + self.assertAlmostEqual(thePoint.y(), theCoordinates[1]) + + def checkPointOnLine(self, theCoordinates): + self.assertAlmostEqual(model.distancePointLine(theCoordinates, self.myLine), 0.) + + def test_move_start_of_free_line(self): + """ Test 1. Movement of start point of a free line + """ + newPosition = [self.myStart[0] + 20., self.myStart[1] + 10.] + self.mySketch.move(self.myLine.startPoint(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myLine.startPoint(), newPosition) + self.checkPointCoordinates(self.myLine.endPoint(), self.myEnd) + + def test_move_end_of_free_line(self): + """ Test 2. Movement of end point of a free line + """ + newPosition = [self.myEnd[0] + 20., self.myEnd[1] + 10.] + self.mySketch.move(self.myLine.endPoint(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myLine.startPoint(), self.myStart) + self.checkPointCoordinates(self.myLine.endPoint(), newPosition) + + def test_move_free_line(self): + """ Test 3. Movement of free line + """ + diff = [self.myEnd[0] - self.myStart[0], self.myEnd[1] - self.myStart[1]] + + newPosition = [100., 100.] + self.mySketch.move(self.myLine.defaultResult(), newPosition[0], newPosition[1]) + model.do() + self.checkPointOnLine(newPosition) + + # additionally check the line keeps geometry (relative positions of extremities) + startPoint = self.myLine.startPoint() + endPoint = [startPoint.x() + diff[0], startPoint.y() + diff[1]] + self.checkPointCoordinates(self.myLine.endPoint(), endPoint) + + def test_move_line_start_fixed(self): + """ Test 4. Movement of a line, which start point is fixed + """ + fixed = self.mySketch.setFixed(self.myLine.startPoint()) + self.myDOF -= 2 + model.do() + self.checkDOF() + + newPosition = [100., 100.] + self.mySketch.move(self.myLine.defaultResult(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myLine.startPoint(), self.myStart) + self.assertNotEqual(self.myLine.endPoint().x(), self.myEnd[0]) + self.assertNotEqual(self.myLine.endPoint().y(), self.myEnd[1]) + + def test_move_line_end_fixed(self): + """ Test 5. Movement of a line, which end point is fixed + """ + fixed = self.mySketch.setFixed(self.myLine.endPoint()) + self.myDOF -= 2 + model.do() + self.checkDOF() + + newPosition = [100., 100.] + self.mySketch.move(self.myLine.defaultResult(), newPosition[0], newPosition[1]) + model.do() + self.assertNotEqual(self.myLine.startPoint().x(), self.myStart[0]) + self.assertNotEqual(self.myLine.startPoint().y(), self.myStart[1]) + self.checkPointCoordinates(self.myLine.endPoint(), self.myEnd) + + def test_move_line_fully_fixed(self): + """ Test 6. Movement of fully fixed line (should not change its coordinates) + """ + fixed = self.mySketch.setFixed(self.myLine.defaultResult()) + self.myDOF -= 4 + model.do() + + newPosition = [100., 100.] + self.mySketch.move(self.myLine.defaultResult(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myLine.startPoint(), self.myStart) + self.checkPointCoordinates(self.myLine.endPoint(), self.myEnd) + + + if __name__ == '__main__': + unittest.main() diff --cc src/SketchPlugin/Test/TestMovePoint.py index 000000000,88a143a17..60b0a43b6 mode 000000,100644..100644 --- a/src/SketchPlugin/Test/TestMovePoint.py +++ b/src/SketchPlugin/Test/TestMovePoint.py @@@ -1,0 -1,88 +1,108 @@@ ++## Copyright (C) 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 movement of the sketch point + """ + + import unittest + from GeomDataAPI import geomDataAPI_Point2D + from salome.shaper import model + + __updated__ = "2017-05-11" + + class TestMovePoint(unittest.TestCase): + def setUp(self): + model.begin() + self.myDocument = model.moduleDocument() + self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY")) + self.myOrigin = self.mySketch.addPoint(model.selection("VERTEX", "Origin")) + self.myPoint = self.mySketch.addPoint(70, 50) + self.myPointCoordinates = geomDataAPI_Point2D(self.myPoint.coordinates()) + self.myDOF = 2 + model.do() + self.checkDOF() + + def tearDown(self): + self.checkDOF() + model.end() + assert(model.checkPythonDump()) + + def checkDOF(self): + self.assertEqual(model.dof(self.mySketch), self.myDOF) + + def test_move_free_point(self): + """ Test 1. Movement of free point + """ + newPosition = [100., 100.] + self.mySketch.move(self.myPoint, newPosition[0], newPosition[1]) + model.do() + self.assertAlmostEqual(self.myPointCoordinates.x(), newPosition[0]) + self.assertAlmostEqual(self.myPointCoordinates.y(), newPosition[1]) + + def test_move_fixed_x(self): + """ Test 2. Movement of partially fixed point (fixed x coordinate) + """ + DISTANCE = 50. + horizDistance = self.mySketch.setHorizontalDistance(self.myOrigin.result(), self.myPoint.coordinates(), DISTANCE) + self.myDOF -= 1 + model.do() + self.checkDOF() + + newPosition = [100., 100.] + self.mySketch.move(self.myPoint, newPosition[0], newPosition[1]) + model.do() + self.assertAlmostEqual(self.myPointCoordinates.x(), DISTANCE) + self.assertAlmostEqual(self.myPointCoordinates.y(), newPosition[1]) + + def test_move_fixed_y(self): + """ Test 3. Movement of partially fixed point (fixed y coordinate) + """ + DISTANCE = 50. + vertDistance = self.mySketch.setVerticalDistance(self.myOrigin.result(), self.myPoint.coordinates(), DISTANCE) + self.myDOF -= 1 + model.do() + self.checkDOF() + + newPosition = [100., 100.] + self.mySketch.move(self.myPoint, newPosition[0], newPosition[1]) + model.do() + self.assertAlmostEqual(self.myPointCoordinates.x(), newPosition[0]) + self.assertAlmostEqual(self.myPointCoordinates.y(), DISTANCE) + + def test_move_fully_fixed(self): + """ Test 4. Movement of fully fixed point (should not be changed) + """ + coord = [self.myPointCoordinates.x(), self.myPointCoordinates.y()] + + fixed = self.mySketch.setFixed(self.myPoint.result()) + self.myDOF -= 2 + model.do() + self.checkDOF() + + newPosition = [100., 100.] + self.mySketch.move(self.myPoint, newPosition[0], newPosition[1]) + model.do() + self.assertAlmostEqual(self.myPointCoordinates.x(), coord[0]) + self.assertAlmostEqual(self.myPointCoordinates.y(), coord[1]) + + + if __name__ == '__main__': + unittest.main() diff --cc src/SketchPlugin/Test/TestMovementComplex.py index 000000000,6b576fdcc..6fe6afe90 mode 000000,100644..100644 --- a/src/SketchPlugin/Test/TestMovementComplex.py +++ b/src/SketchPlugin/Test/TestMovementComplex.py @@@ -1,0 -1,364 +1,384 @@@ ++## Copyright (C) 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 moving the entities in the complex sketch by the example of a clamp + """ + + from salome.shaper import model + from SketchAPI import * + from GeomAPI import * + import math + + TOLERANCE = 1.e-7 + + model.begin() + partSet = model.moduleDocument() + Part_1 = model.addPart(partSet) + Part_1_doc = Part_1.document() + + # Create sketch representing main part of clamp + Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) + SketchLine_1 = Sketch_1.addLine(20, 165, 175, 165) + SketchLine_2 = Sketch_1.addLine(175, 165, 175, 120) + SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) + SketchLine_3 = Sketch_1.addLine(175, 120, 80, 20) + SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) + SketchLine_4 = Sketch_1.addLine(80, 20, 20, 20) + SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint()) + SketchLine_5 = Sketch_1.addLine(20, 20, 20, 165) + SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint()) + SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_5.endPoint()) + SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 155) + SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result()) + SketchConstraintPerpendicular_1 = Sketch_1.setPerpendicular(SketchLine_2.result(), SketchLine_1.result()) + SketchConstraintParallel_1 = Sketch_1.setParallel(SketchLine_1.result(), SketchLine_4.result()) + SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_5.result()) + SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_2.result(), 45) + SketchConstraintDistance_1 = Sketch_1.setDistance(SketchLine_4.startPoint(), SketchLine_1.result(), 145) + SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchLine_4.startPoint(), SketchLine_3.startPoint(), 95) + SketchPoint_1 = Sketch_1.addPoint(model.selection("VERTEX", "PartSet/Origin")) + SketchConstraintDistanceHorizontal_2 = Sketch_1.setHorizontalDistance(SketchPoint_1.coordinates(), SketchLine_5.endPoint(), 20) + SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchPoint_1.coordinates(), SketchLine_5.endPoint(), 165) + model.do() + + # ============================================================================= + # Test 1. Create fillet and move fillet arc + # ============================================================================= + Sketch_1.setFillet(SketchLine_5.startPoint()) + SketchArc_1 = SketchAPI_Arc(model.lastSubFeature(Sketch_1, "SketchArc")) + model.do() + anArcCenter = [SketchArc_1.center().x(), SketchArc_1.center().y()] + anArcStart = [SketchArc_1.startPoint().x(), SketchArc_1.startPoint().y()] + anArcEnd = [SketchArc_1.endPoint().x(), SketchArc_1.endPoint().y()] + # move arc dragging center + delta = [1., 1.] + for i in range(1, 10): + anArcCenter = [anArcCenter[0] + delta[0], anArcCenter[1] + delta[1]] + Sketch_1.move(SketchArc_1.center(), anArcCenter[0], anArcCenter[1]) + model.do() + model.assertArcValidity(SketchArc_1) + model.assertPoint(SketchArc_1.center(), anArcCenter) + assert(SketchArc_1.startPoint().x() == anArcStart[0]) + assert(SketchArc_1.endPoint().y() == anArcEnd[1]) + if i == 5: + delta = [-1., -1.] + # move arc dragging start point + delta = [1., 1.] + aPosition = anArcStart + for i in range(1, 10): + aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]] + Sketch_1.move(SketchArc_1.startPoint(), aPosition[0], aPosition[1]) + model.do() + model.assertArcValidity(SketchArc_1) + assert(SketchArc_1.startPoint().x() == anArcStart[0]) + assert(SketchArc_1.endPoint().y() == anArcEnd[1]) + if i == 5: + delta = [-1., -1.] + # move arc dragging end point + delta = [1., 1.] + aPosition = anArcEnd + for i in range(1, 10): + aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]] + Sketch_1.move(SketchArc_1.endPoint(), aPosition[0], aPosition[1]) + model.do() + model.assertArcValidity(SketchArc_1) + assert(SketchArc_1.startPoint().x() == anArcStart[0]) + assert(SketchArc_1.endPoint().y() == anArcEnd[1]) + if i == 5: + delta = [-1., -1.] + + # ============================================================================= + # Test 2. Create circle and move it near its potential position + # ============================================================================= + aCircleCenter = [0, 0] + aCircleRadius = 5 + SketchCircle_1 = Sketch_1.addCircle(aCircleCenter[0], aCircleCenter[1], aCircleRadius) + model.do() + # move center + delta = [3., 2.] + for i in range(1, 15): + aCircleCenter = [aCircleCenter[0] + delta[0], aCircleCenter[1] + delta[1]] + Sketch_1.move(SketchCircle_1.center(), aCircleCenter[0], aCircleCenter[1]) + model.do() + model.assertPoint(SketchCircle_1.center(), aCircleCenter) + assert(SketchCircle_1.radius().value() == aCircleRadius) + # move circle by dragging edge + aPosition = [aCircleCenter[0] + aCircleRadius, aCircleCenter[1]] + delta = [1., 1.] + for i in range(1, 10): + aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]] + Sketch_1.move(SketchCircle_1.defaultResult(), aPosition[0], aPosition[1]) + model.do() + model.assertPoint(SketchCircle_1.center(), aCircleCenter) + assert(math.fabs(SketchCircle_1.radius().value() - model.distancePointPoint(aPosition, aCircleCenter)) < TOLERANCE) + + # ============================================================================= + # Test 3. Constrain center of circle and move it again + # ============================================================================= + SketchConstraintDistanceHorizontal_3 = Sketch_1.setHorizontalDistance(SketchCircle_1.center(), SketchArc_1.startPoint(), -30) + model.do() + # move center + delta = [1., 1.] + aCircleCenter = [SketchCircle_1.center().x(), SketchCircle_1.center().y()] + aPosition = aCircleCenter + for i in range(1, 10): + aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]] + Sketch_1.move(SketchCircle_1.center(), aPosition[0], aPosition[1]) + model.do() + assert(SketchCircle_1.center().x() == aCircleCenter[0]) + if i == 5: + delta = [-1., -1.] + # move circle by dragging edge + aCircleCenter = [SketchCircle_1.center().x(), SketchCircle_1.center().y()] + aPosition = [aCircleCenter[0] + aCircleRadius, aCircleCenter[1]] + delta = [1., 1.] + for i in range(1, 10): + aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]] + Sketch_1.move(SketchCircle_1.defaultResult(), aPosition[0], aPosition[1]) + model.do() + model.assertPoint(SketchCircle_1.center(), aCircleCenter) + assert(math.fabs(SketchCircle_1.radius().value() - model.distancePointPoint(aPosition, aCircleCenter)) < TOLERANCE) + # set radius of the circle + aCircleRadius = 17.5 + SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], aCircleRadius) + model.do() + # move center + delta = [1., 1.] + aCircleCenter = [SketchCircle_1.center().x(), SketchCircle_1.center().y()] + aPosition = aCircleCenter + for i in range(1, 10): + aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]] + Sketch_1.move(SketchCircle_1.center(), aPosition[0], aPosition[1]) + model.do() + assert(SketchCircle_1.center().x() == aCircleCenter[0]) + assert(SketchCircle_1.radius().value() == aCircleRadius) + if i == 5: + delta = [-1., -1.] + # move circle by dragging edge + aCircleCenter = [SketchCircle_1.center().x(), SketchCircle_1.center().y()] + aPosition = [aCircleCenter[0] + aCircleRadius, aCircleCenter[1]] + delta = [1., 1.] + for i in range(1, 10): + aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]] + Sketch_1.move(SketchCircle_1.defaultResult(), aPosition[0], aPosition[1]) + model.do() + assert(SketchCircle_1.center().x() == aCircleCenter[0]) + assert(SketchCircle_1.radius().value() == aCircleRadius) + + # ============================================================================= + # Test 4. Set centers of circle and arc coincident and move circle + # ============================================================================= + SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchCircle_1.center(), SketchArc_1.center()) + model.do() + assert(model.dof(Sketch_1) == 0) + # move circle + aCircleCenter = [SketchCircle_1.center().x(), SketchCircle_1.center().y()] + aPosition = [aCircleCenter[0], aCircleCenter[1] + aCircleRadius] + delta = [0., 1.] + for i in range(1, 10): + aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]] + Sketch_1.move(SketchCircle_1.defaultResult(), aPosition[0], aPosition[1]) + model.do() + model.assertPoint(SketchCircle_1.center(), aCircleCenter) + assert(SketchCircle_1.radius().value() == aCircleRadius) + assert(model.dof(Sketch_1) == 0) + + # Extrude main part of clamp + Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2r-SketchLine_3r-SketchLine_4r-SketchLine_5r-SketchArc_1_2f-SketchCircle_1_2r")], model.selection(), 10, 0) + model.do() + + + # Create sketch representing orthogonal part of clamp + Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ")) + SketchRectangle_1 = Sketch_2.addRectangle(20, 0, 100, 50) + [SketchLine_6, SketchLine_7, SketchLine_8, SketchLine_9] = SketchRectangle_1.lines() + SketchProjection_1 = Sketch_2.addProjection(model.selection("EDGE", "Sketch_1/Edge-SketchLine_1")) + SketchLine_10 = SketchProjection_1.createdFeature() + SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchAPI_Line(SketchLine_7).startPoint(), SketchAPI_Line(SketchLine_10).startPoint()) + SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_8.result(), SketchLine_10.result()) + SketchConstraintLength_3 = Sketch_2.setLength(SketchLine_7.result(), 80) + model.do() + assert(model.dof(Sketch_2) == 0) + + # Create auxiliary lines for further holes + SketchLine_11 = Sketch_2.addLine(20, 10, 175, 10) + SketchLine_11.setAuxiliary(True) + SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_11.startPoint(), SketchLine_7.result()) + SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_11.endPoint(), SketchLine_9.result()) + SketchConstraintParallel_2 = Sketch_2.setParallel(SketchLine_11.result(), SketchLine_8.result()) + SketchLine_12 = Sketch_2.addLine(150, 0, 150, 80) + SketchLine_12.setAuxiliary(True) + SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_12.startPoint(), SketchLine_6.result()) + SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchLine_12.endPoint(), SketchLine_8.result()) + SketchConstraintPerpendicular_2 = Sketch_2.setPerpendicular(SketchLine_11.result(), SketchLine_12.result()) + model.do() + assert(model.dof(Sketch_2) == 2) + + # ============================================================================= + # Test 5. Create circular hole and move it + # ============================================================================= + SketchCircle_2 = Sketch_2.addCircle(50, 10, 10) + SketchConstraintCoincidence_12 = Sketch_2.setCoincident(SketchCircle_2.center(), SketchLine_11.result()) + model.do() + # move center + delta = [2., 1.] + aCircleCenter = [SketchCircle_2.center().x(), SketchCircle_2.center().y()] + aCircleRadius = SketchCircle_2.radius().value() + for i in range(1, 10): + aCircleCenter = [aCircleCenter[0] + delta[0], aCircleCenter[1] + delta[1]] + Sketch_2.move(SketchCircle_2.center(), aCircleCenter[0], aCircleCenter[1]) + model.do() + model.assertPoint(SketchCircle_2.center(), aCircleCenter) + assert(aCircleRadius == SketchCircle_2.radius().value()) + # move circle by dragging edge + aCircleCenter = [SketchCircle_2.center().x(), SketchCircle_2.center().y()] + aPosition = [aCircleCenter[0] + aCircleRadius, aCircleCenter[1]] + delta = [0., 1.] + for i in range(1, 10): + aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]] + Sketch_1.move(SketchCircle_2.defaultResult(), aPosition[0], aPosition[1]) + model.do() + model.assertPoint(SketchCircle_2.center(), aCircleCenter) + assert(math.fabs(SketchCircle_2.radius().value() - model.distancePointPoint(aPosition, aCircleCenter)) < TOLERANCE) + + SketchConstraintDistanceHorizontal_4 = Sketch_2.setHorizontalDistance(SketchLine_11.startPoint(), SketchCircle_2.center(), 21.5) + model.do() + assert(model.dof(Sketch_2) == 3) + + # ============================================================================= + # Test 6. Create oval hole and move it + # ============================================================================= + anArcRadius = 5 + anArcCenter = [SketchLine_11.endPoint().x() + anArcRadius, SketchCircle_2.center().y()] + SketchArc_2 = Sketch_2.addArc(anArcCenter[0], anArcCenter[1], anArcCenter[0], anArcCenter[1] + anArcRadius, anArcCenter[0], anArcCenter[1] - anArcRadius, True) + SketchConstraintCoincidence_13 = Sketch_2.setCoincident(SketchArc_2.center(), SketchLine_11.result()) + SketchLine_13 = Sketch_2.addLine(anArcCenter[0], anArcCenter[1] + anArcRadius, SketchLine_12.startPoint().x(), anArcCenter[1] + anArcRadius) + SketchConstraintCoincidence_14 = Sketch_2.setCoincident(SketchArc_2.startPoint(), SketchLine_13.startPoint()) + SketchConstraintCoincidence_15 = Sketch_2.setCoincident(SketchLine_13.endPoint(), SketchLine_12.result()) + SketchConstraintPerpendicular_3 = Sketch_2.setPerpendicular(SketchLine_13.result(), SketchLine_12.result()) + SketchLine_14 = Sketch_2.addLine(anArcCenter[0], anArcCenter[1] - anArcRadius, SketchLine_12.startPoint().x(), anArcCenter[1] - anArcRadius) + SketchConstraintCoincidence_16 = Sketch_2.setCoincident(SketchArc_2.endPoint(), SketchLine_14.startPoint()) + SketchConstraintCoincidence_17 = Sketch_2.setCoincident(SketchLine_14.endPoint(), SketchLine_12.result()) + SketchConstraintPerpendicular_4 = Sketch_2.setPerpendicular(SketchLine_14.result(), SketchLine_12.result()) + SketchConstraintTangent_1 = Sketch_2.setTangent(SketchArc_2.results()[1], SketchLine_13.result()) + SketchConstraintTangent_2 = Sketch_2.setTangent(SketchArc_2.results()[1], SketchLine_14.result()) + model.do() + assert(model.dof(Sketch_2) == 5) + # move center of arc + delta = [-2., 1.] + anArcCenter = [SketchArc_2.center().x(), SketchArc_2.center().y()] + for i in range(1, 10): + anArcCenter = [anArcCenter[0] + delta[0], anArcCenter[1] + delta[1]] + Sketch_2.move(SketchArc_2.center(), anArcCenter[0], anArcCenter[1]) + model.do() + model.assertArc(SketchArc_2, anArcCenter, [], []) + + # Complete the oval hole + SketchConstraintMirror_1_objects = [SketchLine_13.result(), SketchArc_2.results()[1], SketchLine_14.result()] + SketchConstraintMirror_1 = Sketch_2.addMirror(SketchLine_12.result(), SketchConstraintMirror_1_objects) + [SketchLine_15, SketchArc_3, SketchLine_16] = SketchConstraintMirror_1.mirrored() + model.do() + + # ============================================================================= + # Test 7. Set arc and circle equal radii and move arc + # ============================================================================= + SketchConstraintEqual_2 = Sketch_2.setEqual(SketchCircle_2.results()[1], SketchArc_2.results()[1]) + model.do() + # move center of arc + delta = [-1., -1.] + anArcCenter = [SketchArc_2.center().x(), SketchArc_2.center().y()] + aCircleCenter = [SketchCircle_2.center().x(), SketchCircle_2.center().y()] + for i in range(1, 10): + anArcCenter = [anArcCenter[0] + delta[0], anArcCenter[1] + delta[1]] + Sketch_2.move(SketchArc_2.center(), anArcCenter[0], anArcCenter[1]) + model.do() + model.assertArc(SketchArc_2, anArcCenter, [], []) + model.assertPoint(SketchCircle_2.center(), [aCircleCenter[0], anArcCenter[1]]) + anArcRadius = model.distancePointPoint(SketchArc_2.center(), SketchArc_2.startPoint()) + assert(math.fabs(SketchCircle_2.radius().value() - anArcRadius) < TOLERANCE) + # move arc by dragging edge + aCircleCenter = [SketchCircle_2.center().x(), SketchCircle_2.center().y()] + anArcCenter = [SketchArc_2.center().x(), SketchArc_2.center().y()] + aPosition = [anArcCenter[0] + anArcRadius, anArcCenter[1]] + delta = [1., 1.] + for i in range(1, 10): + aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]] + Sketch_2.move(SketchArc_2.defaultResult(), aPosition[0], aPosition[1]) + model.do() + model.assertArc(SketchArc_2, anArcCenter, [], []) + model.assertPoint(SketchCircle_2.center(), aCircleCenter) + anArcRadius = model.distancePointPoint(SketchArc_2.center(), SketchArc_2.startPoint()) + assert(math.fabs(SketchCircle_2.radius().value() - anArcRadius) < TOLERANCE) + if i == 5: + delta = [-1., -1.] + + # Fix all DOF in Sketch_2 + SketchConstraintDistance_2 = Sketch_2.setDistance(SketchArc_2.center(), SketchLine_9.result(), 21.5) + SketchConstraintLength_4 = Sketch_2.setLength(SketchLine_13.result(), 3.5) + SketchConstraintRadius_2 = Sketch_2.setRadius(SketchCircle_2.results()[1], 6.5) + SketchConstraintDistance_3 = Sketch_2.setDistance(SketchCircle_2.center(), SketchLine_8.result(), 30) + model.do() + + Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_6r-SketchLine_7r-SketchLine_8r-SketchLine_9r-SketchCircle_2_2r-SketchArc_2_2r-SketchLine_13r-SketchLine_14f-SketchLine_15f-SketchArc_3_2r-SketchLine_16r")], model.selection(), -165, 155) + Boolean_1 = model.addFuse(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], [model.selection("SOLID", "Extrusion_2_1")]) + + Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "Boolean_1_1/Modified_8")) + SketchLine_17 = Sketch_3.addLine(145, 0, 165, 0) + SketchPoint_2 = Sketch_3.addPoint(model.selection("VERTEX", "Boolean_1_1/Modified_7&Boolean_1_1/Modified_6&Boolean_1_1/Modified_2")) + SketchConstraintCoincidence_23 = Sketch_3.setCoincident(SketchLine_17.endPoint(), SketchPoint_2.result()) + SketchLine_18 = Sketch_3.addLine(165, 0, 165, -20) + SketchLine_19 = Sketch_3.addLine(165, -20, 145, -20) + SketchLine_20 = Sketch_3.addLine(145, -20, 145, 0) + SketchConstraintCoincidence_24 = Sketch_3.setCoincident(SketchLine_20.endPoint(), SketchLine_17.startPoint()) + SketchConstraintCoincidence_25 = Sketch_3.setCoincident(SketchLine_17.endPoint(), SketchLine_18.startPoint()) + SketchConstraintCoincidence_26 = Sketch_3.setCoincident(SketchLine_18.endPoint(), SketchLine_19.startPoint()) + SketchConstraintCoincidence_27 = Sketch_3.setCoincident(SketchLine_19.endPoint(), SketchLine_20.startPoint()) + SketchConstraintHorizontal_4 = Sketch_3.setHorizontal(SketchLine_17.result()) + SketchConstraintVertical_4 = Sketch_3.setVertical(SketchLine_18.result()) + SketchConstraintHorizontal_5 = Sketch_3.setHorizontal(SketchLine_19.result()) + SketchConstraintVertical_5 = Sketch_3.setVertical(SketchLine_20.result()) + SketchArc_4 = Sketch_3.addArc(145, -20, 165, -20, 145, 0, False) + SketchConstraintCoincidence_28 = Sketch_3.setCoincident(SketchLine_19.endPoint(), SketchArc_4.center()) + SketchConstraintCoincidence_29 = Sketch_3.setCoincident(SketchLine_18.endPoint(), SketchArc_4.startPoint()) + SketchConstraintCoincidence_30 = Sketch_3.setCoincident(SketchArc_4.endPoint(), SketchLine_20.endPoint()) + SketchConstraintRadius_3 = Sketch_3.setRadius(SketchArc_4.results()[1], 20) + SketchArc_5 = Sketch_3.addArc(145, -20, 155, -20, 145, -10, False) + SketchConstraintCoincidence_31 = Sketch_3.setCoincident(SketchLine_19.endPoint(), SketchArc_5.center()) + SketchConstraintCoincidence_32 = Sketch_3.setCoincident(SketchLine_20.result(), SketchArc_5.endPoint()) + SketchConstraintCoincidence_33 = Sketch_3.setCoincident(SketchArc_5.startPoint(), SketchLine_19.result()) + SketchLine_21 = Sketch_3.addLine(model.selection("EDGE", "Boolean_1_1/Modified_12&Boolean_1_1/Modified_11")) + SketchConstraintTangent_5 = Sketch_3.setTangent(SketchArc_5.results()[1], SketchLine_21.result()) + model.do() + + ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchLine_17r-SketchLine_18r-SketchArc_4_2r")], model.selection(), model.selection("FACE", "Boolean_1_1/Modified_5"), 0, model.selection(), 0, [model.selection("SOLID", "Boolean_1_1")]) + ExtrusionFuse_1 = model.addExtrusionFuse(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchLine_19r-SketchLine_20r-SketchArc_4_2f-SketchArc_5_2r")], model.selection(), model.selection("FACE", "ExtrusionCut_1_1/Modfied_7"), 0, model.selection(), 0, [model.selection("SOLID", "ExtrusionCut_1_1")]) + model.do() + + model.end() + + model.testNbResults(ExtrusionFuse_1, 1) + model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.SOLID, [1]) + model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.FACE, [30]) + model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.EDGE, [140]) + model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.VERTEX, [280]) + model.testResultsVolumes(ExtrusionFuse_1, [260653.824775497108930721879005432]) + + assert(model.checkPythonDump()) diff --cc src/SketchPlugin/plugin-Sketch.xml index d5b54374a,106733478..6099d82b9 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@@ -26,9 -7,10 +26,10 @@@ email : webmaster.salome@opencascade.co id="Sketch" nested="SketchPoint SketchIntersectionPoint SketchLine SketchCircle SketchMacroCircle SketchArc SketchMacroArc - SketchEllipse SketchMacroEllipse ++ SketchRectangle SketchProjection - SketchConstraintLength SketchConstraintRadius SketchConstraintDistance + SketchConstraintLength SketchConstraintRadius SketchConstraintDistance SketchConstraintDistanceHorizontal SketchConstraintDistanceVertical SketchConstraintParallel SketchConstraintPerpendicular SketchConstraintRigid SketchConstraintHorizontal SketchConstraintVertical SketchConstraintEqual SketchConstraintTangent @@@ -359,6 -341,95 +360,97 @@@ ++ + + + + + + + + + + + + + + + + + + + + + + + + + + ++--> +