Topology and Geometry in OpenCascade-Vertex

本文简要介绍了 OpenCascade 中几何造型中的边界表示法 (BRep),结合程序说明了 BRep 中顶点、边、面的具体实现。重点阐述了顶点的数据结构、容差、朝向等属性,并提供了从底层创建顶点的示例代码。同时,分析了 BRep 文件中顶点的数据表示方式,以及如何通过 BRep_Tool 访问顶点的几何信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Topology and Geometry in OpenCascade-Vertex

eryar@163.com

摘要Abstract:本文简要介绍了几何造型中的边界表示法(BRep),并结合程序说明OpenCascade中的边界表示的具体实现,即拓朴与几何的联系。对具有几何信息的拓朴结构顶点(vertex)、边(edge)、面(face)进行了详细说明。本文只对顶点数据进行说明。 

关键字Key Words:OpenCascade、BRep、Topology、Geometry 

一、引言 Introduction

边界表示(Boundary Representation)也称为BRep表示,它是几何造型中最成熟、无二义的表示法。实体的边界通常是由面的并集来表示,而每个面又由它所在的曲面的定义加上其边界来表示,面的边界是边的并集,而边又是由点来表示的。 

边界表示的一个重要特征是描述形体的信息包括几何信息(Geometry)和拓朴信息(Topology)两个方面。拓朴信息描述形体上的顶点、边、面的连接关系,它形成物体边界表示的“骨架”。形体的几何信息犹如附着在“骨架”上的肌肉。例如,形体的某个面位于某一个曲面上,定义这一曲面方程的数据就是几何信息。此外,边的形状、顶点在三维空间中的位置(点的坐标)等都是几何信息,一般来说,几何信息描述形体的大小、尺寸、位置和形状等。 

在边界表示法中,边界表示就按照体-面-环-边-点的层次,详细记录构成形体的所有几何元素的几何信息及其相互连接的拓朴关系。这样,在进行各种运算和操作中,就可以直接取得这些信息。 

下图所示为由一条边连接的两个面组成的壳(shell): 

wps_clip_image-13951

Figure 1.1 Structure of a shell formed from two faces 

上图所示的形状表示为TS, 面TF1和TF2,有七条边TE1~TE7和六个顶点TV1~TV6。 

环TW1引用边TE1~TE4;环TW2引用TE4~TE7 。边引用的顶点如下:TE1(TV1,TV4),TE2(TV1,TV2),TE3(TV2,TV3),TE4(TV3,TV4),TE5(TV4,TV5),TE6(TV5,TV6),TE7(TV3,TV6)。 

wps_clip_image-26435

Figure 1.2 Data structure of the shell formed from two faces connected at an edge 

注:OpenCascade中的这个数据结构中不包含“回溯引用(back references)”,即所有的引用只从复杂形状到简单形状。(Note that this data structure does not contain any “back references”. All references go from more comples underlying shapes to less complex ones.)有点有向图的意思。 

二、OpenCascade中的边界表示 BRep in OpenCascade

2.1 拓朴结构 TopoDS_Shape data structure

OpenCascade中的拓朴(topology)是根据STEP标准ISO-10303-42设计的。也许读一下这个标准中的有关概念还是很有帮助的。STEP ISO-10303-42的相关资源: 

http://www.steptools.com/support/stdev_docs/express/step_irs/index.html

wps_clip_image-23948

Figure 2.1 Topology data structure in OpenCascade 

wps_clip_image-14563

TopoDS_Shape由值控制,包含三个成员变量:myLocation、myOrient、myTShape。 

wps_clip_image-9340

Figure 2.2 TopoDS_Shape member fields 

2.2 拓朴与几何的联系 Connection with Geometry

现在我们来考虑一下拓朴结构与几何的关系。通过继承TopoDS包中的抽象的拓朴类实现了边界表示模型。如下图所示: 

wps_clip_image-67

Figure 2.3 Topology data structure in OpenCascade 

从上面的类图可以看出只有三种拓朴对象有几何表示数据:顶点(vertex)、边(edge)、面(face),分别为BRep_TVertex、BRep_TEdge、BRep_TFace。 

wps_clip_image-2791

Figure 2.4 TopoDS_TShape class diagram 

三、顶点 Vertex

顶点(vertex)的位置用几何点(gp_Pnt)来表示。点是几何造型中的最基本元素,自由曲线、曲面或其他形体均可用有序的点集表示。用计算机存储、管理、输出形体的实质就是对点集及其连接关系的处理。在正则形体定义中,不允许孤立点存在。 

顶点的另一个重要属性是容差(Tolerance),用来表示位置精度。顶点容差T的几何意义为以顶点为圆心半径为T的球。这个球必须包含所有与这个顶点相连的边的曲线的端点。 

wps_clip_image-25604

Figure 3.1 Vertex Tolerance 

与其他几何库有全局精度(global precision)不同,OpenCascade把容差作为局部属性(local properties)。由图2.4可知,容差是顶点、边、面的属性。这种方法有助于用更一般的方式来描述高精度的模型。如下图所示: 

wps_clip_image-13508

Figure 3.2 Vertex with different tolerance 

如果从底层来创建形状,最好的方法就是指定最小的允许误差。默认值Precision::Confusion()为1e-07。 

下面讨论顶点的朝向(orientation)属性。它没有直接的几何意义,但是根据约定,若顶点的朝向属性值为TopAbs_FORWARD,它就必须与表示边的曲线的参数值小的端部匹配。相应地,TopAbs_REVERSED的顶点与参数值大的端部匹配。例如,有条边位于圆弧上,圆弧半径为1且在Z=0的平面上,起点为(1,0,0),向-Z轴向,曲线为逆时针方向。所以顶点(1,0,0)的朝向为TopAbs_FORWARD,顶点(0,1,0)的朝向为TopAbs_REVERSED。如下图所示: 

wps_clip_image-6315

Figure 3.3 Vertex Orientation attribute 

实现上图所示的程序代码如下所示: 

/*
*    Copyright (c) 2013 eryar All Rights Reserved.
*
*        File    : Main.cpp
*        Author  : eryar@163.com
*        Date    : 2013-08-17 21:46
*        Version : 1.0v
*
*    Description : Demonstrate how to build a edge bottom-up by BRepBuilderAPI_MakeEdge,
*                  and how to access vertex infomation by BRep_Tool.
*                  
*/

// OpenCascade library.
#define WNT
#include <gp_Circ.hxx>
#include <GC_MakeArcOfCircle.hxx>

#include <TopoDS_Edge.hxx>
#include <BRep_Tool.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeVertex.hxx>

#pragma comment(lib, "TKernel.lib")
#pragma comment(lib, "TKMath.lib")
#pragma comment(lib, "TKBRep.lib")
#pragma comment(lib, "TKGeomBase.lib")
#pragma comment(lib, "TKTopAlgo.lib")

/**
* @breif Dump orientation types.
*        Orientation definitaion:
*        enum TopAbs_Orientation {
*            TopAbs_FORWARD,
*            TopAbs_REVERSED,
*            TopAbs_INTERNAL,
*            TopAbs_EXTERNAL
*        };
*/
std::string DumpOrientation(const TopAbs_Orientation& orient)
{
    std::string strType;

    switch (orient)
    {
    case TopAbs_FORWARD:
        strType = "TopAbs_FORWARD";
        break;

    case TopAbs_REVERSED:
        strType = "TopAbs_REVERSED";
        break;

    case TopAbs_INTERNAL:
        strType = "TopAbs_INTERNAL";
        break;

    case TopAbs_EXTERNAL:
        strType = "TopAbs_EXTERNAL";
        break;
    }

    return strType;
}

/**
* @breif Dump attributes of the vertex.
*/
void DumpVertex(const TopoDS_Vertex& v)
{
    gp_Pnt p = BRep_Tool::Pnt(v);
    Standard_Real dTolerance = BRep_Tool::Tolerance(v);

    std::cout<<"Vertex position: ("<<p.X()<<", "<<p.Y()<<", "<<p.Z()<<")"<<std::endl;
    std::cout<<"Vertex Tolerance: "<<dTolerance<<std::endl;
    std::cout<<"Vertex orientation: "<<DumpOrientation(v.Orientation())<<std::endl;
    std::cout<<std::endl;
}

int main(int argc, char* argv[])
{
    gp_Circ circle;
    TopoDS_Edge edge;
    TopoDS_Vertex vertex1;
    TopoDS_Vertex vertex2;
    BRepBuilderAPI_MakeEdge edgeBuilder;

    circle.SetRadius(1.0);
    circle.SetAxis(gp::OZ());

    edgeBuilder.Init(GC_MakeArcOfCircle(circle, 0.0, M_PI/2.0, Standard_True));

    // Test single vertex.
    /*vertex1 = BRepBuilderAPI_MakeVertex(gp_Pnt(100.0, 200.0, 300.0));
    vertex2 = BRepBuilderAPI_MakeVertex(gp_Pnt(500.0, 600.0, 700.0));

    std::cout<<"Single vetex test: "<<std::endl;

    std::cout<<"Vertex 1 attributes: "<<std::endl;
    DumpVertex(vertex1);

    std::cout<<"Vertex 2 attributes: "<<std::endl;
    DumpVertex(vertex2);*/

    edge = edgeBuilder.Edge();
    vertex1 = edgeBuilder.Vertex1();
    vertex2 = edgeBuilder.Vertex2();

    std::cout<<"Test vertex belong to edge:"<<std::endl;

    std::cout<<"Vertex 1 attributes: "<<std::endl;
    DumpVertex(vertex1);

    std::cout<<"Vertex 2 attributes: "<<std::endl;
    DumpVertex(vertex2);

    return 0;
}

程序运行结果如下图所示: 

wps_clip_image-27439

Figure 3.4 Code example result 

BRep_Builder是从底层创建拓朴结构的类。如下代码所示为从底层创建顶点的示例:

gp_Pnt aPoint(100.0, 200.0, 300.0)
BRep_Builder aBuilder;
TopoDS_Vertex aVertex;

aBuilder.MakeVertex(aVertex, aPoint, Precision::Confusion());
aVertex.Orientation(TopAbs_REVERSED);

有一个方便的类也可用来创建顶点BRepBuilderAPI_MakeVertex,其内部也是使用了类BRep_Builder。所以,若想从底层创建拓朴结构,必须要熟悉BRep_Builder。 

BRep_Tool是用来访问拓朴结构中几何信息的工具,他的大部分的函数是静态的。如下代码所示为获取顶点的容差和几何点的方法:

Standard_Real aTolerance = BRep_Tool::Tolerance(aVertex);
gp_Pnt aPoint = BRep_Tool::Pnt(aVertex);

 

四、BRep文件中Vertex的数据

结合《BRep Format Description White Paper》中对<vertex data>的描述,及程序代码中对顶点数据的读取,分析OpenCascade的BRep表示中的顶点。 

wps_clip_image-14063

Figure 4.1 NBF-like definition of Vertex 

详细说明: 

<vertex data representation u parameter>u的使用方法说明如下: 

<vertex data representation data 1> 和参数u定义了三维曲线C上的点V的位置。参数u是曲线C上点V对应的参数:C(u)=V。 

<vertex data representation data 2>和参数u定义了曲面上的二维曲线C上点V的位置。参数u是曲线C上点V对应的参数:C(u)=V。 

<vertex data representation data 3>和参数u及<vertex data representation v parameter>v定义了曲面S上的点V:S(u,v)=V。 

<vertex data tolerance>t定义如下所示: 

wps_clip_image-4091

读取Vertex部分的程序代码摘抄如下:

case TopAbs_VERTEX :
    {
      TopoDS_Vertex& V = TopoDS::Vertex(S);
      
      // Read the point geometry
      IS >> tol;
      IS >> X >> Y >> Z;
      myBuilder.MakeVertex(V,gp_Pnt(X,Y,Z),tol);
      Handle(BRep_TVertex) TV = Handle(BRep_TVertex)::DownCast(V.TShape());

      BRep_ListOfPointRepresentation& lpr = TV->ChangePoints();
      TopLoc_Location L;

      do {
        IS >> p1 >> val;
        
        Handle(BRep_PointRepresentation) PR;
        switch (val) {

        case 1 :
          {
            IS >> c;

//  Modified by Sergey KHROMOV - Wed Apr 24 13:59:09 2002 Begin
        if (myCurves.Curve(c).IsNull())
          break;
//  Modified by Sergey KHROMOV - Wed Apr 24 13:59:13 2002 End

            Handle(BRep_PointOnCurve) POC =
              new BRep_PointOnCurve(p1,
                                    myCurves.Curve(c),
                                    L);
            PR = POC;
          }
          break;

        case 2 :
          {
            IS >> pc >> s;

//  Modified by Sergey KHROMOV - Wed Apr 24 13:59:09 2002 Begin
        if (myCurves2d.Curve2d(pc).IsNull() ||
        mySurfaces.Surface(s).IsNull())
          break;
//  Modified by Sergey KHROMOV - Wed Apr 24 13:59:13 2002 End

            Handle(BRep_PointOnCurveOnSurface) POC =
              new BRep_PointOnCurveOnSurface(p1,
                                             myCurves2d.Curve2d(pc),
                                             mySurfaces.Surface(s),
                                             L);
            PR = POC;
          }
          break;

        case 3 :
          {
            IS >> p2 >> s;

//  Modified by Sergey KHROMOV - Wed Apr 24 13:59:09 2002 Begin
        if (mySurfaces.Surface(s).IsNull())
          break;
//  Modified by Sergey KHROMOV - Wed Apr 24 13:59:13 2002 End

            Handle(BRep_PointOnSurface) POC =
              new BRep_PointOnSurface(p1,p2,
                                      mySurfaces.Surface(s),
                                      L);
            PR = POC;
          }
          break;
        }

        if (val > 0) {
          IS >> l;
      if (!PR.IsNull()) {
        PR->Location(Locations().Location(l));
        lpr.Append(PR);
      }
        }
      } while (val > 0);
    }
    break;

从BRep文件中可知,大部分的Vertex只有如下数据:

0101101
*
Ve
1e-007
2 3 0
0 0

即只使用了BRep_Builder.MakeVertex()创建创建顶点(vertex),还可记录顶点的类型: 

1. 若顶点在三维空间中的曲线上Geom_Curve,则记录三维曲线的索引号及参数u; 

2. 若顶点在二维空间中的曲线上Geom2d_Curve,则记录二维曲线的索引号及参数u; 

3. 若顶点在曲面上Geom_Surface,则记录曲面的索引号及参数(u,v); 

五、结论 Conclusion

结合博客“OpenCascade notes”及《BRep format Description white paper》对OpenCascade的拓朴结构中的顶点(vertex)的属性数据进行说明。结合程序说明了顶点的容差及朝向的意义及从底层创建顶点的方法。通过BRep_Tool的静态函数可以获取顶点的几何数据及其他属性。 

发现在BRep文件中还对顶点进行了分类:三维曲线上的点、二维曲线上的点和曲面上的点。 

六、参考资料 

1. OpenCascade notes: opencascade.blogspot.com 

2. 孙家广等. 计算机图形学. 清华大学出版社 

 

转载于:https://www.cnblogs.com/opencascade/p/3603004.html

<think>嗯,我现在遇到了一个Python调用OCC库的问题,具体是在使用BRep_Tool.IsGeometric方法时出现了TypeError错误,提示参数类型或数量不匹配。我需要仔细分析一下这个问题,找出原因并解决它。 首先,我应该回忆一下OCC库中BRep_Tool.IsGeometric方法的正确用法。根据之前的经验,OCC的Python绑定有时候参数传递易出错,特别是类型转换的问题。比如,可能需要先获取TopoDS_Shape的特定类型,如面(Face)、边(Edge)或顶点(Vertex),然后再进行几何检查。 然后,看看用户提供的引用内里提到的一些转换方法,比如TopoDS转换成Geom,使用BRep_Tool.Surface或Curve来获取几何对象。这可能说明在处理形状时,需要先确认形状的类型,再调用相应的几何提取方法。而IsGeometric方法可能需要特定的参数类型,比如TopoDS_Face、TopoDS_Edge等,而不是直接传入TopoDS_Shape。 可能的问题出在用户直接将一个TopoDS_Shape对象传递给了IsGeometric方法,而没有先进行类型转换。例如,如果用户有一个Shape,假设它是一个面,应该先转换为TopoDS_Face类型,再作为参数传递给IsGeometric。 另外,还要检查参数的数量是否正确。是否有遗漏某个参数,或者是否传递了多余的参数。比如,某些方法可能需要一个形状和一个布尔参数,或者其他附加参数,这时候参数数量不对就会报错。 接下来,我需要查阅OCC的官方文档或可靠的示例,确认BRep_Tool.IsGeometric的方法签名。假设正确的方法应该是这样的:BRep_Tool.IsGeometric(TopoDS_Face)返回布尔值,判断该面是否是几何的。或者可能是其他类型,如边或顶点。 如果用户传递的是TopoDS_Shape而不是具体的子类型,那么Python绑定的类型检查可能无法通过,导致TypeError。因此,需要先将Shape转换为具体的类型,例如使用TopoDS.Face(shape)来转换,但需要注意转换是否有效,即该shape确实是一个面。 例如,正确的步骤可能是: 1. 遍历形状的子部件,确认其类型(面、边等)。 2. 对每个子部件进行类型转换,比如转换为TopoDS_Face。 3. 调用BRep_Tool.IsGeometric(转换后的对象)。 可能还需要处理形状的定位(Location)问题,因为OCC中的形状可能有位置变换,需要正确应用这些变换才能获取几何信息。 此外,用户提到的引用中提到了AIS_ColoredShape的使用,这可能显示有关,但问题核心在于参数类型是否正确传递。因此,解决的关键点在于确保传递给IsGeometric的参数是具体的TopoDS_Face、TopoDS_Edge或TopoDS_Vertex类型,而不是通用的TopoDS_Shape。 举个例子,如果用户有一个面(face),应该这样使用: face = TopoDS.Face(shape) is_geom = BRep_Tool.IsGeometric(face) 如果shape确实是一个面,那么转换成功,否则转换会失败,需要处理异常情况。 总结可能的解决方案步骤: 1. 检查传入IsGeometric的参数是否为具体的TopoDS类型(如Face、Edge等)。 2. 使用正确的类型转换方法(如TopoDS.Face())来转换形状。 3. 确保转换后的对象有效,即原始形状确实属于该类型。 4. 处理可能的定位(Location)问题,应用必要的变换。 如果用户没有进行类型转换直接传递TopoDS_Shape,就会导致参数类型不匹配的错误。因此,解决方法就是先进行正确的类型转换,再调用方法。</think>要解决在Python调用OCC库时出现的`BRep_Tool.IsGeometric`参数类型错误问题,需明确以下几点: ### 1. **参数类型要求** `BRep_Tool.IsGeometric`方法的参数需为具体类型的TopoDS对象(如`TopoDS_Face`、`TopoDS_Edge`或`TopoDS_Vertex`),而非通用的`TopoDS_Shape`。直接传递`TopoDS_Shape`会因类型不匹配导致`TypeError`[^1]。 ### 2. **正确使用步骤** #### (1) **获取具体类型对象** 通过`TopoDS`工具将`TopoDS_Shape`转换为具体类型: ```python from OCC.Core.TopoDS import TopoDS_Face, TopoDS_Edge # 假设shape是从模型获取的TopoDS_Shape对象 face = TopoDS.Face(shape) # 转换为面 edge = TopoDS.Edge(shape) # 转换为边 ``` **注意**:需确保原始`shape`确实为对应类型,否则转换会失败。 #### (2) **调用IsGeometric方法** 对转换后的对象调用方法: ```python from OCC.Core.BRep_Tool import BRep_Tool # 检查面是否为几何对象 is_face_geometric = BRep_Tool.IsGeometric(face) # 检查边是否为几何对象 is_edge_geometric = BRep_Tool.IsGeometric(edge) ``` ### 3. **错误处理** 若形状类型不匹配,需提前验证类型: ```python from OCC.Core.TopAbs import TopAbs_FACE if shape.ShapeType() == TopAbs_FACE: face = TopoDS.Face(shape) print(BRep_Tool.IsGeometric(face)) else: print("非面类型") ``` ### 4. **定位(Location)处理** 若形状有变换(如旋转、平移),需应用定位信息以正确获取几何属性: ```python from OCC.Core.gp import gp_Trsf trsf = face.Location().Transformation() # 应用变换到几何对象(如Surface) surface = BRep_Tool.Surface(face).Transformed(trsf) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值