0020432: EDF 1029 GEOM : Fillet 1D

This commit is contained in:
ptv 2009-08-18 11:15:10 +00:00
parent 3e98d95f41
commit 3f0d846753
34 changed files with 1767 additions and 52 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,29 @@
/*!
\page fillet1d_operation_page Fillet 1D
This operation creates fillets on the corners of a <b>Wire with Planar
Edges</b>.
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 <b>Main Menu</b> select
<b>Operations - > Transformation - > Fillet 1D</b>
Define the <b>Wire with planar Edges</b> 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 <b>Planar Edges</b> Only.
<b>TUI Command:</b> <em>geompy.MakeFillet1D(Shape, R, ListVertexes)</em>
\n <b>Arguments:</b> Name + 1 shape + empty list or several vertexes + 1 value (Fillet radius).
<b>Examples:</b>
\image html fillet1d_1.png
Our <b>TUI Scripts</b> provide you with useful examples of the use of
\ref tui_fillet1d "Transformation Operations".
*/

View File

@ -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 <b>Planar 2D</b> Faces Only.
<b>TUI Command:</b> <em>geompy.MakeFillet(Shape, R, ListVertexes)</em>
<b>TUI Command:</b> <em>geompy.MakeFillet2D(Shape, R, ListVertexes)</em>
\n <b>Arguments:</b> Name + 1 shape + one or several vertexes + 1 value (Fillet radius).
<b>Examples:</b>

View File

@ -20,6 +20,8 @@ factors.</li>
<li>Create a simultaneous \subpage multi_rotation_operation_page</li> "Rotation in several directions".</li>
<li>Produce a \subpage fillet_operation_page "Fillet" on the selected
edges of the object.</li>
<li>Produce a \subpage fillet1d_operation_page "1D Fillet" on the
corners of a Wire with Planar Edges.</li>
<li>Produce a \subpage fillet2d_operation_page "2D Fillet" on the corners of a Planar Face.</li>
<li>Produce a \subpage chamfer_operation_page "Chamfer" on the
selected edges of the object.</li>

View File

@ -370,6 +370,29 @@ gg.createAndDisplayGO(id_face)
gg.createAndDisplayGO(id_fillet2d)
\endcode
\anchor tui_fillet1d
<br><h2>Fillet 1D</h2>
\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
<br><h2>Fillet</h2>

View File

@ -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
* <VAR>GEOM_IShapesOperations.GetSubShapeIndex()</VAR>.
* \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.

View File

@ -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 \

BIN
resources/fillet1d.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 819 B

BIN
resources/filletwire.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 772 B

View File

@ -225,6 +225,10 @@
<source>ICON_DLG_FILLET</source>
<translation>fillet.png</translation>
</message>
<message>
<source>ICON_DLG_FILLET_1D</source>
<translation>fillet1d.png</translation>
</message>
<message>
<source>ICON_DLG_FILLET_2D</source>
<translation>fillet2d.png</translation>
@ -237,6 +241,10 @@
<source>ICON_DLG_FILLET_EDGE</source>
<translation>filletedge.png</translation>
</message>
<message>
<source>ICON_DLG_FILLET_WIRE</source>
<translation>filletwire.png</translation>
</message>
<message>
<source>ICON_DLG_FILLET_FACE</source>
<translation>filletface.png</translation>
@ -765,6 +773,10 @@
<source>ICO_FILLET</source>
<translation>fillet.png</translation>
</message>
<message>
<source>ICO_FILLET_1D</source>
<translation>fillet1d.png</translation>
</message>
<message>
<source>ICO_FILLET_2D</source>
<translation>fillet2d.png</translation>

View File

@ -623,6 +623,10 @@ Please, select face, shell or solid and try again</translation>
<source>GEOM_FILLET_2D</source>
<translation>Fillet 2D</translation>
</message>
<message>
<source>GEOM_FILLET_1D</source>
<translation>Fillet 1D</translation>
</message>
<message>
<source>GEOM_FILLET_ABORT</source>
<translation>Fillet can't be computed with radius %1</translation>
@ -635,6 +639,10 @@ Please, select face, shell or solid and try again</translation>
<source>GEOM_FILLET_EDGES</source>
<translation>Fillet On Edges From Shape</translation>
</message>
<message>
<source>GEOM_FILLET_WIRES</source>
<translation>Fillet On Wires From Shape</translation>
</message>
<message>
<source>GEOM_FILLET_FACES</source>
<translation>Fillet On Faces From Shape</translation>
@ -651,6 +659,10 @@ Please, select face, shell or solid and try again</translation>
<source>GEOM_FILLET_2D_TITLE</source>
<translation>2D Fillet Construction</translation>
</message>
<message>
<source>GEOM_FILLET_1D_TITLE</source>
<translation>1D Fillet Construction</translation>
</message>
<message>
<source>GEOM_FILLING</source>
<translation>Filling</translation>
@ -2187,6 +2199,10 @@ Please, select face, shell or solid and try again</translation>
<source>MEN_FILLET</source>
<translation>Fillet</translation>
</message>
<message>
<source>MEN_FILLET_1D</source>
<translation>Fillet 1D</translation>
</message>
<message>
<source>MEN_FILLET_2D</source>
<translation>Fillet 2D</translation>
@ -3707,6 +3723,10 @@ Please, select face, shell or solid and try again</translation>
<source>GEOM_PLANAR_FACE</source>
<translation>Planar Face</translation>
</message>
<message>
<source>GEOM_PLANAR_EDGE_WIRE</source>
<translation>Wire with Planar Edges</translation>
</message>
<message>
<source>GEOM_POLYGON</source>
<translation>Polygon</translation>

View File

@ -397,6 +397,10 @@
<source>GEOM_FILLET_EDGES</source>
<translation>Cong sur Edges de la Shape</translation>
</message>
<message>
<source>GEOM_FILLET_WIRES</source>
<translation>Cong sur Wires de la Shape</translation>
</message>
<message>
<source>GEOM_FILLET_FACES</source>
<translation>Cong sur Faces de la Shape</translation>

View File

@ -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 );

View File

@ -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

View File

@ -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 <BRep_Tool.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <ElCLib.hxx>
#include <ElSLib.hxx>
#include <gp_Circ.hxx>
#include <Geom2d_Line.hxx>
#include <Geom2dAPI_ProjectPointOnCurve.hxx>
#include <Geom2dAPI_InterCurveCurve.hxx>
#include <GeomAPI_ProjectPointOnCurve.hxx>
#include <GeomProjLib.hxx>
#include <Geom_Circle.hxx>
#include <Precision.hxx>
#include <TColStd_ListIteratorOfListOfReal.hxx>
/**
* 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);
}

View File

@ -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 <gp_Pnt.hxx>
#include <Geom_Plane.hxx>
#include <Geom2d_Curve.hxx>
#include <TopoDS_Edge.hxx>
#include <TColStd_ListOfReal.hxx>
#include <TColStd_SequenceOfReal.hxx>
#include <TColStd_SequenceOfInteger.hxx>
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

View File

@ -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 <Standard_Stream.hxx>
#include <GEOMImpl_Fillet1dDriver.hxx>
#include <GEOMImpl_Fillet1d.hxx>
#include <GEOMImpl_IFillet1d.hxx>
#include <GEOMImpl_Types.hxx>
#include <GEOMImpl_ILocalOperations.hxx>
#include <GEOM_Function.hxx>
#include <gp_Pln.hxx>
#include <gp_Dir.hxx>
#include <gp_XYZ.hxx>
#include <BRep_Tool.hxx>
#include <BRepTools.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepCheck_Analyzer.hxx>
#include <Precision.hxx>
#include <ShapeFix_Wire.hxx>
#include <StdFail_NotDone.hxx>
#include <Standard_ConstructionError.hxx>
#include <TopAbs.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Wire.hxx>
#include <TopoDS_Shape.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopTools_DataMapOfShapeShape.hxx>
#include <TopTools_ListOfShape.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
//=======================================================================
//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 ;
}

View File

@ -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 <TColStd_SequenceOfExtendedString.hxx>
#endif
#ifndef _Standard_TypeMismatch_HeaderFile
#include <Standard_TypeMismatch.hxx>
#endif
#ifndef _Standard_HeaderFile
#include <Standard.hxx>
#endif
#ifndef _Standard_Macro_HeaderFile
#include <Standard_Macro.hxx>
#endif
#ifndef _Standard_HeaderFile
#include <Standard.hxx>
#endif
#ifndef _Standard_GUID_HeaderFile
#include <Standard_GUID.hxx>
#endif
#ifndef _Handle_TFunction_Driver_HeaderFile
#include <Handle_TFunction_Driver.hxx>
#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 <TFunction_Driver.hxx>
#endif
#ifndef _TFunction_Logbook_HeaderFile
#include <TFunction_Logbook.hxx>
#endif
#ifndef _Standard_CString_HeaderFile
#include <Standard_CString.hxx>
#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

View File

@ -62,6 +62,7 @@
#include <GEOMImpl_BooleanDriver.hxx>
#include <GEOMImpl_ChamferDriver.hxx>
#include <GEOMImpl_FilletDriver.hxx>
#include <GEOMImpl_Fillet1dDriver.hxx>
#include <GEOMImpl_Fillet2dDriver.hxx>
#include <GEOMImpl_TranslateDriver.hxx>
#include <GEOMImpl_RotateDriver.hxx>
@ -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());

View File

@ -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;
};

View File

@ -29,10 +29,12 @@
#include <GEOMImpl_Types.hxx>
#include <GEOMImpl_FilletDriver.hxx>
#include <GEOMImpl_Fillet1dDriver.hxx>
#include <GEOMImpl_Fillet2dDriver.hxx>
#include <GEOMImpl_ChamferDriver.hxx>
#include <GEOMImpl_IFillet.hxx>
#include <GEOMImpl_IFillet1d.hxx>
#include <GEOMImpl_IFillet2d.hxx>
#include <GEOMImpl_IChamfer.hxx>
@ -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<int> 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<int>::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

View File

@ -48,6 +48,8 @@ class GEOMImpl_ILocalOperations : public GEOM_IOperations {
std::list<int> theFaces);
Standard_EXPORT Handle(GEOM_Object) MakeFillet2D (Handle(GEOM_Object) theShape, double theR,
std::list<int> theVertexes);
Standard_EXPORT Handle(GEOM_Object) MakeFillet1D (Handle(GEOM_Object) theShape, double theR,
std::list<int> theVertexes);
Standard_EXPORT Handle(GEOM_Object) MakeChamferAll (Handle(GEOM_Object) theShape, double theD);
Standard_EXPORT Handle(GEOM_Object) MakeChamferEdge (Handle(GEOM_Object) theShape,

View File

@ -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

View File

@ -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 \

View File

@ -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<int> 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

View File

@ -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,

View File

@ -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<GEOM::ListOfLong>* aListImplV =
dynamic_cast<GEOM_List_i<GEOM::ListOfLong>*>(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:
//=============================================================================

View File

@ -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,

View File

@ -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.

View File

@ -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

View File

@ -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 ) );
}

View File

@ -19,11 +19,11 @@
//
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
// File : OperationGUI_Fillet2dDlg.cxx
// File : OperationGUI_Fillet1d2dDlg.cxx
// Author : DMV, OCN.
//
#include "OperationGUI_Fillet2dDlg.h"
#include "OperationGUI_Fillet1d2dDlg.h"
#include <DlgRef.h>
#include <GeometryGUI.h>
@ -45,30 +45,34 @@
#include <GEOMImpl_Types.hxx>
//=================================================================================
// class : OperationGUI_Fillet2dDlg()
// purpose : Constructs a OperationGUI_Fillet2dDlg which is a child of 'parent', with the
// 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_Fillet2dDlg::OperationGUI_Fillet2dDlg (GeometryGUI* theGeometryGUI, QWidget* parent)
: GEOMBase_Skeleton(theGeometryGUI, parent, false)
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", tr("ICON_DLG_FILLET_2D")));
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(tr("GEOM_FILLET_2D_TITLE"));
setWindowTitle(myIs1D ? tr("GEOM_FILLET_1D_TITLE") : tr("GEOM_FILLET_2D_TITLE"));
/***************************************************************/
mainFrame()->GroupConstructors->setTitle(tr("GEOM_FILLET_2D"));
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(tr("GEOM_FILLET_2D"));
GroupVertexes->TextLabel1->setText(tr("GEOM_PLANAR_FACE"));
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);
@ -86,7 +90,7 @@ OperationGUI_Fillet2dDlg::OperationGUI_Fillet2dDlg (GeometryGUI* theGeometryGUI,
double SpecificStep = 10.0;
initSpinBox(GroupVertexes->SpinBox_DX, 0.00001, COORD_MAX, SpecificStep, 5); // VSR: TODO: DBL_DIGITS_DISPLAY
setHelpFileName("fillet2d_operation_page.html");
setHelpFileName(myIs1D ? "fillet1d_operation_page.html" : "fillet2d_operation_page.html");
// Initialisation
Init();
@ -94,10 +98,10 @@ OperationGUI_Fillet2dDlg::OperationGUI_Fillet2dDlg (GeometryGUI* theGeometryGUI,
}
//=================================================================================
// function : ~OperationGUI_Fillet2dDlg()
// function : ~OperationGUI_Fillet1d2dDlg()
// purpose : Destroys the object and frees any allocated resources
//=================================================================================
OperationGUI_Fillet2dDlg::~OperationGUI_Fillet2dDlg()
OperationGUI_Fillet1d2dDlg::~OperationGUI_Fillet1d2dDlg()
{
}
@ -105,7 +109,7 @@ OperationGUI_Fillet2dDlg::~OperationGUI_Fillet2dDlg()
// function : Init()
// purpose :
//=================================================================================
void OperationGUI_Fillet2dDlg::Init()
void OperationGUI_Fillet1d2dDlg::Init()
{
// Set Initial values of spinboxes
GroupVertexes->SpinBox_DX->setValue(5);
@ -133,7 +137,7 @@ void OperationGUI_Fillet2dDlg::Init()
connect(GroupVertexes->SpinBox_DX, SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double)));
initName(tr("GEOM_FILLET_2D"));
initName(myIs1D ? tr("GEOM_FILLET_1D") : tr("GEOM_FILLET_2D"));
GroupVertexes->PushButton1->click();
}
@ -141,7 +145,7 @@ void OperationGUI_Fillet2dDlg::Init()
// function : ClickOnOk()
// purpose :
//=================================================================================
void OperationGUI_Fillet2dDlg::ClickOnOk()
void OperationGUI_Fillet1d2dDlg::ClickOnOk()
{
if (ClickOnApply())
ClickOnCancel();
@ -151,7 +155,7 @@ void OperationGUI_Fillet2dDlg::ClickOnOk()
// function : ClickOnApply()
// purpose :
//=================================================================================
bool OperationGUI_Fillet2dDlg::ClickOnApply()
bool OperationGUI_Fillet1d2dDlg::ClickOnApply()
{
if (!onAccept())
return false;
@ -171,7 +175,7 @@ bool OperationGUI_Fillet2dDlg::ClickOnApply()
// function : SelectionIntoArgument()
// purpose : Called when selection is changed or on dialog initialization or activation
//=================================================================================
void OperationGUI_Fillet2dDlg::SelectionIntoArgument()
void OperationGUI_Fillet1d2dDlg::SelectionIntoArgument()
{
erasePreview();
myEditCurrentArgument->setText("");
@ -196,7 +200,7 @@ void OperationGUI_Fillet2dDlg::SelectionIntoArgument()
aSelMgr->GetIndexes(aSelList.First(), aMap);
if ( aMap.Extent() == 1 ) { // Local Selection
int anIndex = aMap( 1 );
aName += QString( ":face_%1" ).arg( anIndex );
aName += QString( myIs1D ? ":wire_%1" : ":face_%1" ).arg( anIndex );
//Find SubShape Object in Father
GEOM::GEOM_Object_var aFindedObject = GEOMBase_Helper::findObjectInFather( anObj, aName );
@ -209,7 +213,7 @@ void OperationGUI_Fillet2dDlg::SelectionIntoArgument()
anObj = aFindedObject; // get Object from study
}
else { // Global Selection
if ( aShape.ShapeType() != TopAbs_FACE ) {
if ( aShape.ShapeType() != (myIs1D ? TopAbs_WIRE : TopAbs_FACE) ) {
anObj = GEOM::GEOM_Object::_nil();
aName = "";
}
@ -223,6 +227,7 @@ void OperationGUI_Fillet2dDlg::SelectionIntoArgument()
}
} else if (myEditCurrentArgument == GroupVertexes->LineEdit2) {
myVertexes.Clear();
bool isPreview = myIs1D;
if (aSelList.Extent() == 1) {
Standard_Boolean aResult = Standard_False;
GEOM::GEOM_Object_var anObj =
@ -241,12 +246,14 @@ void OperationGUI_Fillet2dDlg::SelectionIntoArgument()
else
aName = tr("GEOM_MEN_POPUP_NAME").arg(anIndexes.Extent());
isPreview = true;
myEditCurrentArgument->setText(aName);
myVertexes = anIndexes;
displayPreview();
}
}
}
if ( isPreview )
displayPreview();
}
if (myEditCurrentArgument == GroupVertexes->LineEdit1) {
@ -259,7 +266,7 @@ void OperationGUI_Fillet2dDlg::SelectionIntoArgument()
// function : SetEditCurrentArgument()
// purpose :
//=================================================================================
void OperationGUI_Fillet2dDlg::SetEditCurrentArgument()
void OperationGUI_Fillet1d2dDlg::SetEditCurrentArgument()
{
QPushButton* send = (QPushButton*)sender();
@ -290,7 +297,7 @@ void OperationGUI_Fillet2dDlg::SetEditCurrentArgument()
// function : LineEditReturnPressed()
// purpose :
//=================================================================================
void OperationGUI_Fillet2dDlg::LineEditReturnPressed()
void OperationGUI_Fillet1d2dDlg::LineEditReturnPressed()
{
QLineEdit* send = (QLineEdit*)sender();
@ -308,7 +315,7 @@ void OperationGUI_Fillet2dDlg::LineEditReturnPressed()
// function : ActivateThisDialog()
// purpose :
//=================================================================================
void OperationGUI_Fillet2dDlg::ActivateThisDialog()
void OperationGUI_Fillet1d2dDlg::ActivateThisDialog()
{
GEOMBase_Skeleton::ActivateThisDialog();
}
@ -317,7 +324,7 @@ void OperationGUI_Fillet2dDlg::ActivateThisDialog()
// function : enterEvent()
// purpose :
//=================================================================================
void OperationGUI_Fillet2dDlg::enterEvent (QEvent*)
void OperationGUI_Fillet1d2dDlg::enterEvent (QEvent*)
{
if (!mainFrame()->GroupConstructors->isEnabled())
this->ActivateThisDialog();
@ -327,7 +334,7 @@ void OperationGUI_Fillet2dDlg::enterEvent (QEvent*)
// function : ValueChangedInSpinBox()
// purpose :
//=================================================================================
void OperationGUI_Fillet2dDlg::ValueChangedInSpinBox (double)
void OperationGUI_Fillet1d2dDlg::ValueChangedInSpinBox (double)
{
displayPreview();
}
@ -336,12 +343,13 @@ void OperationGUI_Fillet2dDlg::ValueChangedInSpinBox (double)
// function : activateSelection
// purpose : Activate selection in accordance with myEditCurrentArgument
//=================================================================================
void OperationGUI_Fillet2dDlg::activateSelection()
void OperationGUI_Fillet1d2dDlg::activateSelection()
{
disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0);
globalSelection();
if (myEditCurrentArgument == GroupVertexes->LineEdit1)
globalSelection( GEOM_FACE ); // localSelection(myShape, TopAbs_FACE);
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);
@ -353,7 +361,7 @@ void OperationGUI_Fillet2dDlg::activateSelection()
// function : createOperation
// purpose :
//=================================================================================
GEOM::GEOM_IOperations_ptr OperationGUI_Fillet2dDlg::createOperation()
GEOM::GEOM_IOperations_ptr OperationGUI_Fillet1d2dDlg::createOperation()
{
return getGeomEngine()->GetILocalOperations(getStudyId());
}
@ -362,16 +370,16 @@ GEOM::GEOM_IOperations_ptr OperationGUI_Fillet2dDlg::createOperation()
// function : isValid()
// purpose : Verify validity of input data
//=================================================================================
bool OperationGUI_Fillet2dDlg::isValid (QString&)
bool OperationGUI_Fillet1d2dDlg::isValid (QString&)
{
return !myShape->_is_nil() && myVertexes.Extent() > 0;
return !myShape->_is_nil() && (myIs1D || myVertexes.Extent() > 0);
}
//=================================================================================
// function : execute
// purpose :
//=================================================================================
bool OperationGUI_Fillet2dDlg::execute (ObjectList& objects)
bool OperationGUI_Fillet1d2dDlg::execute (ObjectList& objects)
{
GEOM::GEOM_Object_var anObj;
@ -381,8 +389,10 @@ bool OperationGUI_Fillet2dDlg::execute (ObjectList& objects)
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);
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());
@ -394,7 +404,7 @@ bool OperationGUI_Fillet2dDlg::execute (ObjectList& objects)
// function : getRadius
// purpose : Get radius
//=================================================================================
double OperationGUI_Fillet2dDlg::getRadius() const
double OperationGUI_Fillet1d2dDlg::getRadius() const
{
return GroupVertexes ->SpinBox_DX->value();
}

View File

@ -19,12 +19,12 @@
//
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
// File : OperationGUI_Fillet2dDlg.h
// File : OperationGUI_Fillet1d2dDlg.h
// Author : DMV, OCN
//
#ifndef OPERATIONGUI_FILLET2DDLG_H
#define OPERATIONGUI_FILLET2DDLG_H
#ifndef OPERATIONGUI_Fillet1d2dDLG_H
#define OPERATIONGUI_Fillet1d2dDLG_H
#include <GEOMBase_Skeleton.h>
@ -33,16 +33,16 @@
class DlgRef_2Sel1Spin;
//=================================================================================
// class : OperationGUI_Fillet2dDlg
// class : OperationGUI_Fillet1d2dDlg
// purpose :
//=================================================================================
class OperationGUI_Fillet2dDlg : public GEOMBase_Skeleton
class OperationGUI_Fillet1d2dDlg : public GEOMBase_Skeleton
{
Q_OBJECT
public:
OperationGUI_Fillet2dDlg( GeometryGUI*, QWidget* );
~OperationGUI_Fillet2dDlg();
OperationGUI_Fillet1d2dDlg( GeometryGUI*, QWidget*, bool theIs1D );
~OperationGUI_Fillet1d2dDlg();
protected:
// redefined from GEOMBase_Helper
@ -66,10 +66,11 @@ private:
double getRadius() const;
private:
bool myIs1D;
GEOM::GEOM_Object_var myShape;
TColStd_IndexedMapOfInteger myVertexes;
DlgRef_2Sel1Spin* GroupVertexes;
};
#endif // OPERATIONGUI_FILLET2DDLG_H
#endif // OPERATIONGUI_Fillet1d2dDLG_H