From: ptv Date: Tue, 18 Aug 2009 11:15:10 +0000 (+0000) Subject: 0020432: EDF 1029 GEOM : Fillet 1D X-Git-Tag: V5_1_3rc1~50 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=3f0d8467530f7c60b842c2ebacc4133e085f42d1;p=modules%2Fgeom.git 0020432: EDF 1029 GEOM : Fillet 1D --- diff --git a/doc/salome/gui/GEOM/images/fillet1d_1.png b/doc/salome/gui/GEOM/images/fillet1d_1.png new file mode 100644 index 000000000..00ddc0854 Binary files /dev/null and b/doc/salome/gui/GEOM/images/fillet1d_1.png differ diff --git a/doc/salome/gui/GEOM/images/fillet1d_2.png b/doc/salome/gui/GEOM/images/fillet1d_2.png new file mode 100644 index 000000000..a67c4ba5b Binary files /dev/null and b/doc/salome/gui/GEOM/images/fillet1d_2.png differ diff --git a/doc/salome/gui/GEOM/input/fillet1d_operation.doc b/doc/salome/gui/GEOM/input/fillet1d_operation.doc new file mode 100644 index 000000000..4d9ef7f9d --- /dev/null +++ b/doc/salome/gui/GEOM/input/fillet1d_operation.doc @@ -0,0 +1,29 @@ +/*! + +\page fillet1d_operation_page Fillet 1D + +This operation creates fillets on the corners of a Wire with Planar +Edges. +Note, that each couple of edges connected with a vertex, where 1D fillet should be +constructed, have to be in same plane. +\image html fillet1d_2.png + +To produce a \b Fillet 1D in the Main Menu select +Operations - > Transformation - > Fillet 1D + +Define the Wire with planar Edges to create a fillet on, select the necessary +vertexes on this wire in the OCC Viewer and define the \b Radius of the Fillet. + +\b Note: This Operation Works for the Wires with Planar Edges Only. + +TUI Command: geompy.MakeFillet1D(Shape, R, ListVertexes) +\n Arguments: Name + 1 shape + empty list or several vertexes + 1 value (Fillet radius). + +Examples: + +\image html fillet1d_1.png + +Our TUI Scripts provide you with useful examples of the use of +\ref tui_fillet1d "Transformation Operations". + +*/ diff --git a/doc/salome/gui/GEOM/input/fillet2d_operation.doc b/doc/salome/gui/GEOM/input/fillet2d_operation.doc index 43701ed90..74b044b05 100755 --- a/doc/salome/gui/GEOM/input/fillet2d_operation.doc +++ b/doc/salome/gui/GEOM/input/fillet2d_operation.doc @@ -14,7 +14,7 @@ vertexes on this face in the OCC Viewer and define the \b Radius of the Fillet. \b Note: This Operation Works for the Planar 2D Faces Only. -TUI Command: geompy.MakeFillet(Shape, R, ListVertexes) +TUI Command: geompy.MakeFillet2D(Shape, R, ListVertexes) \n Arguments: Name + 1 shape + one or several vertexes + 1 value (Fillet radius). Examples: diff --git a/doc/salome/gui/GEOM/input/transformation_operations.doc b/doc/salome/gui/GEOM/input/transformation_operations.doc index faa58dc93..3a46456d4 100644 --- a/doc/salome/gui/GEOM/input/transformation_operations.doc +++ b/doc/salome/gui/GEOM/input/transformation_operations.doc @@ -20,9 +20,11 @@ factors.
  • Create a simultaneous \subpage multi_rotation_operation_page
  • "Rotation in several directions".
  • Produce a \subpage fillet_operation_page "Fillet" on the selected edges of the object.
  • +
  • Produce a \subpage fillet1d_operation_page "1D Fillet" on the +corners of a Wire with Planar Edges.
  • Produce a \subpage fillet2d_operation_page "2D Fillet" on the corners of a Planar Face.
  • Produce a \subpage chamfer_operation_page "Chamfer" on the selected edges of the object.
  • -*/ \ No newline at end of file +*/ diff --git a/doc/salome/gui/GEOM/input/tui_transformation_operations.doc b/doc/salome/gui/GEOM/input/tui_transformation_operations.doc index 7fd356e7c..247568840 100644 --- a/doc/salome/gui/GEOM/input/tui_transformation_operations.doc +++ b/doc/salome/gui/GEOM/input/tui_transformation_operations.doc @@ -370,6 +370,29 @@ gg.createAndDisplayGO(id_face) gg.createAndDisplayGO(id_fillet2d) \endcode +\anchor tui_fillet1d +

    Fillet 1D

    + +\code +import geompy +import salome +gg = salome.ImportComponentGUI("GEOM") + +# create box +Box_1 = geompy.MakeBoxDXDYDZ(200, 200, 200) +# take box edges to create custom complex wire +[Edge_1,Edge_2,Edge_3,Edge_4,Edge_5,Edge_6,Edge_7,Edge_8,Edge_9,Edge_10,Edge_11,Edge_12] = geompy.SubShapeAllSorted(Box_1, geompy.ShapeType["EDGE"]) +# create wire +Wire_1 = geompy.MakeWire([Edge_12, Edge_7, Edge_11, Edge_6, Edge_1,Edge_4]) +# make fillet at given wire vertices with giver radius +Fillet_1D_1 = geompy.MakeFillet1D(Wire_1, 55, [3, 4, 6, 8, 10]) + + +# display disks +gg.createAndDisplayGO(Wire_1) +gg.createAndDisplayGO(Fillet_1D_1) +\endcode + \anchor tui_fillet

    Fillet

    diff --git a/idl/GEOM_Gen.idl b/idl/GEOM_Gen.idl index 62e06e217..5ab6a4070 100644 --- a/idl/GEOM_Gen.idl +++ b/idl/GEOM_Gen.idl @@ -2333,6 +2333,21 @@ module GEOM in double theR, in ListOfLong theVertexes); + /*! + * Perform a fillet on edges of the specified vertexes of the given wire. + * \param theShape Shape, to perform fillet on. + * \param theR Fillet radius. + * \param theVertexes Global indices of vertexes to perform fillet on. + * \note Global index of sub-shape can be obtained, using method + * GEOM_IShapesOperations.GetSubShapeIndex(). + * \note The list of vertices coudl be empty, in this case fillet fill be done + * at all vertices in given wire + * \return New GEOM_Object, containing the result shape. + */ + GEOM_Object MakeFillet1D (in GEOM_Object theShape, + in double theR, + in ListOfLong theVertexes); + /*! * Perform a symmetric chamfer on all edges of the given shape. * \param theShape Shape, to perform chamfer on. diff --git a/resources/Makefile.am b/resources/Makefile.am index e8bc26310..7e74345c4 100644 --- a/resources/Makefile.am +++ b/resources/Makefile.am @@ -86,9 +86,11 @@ eraseall.png \ face_hw.png \ face_vechw.png \ fillet.png \ +fillet1d.png \ fillet2d.png \ filletall.png \ filletedge.png \ +filletwire.png \ filletface.png \ filling.png \ fuse.png \ diff --git a/resources/fillet1d.png b/resources/fillet1d.png new file mode 100644 index 000000000..c62a1769b Binary files /dev/null and b/resources/fillet1d.png differ diff --git a/resources/filletwire.png b/resources/filletwire.png new file mode 100644 index 000000000..961c17cc5 Binary files /dev/null and b/resources/filletwire.png differ diff --git a/src/GEOMGUI/GEOM_images.ts b/src/GEOMGUI/GEOM_images.ts index 91d67566e..2e25def67 100644 --- a/src/GEOMGUI/GEOM_images.ts +++ b/src/GEOMGUI/GEOM_images.ts @@ -225,6 +225,10 @@ ICON_DLG_FILLET fillet.png + + ICON_DLG_FILLET_1D + fillet1d.png + ICON_DLG_FILLET_2D fillet2d.png @@ -237,6 +241,10 @@ ICON_DLG_FILLET_EDGE filletedge.png + + ICON_DLG_FILLET_WIRE + filletwire.png + ICON_DLG_FILLET_FACE filletface.png @@ -765,6 +773,10 @@ ICO_FILLET fillet.png + + ICO_FILLET_1D + fillet1d.png + ICO_FILLET_2D fillet2d.png diff --git a/src/GEOMGUI/GEOM_msg_en.ts b/src/GEOMGUI/GEOM_msg_en.ts index 9abfa6421..a63dd13e1 100644 --- a/src/GEOMGUI/GEOM_msg_en.ts +++ b/src/GEOMGUI/GEOM_msg_en.ts @@ -623,6 +623,10 @@ Please, select face, shell or solid and try again GEOM_FILLET_2D Fillet 2D + + GEOM_FILLET_1D + Fillet 1D + GEOM_FILLET_ABORT Fillet can't be computed with radius %1 @@ -635,6 +639,10 @@ Please, select face, shell or solid and try again GEOM_FILLET_EDGES Fillet On Edges From Shape + + GEOM_FILLET_WIRES + Fillet On Wires From Shape + GEOM_FILLET_FACES Fillet On Faces From Shape @@ -651,6 +659,10 @@ Please, select face, shell or solid and try again GEOM_FILLET_2D_TITLE 2D Fillet Construction + + GEOM_FILLET_1D_TITLE + 1D Fillet Construction + GEOM_FILLING Filling @@ -2187,6 +2199,10 @@ Please, select face, shell or solid and try again MEN_FILLET Fillet + + MEN_FILLET_1D + Fillet 1D + MEN_FILLET_2D Fillet 2D @@ -3707,6 +3723,10 @@ Please, select face, shell or solid and try again GEOM_PLANAR_FACE Planar Face + + GEOM_PLANAR_EDGE_WIRE + Wire with Planar Edges + GEOM_POLYGON Polygon diff --git a/src/GEOMGUI/GEOM_msg_fr.ts b/src/GEOMGUI/GEOM_msg_fr.ts index 608ad2570..4ba2ff038 100644 --- a/src/GEOMGUI/GEOM_msg_fr.ts +++ b/src/GEOMGUI/GEOM_msg_fr.ts @@ -397,6 +397,10 @@ GEOM_FILLET_EDGES Cong sur Edges de la Shape + + GEOM_FILLET_WIRES + Cong sur Wires de la Shape + GEOM_FILLET_FACES Cong sur Faces de la Shape diff --git a/src/GEOMGUI/GeometryGUI.cxx b/src/GEOMGUI/GeometryGUI.cxx index 86ef36d17..e33a927cc 100644 --- a/src/GEOMGUI/GeometryGUI.cxx +++ b/src/GEOMGUI/GeometryGUI.cxx @@ -505,7 +505,8 @@ void GeometryGUI::OnGUIEvent( int id ) id == 506 || // MENU OPERATION - CHAMFER id == 507 || // MENU OPERATION - CLIPPING RANGE id == 508 || // MENU OPERATION - GET SHAPES ON SHAPE - id == 509 ) { // MENU OPERATION - FILLET 2D + id == 509 || // MENU OPERATION - FILLET 2D + id == 510 ) { // MENU OPERATION - FILLET 1D #ifndef WNT library = getLibrary( "libOperationGUI.so" ); #else @@ -842,6 +843,7 @@ void GeometryGUI::initialize( CAM_Application* app ) createGeomAction( 506, "CHAMFER" ); //createGeomAction( 507, "CLIPPING" ); createGeomAction( 508, "GET_SHAPES_ON_SHAPES" ); + createGeomAction( 510, "FILLET_1D" ); createGeomAction( 509, "FILLET_2D" ); createGeomAction( 9998, "MUL_TRANSFORM" ); @@ -1001,6 +1003,7 @@ void GeometryGUI::initialize( CAM_Application* app ) createMenu( 504, operId, -1 ); createMenu( 508, operId, -1 ); createMenu( separator(), operId, -1 ); + createMenu( 510, transId, -1 ); createMenu( 509, transId, -1 ); createMenu( 505, transId, -1 ); createMenu( 506, transId, -1 ); diff --git a/src/GEOMImpl/GEOMImpl.pro b/src/GEOMImpl/GEOMImpl.pro index 87d10eaee..1af0cc929 100644 --- a/src/GEOMImpl/GEOMImpl.pro +++ b/src/GEOMImpl/GEOMImpl.pro @@ -108,6 +108,7 @@ SOURCES += GEOMImpl_ArcDriver.cxx SOURCES += GEOMImpl_SplineDriver.cxx SOURCES += GEOMImpl_SketcherDriver.cxx SOURCES += GEOMImpl_FilletDriver.cxx +SOURCES += GEOMImpl_Fillet1dDriver.cxx SOURCES += GEOMImpl_Fillet2dDriver.cxx SOURCES += GEOMImpl_ChamferDriver.cxx SOURCES += GEOMImpl_BooleanDriver.cxx diff --git a/src/GEOMImpl/GEOMImpl_Fillet1d.cxx b/src/GEOMImpl/GEOMImpl_Fillet1d.cxx new file mode 100644 index 000000000..27153dbb4 --- /dev/null +++ b/src/GEOMImpl/GEOMImpl_Fillet1d.cxx @@ -0,0 +1,759 @@ +// Copyright (C) 2005 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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. +// +// 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 : GEOMImpl_Fillet1d.cxx +// Module : GEOMImpl + +#include "GEOMImpl_Fillet1d.hxx" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * class GEOMImpl_Fillet1d + */ + + +//======================================================================= +//function : Constructor +//purpose : +//======================================================================= +GEOMImpl_Fillet1d::GEOMImpl_Fillet1d(const TopoDS_Edge& theEdge1, + const TopoDS_Edge& theEdge2, + const gp_Pln& thePlane) +: myEdgesExchnged( Standard_False ) +{ + myPlane = new Geom_Plane(thePlane); + + BRepAdaptor_Curve aBAC1(theEdge1); + BRepAdaptor_Curve aBAC2(theEdge2); + if (aBAC1.GetType() < aBAC2.GetType()) + { // first curve must be more complicated + myEdge1 = theEdge2; + myEdge2 = theEdge1; + myEdgesExchnged = Standard_True; + } + else + { + myEdge1 = theEdge1; + myEdge2 = theEdge2; + } + + Handle(Geom_Curve) aCurve1 = BRep_Tool::Curve(myEdge1, myStart1, myEnd1); + Handle(Geom_Curve) aCurve2 = BRep_Tool::Curve(myEdge2, myStart2, myEnd2); + + myCurve1 = GeomProjLib::Curve2d(aCurve1, myStart1, myEnd1, myPlane); + myCurve2 = GeomProjLib::Curve2d(aCurve2, myStart2, myEnd2, myPlane); + + while (myCurve1->IsPeriodic() && myStart1 >= myEnd1) + myEnd1 += myCurve1->Period(); + while (myCurve2->IsPeriodic() && myStart2 >= myEnd2) + myEnd2 += myCurve2->Period(); + + if (aBAC1.GetType() == aBAC2.GetType()) + { + if (myEnd2 - myStart2 < myEnd1 - myStart1) + { // first curve must be parametrically shorter + TopoDS_Edge anEdge = myEdge1; + myEdge1 = myEdge2; + myEdge2 = anEdge; + Handle(Geom2d_Curve) aCurve = myCurve1; + myCurve1 = myCurve2; + myCurve2 = aCurve; + Standard_Real a = myStart1; + myStart1 = myStart2; + myStart2 = a; + a = myEnd1; + myEnd1 = myEnd2; + myEnd2 = a; + myEdgesExchnged = Standard_True; + } + } +} + +//======================================================================= +//function : isRadiusIntersected +//purpose : local function +//======================================================================= +static Standard_Boolean isRadiusIntersected(const Handle(Geom2d_Curve)& theCurve, + const gp_Pnt2d theStart, + const gp_Pnt2d theEnd, + const Standard_Boolean theStartConnected) +{ + const Standard_Real aTol = Precision::Confusion(); + const Standard_Real anAngTol = Precision::Angular(); + Geom2dAPI_InterCurveCurve anInter(theCurve, new Geom2d_Line(theStart, + gp_Dir2d(gp_Vec2d(theStart, theEnd))), aTol); + Standard_Integer a; + gp_Pnt2d aPoint; + for(a = anInter.NbPoints(); a > 0; a--) + { + aPoint = anInter.Point(a); + if (aPoint.Distance(theStart) < aTol) + if (!theStartConnected) + return Standard_True; + if (aPoint.Distance(theEnd) < aTol) + return Standard_True; + if (gp_Vec2d(aPoint, theStart).IsOpposite(gp_Vec2d(aPoint, theEnd), anAngTol)) + return Standard_True; + } + Handle(Geom2d_Curve) aCurve; + for(a = anInter.NbSegments(); a > 0; a--) + { + anInter.Segment(a, aCurve); + aPoint = aCurve->Value(aCurve->FirstParameter()); + if (aPoint.Distance(theStart) < aTol) + if (!theStartConnected) + return Standard_True; + if (aPoint.Distance(theEnd) < aTol) + return Standard_True; + if (gp_Vec2d(aPoint, theStart).IsOpposite(gp_Vec2d(aPoint, theEnd), anAngTol)) + return Standard_True; + aPoint = aCurve->Value(aCurve->LastParameter()); + if (aPoint.Distance(theStart) < aTol) + if (!theStartConnected) + return Standard_True; + if (aPoint.Distance(theEnd) < aTol) + return Standard_True; + if (gp_Vec2d(aPoint, theStart).IsOpposite(gp_Vec2d(aPoint, theEnd), anAngTol)) + return Standard_True; + } + return Standard_False; +} + + +//======================================================================= +//function : fillPoint +//purpose : +//======================================================================= +void GEOMImpl_Fillet1d::fillPoint(GEOMImpl_Fillet1dPoint* thePoint) +{ + gp_Pnt2d aPoint; + gp_Vec2d aVec; + const Standard_Real aTol = Precision::Confusion(); + myCurve1->D1(thePoint->GetParam(), aPoint, aVec); + if (aVec.SquareMagnitude() < aTol) + return; + + gp_Vec2d aPerp(((myStartSide)?-1:1) * aVec.Y(), ((myStartSide)?1:-1) * aVec.X()); + aPerp.Normalize(); + aPerp.Multiply(myRadius); + gp_Pnt2d aCenter = aPoint.Translated(aPerp); + thePoint->SetCenter(aCenter); + + // on the intersection point + Standard_Boolean aValid = Standard_True; + Geom2dAPI_ProjectPointOnCurve aProjInt(aPoint, myCurve2); + if (aProjInt.NbPoints() && aPoint.Distance(aProjInt.NearestPoint()) < aTol) + aValid = Standard_False; + else + aValid = !isRadiusIntersected(myCurve2, aPoint, aCenter, Standard_True); + + Geom2dAPI_ProjectPointOnCurve aProj(aCenter, myCurve2); + Standard_Integer a, aNB = aProj.NbPoints(); + for(a = aNB; a > 0; a--) + { + if (aPoint.Distance(aProj.Point(a)) < aTol) + continue; + + Standard_Boolean aValid2 = aValid; + if (aValid2) + aValid2 = !isRadiusIntersected(myCurve1, aCenter, aProj.Point(a), Standard_False); + + // checking the right parameter + Standard_Real aParam = aProj.Parameter(a); + while(myCurve2->IsPeriodic() && aParam < myStart2) + aParam += myCurve2->Period(); + + thePoint->AddValue(aProj.Distance(a) * aProj.Distance(a) - myRadius * myRadius, + (aParam >= myStart2 && aParam <= myEnd2 && aValid2)); + if (fabs(fabs(aProj.Distance(a)) - myRadius) < aTol) + thePoint->SetParam2(aParam); + } +} + +//======================================================================= +//function : fillDiff +//purpose : +//======================================================================= +void GEOMImpl_Fillet1d::fillDiff(GEOMImpl_Fillet1dPoint* thePoint, Standard_Real theDiffStep, Standard_Boolean theFront) +{ + GEOMImpl_Fillet1dPoint* aDiff = + new GEOMImpl_Fillet1dPoint(thePoint->GetParam() + (theFront?(theDiffStep):(-theDiffStep))); + fillPoint(aDiff); + if (!thePoint->ComputeDifference(aDiff)) + { + aDiff->SetParam(thePoint->GetParam() + (theFront?(-theDiffStep):(theDiffStep))); + fillPoint(aDiff); + thePoint->ComputeDifference(aDiff); + } + delete aDiff; +} + +//======================================================================= +//function : Perform +//purpose : +//======================================================================= +Standard_Boolean GEOMImpl_Fillet1d::Perform(const Standard_Real theRadius) +{ + myResultParams.Clear(); + myResultOrientation.Clear(); + + Standard_Real aNBSteps = 100; + Geom2dAdaptor_Curve aGAC(myCurve1); + switch (aGAC.GetType()) + { + case GeomAbs_Line: + aNBSteps = 2; + break; + case GeomAbs_Circle: + aNBSteps = 4; + break; + case GeomAbs_Ellipse: + aNBSteps = 5; + break; + case GeomAbs_BezierCurve: + case GeomAbs_BSplineCurve: + aNBSteps = 2 + aGAC.Degree() * aGAC.NbPoles(); + break; + default: // unknown: maximum + aNBSteps = 100; + } + + myRadius = theRadius; + Standard_Real aParam, aStep, aDStep; + aStep = (myEnd1 - myStart1) / aNBSteps; + aDStep = aStep/1000.; + + Standard_Integer aCycle; + for(aCycle = 2, myStartSide = Standard_False; aCycle; myStartSide = !myStartSide, aCycle--) + { + GEOMImpl_Fillet1dPoint *aLeft = NULL, *aRight = NULL; + + for(aParam = myStart1 + aStep; aParam < myEnd1 || fabs(myEnd1 - aParam) < Precision::Confusion(); aParam += aStep) + { + if (!aLeft) + { + aLeft = new GEOMImpl_Fillet1dPoint(aParam - aStep); + fillPoint(aLeft); + fillDiff(aLeft, aDStep, Standard_True); + } + + aRight = new GEOMImpl_Fillet1dPoint(aParam); + fillPoint(aRight); + fillDiff(aRight, aDStep, Standard_False); + + aLeft->FilterPoints(aRight); + performNewton(aLeft, aRight); + + delete aLeft; + aLeft = aRight; + } + delete aLeft; + } + + if (myResultParams.Extent()) + return Standard_True; + + return Standard_False; +} + +//======================================================================= +//function : processPoint +//purpose : +//======================================================================= +Standard_Boolean GEOMImpl_Fillet1d::processPoint(GEOMImpl_Fillet1dPoint* theLeft, + GEOMImpl_Fillet1dPoint* theRight, + Standard_Real theParameter) +{ + if (theParameter >= theLeft->GetParam() && theParameter < theRight->GetParam()) + { + Standard_Real aDX = theRight->GetParam() - theLeft->GetParam(); + if (theParameter - theLeft->GetParam() < aDX / 100.) + { + theParameter = theLeft->GetParam() + aDX / 100.; + } + if (theRight->GetParam() - theParameter < aDX / 100.) + { + theParameter = theRight->GetParam() - aDX / 100.; + } + + GEOMImpl_Fillet1dPoint* aPoint1 = theLeft->Copy(); + GEOMImpl_Fillet1dPoint* aPoint2 = new GEOMImpl_Fillet1dPoint(theParameter); + fillPoint(aPoint2); + fillDiff(aPoint2, aDX / 1000., Standard_True); + + aPoint1->FilterPoints(aPoint2); + performNewton(aPoint1, aPoint2); + aPoint2->FilterPoints(theRight); + performNewton(aPoint2, theRight); + + delete aPoint1; + delete aPoint2; + return Standard_True; + } + + return Standard_False; +} + +//======================================================================= +//function : performNewton +//purpose : +//======================================================================= +void GEOMImpl_Fillet1d::performNewton(GEOMImpl_Fillet1dPoint* theLeft, + GEOMImpl_Fillet1dPoint* theRight) +{ + Standard_Integer a; + // check the left: if this is solution store it and remove it from the list of researching points of theLeft + a = theLeft->HasSolution(myRadius); + if (a) + { + if (theLeft->IsValid(a)) + { + myResultParams.Append(theLeft->GetParam()); + myResultOrientation.Append(myStartSide); + } + return; + } + + Standard_Real aDX = theRight->GetParam() - theLeft->GetParam(); + if (aDX < gp::Resolution()/*Precision::Confusion() / 1000000.*/) + { + a = theRight->HasSolution(myRadius); + if (a) + if (theRight->IsValid(a)) + { + myResultParams.Append(theRight->GetParam()); + myResultOrientation.Append(myStartSide); + } + return; + } + + for(a = 1; a <= theLeft->GetNBValues(); a++) + { + Standard_Integer aNear = theLeft->GetNear(a); + + Standard_Real aA = (theRight->GetDiff(aNear) - theLeft->GetDiff(a)) / aDX; + Standard_Real aB = theLeft->GetDiff(a) - aA * theLeft->GetParam(); + Standard_Real aC = theLeft->GetValue(a) - theLeft->GetDiff(a) * theLeft->GetParam() + + aA * theLeft->GetParam() * theLeft->GetParam() / 2.0; + Standard_Real aDet = aB * aB - 2.0 * aA * aC; + + if (fabs(aA) < Precision::Confusion()) + { // linear case + if (fabs(aB) > 10e-20) + { + Standard_Real aX0 = - aC / aB; // use extremum + if (aX0 > theLeft->GetParam() && aX0 < theRight->GetParam()) + processPoint(theLeft, theRight, aX0); + } + else + { + processPoint(theLeft, theRight, theLeft->GetParam() + aDX / 2.0); // linear division otherwise + } + } + else + { + if (fabs(aB) > fabs(aDet * 1000000.)) + { // possible floating point operations accurancy errors + processPoint(theLeft, theRight, theLeft->GetParam() + aDX / 2.0); // linear division otherwise + } + else + { + if (aDet > 0) + { // two solutions + aDet = sqrt(aDet); + Standard_Boolean aRes = processPoint(theLeft, theRight, (- aB + aDet) / aA); + if (!aRes) + aRes = processPoint(theLeft, theRight, (- aB - aDet) / aA); + if (!aRes) + processPoint(theLeft, theRight, theLeft->GetParam() + aDX / 2.0); // linear division otherwise + } + else + { + Standard_Real aX0 = - aB / aA; // use extremum + if (aX0 > theLeft->GetParam() && aX0 < theRight->GetParam()) + processPoint(theLeft, theRight, aX0); + else + processPoint(theLeft, theRight, theLeft->GetParam() + aDX / 2.0); // linear division otherwise + } + } + } + } +} + +//======================================================================= +//function : Result +//purpose : +//======================================================================= +TopoDS_Edge GEOMImpl_Fillet1d::Result(const gp_Pnt& thePoint, + TopoDS_Edge& theEdge1, + TopoDS_Edge& theEdge2) +{ + TopoDS_Edge aResult; + gp_Pnt2d aTargetPoint2d; + Standard_Real aX, aY; + ElSLib::PlaneParameters(myPlane->Pln().Position(), thePoint, aX, aY); + aTargetPoint2d.SetCoord(aX, aY); + + // choose the nearest circle + Standard_Real aDistance, aP; + GEOMImpl_Fillet1dPoint *aNearest; + Standard_Integer a; + TColStd_ListIteratorOfListOfReal anIter(myResultParams); + for(aNearest = NULL, a = 1; anIter.More(); anIter.Next(), a++) + { + myStartSide = (myResultOrientation.Value(a)) ? Standard_True : Standard_False; + GEOMImpl_Fillet1dPoint *aPoint = new GEOMImpl_Fillet1dPoint(anIter.Value()); + fillPoint(aPoint); + if (!aPoint->HasSolution(myRadius)) + continue; + aP = fabs(aPoint->GetCenter().Distance(aTargetPoint2d) - myRadius); + if (!aNearest || aP < aDistance) + { + aNearest = aPoint; + aDistance = aP; + } + else + { + delete aPoint; + } + } + + if (!aNearest) + return aResult; + + // create circle edge + gp_Pnt aCenter = ElSLib::PlaneValue(aNearest->GetCenter().X(), + aNearest->GetCenter().Y(), + myPlane->Pln().Position()); + Handle(Geom_Circle) aCircle = + new Geom_Circle(gp_Ax2(aCenter, myPlane->Pln().Axis().Direction()), myRadius); + gp_Pnt2d aPoint2d1, aPoint2d2; + myCurve1->D0(aNearest->GetParam(), aPoint2d1); + myCurve2->D0(aNearest->GetParam2(), aPoint2d2); + gp_Pnt aPoint1 = ElSLib::PlaneValue(aPoint2d1.X(), aPoint2d1.Y(), myPlane->Pln().Position()); + gp_Pnt aPoint2 = ElSLib::PlaneValue(aPoint2d2.X(), aPoint2d2.Y(), myPlane->Pln().Position()); + + GeomAPI_ProjectPointOnCurve aProj(thePoint, aCircle); + Standard_Real aTarGetParam = aProj.LowerDistanceParameter(); + gp_Pnt aPointOnCircle = aProj.NearestPoint(); + + // Check extrema point manually, because there is a bug in Open CASCADE + // in calculation of nearest point to a circle near the parameter 0.0 + gp_Pnt p0 = ElCLib::Value(0.0, aCircle->Circ()); + if (p0.Distance(thePoint) < aPointOnCircle.Distance(thePoint)) + { + aTarGetParam = 0.0; + aPointOnCircle = p0; + } + + aProj.Perform(aPoint1); + Standard_Real aParam1 = aProj.LowerDistanceParameter(); + aProj.Perform(aPoint2); + Standard_Real aParam2 = aProj.LowerDistanceParameter(); + Standard_Boolean aIsOut = ((aParam1 < aTarGetParam && aParam2 < aTarGetParam) || + (aParam1 > aTarGetParam && aParam2 > aTarGetParam)); + if (aParam1 > aParam2) + aIsOut = !aIsOut; + BRepBuilderAPI_MakeEdge aBuilder(aCircle->Circ(), + aIsOut ? aParam2 : aParam1, + aIsOut? aParam1 : aParam2); + aResult = aBuilder.Edge(); + + // divide edges + Standard_Real aStart, anEnd; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(myEdge1, aStart, anEnd); + gp_Vec aDir; + aCurve->D1(aNearest->GetParam(), aPoint1, aDir); + + gp_Vec aCircleDir; + aCircle->D1(aParam1, aPoint1, aCircleDir); + if ((aCircleDir.Angle(aDir) > PI / 2.0) ^ aIsOut) + aStart = aNearest->GetParam(); + else + anEnd = aNearest->GetParam(); + + //Check the case when start and end are identical. This happens + //when the edge decreases to size 0. Old ww5 allows such + //cases. So we are again bug compatible + if (fabs(aStart - anEnd) < Precision::PConfusion()/*gp::Resolution()*/) + anEnd = 0.01; + //Divide edge + BRepBuilderAPI_MakeEdge aDivider1(aCurve, aStart, anEnd); + if (myEdgesExchnged) + theEdge2 = aDivider1.Edge(); + else + theEdge1 = aDivider1.Edge(); + + + aCurve = BRep_Tool::Curve(myEdge2, aStart, anEnd); + aCurve->D1(aNearest->GetParam2(), aPoint2, aDir); + + aCircle->D1(aParam2, aPoint2, aCircleDir); + if ((aCircleDir.Angle(aDir) > PI / 2.0) ^ (!aIsOut)) + aStart = aNearest->GetParam2(); + else + anEnd = aNearest->GetParam2(); + + //Check the case when start and end are identical. This happens + //when the edge decreases to size 0. Old ww5 allows such + //cases. So we are again bug compatible + if (fabs(aStart - anEnd) < Precision::PConfusion()/*gp::Resolution()*/) + anEnd = 0.01; + BRepBuilderAPI_MakeEdge aDivider2(aCurve, aStart, anEnd); + if (myEdgesExchnged) + theEdge1 = aDivider2.Edge(); + else + theEdge2 = aDivider2.Edge(); + + delete aNearest; + return aResult; +} + +//======================================================================= +//function : AddValue +//purpose : +//======================================================================= +void GEOMImpl_Fillet1dPoint::AddValue(Standard_Real theValue, Standard_Boolean theValid) +{ + Standard_Integer a; + for(a = 1; a <= myV.Length(); a++) + { + if (theValue < myV.Value(a)) + { + myV.InsertBefore(a, theValue); + myValid.InsertBefore(a, (Standard_Integer)theValid); + return; + } + } + myV.Append(theValue); + myValid.Append((Standard_Integer)theValid); +} + +//======================================================================= +//function : ComputeDifference +//purpose : +//======================================================================= +Standard_Boolean GEOMImpl_Fillet1dPoint::ComputeDifference(GEOMImpl_Fillet1dPoint* thePoint) +{ + Standard_Integer a; + Standard_Boolean aDiffsSet = (myD.Length() != 0); + Standard_Real aDX = thePoint->GetParam() - myParam, aDY; + if (thePoint->myV.Length() == myV.Length()) + { // absolutely the same points + for(a = 1; a <= myV.Length(); a++) + { + aDY = thePoint->myV.Value(a) - myV.Value(a); + if (aDiffsSet) + myD.SetValue(a, aDY / aDX); + else + myD.Append(aDY / aDX); + } + return Standard_True; + } + // between the diffeerent points searching for nearest analogs + Standard_Integer b; + for(a = 1; a <= myV.Length(); a++) + { + for(b = 1; b <= thePoint->myV.Length(); b++) + { + if (b == 1 || fabs(thePoint->myV.Value(b) - myV.Value(a)) < fabs(aDY)) + aDY = thePoint->myV.Value(b) - myV.Value(a); + } + if (aDiffsSet) + { + if (fabs(aDY / aDX) < fabs(myD.Value(a))) + myD.SetValue(a, aDY / aDX); + } + else + { + myD.Append(aDY / aDX); + } + } + + return Standard_False; +} + +//======================================================================= +//function : FilterPoints +//purpose : +//======================================================================= +void GEOMImpl_Fillet1dPoint::FilterPoints(GEOMImpl_Fillet1dPoint* thePoint) +{ + Standard_Integer a, b; + TColStd_SequenceOfReal aDiffs; + Standard_Real aY, aY2, aDX = thePoint->GetParam() - myParam; + for(a = 1; a <= myV.Length(); a++) + { + // searching for near point from thePoint + Standard_Integer aNear = 0; + Standard_Real aDiff = aDX * 10000.; + aY = myV.Value(a) + myD.Value(a) * aDX; + for(b = 1; b <= thePoint->myV.Length(); b++) + { + // calculate hypothesis value of the Y2 with the constant first and second derivative + aY2 = aY + aDX * (thePoint->myD.Value(b) - myD.Value(a)) / 2.0; + if (aNear == 0 || fabs(aY2 - thePoint->myV.Value(b)) < fabs(aDiff)) + { + aNear = b; + aDiff = aY2 - thePoint->myV.Value(b); + } + }//for b... + + if (aNear) + { + if (myV.Value(a) * thePoint->myV.Value(aNear) > 0) + {// the same sign at the same sides of the interval + if (myV.Value(a) * myD.Value(a) > 0) + { + if (fabs(myD.Value(a)) > Precision::Confusion()) + aNear = 0; + } + else + { + if (fabs(myV.Value(a)) > fabs(thePoint->myV.Value(aNear))) + if (thePoint->myV.Value(aNear) * thePoint->myD.Value(aNear) < 0 && + fabs(thePoint->myD.Value(aNear)) > Precision::Confusion()) + { + aNear = 0; + } + } + } + } + + if (aNear) + { + if (myV.Value(a) * thePoint->myV.Value(aNear) > 0) + { + if ((myV.Value(a) + myD.Value(a) * aDX) * myV.Value(a) > Precision::Confusion() && + (thePoint->myV.Value(aNear) + thePoint->myD.Value(aNear) * aDX) * thePoint->myV.Value(aNear) > Precision::Confusion()) + { + aNear = 0; + } + } + } + + if (aNear) + { + if (fabs(aDiff / aDX) > 1.e+7) + { + aNear = 0; + } + } + + if (aNear == 0) + { // there is no near: remove it from the list + myV.Remove(a); + myD.Remove(a); + myValid.Remove(a); + a--; + } + else + { + Standard_Boolean aFound = Standard_False; + for(b = 1; b <= myNear.Length(); b++) + { + if (myNear.Value(b) == aNear) + { + if (fabs(aDiffs.Value(b)) < fabs(aDiff)) + { // return this 'near' + aFound = Standard_True; + myV.Remove(a); + myD.Remove(a); + myValid.Remove(a); + a--; + break; + } + else + { // remove the old 'near' + myV.Remove(b); + myD.Remove(b); + myValid.Remove(b); + myNear.Remove(b); + aDiffs.Remove(b); + a--; + break; + } + } + }//for b... + if (!aFound) + { + myNear.Append(aNear); + aDiffs.Append(aDiff); + } + } + }//for a... +} + +//======================================================================= +//function : Copy +//purpose : +//======================================================================= +GEOMImpl_Fillet1dPoint* GEOMImpl_Fillet1dPoint::Copy() +{ + GEOMImpl_Fillet1dPoint* aCopy = new GEOMImpl_Fillet1dPoint(myParam); + Standard_Integer a; + for(a = 1; a <= myV.Length(); a++) + { + aCopy->myV.Append(myV.Value(a)); + aCopy->myD.Append(myD.Value(a)); + aCopy->myValid.Append(myValid.Value(a)); + } + return aCopy; +} + +//======================================================================= +//function : HasSolution +//purpose : +//======================================================================= +Standard_Integer GEOMImpl_Fillet1dPoint::HasSolution(const Standard_Real theRadius) +{ + Standard_Integer a; + for(a = 1; a <= myV.Length(); a++) + { + if (fabs(sqrt(fabs(fabs(myV.Value(a)) + theRadius * theRadius)) - theRadius) < Precision::Confusion() / 10.) + return a; + } + return 0; +} + +//======================================================================= +//function : RemoveSolution +//purpose : +//======================================================================= +void GEOMImpl_Fillet1dPoint::RemoveSolution(Standard_Integer theIndex) +{ + myV.Remove(theIndex); + myD.Remove(theIndex); + myValid.Remove(theIndex); + myNear.Remove(theIndex); +} diff --git a/src/GEOMImpl/GEOMImpl_Fillet1d.hxx b/src/GEOMImpl/GEOMImpl_Fillet1d.hxx new file mode 100644 index 000000000..90c5ae9e8 --- /dev/null +++ b/src/GEOMImpl/GEOMImpl_Fillet1d.hxx @@ -0,0 +1,141 @@ +// Copyright (C) 2009 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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. +// +// 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 : GEOMImpl_Fillet1d.hxx +// Module : GEOMImpl + +#ifndef _GEOMImpl_Fillet1d_HeaderFile +#define _GEOMImpl_Fillet1d_HeaderFile + +#include +#include +#include + +#include +#include +#include +#include + +class GEOMImpl_Fillet1dPoint; + +/** +* GEOMImpl_Fillet1d is 1D fillet algorithm on two planar edges with given radius +*/ + +class GEOMImpl_Fillet1d +{ +public: + //! Constructor + //! The fillet 1D algorithm initialise by two edges and plane + Standard_EXPORT GEOMImpl_Fillet1d(const TopoDS_Edge& theEdge1, + const TopoDS_Edge& theEdge2, + const gp_Pln& thePlane); + //! Makes fillet with given radius + //! @returns Standard_True, if at least one result computed + Standard_EXPORT Standard_Boolean Perform(const Standard_Real theRadius); + //! Returns result fillet edge and modified edges as out parameters + Standard_EXPORT TopoDS_Edge Result(const gp_Pnt& thePoint, TopoDS_Edge& theEdge1, TopoDS_Edge& theEdge2); + +private: + //! private methods + void fillPoint(GEOMImpl_Fillet1dPoint*); + void fillDiff(GEOMImpl_Fillet1dPoint*, Standard_Real, Standard_Boolean); + void performNewton(GEOMImpl_Fillet1dPoint*, GEOMImpl_Fillet1dPoint*); + Standard_Boolean processPoint(GEOMImpl_Fillet1dPoint*, GEOMImpl_Fillet1dPoint*, Standard_Real); + + +private: + //! private fields + TopoDS_Edge myEdge1, myEdge2; + Handle(Geom_Plane) myPlane; + Handle(Geom2d_Curve) myCurve1, myCurve2; + Standard_Real myStart1, myEnd1, myStart2, myEnd2, myRadius; + TColStd_ListOfReal myResultParams; + TColStd_SequenceOfInteger myResultOrientation; + Standard_Boolean myStartSide, myEdgesExchnged; +}; + + +/** +* GEOMImpl_Fillet1dPoint is an internal class for 1D fillet algorithm +* to store and compare computed solutions on edges +*/ + +class GEOMImpl_Fillet1dPoint +{ +public: + //! Puiblic methods + + //! Constructor + Standard_EXPORT GEOMImpl_Fillet1dPoint(Standard_Real theParam) + {myParam = theParam;} + + //! Make copy of point + //!WARNING: Copies only field values: myParam, myV, myD, myValid + Standard_EXPORT GEOMImpl_Fillet1dPoint* Copy(); // warning: this is not the full copy! + + //! Set/Get parameter + Standard_EXPORT inline void SetParam(Standard_Real theParam) + {myParam = theParam;} + Standard_EXPORT inline Standard_Real GetParam() const + {return myParam;} + Standard_EXPORT inline void SetParam2(const Standard_Real theParam2) + {myParam2 = theParam2;} + Standard_EXPORT inline Standard_Real GetParam2() + { return myParam2 ; } + + //! Returns validity + Standard_EXPORT inline Standard_Boolean IsValid(int theIndex) + {return (Standard_Boolean)myValid.Value(theIndex);} + + //! Get values + Standard_EXPORT inline Standard_Integer GetNBValues() {return myV.Length();} + Standard_EXPORT inline Standard_Real GetValue(Standard_Integer theIndex) + {return myV.Value(theIndex);} + Standard_EXPORT inline Standard_Real GetDiff(Standard_Integer theIndex) + {return myD.Value(theIndex);} + Standard_EXPORT inline Standard_Integer GetNear(Standard_Integer theIndex) + {return myNear.Value(theIndex);} + + //! Set/Get center point + Standard_EXPORT inline void SetCenter(const gp_Pnt2d thePoint) + {myCenter = thePoint;} + Standard_EXPORT inline const gp_Pnt2d GetCenter() + {return myCenter;} + + Standard_EXPORT void AddValue(Standard_Real theValue, Standard_Boolean theIsValid); + + //! compute difference between this and given point + Standard_EXPORT Standard_Boolean ComputeDifference(GEOMImpl_Fillet1dPoint*); + Standard_EXPORT void FilterPoints(GEOMImpl_Fillet1dPoint*); + + //! Check is point contains solution and returns the index of them if any + Standard_EXPORT Standard_Integer HasSolution(Standard_Real theRadius); + //! Remove solution by index + void RemoveSolution(Standard_Integer theIndex); + +private: + //! Private fields + gp_Pnt2d myCenter; + Standard_Real myParam, myParam2; + TColStd_SequenceOfReal myV, myD; + TColStd_SequenceOfInteger myValid, myNear; +}; + +#endif diff --git a/src/GEOMImpl/GEOMImpl_Fillet1dDriver.cxx b/src/GEOMImpl/GEOMImpl_Fillet1dDriver.cxx new file mode 100644 index 000000000..fc54a402b --- /dev/null +++ b/src/GEOMImpl/GEOMImpl_Fillet1dDriver.cxx @@ -0,0 +1,312 @@ +// Copyright (C) 2009 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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. +// +// 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 +#include +#include +#include + +//======================================================================= +//function : GetID +//purpose : +//======================================================================= +const Standard_GUID& GEOMImpl_Fillet1dDriver::GetID() +{ + static Standard_GUID aFillet1dDriver("FF60908B-AB2E-4b71-B098-5C256C37D961"); + return aFillet1dDriver; +} + +//======================================================================= +//function : GEOMImpl_Fillet1dDriver +//purpose : +//======================================================================= +GEOMImpl_Fillet1dDriver::GEOMImpl_Fillet1dDriver() +{ +} + +//======================================================================= +//function : anotherVertex +//purpose : local function to get vertex from edge +//======================================================================= +static TopoDS_Vertex anotherVertex( const TopoDS_Edge& theE, + const TopoDS_Vertex& theV ) +{ + // here is an assumption that edge has different vertices + TopoDS_Vertex aV; + TopExp_Explorer anExp( theE, TopAbs_VERTEX ); + for ( ; anExp.More(); anExp.Next() ) + { + if ( BRepTools::Compare(theV,TopoDS::Vertex(anExp.Current())) /*theV.IsSame(anExp.Current())*/ ) + continue; + aV = TopoDS::Vertex( anExp.Current() ); + break; + } + return aV; +} + +//======================================================================= +//function : takePlane +//purpose : local function returns plane of given edges +//======================================================================= +static Standard_Boolean takePlane( const TopoDS_Edge& theE1, + const TopoDS_Edge& theE2, + const TopoDS_Vertex& theV, + gp_Pln& thePlane ) +{ + TopoDS_Vertex aV12 = anotherVertex( theE1, theV ); + TopoDS_Vertex aV22 = anotherVertex( theE2, theV ); + // check can closed wire be created by two initial edges + if ( aV12.IsNull() || aV22.IsNull() || aV12.IsSame( aV22 ) ) + return false; + + // create plane by 3 points + gp_XYZ aXYZ = BRep_Tool::Pnt( theV ).XYZ(); + gp_XYZ aXYZ1 = BRep_Tool::Pnt( aV12 ).XYZ(); + gp_XYZ aXYZ2 = BRep_Tool::Pnt( aV22 ).XYZ(); + try { + gp_Dir aDir1( aXYZ - aXYZ1 ); + gp_Dir aDir2( aXYZ2 - aXYZ ); + Standard_Real anAngle = aDir1.Angle(aDir2); + if ( fabs(anAngle) <= gp::Resolution() || + fabs(anAngle - PI) <= gp::Resolution() ) + return false; + //thePlane = gp_Pln( gp_Pnt(aXYZ), aDir1^ aDir2); + thePlane = gp_Pln( gp_Pnt(aXYZ), gp_Dir(0,0,1)); + } + catch (Standard_Failure) { + return false; + } + return true; +} + +//======================================================================= +//function : addEdgeRelation +//purpose : local function to remember relation between initial and modified edge +//======================================================================= +static void addEdgeRelation(TopTools_DataMapOfShapeShape& theMap, + const TopoDS_Edge& theInitE, + const TopoDS_Edge& theResE) +{ + if ( theMap.IsBound( theInitE ) ) + theMap.ChangeFind( theInitE ) = theResE; + else + theMap.Bind( theInitE, theResE ); +} + +//======================================================================= +//function : Execute +//purpose : +//======================================================================= +Standard_Integer GEOMImpl_Fillet1dDriver::Execute(TFunction_Logbook& log) const +{ + if (Label().IsNull()) return 0; + Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); + + GEOMImpl_IFillet1d aCI (aFunction); + + Handle(GEOM_Function) aRefShape = aCI.GetShape(); + TopoDS_Shape aShape = aRefShape->GetValue(); + if (aShape.ShapeType() != TopAbs_WIRE) + Standard_ConstructionError::Raise("Wrong arguments: polyline as wire must be given"); + + TopoDS_Wire aWire = TopoDS::Wire(aShape); + + double rad = aCI.GetR(); + + // collect vertices for make fillet + TopTools_ListOfShape aVertexList; + int aLen = aCI.GetLength(); + if ( aLen > 0 ) + { + for (int ind = 1; ind <= aLen; ind++) { + TopoDS_Shape aShapeVertex; + if (GEOMImpl_ILocalOperations::GetSubShape + (aWire, aCI.GetVertex(ind), aShapeVertex)) + aVertexList.Append( aShapeVertex ); + } + } + else + { + // get all vertices from wire + TopExp_Explorer anExp( aWire, TopAbs_VERTEX ); + for ( ; anExp.More(); anExp.Next() ) + aVertexList.Append( anExp.Current() ); + } + if (aVertexList.IsEmpty()) + Standard_ConstructionError::Raise("Invalid input no vertices to make fillet"); + + bool res = false; + //INFO: this algorithm implemented in assumption that user can select both + // vertices of some edges to make fillet. In this case we should remember + // already modified initial edges to take care in next fillet step + TopTools_DataMapOfShapeShape anEdgeToEdgeMap; + + //iterates on vertices, and make fillet on each couple of edges + //collect result fillet edges in list + TopTools_ListOfShape aListOfNewEdge; + // remember relation between initial and modified map + TopTools_IndexedDataMapOfShapeListOfShape aMapVToEdges; + TopExp::MapShapesAndAncestors( aWire, TopAbs_VERTEX, TopAbs_EDGE, aMapVToEdges ); + TopTools_ListIteratorOfListOfShape anIt( aVertexList ); + for ( ; anIt.More(); anIt.Next() ) + { + TopoDS_Vertex aV = TopoDS::Vertex( anIt.Value() ); + if ( aV.IsNull() || !aMapVToEdges.Contains( aV ) ) + continue; + const TopTools_ListOfShape& aVertexEdges = aMapVToEdges.FindFromKey( aV ); + if ( aVertexEdges.Extent() != 2 ) + continue; // no input data to make fillet + TopoDS_Edge anEdge1 = TopoDS::Edge( aVertexEdges.First() ); + TopoDS_Edge anEdge2 = TopoDS::Edge( aVertexEdges.Last() ); + // check if initial edges already modified in previous fillet operation + if ( anEdgeToEdgeMap.IsBound( anEdge1 ) ) anEdge1 = TopoDS::Edge(anEdgeToEdgeMap.Find( anEdge1 )); + if ( anEdgeToEdgeMap.IsBound( anEdge2 ) ) anEdge2 = TopoDS::Edge(anEdgeToEdgeMap.Find( anEdge2 )); + if ( anEdge1.IsNull() || anEdge2.IsNull() || anEdge1.IsSame( anEdge2 ) ) + continue; //no input data to make fillet + + // create plane on 2 edges + gp_Pln aPlane; + if ( !takePlane(anEdge1, anEdge2, aV, aPlane) ) + continue; // seems edges does not belong to same plane or parallel (fillet can not be build) + + GEOMImpl_Fillet1d aFilletAlgo(anEdge1, anEdge2, aPlane); + if ( !aFilletAlgo.Perform(rad) ) + continue; // can not create fillet with given radius + + // take fillet result in given vertex + TopoDS_Edge aModifE1, aModifE2; + TopoDS_Edge aNewE = aFilletAlgo.Result(BRep_Tool::Pnt(aV), aModifE1, aModifE2); + if (aNewE.IsNull()) + continue; // no result found + + res |= true; + // add new created edges and take modified edges + aListOfNewEdge.Append( aNewE ); + + // check if face edges modified, + // if yes, than map to original edges (from vertex-edges list), because edges can be modified before + if (!aModifE1.IsNull() || !aModifE1.IsSame( anEdge1 )) + addEdgeRelation( anEdgeToEdgeMap, TopoDS::Edge(aVertexEdges.First()), aModifE1 ); + if (!aModifE2.IsNull() || !aModifE2.IsSame( anEdge2 )) + addEdgeRelation( anEdgeToEdgeMap, TopoDS::Edge(aVertexEdges.Last()), aModifE2 ); + } + + if ( !res && anEdgeToEdgeMap.IsEmpty() && aListOfNewEdge.IsEmpty() ) + { + StdFail_NotDone::Raise("1D Fillet can't be computed on the given shape with the given radius"); + return 0; // nothing done :( + } + + // create new wire instead of original + for ( TopExp_Explorer anExp( aWire, TopAbs_EDGE ); anExp.More(); anExp.Next() ) + { + TopoDS_Shape anEdge = anExp.Current(); + if ( !anEdgeToEdgeMap.IsBound( anEdge ) ) + aListOfNewEdge.Append( anEdge ); + else + aListOfNewEdge.Append( anEdgeToEdgeMap.Find( anEdge ) ); + } + BRepBuilderAPI_MakeWire aWireTool; + aWireTool.Add( aListOfNewEdge ); + aWireTool.Build(); + if (!aWireTool.IsDone()) + return 0; + + aWire = aWireTool.Wire(); + aFunction->SetValue(aWire); + log.SetTouched(Label()); + + return 1; +} + + +//======================================================================= +//function : GEOMImpl_Fillet1dDriver_Type_ +//purpose : +//======================================================================= +Standard_EXPORT Handle_Standard_Type& GEOMImpl_Fillet1dDriver_Type_() +{ + + static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver); + if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver); + static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared); + if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared); + static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient); + if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient); + + + static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL}; + static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_Fillet1dDriver", + sizeof(GEOMImpl_Fillet1dDriver), + 1, + (Standard_Address)_Ancestors, + (Standard_Address)NULL); + + return _aType; +} + +//======================================================================= +//function : DownCast +//purpose : +//======================================================================= +const Handle(GEOMImpl_Fillet1dDriver) Handle(GEOMImpl_Fillet1dDriver)::DownCast(const Handle(Standard_Transient)& AnObject) +{ + Handle(GEOMImpl_Fillet1dDriver) _anOtherObject; + + if (!AnObject.IsNull()) { + if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_Fillet1dDriver))) { + _anOtherObject = Handle(GEOMImpl_Fillet1dDriver)((Handle(GEOMImpl_Fillet1dDriver)&)AnObject); + } + } + + return _anOtherObject ; +} diff --git a/src/GEOMImpl/GEOMImpl_Fillet1dDriver.hxx b/src/GEOMImpl/GEOMImpl_Fillet1dDriver.hxx new file mode 100644 index 000000000..a8aeb60e7 --- /dev/null +++ b/src/GEOMImpl/GEOMImpl_Fillet1dDriver.hxx @@ -0,0 +1,160 @@ +// Copyright (C) 2009 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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. +// +// 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 : GEOMImpl_Fillet1dDriver.ixx +// Module : GEOMImpl + +#ifndef _GEOMImpl_Fillet1dDriver_HeaderFile +#define _GEOMImpl_Fillet1dDriver_HeaderFile + +#ifndef _TColStd_SequenceOfExtendedString_HeaderFile +#include +#endif +#ifndef _Standard_TypeMismatch_HeaderFile +#include +#endif + +#ifndef _Standard_HeaderFile +#include +#endif + +#ifndef _Standard_Macro_HeaderFile +#include +#endif +#ifndef _Standard_HeaderFile +#include +#endif +#ifndef _Standard_GUID_HeaderFile +#include +#endif + +#ifndef _Handle_TFunction_Driver_HeaderFile +#include +#endif + +class Standard_Transient; +class Handle_Standard_Type; +class Handle(TFunction_Driver); +class GEOMImpl_Fillet1dDriver; + +Standard_EXPORT Handle_Standard_Type& STANDARD_TYPE(GEOMImpl_Fillet1dDriver); + +class Handle(GEOMImpl_Fillet1dDriver) : public Handle(TFunction_Driver) { + public: + inline void* operator new(size_t,void* anAddress) + { + return anAddress; + } + inline void* operator new(size_t size) + { + return Standard::Allocate(size); + } + inline void operator delete(void *anAddress) + { + if (anAddress) Standard::Free((Standard_Address&)anAddress); + } + + Handle(GEOMImpl_Fillet1dDriver)():Handle(TFunction_Driver)() {} + Handle(GEOMImpl_Fillet1dDriver)(const Handle(GEOMImpl_Fillet1dDriver)& aHandle) : Handle(TFunction_Driver)(aHandle) + { + } + + Handle(GEOMImpl_Fillet1dDriver)(const GEOMImpl_Fillet1dDriver* anItem) : Handle(TFunction_Driver)((TFunction_Driver *)anItem) + { + } + + Handle(GEOMImpl_Fillet1dDriver)& operator=(const Handle(GEOMImpl_Fillet1dDriver)& aHandle) + { + Assign(aHandle.Access()); + return *this; + } + + Handle(GEOMImpl_Fillet1dDriver)& operator=(const GEOMImpl_Fillet1dDriver* anItem) + { + Assign((Standard_Transient *)anItem); + return *this; + } + + GEOMImpl_Fillet1dDriver* operator->() + { + return (GEOMImpl_Fillet1dDriver *)ControlAccess(); + } + + GEOMImpl_Fillet1dDriver* operator->() const + { + return (GEOMImpl_Fillet1dDriver *)ControlAccess(); + } + + Standard_EXPORT ~Handle(GEOMImpl_Fillet1dDriver)() {}; + + Standard_EXPORT static const Handle(GEOMImpl_Fillet1dDriver) DownCast(const Handle(Standard_Transient)& AnObject); +}; + +#ifndef _TFunction_Driver_HeaderFile +#include +#endif +#ifndef _TFunction_Logbook_HeaderFile +#include +#endif +#ifndef _Standard_CString_HeaderFile +#include +#endif + +class TColStd_SequenceOfExtendedString; + + +class GEOMImpl_Fillet1dDriver : public TFunction_Driver { + +public: + + inline void* operator new(size_t,void* anAddress) + { + return anAddress; + } + inline void* operator new(size_t size) + { + return Standard::Allocate(size); + } + inline void operator delete(void *anAddress) + { + if (anAddress) Standard::Free((Standard_Address&)anAddress); + } + + // Methods PUBLIC + // +Standard_EXPORT GEOMImpl_Fillet1dDriver(); +Standard_EXPORT virtual Standard_Integer Execute(TFunction_Logbook& log) const; +Standard_EXPORT virtual void Validate(TFunction_Logbook&) const {} +Standard_EXPORT Standard_Boolean MustExecute(const TFunction_Logbook&) const { return Standard_True; } +Standard_EXPORT static const Standard_GUID& GetID(); +Standard_EXPORT ~GEOMImpl_Fillet1dDriver() {}; + + + // Type management + // +Standard_EXPORT friend Handle_Standard_Type& GEOMImpl_Fillet1dDriver_Type_(); +Standard_EXPORT const Handle(Standard_Type)& DynamicType() const + { return STANDARD_TYPE(GEOMImpl_Fillet1dDriver) ; } +Standard_EXPORT Standard_Boolean IsKind(const Handle(Standard_Type)& AType) const + { return (STANDARD_TYPE(GEOMImpl_Fillet1dDriver) == AType || TFunction_Driver::IsKind(AType)); } + + +}; + +#endif diff --git a/src/GEOMImpl/GEOMImpl_Gen.cxx b/src/GEOMImpl/GEOMImpl_Gen.cxx index b01b3f88a..a920fe3cf 100644 --- a/src/GEOMImpl/GEOMImpl_Gen.cxx +++ b/src/GEOMImpl/GEOMImpl_Gen.cxx @@ -62,6 +62,7 @@ #include #include #include +#include #include #include #include @@ -134,6 +135,7 @@ GEOMImpl_Gen::GEOMImpl_Gen() // Local Operations TFunction_DriverTable::Get()->AddDriver(GEOMImpl_ChamferDriver::GetID(), new GEOMImpl_ChamferDriver()); TFunction_DriverTable::Get()->AddDriver(GEOMImpl_FilletDriver::GetID(), new GEOMImpl_FilletDriver()); + TFunction_DriverTable::Get()->AddDriver(GEOMImpl_Fillet1dDriver::GetID(), new GEOMImpl_Fillet1dDriver()); TFunction_DriverTable::Get()->AddDriver(GEOMImpl_Fillet2dDriver::GetID(), new GEOMImpl_Fillet2dDriver()); TFunction_DriverTable::Get()->AddDriver(GEOMImpl_ArchimedeDriver::GetID(), new GEOMImpl_ArchimedeDriver()); diff --git a/src/GEOMImpl/GEOMImpl_IFillet1d.hxx b/src/GEOMImpl/GEOMImpl_IFillet1d.hxx new file mode 100644 index 000000000..daa0ebca9 --- /dev/null +++ b/src/GEOMImpl/GEOMImpl_IFillet1d.hxx @@ -0,0 +1,51 @@ +// Copyright (C) 2005 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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. +// +// 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 +// +//NOTE: This is an interface to a function for the Fillet1d and creation. + + +#include "GEOM_Function.hxx" + +#define FILLET1D_ARG_SH 1 +#define FILLET1D_ARG_R 2 +#define FILLET1D_ARG_LENG 3 +#define FILLET1D_ARG_LAST 4 + +class GEOMImpl_IFillet1d +{ + public: + + GEOMImpl_IFillet1d(Handle(GEOM_Function) theFunction): _func(theFunction) {} + + void SetShape(Handle(GEOM_Function) theRef) { _func->SetReference(FILLET1D_ARG_SH, theRef); } + Handle(GEOM_Function) GetShape() { return _func->GetReference(FILLET1D_ARG_SH); } + + void SetR(double theR) { _func->SetReal(FILLET1D_ARG_R, theR); } + void SetLength(int theLen) { _func->SetInteger(FILLET1D_ARG_LENG, theLen); } + void SetVertex(int theInd, int theVertex) + { _func->SetInteger(FILLET1D_ARG_LAST + theInd, theVertex); } + + double GetR() { return _func->GetReal(FILLET1D_ARG_R); } + int GetLength() { return _func->GetInteger(FILLET1D_ARG_LENG); } + int GetVertex(int theInd) { return _func->GetInteger(FILLET1D_ARG_LAST + theInd); } + + private: + + Handle(GEOM_Function) _func; +}; diff --git a/src/GEOMImpl/GEOMImpl_ILocalOperations.cxx b/src/GEOMImpl/GEOMImpl_ILocalOperations.cxx index 9e552229a..61a737697 100644 --- a/src/GEOMImpl/GEOMImpl_ILocalOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_ILocalOperations.cxx @@ -29,10 +29,12 @@ #include #include +#include #include #include #include +#include #include #include @@ -481,6 +483,75 @@ Handle(GEOM_Object) GEOMImpl_ILocalOperations::MakeFillet2D return aFillet2D; } +//============================================================================= +/*! + * MakeFillet1D + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_ILocalOperations::MakeFillet1D + (Handle(GEOM_Object) theShape, double theR, std::list theVertexes) +{ + SetErrorCode(KO); + + //Add a new Fillet object + Handle(GEOM_Object) aFillet1D = GetEngine()->AddObject(GetDocID(), GEOM_FILLET_1D); + + //Add a new Fillet function + Handle(GEOM_Function) aFunction = + aFillet1D->AddFunction(GEOMImpl_Fillet1dDriver::GetID(), FILLET_1D_SHAPE_VERTEXES); + if (aFunction.IsNull()) return NULL; + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_Fillet1dDriver::GetID()) return NULL; + + GEOMImpl_IFillet1d aCI (aFunction); + + Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); + if (aRefShape.IsNull()) return NULL; + + aCI.SetShape(aRefShape); + aCI.SetR(theR); + int aLen = theVertexes.size(); + aCI.SetLength(aLen); + + int ind = 1; + std::list::iterator it = theVertexes.begin(); + for (; it != theVertexes.end(); it++, ind++) { + aCI.SetVertex(ind, (*it)); + } + + //Compute the Fillet value + try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + OCC_CATCH_SIGNALS; +#endif + if (!GetSolver()->ComputeFunction(aFunction)) { + SetErrorCode("1D Fillet driver failed"); + return NULL; + } + } + catch (Standard_Failure) { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + SetErrorCode(aFail->GetMessageString()); + return NULL; + } + + //Make a Python command + GEOM::TPythonDump pd (aFunction); + pd << aFillet1D << " = geompy.MakeFillet1D(" << theShape + << ", " << theR << ", ["; + + it = theVertexes.begin(); + pd << (*it++); + while (it != theVertexes.end()) { + pd << ", " << (*it++); + } + pd << "])"; + + SetErrorCode(OK); + return aFillet1D; +} + //============================================================================= /*! * MakeChamferAll diff --git a/src/GEOMImpl/GEOMImpl_ILocalOperations.hxx b/src/GEOMImpl/GEOMImpl_ILocalOperations.hxx index 15acc6eaf..5bdf61848 100644 --- a/src/GEOMImpl/GEOMImpl_ILocalOperations.hxx +++ b/src/GEOMImpl/GEOMImpl_ILocalOperations.hxx @@ -48,6 +48,8 @@ class GEOMImpl_ILocalOperations : public GEOM_IOperations { std::list theFaces); Standard_EXPORT Handle(GEOM_Object) MakeFillet2D (Handle(GEOM_Object) theShape, double theR, std::list theVertexes); + Standard_EXPORT Handle(GEOM_Object) MakeFillet1D (Handle(GEOM_Object) theShape, double theR, + std::list theVertexes); Standard_EXPORT Handle(GEOM_Object) MakeChamferAll (Handle(GEOM_Object) theShape, double theD); Standard_EXPORT Handle(GEOM_Object) MakeChamferEdge (Handle(GEOM_Object) theShape, diff --git a/src/GEOMImpl/GEOMImpl_Types.hxx b/src/GEOMImpl/GEOMImpl_Types.hxx index 01c24ccb0..d1f474acf 100755 --- a/src/GEOMImpl/GEOMImpl_Types.hxx +++ b/src/GEOMImpl/GEOMImpl_Types.hxx @@ -49,6 +49,7 @@ #define GEOM_FILLET 20 #define GEOM_FILLET_2D 45 +#define GEOM_FILLET_1D 46 #define GEOM_CHAMFER 21 #define GEOM_EDGE 22 @@ -233,6 +234,7 @@ #define FILLET_SHAPE_FACES_2R 5 #define FILLET_2D_SHAPE_VERTEXES 1 +#define FILLET_1D_SHAPE_VERTEXES 1 #define CHAMFER_SHAPE_ALL 1 #define CHAMFER_SHAPE_EDGE 2 diff --git a/src/GEOMImpl/Makefile.am b/src/GEOMImpl/Makefile.am index 1c403da1b..0bbbdf176 100644 --- a/src/GEOMImpl/Makefile.am +++ b/src/GEOMImpl/Makefile.am @@ -56,6 +56,7 @@ salomeinclude_HEADERS = \ GEOMImpl_ISpline.hxx \ GEOMImpl_IEllipse.hxx \ GEOMImpl_IFillet.hxx \ + GEOMImpl_IFillet1d.hxx \ GEOMImpl_IFillet2d.hxx \ GEOMImpl_IChamfer.hxx \ GEOMImpl_ICopy.hxx \ @@ -128,6 +129,8 @@ salomeinclude_HEADERS = \ GEOMImpl_SketcherDriver.hxx \ GEOMImpl_3DSketcherDriver.hxx \ GEOMImpl_FilletDriver.hxx \ + GEOMImpl_Fillet1d.hxx \ + GEOMImpl_Fillet1dDriver.hxx \ GEOMImpl_Fillet2dDriver.hxx \ GEOMImpl_ChamferDriver.hxx \ GEOMImpl_BooleanDriver.hxx \ @@ -191,6 +194,8 @@ dist_libGEOMimpl_la_SOURCES = \ GEOMImpl_SketcherDriver.cxx \ GEOMImpl_3DSketcherDriver.cxx \ GEOMImpl_FilletDriver.cxx \ + GEOMImpl_Fillet1d.cxx \ + GEOMImpl_Fillet1dDriver.cxx \ GEOMImpl_Fillet2dDriver.cxx \ GEOMImpl_ChamferDriver.cxx \ GEOMImpl_BooleanDriver.cxx \ diff --git a/src/GEOM_I/GEOM_ILocalOperations_i.cc b/src/GEOM_I/GEOM_ILocalOperations_i.cc index 5b3289eec..fe1091f5b 100644 --- a/src/GEOM_I/GEOM_ILocalOperations_i.cc +++ b/src/GEOM_I/GEOM_ILocalOperations_i.cc @@ -237,6 +237,38 @@ GEOM::GEOM_Object_ptr GEOM_ILocalOperations_i::MakeFillet2D return GetObject(anObject); } +//============================================================================= +/*! + * MakeFillet1D + */ +//============================================================================= +GEOM::GEOM_Object_ptr GEOM_ILocalOperations_i::MakeFillet1D + (GEOM::GEOM_Object_ptr theShape, CORBA::Double theR, + const GEOM::ListOfLong& theVertexes) +{ + GEOM::GEOM_Object_var aGEOMObject; + + //Get the reference shape (wire) + Handle(GEOM_Object) aShapeRef = GetObjectImpl(theShape); + if (aShapeRef.IsNull()) return aGEOMObject._retn(); + + //Get the reference vertex + int ind = 0; + int aLen = theVertexes.length(); + list aVertexes; + for (; ind < aLen; ind++) { + aVertexes.push_back(theVertexes[ind]); + } + + //Create the Fillet + Handle(GEOM_Object) anObject = + GetOperations()->MakeFillet1D(aShapeRef, theR, aVertexes); + if (!GetOperations()->IsDone() || anObject.IsNull()) + return aGEOMObject._retn(); + + return GetObject(anObject); +} + //============================================================================= /*! * MakeChamferAll diff --git a/src/GEOM_I/GEOM_ILocalOperations_i.hh b/src/GEOM_I/GEOM_ILocalOperations_i.hh index e13d37f49..6fa95411a 100644 --- a/src/GEOM_I/GEOM_ILocalOperations_i.hh +++ b/src/GEOM_I/GEOM_ILocalOperations_i.hh @@ -63,6 +63,9 @@ class GEOM_I_EXPORT GEOM_ILocalOperations_i : GEOM::GEOM_Object_ptr MakeFillet2D (GEOM::GEOM_Object_ptr theShape, CORBA::Double theR, const GEOM::ListOfLong& theVertexes); + GEOM::GEOM_Object_ptr MakeFillet1D (GEOM::GEOM_Object_ptr theShape, CORBA::Double theR, + const GEOM::ListOfLong& theVertexes); + GEOM::GEOM_Object_ptr MakeChamferAll (GEOM::GEOM_Object_ptr theShape, CORBA::Double theD); GEOM::GEOM_Object_ptr MakeChamferEdge (GEOM::GEOM_Object_ptr theShape, diff --git a/src/GEOM_I_Superv/GEOM_Superv_i.cc b/src/GEOM_I_Superv/GEOM_Superv_i.cc index f749b8641..199f1e693 100644 --- a/src/GEOM_I_Superv/GEOM_Superv_i.cc +++ b/src/GEOM_I_Superv/GEOM_Superv_i.cc @@ -2850,6 +2850,26 @@ GEOM::GEOM_Object_ptr GEOM_Superv_i::MakeFillet2D (GEOM::GEOM_Object_ptr theShap return NULL; } +//============================================================================= +// MakeFillet1D: +//============================================================================= +GEOM::GEOM_Object_ptr GEOM_Superv_i::MakeFillet1D (GEOM::GEOM_Object_ptr theShape, + CORBA::Double theR, + GEOM::GEOM_List_ptr theVertexes) +{ + beginService( " GEOM_Superv_i::MakeFillet1D" ); + MESSAGE("GEOM_Superv_i::MakeFillet1D"); + if (GEOM_List_i* aListImplV = + dynamic_cast*>(GetServant(theVertexes, myPOA).in())) { + getLocalOp(); + GEOM::GEOM_Object_ptr anObj = myLocalOp->MakeFillet1D(theShape, theR, aListImplV->GetList()); + endService( " GEOM_Superv_i::MakeFillet1D" ); + return anObj; + } + endService( " GEOM_Superv_i::MakeFillet1D" ); + return NULL; +} + //============================================================================= // MakeChamferAll: //============================================================================= diff --git a/src/GEOM_I_Superv/GEOM_Superv_i.hh b/src/GEOM_I_Superv/GEOM_Superv_i.hh index 1568f0bb1..4ac9969b6 100644 --- a/src/GEOM_I_Superv/GEOM_Superv_i.hh +++ b/src/GEOM_I_Superv/GEOM_Superv_i.hh @@ -604,6 +604,8 @@ public: CORBA::Double theR2, GEOM::GEOM_List_ptr theFaces); GEOM::GEOM_Object_ptr MakeFillet2D (GEOM::GEOM_Object_ptr theShape, CORBA::Double theR, GEOM::GEOM_List_ptr theVertexes); + GEOM::GEOM_Object_ptr MakeFillet1D (GEOM::GEOM_Object_ptr theShape, CORBA::Double theR, + GEOM::GEOM_List_ptr theVertexes); GEOM::GEOM_Object_ptr MakeChamferAll (GEOM::GEOM_Object_ptr theShape, CORBA::Double theD); GEOM::GEOM_Object_ptr MakeChamferEdge (GEOM::GEOM_Object_ptr theShape, CORBA::Double theD1, CORBA::Double theD2, diff --git a/src/GEOM_SWIG/geompyDC.py b/src/GEOM_SWIG/geompyDC.py index 8cf504f7b..879b02292 100644 --- a/src/GEOM_SWIG/geompyDC.py +++ b/src/GEOM_SWIG/geompyDC.py @@ -2716,6 +2716,20 @@ class geompyDC(GEOM._objref_GEOM_Gen): anObj.SetParameters(Parameters) return anObj + ## Perform a fillet on the specified edges of the given wire shape + # @param theShape - Wire Shape(with planar edges) to perform fillet on. + # @param theR - Fillet radius. + # @param theListOfVertexes Global indices of vertexes to perform fillet on. + # \note Global index of sub-shape can be obtained, using method geompy.GetSubShapeID(). + # @return New GEOM_Object, containing the result shape. + # + # @ref tui_fillet1d "Example" + def MakeFillet1D(self,theShape, theR, theListOfVertexes): + # Example: see GEOM_TestAll.py + anObj = self.LocalOp.MakeFillet1D(theShape, theR, theListOfVertexes) + RaiseIfFailed("MakeFillet1D", self.LocalOp) + return anObj + ## Perform a fillet on the specified edges/faces of the given shape # @param theShape - Face Shape to perform fillet on. # @param theR - Fillet radius. @@ -2730,6 +2744,22 @@ class geompyDC(GEOM._objref_GEOM_Gen): RaiseIfFailed("MakeFillet2D", self.LocalOp) return anObj + ## Perform a fillet on the specified edges of the given shape + # @param theShape - Wire Shape to perform fillet on. + # @param theR - Fillet radius. + # @param theListOfVertexes Global indices of vertexes to perform fillet on. + # \note Global index of sub-shape can be obtained, using method geompy.GetSubShapeID(). + # \note The list of vertices could be empty, + # in this case fillet will done done at all vertices in wire + # @return New GEOM_Object, containing the result shape. + # + # @ref tui_fillet2d "Example" + def MakeFillet1D(self,theShape, theR, theListOfVertexes): + # Example: see GEOM_TestAll.py + anObj = self.LocalOp.MakeFillet1D(theShape, theR, theListOfVertexes) + RaiseIfFailed("MakeFillet1D", self.LocalOp) + return anObj + ## Perform a symmetric chamfer on all edges of the given shape. # @param theShape Shape, to perform chamfer on. # @param theD Chamfer size along each face. diff --git a/src/OperationGUI/Makefile.am b/src/OperationGUI/Makefile.am index fe874c13d..39ca44890 100644 --- a/src/OperationGUI/Makefile.am +++ b/src/OperationGUI/Makefile.am @@ -32,7 +32,7 @@ salomeinclude_HEADERS = \ OperationGUI_ArchimedeDlg.h \ OperationGUI_PartitionDlg.h \ OperationGUI_FilletDlg.h \ - OperationGUI_Fillet2dDlg.h \ + OperationGUI_Fillet1d2dDlg.h \ OperationGUI_ChamferDlg.h \ OperationGUI_GetShapesOnShapeDlg.h \ OperationGUI_ClippingDlg.h @@ -46,7 +46,7 @@ dist_libOperationGUI_la_SOURCES = \ OperationGUI_PartitionDlg.cxx \ OperationGUI_GetShapesOnShapeDlg.cxx \ OperationGUI_FilletDlg.cxx \ - OperationGUI_Fillet2dDlg.cxx \ + OperationGUI_Fillet1d2dDlg.cxx \ OperationGUI_ChamferDlg.cxx \ OperationGUI_ClippingDlg.cxx @@ -55,7 +55,7 @@ MOC_FILES = \ OperationGUI_PartitionDlg_moc.cxx \ OperationGUI_GetShapesOnShapeDlg_moc.cxx\ OperationGUI_FilletDlg_moc.cxx \ - OperationGUI_Fillet2dDlg_moc.cxx \ + OperationGUI_Fillet1d2dDlg_moc.cxx \ OperationGUI_ChamferDlg_moc.cxx \ OperationGUI_ClippingDlg_moc.cxx diff --git a/src/OperationGUI/OperationGUI.cxx b/src/OperationGUI/OperationGUI.cxx index ebc81748d..74906380d 100644 --- a/src/OperationGUI/OperationGUI.cxx +++ b/src/OperationGUI/OperationGUI.cxx @@ -38,7 +38,7 @@ #include "OperationGUI_PartitionDlg.h" // Method PARTITION #include "OperationGUI_ArchimedeDlg.h" // Method ARCHIMEDE #include "OperationGUI_FilletDlg.h" // Method FILLET -#include "OperationGUI_Fillet2dDlg.h" // Method FILLET 2D +#include "OperationGUI_Fillet1d2dDlg.h" // Method FILLET 2D and FILLET 1D #include "OperationGUI_ChamferDlg.h" // Method CHAMFER #include "OperationGUI_ClippingDlg.h" // Clipping dialog box #include "OperationGUI_GetShapesOnShapeDlg.h" @@ -79,7 +79,8 @@ bool OperationGUI::OnGUIEvent( int theCommandID, SUIT_Desktop* parent ) case 506: ( new OperationGUI_ChamferDlg ( getGeometryGUI(), parent ) )->show(); break; case 507: ( new OperationGUI_ClippingDlg ( getGeometryGUI(), parent ) )->show(); break; case 508: ( new OperationGUI_GetShapesOnShapeDlg( getGeometryGUI(), parent ) )->show(); break; - case 509: ( new OperationGUI_Fillet2dDlg ( getGeometryGUI(), parent ) )->show(); break; + case 510: ( new OperationGUI_Fillet1d2dDlg ( getGeometryGUI(), parent,true ) )->show(); break; + case 509: ( new OperationGUI_Fillet1d2dDlg ( getGeometryGUI(), parent,false ) )->show(); break; default: app->putInfo( tr( "GEOM_PRP_COMMAND" ).arg( theCommandID ) ); } diff --git a/src/OperationGUI/OperationGUI_Fillet1d2dDlg.cxx b/src/OperationGUI/OperationGUI_Fillet1d2dDlg.cxx new file mode 100644 index 000000000..43671b149 --- /dev/null +++ b/src/OperationGUI/OperationGUI_Fillet1d2dDlg.cxx @@ -0,0 +1,410 @@ +// GEOM GEOMGUI : GUI for Geometry component +// +// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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. +// +// 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 : OperationGUI_Fillet1d2dDlg.cxx +// Author : DMV, OCN. +// + +#include "OperationGUI_Fillet1d2dDlg.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +// OCCT Includes +#include +#include + +#include + +//================================================================================= +// class : OperationGUI_Fillet1d2dDlg() +// purpose : Constructs a OperationGUI_Fillet1d2dDlg which is a child of 'parent', with the +// name 'name' and widget flags set to 'f'. +// The dialog will by default be modeless, unless you set 'modal' to +// TRUE to construct a modal dialog. +//================================================================================= +OperationGUI_Fillet1d2dDlg::OperationGUI_Fillet1d2dDlg (GeometryGUI* theGeometryGUI, + QWidget* parent, + bool is1D) + : GEOMBase_Skeleton(theGeometryGUI, parent, false), + myIs1D( is1D ) +{ + SUIT_ResourceMgr* aResMgr = myGeomGUI->getApp()->resourceMgr(); + QPixmap image0 (aResMgr->loadPixmap("GEOM", myIs1D ? tr("ICON_DLG_FILLET_1D") + : tr("ICON_DLG_FILLET_2D"))); + QPixmap iconSelect (aResMgr->loadPixmap("GEOM", tr("ICON_SELECT"))); + + setWindowTitle(myIs1D ? tr("GEOM_FILLET_1D_TITLE") : tr("GEOM_FILLET_2D_TITLE")); + + /***************************************************************/ + mainFrame()->GroupConstructors->setTitle(myIs1D ? tr("GEOM_FILLET_1D") : tr("GEOM_FILLET_2D")); + mainFrame()->RadioButton1->setIcon(image0); + mainFrame()->RadioButton2->close(); + mainFrame()->RadioButton3->close(); + + GroupVertexes = new DlgRef_2Sel1Spin(centralWidget()); + GroupVertexes->GroupBox1->setTitle(myIs1D ? tr("GEOM_FILLET_1D") : tr("GEOM_FILLET_2D")); + GroupVertexes->TextLabel1->setText(myIs1D ? tr("GEOM_PLANAR_EDGE_WIRE") : tr("GEOM_PLANAR_FACE")); + GroupVertexes->TextLabel2->setText(tr("GEOM_VERTEXES")); + GroupVertexes->TextLabel3->setText(tr("GEOM_RADIUS")); + GroupVertexes->PushButton1->setIcon(iconSelect); + GroupVertexes->PushButton2->setIcon(iconSelect); + GroupVertexes->LineEdit1->setReadOnly(true); + GroupVertexes->LineEdit2->setReadOnly(true); + + QVBoxLayout* layout = new QVBoxLayout(centralWidget()); + layout->setMargin(0); layout->setSpacing(6); + layout->addWidget(GroupVertexes); + + /***************************************************************/ + + // Set range of spinboxes + double SpecificStep = 10.0; + initSpinBox(GroupVertexes->SpinBox_DX, 0.00001, COORD_MAX, SpecificStep, 5); // VSR: TODO: DBL_DIGITS_DISPLAY + + setHelpFileName(myIs1D ? "fillet1d_operation_page.html" : "fillet2d_operation_page.html"); + + // Initialisation + Init(); + resize(100,100); +} + +//================================================================================= +// function : ~OperationGUI_Fillet1d2dDlg() +// purpose : Destroys the object and frees any allocated resources +//================================================================================= +OperationGUI_Fillet1d2dDlg::~OperationGUI_Fillet1d2dDlg() +{ +} + +//================================================================================= +// function : Init() +// purpose : +//================================================================================= +void OperationGUI_Fillet1d2dDlg::Init() +{ + // Set Initial values of spinboxes + GroupVertexes->SpinBox_DX->setValue(5); + + // Clear line edits + GroupVertexes->LineEdit1->setText(""); + GroupVertexes->LineEdit2->setText(""); + + myShape = GEOM::GEOM_Object::_nil(); + + myVertexes.Clear(); + + // signals and slots connections + + connect(buttonOk(), SIGNAL(clicked()), this, SLOT(ClickOnOk() )); + connect(buttonApply(), SIGNAL(clicked()), this, SLOT(ClickOnApply())); + + // connect(this, SIGNAL(constructorsClicked(int)), this, SLOT(ConstructorsClicked(int))); + + connect(GroupVertexes->PushButton1, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument())); + connect(GroupVertexes->PushButton2, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument())); + + connect(GroupVertexes->LineEdit1, SIGNAL(returnPressed()), this, SLOT(LineEditReturnPressed())); + connect(GroupVertexes->LineEdit2, SIGNAL(returnPressed()), this, SLOT(LineEditReturnPressed())); + + connect(GroupVertexes->SpinBox_DX, SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double))); + + initName(myIs1D ? tr("GEOM_FILLET_1D") : tr("GEOM_FILLET_2D")); + GroupVertexes->PushButton1->click(); +} + +//================================================================================= +// function : ClickOnOk() +// purpose : +//================================================================================= +void OperationGUI_Fillet1d2dDlg::ClickOnOk() +{ + if (ClickOnApply()) + ClickOnCancel(); +} + +//================================================================================= +// function : ClickOnApply() +// purpose : +//================================================================================= +bool OperationGUI_Fillet1d2dDlg::ClickOnApply() +{ + if (!onAccept()) + return false; + + initName(); + // Reset dialog state + GroupVertexes->LineEdit1->setText(""); + GroupVertexes->LineEdit2->setText(""); + myShape = GEOM::GEOM_Object::_nil(); + myVertexes.Clear(); + GroupVertexes->PushButton1->click(); + + return true; +} + +//================================================================================= +// function : SelectionIntoArgument() +// purpose : Called when selection is changed or on dialog initialization or activation +//================================================================================= +void OperationGUI_Fillet1d2dDlg::SelectionIntoArgument() +{ + erasePreview(); + myEditCurrentArgument->setText(""); + + LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr(); + SALOME_ListIO aSelList; + aSelMgr->selectedObjects(aSelList); + + // If selection of main object is activated + if (myEditCurrentArgument == GroupVertexes->LineEdit1) { + myShape = GEOM::GEOM_Object::_nil(); + if (aSelList.Extent() == 1) { + Standard_Boolean aResult = Standard_False; + GEOM::GEOM_Object_var anObj = + GEOMBase::ConvertIOinGEOMObject(aSelList.First(), aResult); + + if (aResult && !anObj->_is_nil()) { + QString aName = GEOMBase::GetName( anObj ); + TopoDS_Shape aShape; + if ( GEOMBase::GetShape( anObj, aShape, TopAbs_SHAPE ) && !aShape.IsNull() ) { + TColStd_IndexedMapOfInteger aMap; + aSelMgr->GetIndexes(aSelList.First(), aMap); + if ( aMap.Extent() == 1 ) { // Local Selection + int anIndex = aMap( 1 ); + aName += QString( myIs1D ? ":wire_%1" : ":face_%1" ).arg( anIndex ); + + //Find SubShape Object in Father + GEOM::GEOM_Object_var aFindedObject = GEOMBase_Helper::findObjectInFather( anObj, aName ); + + if ( aFindedObject == GEOM::GEOM_Object::_nil() ) { // Object not found in study + GEOM::GEOM_IShapesOperations_var aShapesOp = getGeomEngine()->GetIShapesOperations( getStudyId() ); + anObj = aShapesOp->GetSubShape( anObj, anIndex ); + } + else + anObj = aFindedObject; // get Object from study + } + else { // Global Selection + if ( aShape.ShapeType() != (myIs1D ? TopAbs_WIRE : TopAbs_FACE) ) { + anObj = GEOM::GEOM_Object::_nil(); + aName = ""; + } + } + } + myShape = anObj; + myEditCurrentArgument->setText(aName +); + displayPreview(); + } + } + } else if (myEditCurrentArgument == GroupVertexes->LineEdit2) { + myVertexes.Clear(); + bool isPreview = myIs1D; + if (aSelList.Extent() == 1) { + Standard_Boolean aResult = Standard_False; + GEOM::GEOM_Object_var anObj = + GEOMBase::ConvertIOinGEOMObject(aSelList.First(), aResult); + + if (aResult && !anObj->_is_nil()) { + TColStd_IndexedMapOfInteger anIndexes; + aSelMgr->GetIndexes(aSelList.First(), anIndexes); + + if (anIndexes.Extent() > 0) { + QString aName; + if (anIndexes.Extent() == 1) { + int anIndex = anIndexes(1); + aName = QString(GEOMBase::GetName(anObj)) + QString(":vertex_%1").arg(anIndex); + } + else + aName = tr("GEOM_MEN_POPUP_NAME").arg(anIndexes.Extent()); + + isPreview = true; + myEditCurrentArgument->setText(aName); + myVertexes = anIndexes; + } + } + } + if ( isPreview ) + displayPreview(); + } + + if (myEditCurrentArgument == GroupVertexes->LineEdit1) { + if (!myShape->_is_nil() && myVertexes.Extent() == 0) + GroupVertexes->PushButton2->click(); + } +} + +//================================================================================= +// function : SetEditCurrentArgument() +// purpose : +//================================================================================= +void OperationGUI_Fillet1d2dDlg::SetEditCurrentArgument() +{ + QPushButton* send = (QPushButton*)sender(); + + if (send == GroupVertexes->PushButton1) { + myEditCurrentArgument = GroupVertexes->LineEdit1; + GroupVertexes->PushButton2->setDown(false); + GroupVertexes->LineEdit2->setEnabled(false); + } + else if (send == GroupVertexes->PushButton2) { + myEditCurrentArgument = GroupVertexes->LineEdit2; + GroupVertexes->PushButton1->setDown(false); + GroupVertexes->LineEdit1->setEnabled(false); + } + + // enable line edit + myEditCurrentArgument->setEnabled(true); + myEditCurrentArgument->setFocus(); + // after setFocus(), because it will be setDown(false) when loses focus + send->setDown(true); + + activateSelection(); + + // seems we need it only to avoid preview disappearing, caused by selection mode change + displayPreview(); +} + +//================================================================================= +// function : LineEditReturnPressed() +// purpose : +//================================================================================= +void OperationGUI_Fillet1d2dDlg::LineEditReturnPressed() +{ + QLineEdit* send = (QLineEdit*)sender(); + + if (send == GroupVertexes->LineEdit1) + myEditCurrentArgument = GroupVertexes->LineEdit1; + else if (send == GroupVertexes->LineEdit2) + myEditCurrentArgument = GroupVertexes->LineEdit2; + else + return; + + GEOMBase_Skeleton::LineEditReturnPressed(); +} + +//================================================================================= +// function : ActivateThisDialog() +// purpose : +//================================================================================= +void OperationGUI_Fillet1d2dDlg::ActivateThisDialog() +{ + GEOMBase_Skeleton::ActivateThisDialog(); +} + +//================================================================================= +// function : enterEvent() +// purpose : +//================================================================================= +void OperationGUI_Fillet1d2dDlg::enterEvent (QEvent*) +{ + if (!mainFrame()->GroupConstructors->isEnabled()) + this->ActivateThisDialog(); +} + +//================================================================================= +// function : ValueChangedInSpinBox() +// purpose : +//================================================================================= +void OperationGUI_Fillet1d2dDlg::ValueChangedInSpinBox (double) +{ + displayPreview(); +} + +//================================================================================= +// function : activateSelection +// purpose : Activate selection in accordance with myEditCurrentArgument +//================================================================================= +void OperationGUI_Fillet1d2dDlg::activateSelection() +{ + disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0); + globalSelection(); + if (myEditCurrentArgument == GroupVertexes->LineEdit1) + globalSelection( myIs1D ? GEOM_WIRE : GEOM_FACE ); // localSelection(myShape, myIs1D ? TopAbs_WIRE + // : TopAbs_FACE); + else if (!myShape->_is_nil() && myEditCurrentArgument == GroupVertexes->LineEdit2) + localSelection(myShape, TopAbs_VERTEX); + + connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()), + this, SLOT(SelectionIntoArgument())); +} + +//================================================================================= +// function : createOperation +// purpose : +//================================================================================= +GEOM::GEOM_IOperations_ptr OperationGUI_Fillet1d2dDlg::createOperation() +{ + return getGeomEngine()->GetILocalOperations(getStudyId()); +} + +//================================================================================= +// function : isValid() +// purpose : Verify validity of input data +//================================================================================= +bool OperationGUI_Fillet1d2dDlg::isValid (QString&) +{ + return !myShape->_is_nil() && (myIs1D || myVertexes.Extent() > 0); +} + +//================================================================================= +// function : execute +// purpose : +//================================================================================= +bool OperationGUI_Fillet1d2dDlg::execute (ObjectList& objects) +{ + GEOM::GEOM_Object_var anObj; + + GEOM::ListOfLong_var aListOfIndexes = new GEOM::ListOfLong; + aListOfIndexes->length(myVertexes.Extent()); + + for (int i = 1, n = myVertexes.Extent(); i <= n; i++) + aListOfIndexes[ i - 1 ] = myVertexes(i); + + GEOM::GEOM_ILocalOperations_ptr op = + GEOM::GEOM_ILocalOperations::_narrow(getOperation()); + anObj = (myIs1D ? op->MakeFillet1D(myShape, getRadius(), aListOfIndexes) + : op->MakeFillet2D(myShape, getRadius(), aListOfIndexes)); + + if (!anObj->_is_nil()) + objects.push_back(anObj._retn()); + + return true; +} + +//================================================================================= +// function : getRadius +// purpose : Get radius +//================================================================================= +double OperationGUI_Fillet1d2dDlg::getRadius() const +{ + return GroupVertexes ->SpinBox_DX->value(); +} diff --git a/src/OperationGUI/OperationGUI_Fillet1d2dDlg.h b/src/OperationGUI/OperationGUI_Fillet1d2dDlg.h new file mode 100644 index 000000000..9e7f679d9 --- /dev/null +++ b/src/OperationGUI/OperationGUI_Fillet1d2dDlg.h @@ -0,0 +1,76 @@ +// GEOM GEOMGUI : GUI for Geometry component +// +// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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. +// +// 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 : OperationGUI_Fillet1d2dDlg.h +// Author : DMV, OCN +// + +#ifndef OPERATIONGUI_Fillet1d2dDLG_H +#define OPERATIONGUI_Fillet1d2dDLG_H + +#include + +#include + +class DlgRef_2Sel1Spin; + +//================================================================================= +// class : OperationGUI_Fillet1d2dDlg +// purpose : +//================================================================================= +class OperationGUI_Fillet1d2dDlg : public GEOMBase_Skeleton +{ + Q_OBJECT + +public: + OperationGUI_Fillet1d2dDlg( GeometryGUI*, QWidget*, bool theIs1D ); + ~OperationGUI_Fillet1d2dDlg(); + +protected: + // redefined from GEOMBase_Helper + virtual GEOM::GEOM_IOperations_ptr createOperation(); + virtual bool isValid( QString& ); + virtual bool execute( ObjectList& ); + +private slots: + void ClickOnOk(); + bool ClickOnApply(); + void ActivateThisDialog(); + void LineEditReturnPressed(); + void SelectionIntoArgument(); + void SetEditCurrentArgument(); + void ValueChangedInSpinBox( double ); + +private: + void Init(); + void enterEvent( QEvent* ); + void activateSelection(); + double getRadius() const; + +private: + bool myIs1D; + GEOM::GEOM_Object_var myShape; + TColStd_IndexedMapOfInteger myVertexes; + + DlgRef_2Sel1Spin* GroupVertexes; +}; + +#endif // OPERATIONGUI_Fillet1d2dDLG_H diff --git a/src/OperationGUI/OperationGUI_Fillet2dDlg.cxx b/src/OperationGUI/OperationGUI_Fillet2dDlg.cxx deleted file mode 100755 index dcb073800..000000000 --- a/src/OperationGUI/OperationGUI_Fillet2dDlg.cxx +++ /dev/null @@ -1,400 +0,0 @@ -// GEOM GEOMGUI : GUI for Geometry component -// -// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// 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. -// -// 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 : OperationGUI_Fillet2dDlg.cxx -// Author : DMV, OCN. -// - -#include "OperationGUI_Fillet2dDlg.h" - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -// OCCT Includes -#include -#include - -#include - -//================================================================================= -// class : OperationGUI_Fillet2dDlg() -// purpose : Constructs a OperationGUI_Fillet2dDlg which is a child of 'parent', with the -// name 'name' and widget flags set to 'f'. -// The dialog will by default be modeless, unless you set 'modal' to -// TRUE to construct a modal dialog. -//================================================================================= -OperationGUI_Fillet2dDlg::OperationGUI_Fillet2dDlg (GeometryGUI* theGeometryGUI, QWidget* parent) - : GEOMBase_Skeleton(theGeometryGUI, parent, false) -{ - SUIT_ResourceMgr* aResMgr = myGeomGUI->getApp()->resourceMgr(); - QPixmap image0 (aResMgr->loadPixmap("GEOM", tr("ICON_DLG_FILLET_2D"))); - QPixmap iconSelect (aResMgr->loadPixmap("GEOM", tr("ICON_SELECT"))); - - setWindowTitle(tr("GEOM_FILLET_2D_TITLE")); - - /***************************************************************/ - mainFrame()->GroupConstructors->setTitle(tr("GEOM_FILLET_2D")); - mainFrame()->RadioButton1->setIcon(image0); - mainFrame()->RadioButton2->close(); - mainFrame()->RadioButton3->close(); - - GroupVertexes = new DlgRef_2Sel1Spin(centralWidget()); - GroupVertexes->GroupBox1->setTitle(tr("GEOM_FILLET_2D")); - GroupVertexes->TextLabel1->setText(tr("GEOM_PLANAR_FACE")); - GroupVertexes->TextLabel2->setText(tr("GEOM_VERTEXES")); - GroupVertexes->TextLabel3->setText(tr("GEOM_RADIUS")); - GroupVertexes->PushButton1->setIcon(iconSelect); - GroupVertexes->PushButton2->setIcon(iconSelect); - GroupVertexes->LineEdit1->setReadOnly(true); - GroupVertexes->LineEdit2->setReadOnly(true); - - QVBoxLayout* layout = new QVBoxLayout(centralWidget()); - layout->setMargin(0); layout->setSpacing(6); - layout->addWidget(GroupVertexes); - - /***************************************************************/ - - // Set range of spinboxes - double SpecificStep = 10.0; - initSpinBox(GroupVertexes->SpinBox_DX, 0.00001, COORD_MAX, SpecificStep, 5); // VSR: TODO: DBL_DIGITS_DISPLAY - - setHelpFileName("fillet2d_operation_page.html"); - - // Initialisation - Init(); - resize(100,100); -} - -//================================================================================= -// function : ~OperationGUI_Fillet2dDlg() -// purpose : Destroys the object and frees any allocated resources -//================================================================================= -OperationGUI_Fillet2dDlg::~OperationGUI_Fillet2dDlg() -{ -} - -//================================================================================= -// function : Init() -// purpose : -//================================================================================= -void OperationGUI_Fillet2dDlg::Init() -{ - // Set Initial values of spinboxes - GroupVertexes->SpinBox_DX->setValue(5); - - // Clear line edits - GroupVertexes->LineEdit1->setText(""); - GroupVertexes->LineEdit2->setText(""); - - myShape = GEOM::GEOM_Object::_nil(); - - myVertexes.Clear(); - - // signals and slots connections - - connect(buttonOk(), SIGNAL(clicked()), this, SLOT(ClickOnOk() )); - connect(buttonApply(), SIGNAL(clicked()), this, SLOT(ClickOnApply())); - - // connect(this, SIGNAL(constructorsClicked(int)), this, SLOT(ConstructorsClicked(int))); - - connect(GroupVertexes->PushButton1, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument())); - connect(GroupVertexes->PushButton2, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument())); - - connect(GroupVertexes->LineEdit1, SIGNAL(returnPressed()), this, SLOT(LineEditReturnPressed())); - connect(GroupVertexes->LineEdit2, SIGNAL(returnPressed()), this, SLOT(LineEditReturnPressed())); - - connect(GroupVertexes->SpinBox_DX, SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double))); - - initName(tr("GEOM_FILLET_2D")); - GroupVertexes->PushButton1->click(); -} - -//================================================================================= -// function : ClickOnOk() -// purpose : -//================================================================================= -void OperationGUI_Fillet2dDlg::ClickOnOk() -{ - if (ClickOnApply()) - ClickOnCancel(); -} - -//================================================================================= -// function : ClickOnApply() -// purpose : -//================================================================================= -bool OperationGUI_Fillet2dDlg::ClickOnApply() -{ - if (!onAccept()) - return false; - - initName(); - // Reset dialog state - GroupVertexes->LineEdit1->setText(""); - GroupVertexes->LineEdit2->setText(""); - myShape = GEOM::GEOM_Object::_nil(); - myVertexes.Clear(); - GroupVertexes->PushButton1->click(); - - return true; -} - -//================================================================================= -// function : SelectionIntoArgument() -// purpose : Called when selection is changed or on dialog initialization or activation -//================================================================================= -void OperationGUI_Fillet2dDlg::SelectionIntoArgument() -{ - erasePreview(); - myEditCurrentArgument->setText(""); - - LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr(); - SALOME_ListIO aSelList; - aSelMgr->selectedObjects(aSelList); - - // If selection of main object is activated - if (myEditCurrentArgument == GroupVertexes->LineEdit1) { - myShape = GEOM::GEOM_Object::_nil(); - if (aSelList.Extent() == 1) { - Standard_Boolean aResult = Standard_False; - GEOM::GEOM_Object_var anObj = - GEOMBase::ConvertIOinGEOMObject(aSelList.First(), aResult); - - if (aResult && !anObj->_is_nil()) { - QString aName = GEOMBase::GetName( anObj ); - TopoDS_Shape aShape; - if ( GEOMBase::GetShape( anObj, aShape, TopAbs_SHAPE ) && !aShape.IsNull() ) { - TColStd_IndexedMapOfInteger aMap; - aSelMgr->GetIndexes(aSelList.First(), aMap); - if ( aMap.Extent() == 1 ) { // Local Selection - int anIndex = aMap( 1 ); - aName += QString( ":face_%1" ).arg( anIndex ); - - //Find SubShape Object in Father - GEOM::GEOM_Object_var aFindedObject = GEOMBase_Helper::findObjectInFather( anObj, aName ); - - if ( aFindedObject == GEOM::GEOM_Object::_nil() ) { // Object not found in study - GEOM::GEOM_IShapesOperations_var aShapesOp = getGeomEngine()->GetIShapesOperations( getStudyId() ); - anObj = aShapesOp->GetSubShape( anObj, anIndex ); - } - else - anObj = aFindedObject; // get Object from study - } - else { // Global Selection - if ( aShape.ShapeType() != TopAbs_FACE ) { - anObj = GEOM::GEOM_Object::_nil(); - aName = ""; - } - } - } - myShape = anObj; - myEditCurrentArgument->setText(aName -); - displayPreview(); - } - } - } else if (myEditCurrentArgument == GroupVertexes->LineEdit2) { - myVertexes.Clear(); - if (aSelList.Extent() == 1) { - Standard_Boolean aResult = Standard_False; - GEOM::GEOM_Object_var anObj = - GEOMBase::ConvertIOinGEOMObject(aSelList.First(), aResult); - - if (aResult && !anObj->_is_nil()) { - TColStd_IndexedMapOfInteger anIndexes; - aSelMgr->GetIndexes(aSelList.First(), anIndexes); - - if (anIndexes.Extent() > 0) { - QString aName; - if (anIndexes.Extent() == 1) { - int anIndex = anIndexes(1); - aName = QString(GEOMBase::GetName(anObj)) + QString(":vertex_%1").arg(anIndex); - } - else - aName = tr("GEOM_MEN_POPUP_NAME").arg(anIndexes.Extent()); - - myEditCurrentArgument->setText(aName); - myVertexes = anIndexes; - displayPreview(); - } - } - } - } - - if (myEditCurrentArgument == GroupVertexes->LineEdit1) { - if (!myShape->_is_nil() && myVertexes.Extent() == 0) - GroupVertexes->PushButton2->click(); - } -} - -//================================================================================= -// function : SetEditCurrentArgument() -// purpose : -//================================================================================= -void OperationGUI_Fillet2dDlg::SetEditCurrentArgument() -{ - QPushButton* send = (QPushButton*)sender(); - - if (send == GroupVertexes->PushButton1) { - myEditCurrentArgument = GroupVertexes->LineEdit1; - GroupVertexes->PushButton2->setDown(false); - GroupVertexes->LineEdit2->setEnabled(false); - } - else if (send == GroupVertexes->PushButton2) { - myEditCurrentArgument = GroupVertexes->LineEdit2; - GroupVertexes->PushButton1->setDown(false); - GroupVertexes->LineEdit1->setEnabled(false); - } - - // enable line edit - myEditCurrentArgument->setEnabled(true); - myEditCurrentArgument->setFocus(); - // after setFocus(), because it will be setDown(false) when loses focus - send->setDown(true); - - activateSelection(); - - // seems we need it only to avoid preview disappearing, caused by selection mode change - displayPreview(); -} - -//================================================================================= -// function : LineEditReturnPressed() -// purpose : -//================================================================================= -void OperationGUI_Fillet2dDlg::LineEditReturnPressed() -{ - QLineEdit* send = (QLineEdit*)sender(); - - if (send == GroupVertexes->LineEdit1) - myEditCurrentArgument = GroupVertexes->LineEdit1; - else if (send == GroupVertexes->LineEdit2) - myEditCurrentArgument = GroupVertexes->LineEdit2; - else - return; - - GEOMBase_Skeleton::LineEditReturnPressed(); -} - -//================================================================================= -// function : ActivateThisDialog() -// purpose : -//================================================================================= -void OperationGUI_Fillet2dDlg::ActivateThisDialog() -{ - GEOMBase_Skeleton::ActivateThisDialog(); -} - -//================================================================================= -// function : enterEvent() -// purpose : -//================================================================================= -void OperationGUI_Fillet2dDlg::enterEvent (QEvent*) -{ - if (!mainFrame()->GroupConstructors->isEnabled()) - this->ActivateThisDialog(); -} - -//================================================================================= -// function : ValueChangedInSpinBox() -// purpose : -//================================================================================= -void OperationGUI_Fillet2dDlg::ValueChangedInSpinBox (double) -{ - displayPreview(); -} - -//================================================================================= -// function : activateSelection -// purpose : Activate selection in accordance with myEditCurrentArgument -//================================================================================= -void OperationGUI_Fillet2dDlg::activateSelection() -{ - disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0); - globalSelection(); - if (myEditCurrentArgument == GroupVertexes->LineEdit1) - globalSelection( GEOM_FACE ); // localSelection(myShape, TopAbs_FACE); - else if (!myShape->_is_nil() && myEditCurrentArgument == GroupVertexes->LineEdit2) - localSelection(myShape, TopAbs_VERTEX); - - connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()), - this, SLOT(SelectionIntoArgument())); -} - -//================================================================================= -// function : createOperation -// purpose : -//================================================================================= -GEOM::GEOM_IOperations_ptr OperationGUI_Fillet2dDlg::createOperation() -{ - return getGeomEngine()->GetILocalOperations(getStudyId()); -} - -//================================================================================= -// function : isValid() -// purpose : Verify validity of input data -//================================================================================= -bool OperationGUI_Fillet2dDlg::isValid (QString&) -{ - return !myShape->_is_nil() && myVertexes.Extent() > 0; -} - -//================================================================================= -// function : execute -// purpose : -//================================================================================= -bool OperationGUI_Fillet2dDlg::execute (ObjectList& objects) -{ - GEOM::GEOM_Object_var anObj; - - GEOM::ListOfLong_var aListOfIndexes = new GEOM::ListOfLong; - aListOfIndexes->length(myVertexes.Extent()); - - for (int i = 1, n = myVertexes.Extent(); i <= n; i++) - aListOfIndexes[ i - 1 ] = myVertexes(i); - - anObj = GEOM::GEOM_ILocalOperations::_narrow(getOperation())-> - MakeFillet2D(myShape, getRadius(), aListOfIndexes); - - if (!anObj->_is_nil()) - objects.push_back(anObj._retn()); - - return true; -} - -//================================================================================= -// function : getRadius -// purpose : Get radius -//================================================================================= -double OperationGUI_Fillet2dDlg::getRadius() const -{ - return GroupVertexes ->SpinBox_DX->value(); -} diff --git a/src/OperationGUI/OperationGUI_Fillet2dDlg.h b/src/OperationGUI/OperationGUI_Fillet2dDlg.h deleted file mode 100755 index 523dbad04..000000000 --- a/src/OperationGUI/OperationGUI_Fillet2dDlg.h +++ /dev/null @@ -1,75 +0,0 @@ -// GEOM GEOMGUI : GUI for Geometry component -// -// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// 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. -// -// 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 : OperationGUI_Fillet2dDlg.h -// Author : DMV, OCN -// - -#ifndef OPERATIONGUI_FILLET2DDLG_H -#define OPERATIONGUI_FILLET2DDLG_H - -#include - -#include - -class DlgRef_2Sel1Spin; - -//================================================================================= -// class : OperationGUI_Fillet2dDlg -// purpose : -//================================================================================= -class OperationGUI_Fillet2dDlg : public GEOMBase_Skeleton -{ - Q_OBJECT - -public: - OperationGUI_Fillet2dDlg( GeometryGUI*, QWidget* ); - ~OperationGUI_Fillet2dDlg(); - -protected: - // redefined from GEOMBase_Helper - virtual GEOM::GEOM_IOperations_ptr createOperation(); - virtual bool isValid( QString& ); - virtual bool execute( ObjectList& ); - -private slots: - void ClickOnOk(); - bool ClickOnApply(); - void ActivateThisDialog(); - void LineEditReturnPressed(); - void SelectionIntoArgument(); - void SetEditCurrentArgument(); - void ValueChangedInSpinBox( double ); - -private: - void Init(); - void enterEvent( QEvent* ); - void activateSelection(); - double getRadius() const; - -private: - GEOM::GEOM_Object_var myShape; - TColStd_IndexedMapOfInteger myVertexes; - - DlgRef_2Sel1Spin* GroupVertexes; -}; - -#endif // OPERATIONGUI_FILLET2DDLG_H