Open CASCADE学习|按圆离散旋转体

旋转体是一个非常重要的概念,它涉及到三维空间中由二维曲线绕某一轴线旋转形成的立体形状。这种旋转体的形成过程,实际上是一个连续变化的动态过程,但在数学和几何学中,我们往往通过静态的方式来描述和研究它。

旋转体的基本特性包括其形状、大小、表面积和体积等。这些特性不仅取决于原始二维曲线的形状和大小,还受到旋转轴线位置和方向的影响。例如,一个圆绕其直径旋转会形成球体,而绕其切线旋转则会形成圆柱体。

将旋转体离散为一系列的圆(通常称为"截圆"或"横截面")是一种常用的近似方法,用于在数值计算、计算机图形学以及物理模拟中描述和分析旋转体的性质。这种方法的基本思想是将连续的旋转体划分为一系列离散的、平行的截面,每个截面都是一个圆。

需要注意的是,离散化的精度取决于截面间距的选择。较小的间距可以提高精度,但也会增加计算复杂性和存储需求。因此,在实际应用中,需要根据具体需求和资源限制来选择合适的离散化方案。

cpp 复制代码
#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;
}
相关推荐
@小匠1 小时前
Read Frog:一款开源的 AI 驱动浏览器语言学习扩展
人工智能·学习
W23035765734 小时前
经典算法:最长上升子序列(LIS)深度解析 C++ 实现
开发语言·c++·算法
.Ashy.4 小时前
2026.4.11 蓝桥杯软件类C/C++ G组山东省赛 小记
c语言·c++·蓝桥杯
minji...5 小时前
Linux 线程同步与互斥(三) 生产者消费者模型,基于阻塞队列的生产者消费者模型的代码实现
linux·运维·服务器·开发语言·网络·c++·算法
CoderCodingNo7 小时前
【GESP】C++三级真题 luogu-B4499, [GESP202603 三级] 二进制回文串
数据结构·c++·算法
炽烈小老头8 小时前
【 每天学习一点算法 2026/04/12】x 的平方根
学习·算法
阿杰学AI8 小时前
AI核心知识115—大语言模型之 自监督学习(简洁且通俗易懂版)
人工智能·学习·ai·语言模型·aigc·监督学习·自监督学习
hetao17338379 小时前
2026-04-09~12 hetao1733837 的刷题记录
c++·算法
九英里路9 小时前
OS学习之路——动静态库制作与原理
linux·学习·操作系统·unix·进程·编译·动静态库
6Hzlia9 小时前
【Hot 100 刷题计划】 LeetCode 136. 只出现一次的数字 | C++ 哈希表&异或基础解法
c++·算法·leetcode