OpenCASCADE General Transformation

摘要:
OpenCASCADE的TKPath库提供了上述仿射变换类gp_ GTrsf,它可以比gp_ Trsf执行更一般的变换。对于TopoShape和OpenCASCADE,提供了以下两个类进行转换:vBRepBuilderAPI_GTransformvBREPuilderAPI_Transform在本文中,这两个类的转换结果在OpenCASCADEDrawTestHarness中给出。如果不想更改几何特征,而只想更改模型的位置或方向,建议使用BRepBuilder API _ TransformDrawTestHarness中实现的函数代码如下:staticStandard_Integertransform{ifeturn1;gp_TrsfT;Standard_Integrast=n;constchar*aName=a[0];Standard_BooleanisBasic=Standard_False;if(!trf.IsDone())return1;DBRep::Set;}}return0;}下面展示了如何应用Tcl脚本来实现这些转换

OpenCASCADE General Transformation

eryar@163.com

Abstract. OpenCASCADE provides a general transformation class: gp_GTrsf. It can be a transformation from gp, an affinity, or you can define your own transformation giving the matrix of transformation. The general transformation contains the vectorial part of the transformation and the translation part. A GTrsf transformation is only applicable to coordinates. Be careful if you apply such a transformation to all points of a geometric object, as this can change the nature of the object and thus render it incoherent. Typically a circle is transformed into an ellipse by an affinity transformation. To avoid modifying the nature of an object, use a gp_Trsf transformation instead, as objects of this class respect the nature of geometric objects.

Key Words. OpenCASCADE, Transformation, Affinity Transformation

1. Introduction

仿射变换(Affinity Transformation)是指线性变换后接着平移。因此,仿射变换的集合是线性变换的超集,任何线性变换都是仿射变换,但不是所有的仿射变换都是线性变换。

仿射变换的定义如下:在空间直角坐标系下,点(x,y,z)与点(x’, y’,z’)之间的变换

wps_clip_image-2056

称为仿射变换。如果采用特殊的齐次坐标来表达,仿射变换也可用下列形式:

wps_clip_image-15105

空间仿射变换是把平面变换到平面,直线变换到直线。两个平行平面的像也是平行的。共线三点的的简单比是不变量。平行六面体的体积是权为1的相对不变量。

OpenCASCADE的TKMath库中提供了这上仿射变换类gp_GTrsf,它能执行比gp_Trsf更通用的变换。对于TopoDS_Shape,OpenCASCADE分别提供了如下两个类进行变换:

v BRepBuilderAPI_GTransform

v BRepBuilderAPI_Transform

本文在OpenCASCADE Draw Test Harness中给出这两个类实现变换的结果。如果不想改变几何的特性,只想改变模型的位置或朝向,建议采用BRepBuilderAPI_Transform。

2.BRepBuilderAPI_Transform

OpenCASCADE中使用算法BRepBuilderAPI_Transform来实现:平移、旋转、缩放及镜像变换。在Draw Test Harness中实现的函数代码如下所示:

static Standard_Integer transform(Draw_Interpretor& di,Standard_Integer n,const char** a)
{
  if (n <= 1) return 1;

  gp_Trsf T;
  Standard_Integer last = n;
  const char* aName = a[0];

  Standard_Boolean isBasic = Standard_False;

  if (!strcmp(aName,"reset")) {
  }
  else {
    isBasic = (aName[0] == 'b');
    aName++;

    if (!strcmp(aName,"move")) {
      if (n < 3) return 1;
      TopoDS_Shape SL = DBRep::Get(a[n-1]);
      if (SL.IsNull()) return 0;
      T = SL.Location().Transformation();
      last = n-1;
    }
    else if (!strcmp(aName,"translate")) {
      if (n < 5) return 1;
      T.SetTranslation(gp_Vec(Draw::Atof(a[n-3]),Draw::Atof(a[n-2]),Draw::Atof(a[n-1])));
      last = n-3;
    }
    else if (!strcmp(aName,"rotate")) {
      if (n < 9) return 1;
      T.SetRotation(gp_Ax1(gp_Pnt(Draw::Atof(a[n-7]),Draw::Atof(a[n-6]),Draw::Atof(a[n-5])),
                    gp_Vec(Draw::Atof(a[n-4]),Draw::Atof(a[n-3]),Draw::Atof(a[n-2]))),
                    Draw::Atof(a[n-1])* (M_PI / 180.0));
      last = n-7;
    }
    else if (!strcmp(aName,"mirror")) {
      if (n < 8) return 1;
      T.SetMirror(gp_Ax2(gp_Pnt(Draw::Atof(a[n-6]),Draw::Atof(a[n-5]),Draw::Atof(a[n-4])),
                  gp_Vec(Draw::Atof(a[n-3]),Draw::Atof(a[n-2]),Draw::Atof(a[n-1]))));
      last = n-6;
    }
    else if (!strcmp(aName,"scale")) {
      if (n < 6) return 1;
      T.SetScale(gp_Pnt(Draw::Atof(a[n-4]),Draw::Atof(a[n-3]),Draw::Atof(a[n-2])),Draw::Atof(a[n-1]));
      last = n-4;
    }
  }

  if (T.Form() == gp_Identity || isBasic) {
    TopLoc_Location L(T);
    for (Standard_Integer i = 1; i < last; i++) {
      TopoDS_Shape S = DBRep::Get(a[i]);
      if (S.IsNull())
        di << a[i] << " is not a valid shape
";
      else
        DBRep::Set(a[i],S.Located(L));
    }
  }
  else {
    BRepBuilderAPI_Transform trf(T);
    for (Standard_Integer i = 1; i < last; i++) {
      TopoDS_Shape S = DBRep::Get(a[i]);
      if (S.IsNull()) {
        di << a[i] << " is not a valid shape
";
      }
      else {
        trf.Perform(S);
        if (!trf.IsDone())
          return 1;
        DBRep::Set(a[i],trf.Shape());
      }
    }
  }
  return 0;
}

下面给出应用Tcl脚本来实现这些变换的例子:

# make rotated copies of a sphere in between two cylinders
# create a file source toto.tcl
# toto.tcl code:
pload ALL

#create a sphere
psphere s 3
ttranslate s 25 0 12.

for {set i 0} {$i < 360} {incr i 20} {
    copy s s$i
    trotate s$i 0 0 0 0 0 1 $i
    
    vdisplay s$i
}
# create two cylinders
pcylinder c1 30 5
copy c1 c2
ttranslate c2 0 0 20
vdisplay c1 c2 s

脚本运行效果如下图所示:

wps_clip_image-18963

Figure 2.1 Transform Tcl demo

从Draw中实现的函数来看,移动、旋转及缩放变换都是使用类

BRepBuilderAPI_Transformation来实现。Tcl脚本中先创建出一个球体,再平移后,复制13份,最后又创建出两个圆柱体。如果要对TopoDS_Shape进行变换且不改变其中的几何性质,建议都使用这个类来完成。

3.BRepBuilderAPI_GTransform

在OpenCASCADE也可使用仿射变换BRepBuilderAPI_GTransform来对形状实现上述变换操作,还可提供变形的变换,因此仿射变换是更一般的变换方法。在Draw中实现的函数代码如下所示:

///=======================================================================
// gtransform
//=======================================================================
static Standard_Integer deform(Draw_Interpretor& di,Standard_Integer n,const char** a)
{
  if (n <= 1return 1;
  
  Standard_Integer last = n;
  
  gp_Trsf T;
  gp_GTrsf GT(T);
  
//  gp_Mat rot(Draw::Atof(a[last-3]),0,0,0,Draw::Atof(a[last-2]),0,0,0,Draw::Atof(a[last-1]));
  gp_Mat rot(Draw::Atof(a[3]),0,0,0,Draw::Atof(a[4]),0,0,0,Draw::Atof(a[5]));
  GT.SetVectorialPart(rot);
  last -= 3;
  BRepBuilderAPI_GTransform gtrf(GT);
  BRepBuilderAPI_NurbsConvert nbscv;
  //  for (Standard_Integer i = 1; i < last; i++) {
  //    TopoDS_Shape S = DBRep::Get(a[i]);
  TopoDS_Shape S = DBRep::Get(a[2]);    
  if (S.IsNull()) {
    //cout << a[2] << " is not a valid shape" << endl;
    di << a[2<< " is not a valid shape" << "";
  }
  else {
    gtrf.Perform(S);
    if (gtrf.IsDone()){
      DBRep::Set(a[1],gtrf.Shape());
    }
    else {
      return 1;
    }
  }
  
  return 0;
}

根据仿射变换的定义,给定一个球面的数学表达式:

wps_clip_image-14741

应用如下的仿射变换,将会得到一个椭球面:

wps_clip_image-5848

由变换公式解得:

wps_clip_image-13797

将它代入球面方程得到:

wps_clip_image-17839

在Draw中使用BRepBuilderAPI_GTransform变换得到如下图所示:

wps_clip_image-23346

Figure 3.1 Shape Deformation

关于仿射变换有个重要定理:一般仿射变换是正交变换、沿着三个互相正交方向的压缩或放大和平移这三者的乘积。上述命令的实现代码就是设置了仿射矩阵中的a,b和c值,从而达到对模型变形的效果。

4.Conclusion

在 三维建模软件中经常需要对模型的位置和其朝向进行变换,如果不想改变模型中的几何特性,在OpenCASCADE中建议使用类 BRepBuilderAPI_Transform来实现。如果需要对模型进行更通用的变换即仿射变换,可以使用类 BRepBuilderAPI_GTransform来实现。使用此类后,会改变模型中的几何特性,必须谨慎使用。

5. References

1. OpenCASCADE, OpenCASCADE Draw Test Harness User Guide, 2014

2. 苏步表, 华宣积. 应用几何教程. 复旦大学出版社. 2012

3. Fletcher Dunn. 3D Math Primer for Graphics and Game Development. Wordware. 2002

免责声明:文章转载自《OpenCASCADE General Transformation》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇iOS开发-Runloop详解(简书)如何通过业务过程,对指标管理体系进行设计?下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

PostgresQL中的NUlls first/last功能

Nulls first/last功能简介Nulls first/last功能主要用于order by排序子句中,影响空值Null在排序结果中的位置。简单来说,Nulls first表示Null值在排序时一直排在所有值的前面,也就是处理order by a desc时PostgresQL执行器认为Null值大于所有值,而order by a或order by...

前闭后开区间

任何一个STL算法,都需要获得由一对迭代器(泛型指针)所标识的区间,用以表示操作范围。这一对迭代器所标示的是个所谓的前闭后开区间,以[first,last)表示。也就是说,整个实际范围从first开始,知道last-1。迭代器last所指的是“最后一个元素的下一位置”。这种偏移一格的标示法,带来了许多方便,例如下面两个STL算法的循环设计,就显得干净利落:...

Oracle中shrink space命令详解

从10g开始,oracle开始提供Shrink的命令,假如我们的表空间中支持自动段空间管理(ASSM),就可以使用这个特性缩小段,即降低HWM。这里需要强调一点,10g的这个新特性,仅对ASSM表空间有效,否则会报 ORA-10635: Invalid segment or tablespace type。 1 创建实验环境 1.1 创建ASSM的表空间...

c++实现md5加密

最近发现md5加密算法挺有趣,特点是单向加密不可逆,加密后的字符串长度相等,于是就用C++尝试实现了一下 头文件定义 1 /* 2 ******************************************************* 3 * brief: md5 encryption 4 * author: Monkey.Knight...

Oracle12.2c统一审计(unified auditing)六问

Oracle12.2c统一审计(unified auditing)六问 conghe6716 2018-11-26 15:42:15 325 收藏 1     概述       统一审计体系是Oracle在12c推出的新的日志体系。12.1和12.2虽然都属于该体系,但是12.1与12.2版本相比,明显给人一种半成品的感觉。包括基表,删除...

bootstrap分页插件--Bootstrap Paginator的使用&amp;amp;AJAX版备份(可单独使用)

html部分: <ul class="pagination"></ul> <!--bootstrap3版本用ul包裹--> <div class="pagination"></div><!--bootstrap2版本用div包裹--> 刷新页面版Boo...