旋转体是一个非常重要的概念,它涉及到三维空间中由二维曲线绕某一轴线旋转形成的立体形状。这种旋转体的形成过程,实际上是一个连续变化的动态过程,但在数学和几何学中,我们往往通过静态的方式来描述和研究它。
旋转体的基本特性包括其形状、大小、表面积和体积等。这些特性不仅取决于原始二维曲线的形状和大小,还受到旋转轴线位置和方向的影响。例如,一个圆绕其直径旋转会形成球体,而绕其切线旋转则会形成圆柱体。
将旋转体离散为一系列的圆(通常称为“截圆”或“横截面”)是一种常用的近似方法,用于在数值计算、计算机图形学以及物理模拟中描述和分析旋转体的性质。这种方法的基本思想是将连续的旋转体划分为一系列离散的、平行的截面,每个截面都是一个圆。
需要注意的是,离散化的精度取决于截面间距的选择。较小的间距可以提高精度,但也会增加计算复杂性和存储需求。因此,在实际应用中,需要根据具体需求和资源限制来选择合适的离散化方案。
#include <Geom_CylindricalSurface.hxx>
#include <gp_Ax3.hxx>
#include <GeomAPI_Interpolate.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <GCE2d_MakeSegment.hxx>
#include <GeomAPI_PointsToBSpline.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <GC_MakeCircle.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepOffsetAPI_MakePipe.hxx>
#include <GC_MakeArcOfCircle.hxx>
#include <BRepAlgoAPI_Fuse.hxx>
#include <gp_GTrsf.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#include"Viewer.h"
#include <BRepPrimAPI_MakeCylinder.hxx>
#include <BRepBuilderAPI_MakePolygon.hxx>
#include <BRep_Tool.hxx>
#include <TopoDS.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <BRepAlgoAPI_Common.hxx>
#include <BRepAlgoAPI_Section.hxx>
#include <BRepPrimAPI_MakePrism.hxx>
#include <GC_MakeSegment.hxx>
#include <IntAna2d_AnaIntersection.hxx>
#include <ShapeUpgrade_UnifySameDomain.hxx>
#include <BRepTools_WireExplorer.hxx>
#include <GeomFill_TrihedronLaw.hxx>
#include <GeomFill_Frenet.hxx>
#include <GeomFill_CurveAndTrihedron.hxx>
#include <BRepFill_Edge3DLaw.hxx>
#include <BRepFill_SectionPlacement.hxx>
#include <ShapeUpgrade_RemoveLocations.hxx>
#include <BRepPrimAPI_MakeSphere.hxx>
#include <BRepPrimAPI_MakeRevol.hxx>
#include <BRepAdaptor_CompCurve.hxx>
#include <TopExp_Explorer.hxx>
#include <NCollection_Sequence.hxx>
TopoDS_Edge axis;
NCollection_Sequence<TopoDS_Edge> SplitShapebyaxis(TopoDS_Shape input, TopoDS_Edge cutaxis)
{
Standard_Real startParam(0.), endParam(0.);
Handle(Geom_Curve) c = BRep_Tool::Curve(cutaxis, startParam, endParam);//得到底层曲线
Standard_Real step = (endParam - startParam) / 100;
TColgp_HArray1OfPnt Points(1, 101);
for (int i = 0; i < 101; i++)
{
Points[i + 1] = c->Value(startParam + i * step);
}
gp_Vec dir(Points[1], Points[101]);
NCollection_Sequence<TopoDS_Edge> edgeall;
for (int i = 2; i < 100; i++)
{
gp_Pln cutplane(Points[i], dir);
TopoDS_Face cf = BRepBuilderAPI_MakeFace(cutplane);
// 进行布尔运算
BRepAlgoAPI_Section section(input, cf, Standard_False);
section.ComputePCurveOn1(Standard_True);
section.Approximation(Standard_False);
section.Build();
TopExp_Explorer anExp(section.Shape(), TopAbs_EDGE);
int j = 0;
for (; anExp.More(); anExp.Next())
{
TopoDS_Edge anEdge = TopoDS::Edge(anExp.Current());
edgeall.Append(anEdge);
j++;
}
//std::cout << "j=" << j << std::endl;
}
return edgeall;
}
TopoDS_Edge createHelix(const Standard_Real HelixRadius, const Standard_Real HelixAngle, const Standard_Real HelixLength)
{
Standard_Real u0 = 0.0;
Standard_Real u1 = 2 * M_PI;
Standard_Real v0 = 0.0;
Standard_Real v1 = HelixLength;
double uInter = (u1 - u0) / 1000;
double vInter = (v1 - v0) / 1000;
TColgp_HArray1OfPnt Points(1, 1001);
Handle(Geom_CylindricalSurface) aCylinder = new Geom_CylindricalSurface(gp::XOY(), HelixRadius);
double u;
double v;
//生成点
for (int i = 0; i < 1001; i++) {
u = i * vInter * tan(HelixAngle) / HelixRadius;
v = i * vInter;
Points[i + 1] = aCylinder->Value(u, v);
}
GeomAPI_PointsToBSpline Approx(Points);
Handle_Geom_BSplineCurve K = Approx.Curve();
TopoDS_Edge aHelixEdge = BRepBuilderAPI_MakeEdge(K);
return aHelixEdge;
}
TopoDS_Shape createGrindingwheel2()
{
Standard_Real Line1_angle = 280 * M_PI / 180;
Standard_Real Line1_length = 0.5031;
Standard_Real Line2_angle = 236 * M_PI / 180;
Standard_Real Line2_length = 0.5925;
Standard_Real Arc1_r = 0.112;
Standard_Real Arc1_angle = (180 + 10 + 50) * M_PI / 180;
gp_Pnt Line1_p1(-0.6822 / 2, 0, 0);
gp_Pnt Line2_p1(0.6822 / 2, 0, 0);
gp_Lin Line1(Line1_p1, gp_Dir(cos(Line1_angle), sin(Line1_angle), 0.));
gp_Lin Line2(Line2_p1, gp_Dir(cos(Line2_angle), sin(Line2_angle), 0.));
Handle(Geom_TrimmedCurve) L1 = GC_MakeSegment(Line1, 0., Line1_length);
TopoDS_Edge L1e = BRepBuilderAPI_MakeEdge(L1);
Handle(Geom_TrimmedCurve) L2 = GC_MakeSegment(Line2, 0., Line2_length);
TopoDS_Edge L2e = BRepBuilderAPI_MakeEdge(L2);
gp_Pnt l1end = L1->EndPoint();
gp_Pnt l2end = L2->EndPoint();
gp_Lin Line1v(l1end, gp_Dir(cos(Line1_angle + M_PI_2), sin(Line1_angle + M_PI_2), 0.));
gp_Lin2d Line2v(gp_Pnt2d(l2end.X(), l2end.Y()), gp_Dir2d(cos(Line2_angle - M_PI_2), sin(Line2_angle - M_PI_2)));
gp_Lin Line2v3d(l2end, gp_Dir(cos(Line2_angle - M_PI_2), sin(Line2_angle - M_PI_2), 0.));
Handle(Geom_TrimmedCurve) L1v = GC_MakeSegment(Line1v, 0., Arc1_r);
gp_Pnt l1vend = L1v->EndPoint();
gp_Circ c1(gp_Ax2(l1vend, gp_Dir(0, 0, 1)), Arc1_r);
Handle(Geom_TrimmedCurve) c1c = GC_MakeArcOfCircle(c1, l1end, Arc1_angle, 1);
gp_Pnt c1end = c1c->EndPoint();
gp_Lin2d Line3(gp_Pnt2d(c1end.X(), c1end.Y()), gp_Dir2d(l2end.X() - c1end.X(), l2end.Y() - c1end.Y()));
gp_Lin2d Line3v = Line3.Normal(gp_Pnt2d((l2end.X() + c1end.X()) / 2, (l2end.Y() + c1end.Y()) / 2));
IntAna2d_AnaIntersection aIntAna;
aIntAna.Perform(Line2v, Line3v);
IntAna2d_IntPoint aIntPoint = aIntAna.Point(1);
gp_Pnt o2(aIntPoint.Value().X(), aIntPoint.Value().Y(), 0.);
Handle(Geom_TrimmedCurve) L2v = GC_MakeSegment(Line2v3d, l2end, o2);
Standard_Real r2 = L2v->LastParameter();
gp_Circ c2(gp_Ax2(o2, gp_Dir(0, 0, 1)), r2);
Handle(Geom_TrimmedCurve) c2c = GC_MakeArcOfCircle(c2, c1end, l2end, 0);
gp_Pnt c2low = c2c->Value(M_PI_2);
TopoDS_Edge c1ce = BRepBuilderAPI_MakeEdge(c1c);
TopoDS_Edge L1ev = BRepBuilderAPI_MakeEdge(L1v);
TopoDS_Edge c2ce = BRepBuilderAPI_MakeEdge(c2c);
gp_Pnt Line1_up(-0.9832 / 2, 5, 0);
gp_Pnt Line2_up(0.9832 / 2, 5, 0);
TopoDS_Edge anEdge1 = BRepBuilderAPI_MakeEdge(Line1_p1, Line1_up);
TopoDS_Edge anEdge2 = BRepBuilderAPI_MakeEdge(Line1_up, Line2_up);
TopoDS_Edge anEdge3 = BRepBuilderAPI_MakeEdge(Line2_up, Line2_p1);
TopTools_ListOfShape listEdge;
listEdge.Append(anEdge1);
listEdge.Append(anEdge2);
listEdge.Append(anEdge3);
listEdge.Append(L1e);
listEdge.Append(c1ce);
listEdge.Append(c2ce);
listEdge.Append(L2e);
BRepBuilderAPI_MakeWire mw;
mw.Add(listEdge);
mw.Build();
TopoDS_Edge tmpAxis = BRepBuilderAPI_MakeEdge(gp_Pnt(-0.9832 / 2, 5, 0), gp_Pnt(0.9832 / 2, 5, 0));
TopoDS_Shape gwheel = BRepPrimAPI_MakeRevol(mw, gp_Ax1(gp_Pnt(0, 5, 0), gp_Dir(1, 0, 0)), 2 * M_PI);
//平移到最低点与原点重合
gp_Trsf theTransformation1;
gp_Vec theVectorOfTranslation1(-c2low.X(), -c2low.Y(), 0.);
theTransformation1.SetTranslation(theVectorOfTranslation1);
//往上平移芯厚一半的距离
gp_Trsf theTransformation2;
gp_Vec theVectorOfTranslation2(0., 0.125 / 2, 0.);
theTransformation2.SetTranslation(theVectorOfTranslation2);
//顺时针旋转90°,绕z轴
gp_Trsf theTransformation3;
gp_Ax1 axez = gp_Ax1(gp_Pnt(0, 0, 0), gp_Dir(0., 0., 1.));
theTransformation3.SetRotation(axez, -90 * M_PI / 180);
//顺时针旋转50°,绕x轴
gp_Trsf theTransformation4;
gp_Ax1 axex = gp_Ax1(gp_Pnt(0, 0, 0), gp_Dir(1., 0., 0.));
theTransformation4.SetRotation(axex, -50 * M_PI / 180);
//实施以上变换:对旋转体、对轴线
BRepBuilderAPI_Transform myBRepTransformation(gwheel, theTransformation4 * theTransformation3 * theTransformation2* theTransformation1);
TopoDS_Shape TransformedShape = myBRepTransformation.Shape();
BRepBuilderAPI_Transform myBRepTransformation2(tmpAxis, theTransformation4 * theTransformation3 * theTransformation2 * theTransformation1);
TopoDS_Shape initAxis = myBRepTransformation2.Shape();
axis = TopoDS::Edge(initAxis);
return TransformedShape;
}
TopoDS_Shape getShapeOnPosition(TopoDS_Shape myProfile, Handle(BRepFill_LocationLaw) myLoc, Standard_Real pos, Standard_Real a, Standard_Real b, gp_Trsf myTrsf)
{
TopoDS_Shape myPos;
Handle(GeomFill_LocationLaw) law;
gp_Mat M;
gp_Vec V;
gp_Trsf fila;
Standard_Real first, last;
myLoc->Law(1)->GetDomain(first, last);
Standard_Real px = (pos - a) / (b - a);
myLoc->Law(1)->D0(px, M, V);
fila.SetValues(M(1, 1), M(1, 2), M(1, 3), V.X(),
M(2, 1), M(2, 2), M(2, 3), V.Y(),
M(3, 1), M(3, 2), M(3, 3), V.Z());
fila.Multiply(myTrsf);
myPos = myProfile;
TopLoc_Location LocPos(fila);
if (!LocPos.IsIdentity()) {
myPos = BRepBuilderAPI_Transform(myProfile, fila, Standard_True); //copy
}
ShapeUpgrade_RemoveLocations RemLoc;
RemLoc.SetRemoveLevel(TopAbs_COMPOUND);
RemLoc.Remove(myPos);
myPos = RemLoc.GetResult();
return myPos;
}
int main(int argc, char* argv[])
{
gp_Dir Z(0.0, 0.0, 1.0);
gp_Pnt center(0, 0, 0.0);
gp_Pnt xr(0.5, 0, 0.0);
gp_Pnt yr(0.0, 1.0, 0.0);
gp_Pnt zr(0.0, 0.0, 7.0);
gp_Ax2 wb(center, Z);
gp_Circ wbcircle(wb, 0.125 / 2);
TopoDS_Edge wbe = BRepBuilderAPI_MakeEdge(wbcircle);
TopoDS_Edge xline = BRepBuilderAPI_MakeEdge(center, xr);
TopoDS_Edge yline = BRepBuilderAPI_MakeEdge(center, yr);
TopoDS_Edge zline = BRepBuilderAPI_MakeEdge(center, zr);
//creat a profile of gringing wheel
TopoDS_Shape gw = createGrindingwheel2();
//creat a cylinder surface
Standard_Real R = 0.306 / 2;
Handle(Geom_CylindricalSurface) aCylinder = new Geom_CylindricalSurface(gp::XOY(), R);
TopoDS_Shape cF = BRepBuilderAPI_MakeFace(aCylinder->Cylinder(), 0, 2 * M_PI, 0, 3.);
TopoDS_Solid cys = BRepPrimAPI_MakeCylinder(gp::XOY(), R, 7);
TopoDS_Edge aE = createHelix(R, M_PI / 4, 6.);
TopoDS_Wire spine = BRepBuilderAPI_MakeWire(aE);
TopoDS_Wire mySpine;
TopoDS_Shape myProfile;
TopoDS_Shape myShape;
gp_Trsf myTrsf;
Handle(BRepFill_LocationLaw) myLoc;
Handle(TopTools_HArray2OfShape) mySections;
Handle(TopTools_HArray2OfShape) myFaces;
Handle(TopTools_HArray2OfShape) myEdges;
TopTools_MapOfShape myReversedEdges;
BRepFill_DataMapOfShapeHArray2OfShape myTapes;
BRepFill_DataMapOfShapeHArray2OfShape myRails;
Standard_Integer myCurIndexOfSectionEdge;
TopoDS_Shape myFirst;
TopoDS_Shape myLast;
TopTools_DataMapOfShapeListOfShape myGenMap;
Standard_Integer myDegmax;
Standard_Integer mySegmax;
GeomAbs_Shape myContinuity;
GeomFill_Trihedron myMode;
Standard_Boolean myForceApproxC1;
Standard_Real myErrorOnSurf;
mySections.Nullify();
myFaces.Nullify();
myEdges.Nullify();
mySpine = spine;
myProfile = gw;
//myProfile = BRepPrimAPI_MakeSphere(gp_Pnt(0.306/2, 0., 0.),0.306/2);
TopoDS_Shape TheProf;
Handle(GeomFill_TrihedronLaw) TLaw;
TLaw = new GeomFill_Frenet();
Handle(GeomFill_CurveAndTrihedron) Loc = new (GeomFill_CurveAndTrihedron) (TLaw);
myLoc = new (BRepFill_Edge3DLaw) (mySpine, Loc);
if (myLoc->NbLaw() == 0) {
return 0; // Degenerated case
}
myLoc->TransformInG0Law(); // Set into continuity
BRepFill_SectionPlacement Place(myLoc, gw);
myTrsf = Place.Transformation();
TopLoc_Location Loc2(myTrsf), Loc1;
Loc1 = gw.Location();
TopoDS_Shape aux;
TheProf = myProfile;
TheProf.Location(Loc2.Multiplied(Loc1));
// Construct First && Last Shape
Handle(GeomFill_LocationLaw) law;
gp_Mat M;
gp_Vec V;
gp_Trsf fila;
Standard_Real first, last;
myLoc->Law(1)->GetDomain(first, last);
myLoc->Law(1)->D0(first, M, V);
fila.SetValues(M(1, 1), M(1, 2), M(1, 3), V.X(),
M(2, 1), M(2, 2), M(2, 3), V.Y(),
M(3, 1), M(3, 2), M(3, 3), V.Z());
fila.Multiply(myTrsf);
TopLoc_Location LocFirst(fila);
myFirst = myProfile;
if (!LocFirst.IsIdentity()) {
//myFirst.Location( LocFirst.Multiplied(myProfile.Location()) );
myFirst = BRepBuilderAPI_Transform(myProfile, fila, Standard_True); //copy
}
ShapeUpgrade_RemoveLocations RemLoc;
RemLoc.SetRemoveLevel(TopAbs_COMPOUND);
RemLoc.Remove(myFirst);
myFirst = RemLoc.GetResult();
myLoc->Law(myLoc->NbLaw())->GetDomain(first, last);
myLoc->Law(myLoc->NbLaw())->D0(last, M, V);
// try { // Not good, but there are no other means to test SetValues
fila.SetValues(M(1, 1), M(1, 2), M(1, 3), V.X(),
M(2, 1), M(2, 2), M(2, 3), V.Y(),
M(3, 1), M(3, 2), M(3, 3), V.Z());
fila.Multiply(myTrsf);
TopLoc_Location LocLast(fila);
if (!myLoc->IsClosed() || LocFirst != LocLast) {
myLast = myProfile;
if (!LocLast.IsIdentity()) {
//myLast.Location(LocLast.Multiplied(myProfile.Location()) );
myLast = BRepBuilderAPI_Transform(myProfile, fila, Standard_True); //copy
}
}
else {
myLast = myFirst;
}
RemLoc.Remove(myLast);
myLast = RemLoc.GetResult();
NCollection_Sequence<TopoDS_Edge> es=SplitShapebyaxis(gw, axis);
Viewer vout(50, 50, 500, 500);
vout << wbe;
vout << xline;
vout << yline;
vout << zline;
vout << gw;
vout << axis;
// 遍历点集合
for (int i = 1; i <= es.Length(); ++i) {
vout << es.Value(i);
}
vout.StartMessageLoop();
return 0;
}