当前位置: 首页 > article >正文

1.Occ-基础部分

Occ-几何建模,几何算法,图形渲染,应用框架集大成者

1.基础类型

The primitive types are predefined in the language and they are manipulated by value.

  • Standard_Boolean is used to represent logical data. It may have only two values: Standard_True and Standard_False.
  • Standard_Character designates any ASCII character.
  • Standard_ExtCharacter is an extended character.
  • Standard_Integer is a whole number.
  • Standard_Real denotes a real number (i.e. one with whole and a fractional part, either of which may be null).
  • Standard_ShortReal is a real with a smaller choice of values and memory size.
  • Standard_CString is used for literal constants.
  • Standard_ExtString is an extended string.
  • Standard_Address represents a byte address of undetermined size.
C++ TypesOCCT Types
intStandard_Integer
doubleStandard_Real
floatStandard_ShortReal
boolStandard_Boolean
charStandard_Character
char16_tStandard_Utf16Char
char*Standard_CString
void*Standard_Address
char16_t*Standard_ExtString

Table 1: Equivalence between C++ Types and OCCT Primitive Types

2.值类型,引用类型

1.值类型:

There are three categories of types which are manipulated by value:

  • Primitive types
  • Enumerated types
  • Types defined by classes not inheriting from Standard_Transient, whether directly or not.

2.引用类型

These are types defined by classes inheriting from the Standard_Transient class.

Unlike for a pointer, the delete operator does not work on a handle; the referenced object is automatically destroyed when no longer in use.

3.引用类型实例

Handle(Geom_CartesianPoint) aPnt;
aPnt = new Geom_CartesianPoint (0, 0, 0);
Handle(Geom_CartesianPoint) aCentre;
Standard_Real x, y, z;
// IsNull是引用类型自身实例持有的方法
if (aCentre.IsNull())
{
  aCentre = new PGeom_CartesianPoint (0, 0, 0);
}
// 1.通过重载->运算符得到引用的实例对象指针。2.通过实例对象指针执行其Coord方法
aCentre->Coord (x, y, z);

// 引用计数
{
  Handle(TColStd_HSequenceOfInteger) H1 = new TColStd_HSequenceOfInteger();
  // H1 has one reference and corresponds to 48 bytes of  memory
  {
    Handle(TColStd_HSequenceOfInteger) H2;
    H2 = H1; // H1 has two references
    if (argc == 3)
    {
      Handle(TColStd_HSequenceOfInteger) H3;
      H3 = H1;
      // Here, H1 has three references
      ...
    }
    // Here, H1 has two references
  }
  // Here, H1 has 1 reference
}
// Here, H1 has no reference 
// and the referred TColStd_HSequenceOfInteger object is deleted.

// 引用与指针
void* aPointer;
Handle(Some_Class) aHandle;
// Here only a pointer will be copied
aPointer = &aHandle;
// Here the Handle object will be copied
aHandle = *(Handle(Some_Class)*)aPointer;

引用类型实现方式参考c++智能指针。Standard_NullObject exception will be raised if a field or a method of an object is accessed via a Null handle.

4.引用类型无法适用场景

循环引用下,导致引用计数始终不会为0。需要针对循环引用场景,特别处理来消除循环引用。

Consider for example a graph, whose objects (primitives) have to know the graph object to which they belong, i.e. a primitive must have a reference to complete graph object. If both primitives and the graph are manipulated by handle and they refer to each other by keeping a handle as a field, the cycle appears.

The graph object will not be deleted when the last handle to it is destructed in the application, since there are handles to it stored inside its own data structure (primitives).

There are two approaches how to avoid such situation:

  • Use C++ pointer for one kind of references, e.g. from a primitive to the graph
  • Nullify one set of handles (e.g. handles to a graph in primitives) when a graph object needs to be destroyed

3.RTTI

给基于Occ的派生类提供RTTI能力实例。

对头文件:

// Appli_ExtSurface.hxx
#include <Geom_Surface.hxx>
class Appli_ExtSurface : public Geom_Surface
{
. . .
public:
  // 头文件提供这个
  DEFINE_STANDARD_RTTIEXT(Appli_ExtSurface,Geom_Surface)
};

对源文件:

#include <Appli_ExtSurface.hxx>
// 提供这个
IMPLEMENT_STANDARD_RTTIEXT(Appli_ExtSurface,Geom_Surface)

原理:

These macros define method DynamicType() that returns a type descriptor - handle to singleton instance of the class Standard_Type describing the class. The type descriptor stores the name of the class and the descriptor of its parent class.

To get the type descriptor for a given class type, use macro STANDARD_TYPE() with the name of the class as argument.

使用实例:

Handle(Standard_Transient) aPnt = new Geom_CartesianPoint (0., 0., 0.);
if (aPnt->DynamicType() == STANDARD_TYPE(Geom_CartesianPoint))
{
  std::cout << "Type check OK\n";
}
else
{
  std::cout << "Type check FAILED\n";
}

3.引用类型的泛化和特化

1.泛化(从特殊到一般)

Consider the class Geom_CartesianPoint, a sub-class of Geom_Point; the rule of type conformity can be illustrated as follows:

Handle(Geom_Point) aPnt1;
Handle(Geom_CartesianPoint) aPnt2;
aPnt2 = new Geom_CartesianPoint();
aPnt1 = aPnt2;  // OK, the types are compatible

The compiler sees aPnt1 as a handle to Geom_Point though the actual object referenced by aPnt1 is of the Geom_CartesianPoint type.

2.特化(从一般到特殊)

A handle can be converted explicitly into one of its sub-types if the actual type of the referenced object is a descendant of the object used to cast the handle. If this is not the case, the handle is nullified (explicit type conversion is sometimes called a “safe cast”). Consider the example below.

Handle(Geom_Point) aPnt1;
Handle(Geom_CartesianPoint) aPnt2, aPnt3;
aPnt2 = new Geom_CartesianPoint();
// 从特殊到一般
aPnt1 = aPnt2; // OK, standard assignment
// 从一般到特殊
aPnt3 = Handle(Geom_CartesianPoint)::DownCast (aPnt1);
// OK, the actual type of aPnt1 is Geom_CartesianPoint, 
// although the static type of the handle is Geom_Point

opencascade中基于Handle的对象引用技术本质上和c++智能指针存在存在区别。

具体为:opencascade中引用对象必须派生自Standard_Transient,该类型实例会维护自身的引用计数。在将Standard_Transient实例指针直接作为参数去构造Handle类型时,Handle类型构造中会通过Standard_Transient实例指针递增该实例的引用计数。c++中智能指针如shared_ptr,在基于原始指针构造shared_ptr对象时,会存储原始指针,同时会分配一个空间存储引用计数。引用计数对象的指针存储在shared_ptr实例中。

If conversion is not compatible with the actual type of the referenced object, the handle which was “cast” becomes null (and no exception is raised). So, if you require reliable services defined in a sub-class of the type seen by the handle (static type), write as follows:

void MyFunction (const Handle(A) & a)
{
  Handle(B) b =  Handle(B)::DownCast(a);
  if (! b.IsNull()) {
    // we can use “b” if class B inherits from A
  }
  else {
    // the types are incompatible
  }
}

4.类方法

实例:

Standard_Integer aDegree = Geom_BezierCurve::MaxDegree();

5.内存管理

occ自身提供了内存管理策略。

To allocate memory in a C code with Open CASCADE Technology memory manager, simply use method Standard::Allocate() instead of malloc() and method Standard::Free() instead of free(). In addition, method Standard::Reallocate() is provided to replace C function realloc().

In C++, operators new() and delete() for a class may be defined so as to allocate memory using Standard::Allocate() and free it using Standard::Free(). In that case all objects of that class and all inherited classes will be allocated using the OCCT memory manager.

Preprocessor macro DEFINE_STANDARD_ALLOC provided by header Standard_DefineAlloc.hxx defines new() and delete() in this way. It is used for all OCCT classes (apart from a few exceptions) which thus are allocated using the OCCT memory manager. Since operators new() and delete() are inherited, this is also true for any class derived from an OCCT class, for instance, for all classes derived from Standard_Transient.

1.occ的内存管理策略

1.1.MMGT_OPT为0,MMGT_CLEAR 可配置

默认下的策略。

every memory block is allocated in C memory heap directly (via malloc() and free() functions).

MMGT_CLEAR: if set to 1 (default), every allocated memory block is cleared by zeros; if set to 0, memory block is returned as it is.

1.2.MMGT_OPT为1

Small blocks with a size less than MMGT_CELLSIZE, are not allocated separately. Instead, a large pools of memory are allocated (the size of each pool is MMGT_NBPAGES pages). Every new memory block is arranged in a spare place of the current pool. When the current memory pool is completely occupied, the next one is allocated, and so on.

In the current version memory pools are never returned to the system (until the process finishes). However, memory blocks that are released by the method Standard::Free() are remembered in the free lists and later reused when the next block of the same size is allocated (recycling).

Medium-sized blocks, with a size greater than MMGT_CELLSIZE but less than MMGT_THRESHOLD, are allocated directly in the C heap (using malloc() and free()). When such blocks are released by the method Standard::Free() they are recycled just like small blocks.

However, unlike small blocks, the recycled medium blocks contained in the free lists (i.e. released by the program but held by the memory manager) can be returned to the heap by method Standard::Purge().

Large blocks with a size greater than MMGT_THRESHOLD, including memory pools used for small blocks, are allocated depending on the value of MMGT_MMAP: if it is 0, these blocks are allocated in the C heap; otherwise they are allocated using operating-system specific functions managing memory mapped files. Large blocks are returned to the system immediately when Standard::Free() is called.

2.occ的内存管理策略的好处与坏处

The major benefit of the OCCT memory manager is explained by its recycling of small and medium blocks that makes an application work much faster when it constantly allocates and frees multiple memory blocks of similar sizes. In practical situations, the real gain on the application performance may be up to 50%.

The associated drawback is that recycled memory is not returned to the operating system during program execution. This may lead to considerable memory consumption and even be misinterpreted as a memory leak. To minimize this effect it is necessary to call the method Standard::Purge after the completion of memory-intensive operations.

OCCT memory manager uses mutex to lock access to free lists, therefore it may have less performance than non-optimized mode in situations when different threads often make simultaneous calls to the memory manager. The reason is that modern implementations of malloc() and free() employ several allocation arenas and thus avoid delays waiting mutex release, which are possible in such situations.

6.异常

A hierarchy of commonly used exception classes is provided. The root class is Standard_Failure from the Standard package. So each exception inherits from Standard_Failure either directly or by inheriting from another exception. Exception classes list all exceptions, which can be raised by any OCCT function.

实例:

// 引发异常
throw Standard_DomainError ("Cannot cope with this condition");
// 引发和捕获
try
{
  OCC_CATCH_SIGNALS
  // try block
}
catch (const Standard_DomainError& )
{
  // handle Standard_DomainError exceptions here
}

异常的推荐用法:

Item TCollection_Array1::Value (Standard_Integer theIndex) const
{
  // 用于非法输入检测
  // where myR1 and myR2 are the lower and upper bounds of the array
  if (theIndex < myR1 || theIndex > myR2)
  {
    throw Standard_OutOfRange ("Index out of range in TCollection_Array1::Value");
  }
  return myContents[theIndex];
}

It is a widely used practice to include that kind of protections in a debug build of the program and exclude in release (optimized) build. To support this practice, the macros Raise_if() are provided for every OCCT exception class:

<ErrorTypeName>_Raise_if(condition, "Error message");

where ErrorTypeName is the exception type, condition is the logical expression leading to the raise of the exception, and Error message is the associated message.

The entire call may be removed by defining one of the preprocessor symbols No_Exception or No_ at compile-time:

#define No_Exception // remove all raises

Using this syntax, the Value function becomes:

Item TCollection_Array1::Value (Standard_Integer theIndex) const
{
  Standard_OutOfRange_Raise_if(theIndex < myR1 || theIndex > myR2, 
      "index out of range in TCollection_Array1::Value");
  return myContents[theIndex];
}

In order to handle system signals as exceptions, make sure to insert macro OCC_CATCH_SIGNALS somewhere in the beginning of the relevant code. The recommended location for it is first statement after opening brace of try {} block.

As an example, consider the exceptions of type Standard_NumericError, Standard_Overflow, Standard_Underflow and Standard_DivideByZero, where Standard_NumericError is the parent type of the three others.

void f(1)
{
  try
  {
    OCC_CATCH_SIGNALS
    // try block
  }
  catch (const Standard_Overflow& ) // first handler
  {
    // ...
  }
  catch (const Standard_NumericError& ) // second handler
  {
    // ...
  }
}

One exception of type Standard_Failure is the root of the entire exception hierarchy. Thus, using a handler with Standard_Failure type catches any OCCT exception. It is recommended to set up such a handler in the main routine.

The main routine of a program would look like this:

#include <Standard_ErrorHandler.hxx>
#include <Standard_Failure.hxx>
#include <iostream>
int main (int argc, char* argv[])
{
  try
  {
    OCC_CATCH_SIGNALS
    // main block
    return 0;
  }
  catch (const Standard_Failure& theFailure)
  {
    std::cerr << "Error " + theFailure.DynamicType()->Name() 
        << " [" << theFailure.GetMessageString() << "]\n";
  }
  return 1;
}

将信号统一到异常:

In order for the application to be able to catch system signals (access violation, division by zero, etc.) in the same way as other exceptions, the appropriate signal handler shall be installed in the runtime by the method OSD::SetSignal().

Normally this method is called in the beginning of the main() function. It installs a handler that will convert system signals into OCCT exceptions.

In order to actually convert signals to exceptions, macro OCC_CATCH_SIGNALS needs to be inserted in the source code. The typical place where this macro is put is beginning of the try{} block which catches such exceptions.

7.Collections, Strings, Quantities and Unit Conversion

7.1.Collections

OCCT itself highly relies on its own collections for historical reasons - many features implemented by OCCT were unavailable in earlier versions of STL.

The Collections component provides a wide range of generic collections:

  • Arrays are generally used for a quick access to the item, however an array is a fixed sized aggregate.
  • Sequences are variable-sized structures, they avoid the use of large and quasi-empty arrays. A sequence item is longer to access than an array item: only an exploration in sequence is effective (but sequences are not adapted for numerous explorations).
  • Maps are dynamic structures, where the size is constantly adapted to the number of inserted items and access to an item is the fastest. Maps structures are commonly used in cases of numerous explorations.
  • Lists are similar to sequences but have different algorithms to explore them.
  • Acceleration structures are trees or other structures optimized for fast traverse based on locality criteria (like picking objects by ray in 3D).

实例:

#include <NCollection_Sequence.hxx>
#include <gp_Pnt.hxx>
typedef NCollection_Sequence<gp_Pnt> MyPackage_SequenceOfPnt;

For the case, when sequence itself should be managed by handle, auxiliary macros DEFINE_HSEQUENCE can be used:

#include <NCollection_Sequence.hxx>
#include <NCollection_DefineHSequence.hxx>
#include <gp_Pnt.hxx>
typedef NCollection_Sequence<gp_Pnt> MyPackage_SequenceOfPnt;
// 这样会定义一个新类型MyPackage_HSequenceOfPnt,该类型派生自MyPackage_SequenceOfPnt和Standard_Transient
DEFINE_HSEQUENCE(MyPackage_HSequenceOfPnt, MyPackage_SequenceOfPnt)
...
Handle(MyPackage_HSequenceOfPnt) aSeq = new MyPackage_HSequenceOfPnt();
7.1.1.Arrays and sequences

Standard collections provided by OCCT are:

  • NCollection_Array1 – fixed-size (at initialization) one-dimensional array; note that the index can start at any value, usually 1;
  • NCollection_Array2 – fixed-size (at initialization) two-dimensional array; note that the index can start at any value, usually 1;
  • NCollection_List – plain list;
  • NCollection_Sequence – double-connected list with access by index; note that the index starts at 1;
  • NCollection_Vector – two-step indexed array, expandable in size, but not shrinkable;The first element in vector has index equal to 0.
  • NCollection_SparseArray – array-alike structure with sparse memory allocation for sequences with discontinuities.

NCollection_Sequence基于双向链表实现,但提供了对索引访问的支持(模拟数组的功能)。

NCollection_Vector动态数组。分为两层。第一层存储数组存储指向固定块的指针,每个固定块用于存储固定数量元素的数组。

NCollection_SparseArray稀疏数组。

7.1.2.Maps

OCCT provides several classes for storage of objects by value, providing fast search due to use of hash:

  • NCollection_Map – hash set;

1.基于链式哈希表实现。仅仅存储键。键需要唯一。

  • NCollection_IndexedMap – set with a prefixed order of elements, allowing fast access by index or by value (hash-based);

1.基于链式哈希表实现。仅仅存储键。键需要唯一。

2.但有两个链式哈希表。针对每个键。

以插入键为例:

通过哈希函数计算哈希值,然后在其中一个哈希表中实现插入。

为新插入键分配索引,以索引为哈希值在另一个哈希表中实现插入。

  • NCollection_DataMap – hash map;

1.类似NCollection_Map。但不仅存储键,还存储关联的值。键需要唯一。

  • NCollection_IndexedDataMap – map with a prefixed order of elements, allowing fast access by index or by value (hash-based);

1.类似NCollection_IndexedMap。但不但存储键,还存储关联的值。键需要唯一。

  • NCollection_DoubleMap – two-side hash map (with two keys).

NCollection_DoubleMap 是 OpenCASCADE 中的一种双映射集合类,用于存储两个键之间的双向映射关系。它的实现原理基于两个 NCollection_DataMap,分别用于正向映射和反向映射。

具体来说,它包含两个 NCollection_DataMap

  • 正向映射(Forward Map):用于存储键 Key1 到键 Key2 的映射关系。
  • 反向映射(Reverse Map):用于存储键 Key2 到键 Key1 的映射关系。

Keys, items and hashers are parameters of these OCCT map templates. NCollection_DefaultHasher class describes the functions required by any hasher, which is to be used with a map instantiated from the NCollection component.

7.1.3.迭代器

The common methods of Iterator are:

NameMethodDescription
Init()void Init (MyCollection& )Initializes the iterator on the collection object
More()bool More()Makes a query if there is another non-iterated member
Next()void Next()Increments the iterator
Value()const ItemType& Value()Returns the current member
ChangeValue()ItemType& ChangeValue()Returns the mutable current member

实例:

typedef Ncollection_Sequence<gp_Pnt> MyPackage_SequenceOfPnt;
void Perform (const MyPackage_SequenceOfPnt& theSequence)
{
  for (MyPackage_SequenceOfPnt::Iterator anIter (theSequence); 
  	anIter.More(); anIter.Next())
  {
    const gp_Pnt aPnt& = anIter.Value();
    ...
  }
}

8.Strings

TCollection_AsciiString defines a variable-length sequence of UTF-8 code points (normal 8-bit character type), while TCollection_ExtendedString stores UTF-16/UCS-2 code points (16-bit character type). Both follow value semantics - that is, they are the actual strings, not handles to strings, and are copied through assignment.TCollection_HAsciiString / TCollection_HExtendedString are handle wrappers over TCollection_AsciiString / TCollection_ExtendedString.

String classes provide the following services to manipulate character strings:

  • Editing operations on string objects, using a built-in string manager
  • Handling of dynamically-sized sequences of characters
  • Conversion from/to ASCII and UTF-8 strings.

TCollection_AsciiString and TCollection_ExtendedString provide UTF-8 <-> UTF-16 conversion constructors, making these string classes interchangeable. Resource_Unicode provides functions to convert strings given in ANSI, EUC, GB or SJIS format, to a Unicode string and vice versa. NCollection_UtfIterator class implements an iterator over multibyte UTF-8/UTF-16 strings as a sequence of UTF-32 Unicode symbols.

9.Quantities

Quantities are various classes supporting date and time information and color.

Quantity classes provide the following services:

  • Unit conversion tools providing a uniform mechanism for dealing with quantities and associated physical units: check unit compatibility, perform conversions of values between different units, etc. (see package UnitsAPI)
  • Resources to manage time information such as dates and time periods
  • Resources to manage color definition

A mathematical quantity is characterized by the name and the value (real).

A physical quantity is characterized by the name, the value (real) and the unit. The unit may be either an international unit complying with the International Unit System (SI) or a user defined unit. The unit is managed by the physical quantity user.

10.Unit Conversion

The UnitsAPI global functions are used to convert a value from any unit into another unit. Conversion is executed among three unit systems:

  • the SI System,
  • the user’s Local System,
  • the user’s Current System.

The SI System is the standard international unit system. It is indicated by SI in the signatures of the UnitsAPI functions.

The OCCT (former MDTV) System corresponds to the SI international standard but the length unit and all its derivatives use the millimeter instead of the meter.

Both systems are proposed by Open CASCADE Technology; the SI System is the standard option. By selecting one of these two systems, you define your Local System through the SetLocalSystem function. The Local System is indicated by LS in the signatures of the UnitsAPI functions. The Local System units can be modified in the working environment. You define your Current System by modifying its units through the SetCurrentUnit function. The Current System is indicated by Current in the signatures of the UnitsAPI functions. A physical quantity is defined by a string (example: LENGTH).

11.Vectors and Matrices

The math_Vector and math_Matrix classes provide commonly used mathematical algorithms which include:

  • Basic calculations involving vectors and matrices;
  • Computation of eigenvalues and eigenvectors of a square matrix;
  • Solvers for a set of linear algebraic equations;
  • Algorithms to find the roots of a set of non-linear equations;
  • Algorithms to find the minimum function of one or more independent variables.

These classes also provide a data structure to represent any expression, relation, or function used in mathematics, including the assignment of variables.

Vectors and matrices have arbitrary ranges which must be defined at declaration time and cannot be changed after declaration.

math_Vector aVec (1, 3);
// a vector of dimension 3 with range (1..3)
math_Matrix aMat (0, 2, 0, 2);
// a matrix of dimension 3x3 with range (0..2, 0..2)
math_Vector aVec (N1, N2);
// a vector of dimension N2-N1+1 with range (N1..N2)

Vector and Matrix objects use value semantics. In other words, they cannot be shared and are copied through assignment.

math_Vector aVec1 (1, 3), aVec2 (0, 2);
aVec2 = aVec1;
// aVec1 is copied into aVec2; a modification of aVec1 does not affect aVec2

Vector and Matrix values may be initialized and obtained using indexes which must lie within the range definition of the vector or the matrix.

math_Vector aVec (1, 3);
math_Matrix aMat (1, 3, 1, 3);
Standard_Real aValue;
aVec (2) = 1.0;
aValue = aVec(1);
aMat (1, 3) = 1.0;
aValue = aMat (2, 2);

Some operations on Vector and Matrix objects may not be legal. In this case an exception is raised. Two standard exceptions are used:

  • Standard_DimensionError exception is raised when two matrices or vectors involved in an operation are of incompatible dimensions.
  • Standard_RangeError exception is raised if an access outside the range definition of a vector or of a matrix is attempted.
math_Vector aVec1 (1, 3), aVec2 (1, 2), aVec3 (0, 2);
aVec1 = aVec2;   // error: Standard_DimensionError is raised
aVec1 = aVec3;   // OK: ranges are not equal but dimensions are compatible
aVec1 (0) = 2.0; // error: Standard_RangeError is raised

12.Primitive Geometric Types

  • Descriptions of primitive geometric shapes, such as:

    • Points;
    • Vectors;
    • Lines;
    • Circles and conics;
    • Planes and elementary surfaces;

    Conics” 翻译为中文是 “圆锥曲线”。圆锥曲线是平面与圆锥面相交所产生的曲线,包括 椭圆抛物线双曲线 三种基本类型。

  • Positioning of these shapes in space or in a plane by means of an axis or a coordinate system;

  • Definition and application of geometric transformations to these shapes:

    • Translations;
    • Rotations;
    • Symmetries;
    • Scaling transformations;
    • Composed transformations;
  • Tools (coordinates and matrices) for algebraic computation.

Note that gp curves and surfaces are analytic: there is no parameterization and no orientation on gp entities, i.e. these entities do not provide functions which work with these properties.

If you need, you may use more evolved data structures provided by Geom (in 3D space) and Geom2d (in the plane). However, the definition of gp entities is identical to the one of equivalent Geom and Geom2d entities, and they are located in the plane or in space with the same kind of positioning systems. They implicitly contain the orientation, which they express on the Geom and Geom2d entities, and they induce the definition of their parameterization.

Thus, ElCLib and ElSLib packages provide functions to compute:

  • the point of parameter u on a 2D or 3D gp curve,
  • the point of parameter (u,v) on a gp elementary surface, and
  • any derivative vector at this point.

13.Collections of Primitive Geometric Types

Before creating a geometric object, you must decide whether you are in a 2d or in a 3d context and how you want to handle the object. If you do not need a single instance of a geometric primitive but a set of them then the package which deals with collections of this sort of object, TColgp, will provide the necessary functionality. In particular, this package provides standard and frequently used instantiations of generic classes with geometric objects, i.e. gp_XY, gp_XYZ, gp_Pnt, gp_Pnt2d, gp_Vec, gp_Vec2d, gp_Lin, gp_Lin2d, gp_Circ, gp_Circ2d.

14.Basic Geometric Libraries

If you are dealing with objects created from the gp package, the useful algorithms are in the elementary curves and surfaces libraries – the ElCLib and ElSLib packages.

  • EICLib provides methods for analytic curves. This is a library of simple computations on curves from the gp package (Lines, Circles and Conics). It is possible to compute points with a given parameter or to compute the parameter for a point.

  • EISLib provides methods for analytic surfaces. This is a library of simple computations on surfaces from the package gp (Planes, Cylinders(圆柱体), Spheres(球体), Cones(圆锥体), Tori(环面)). It is possible to compute points with a given pair of parameters or to compute the parameter for a point. There is a library for calculating normals on curves and surfaces.

Additionally, Bnd package provides a set of classes and tools to operate with bounding boxes of geometric objects in 2d and 3d space.

15.Common Math Algorithms

The common math algorithms library provides a C++ implementation of the most frequently used mathematical algorithms. These include:

  • Algorithms to solve a set of linear algebraic equations,
  • Algorithms to find the minimum of a function of one or more independent variables,
  • Algorithms to find roots of one, or of a set, of non-linear equations,
  • An algorithm to find the eigenvalues and eigenvectors of a square matrix.

All mathematical algorithms are implemented using the same principles. They contain:

  • A constructor performing all, or most of, the calculation, given the appropriate arguments. All relevant information is stored inside the resulting object, so that all subsequent calculations or interrogations will be solved in the most efficient way.
  • A function IsDone returning the boolean true if the calculation was successful.
  • A set of functions, specific to each algorithm, enabling all the various results to be obtained. Calling these functions is legal only if the function IsDone answers true, otherwise the exception StdFail_NotDone is raised.

The example below demonstrates the use of the math_Gauss class, which implements the Gauss solution for a set of linear equations. The following definition is an extract(提取) from the header file of the class math_Gauss:

class math_Gauss
{
public:
  math_Gauss (const math_Matrix& A);
  Standard_Boolean IsDone() const;
  void Solve (const math_Vector& B, math_Vector& X) const;
};

Now the main program uses the math_Gauss class to solve the equations a*x1=b1 and a*x2=b2:

#include <math_Gauss.hxx>
#include <math_Matrix.hxx>
#include <math_Vector.hxx>
#include <iostream>
/*
2x +  y -  z = 8
-3x - y + 2z = -11
-2x + y + 2z = -3
*/
int main() {
    // 定义系数矩阵 A
    math_Matrix A(1, 3, 1, 3);
    A(1, 1) = 2;  A(1, 2) = 1;  A(1, 3) = -1;
    A(2, 1) = -3; A(2, 2) = -1; A(2, 3) = 2;
    A(3, 1) = -2; A(3, 2) = 1;  A(3, 3) = 2;
    // 定义常数向量 B
    math_Vector B(1, 3);
    B(1) = 8;
    B(2) = -11;
    B(3) = -3;
    // 创建 math_Gauss 对象并求解
    math_Gauss Gauss(A);
    if (Gauss.IsDone()) {
        math_Vector X(1, 3);
        Gauss.Solve(B, X);
        // 输出结果
        std::cout << "解向量 X:" << std::endl;
        std::cout << "x = " << X(1) << std::endl;
        std::cout << "y = " << X(2) << std::endl;
        std::cout << "z = " << X(3) << std::endl;
    } else {
        std::cout << "求解失败,矩阵可能奇异或不可逆。" << std::endl;
    }

    return 0;
}

The next example demonstrates the use of the math_BissecNewton class, which implements a combination of the Newton and Bissection algorithms to find the root of a function known to lie between two bounds. The definition is an extract from the header file of the class math_BissecNewton:

class math_BissecNewton
{
public:
  math_BissecNewton (math_FunctionWithDerivative& f,
     const Standard_Real bound1, const Standard_Real bound2, const Standard_Real tolx);
  Standard_Boolean IsDone() const;
  Standard_Real Root();
}; 

The abstract class math_FunctionWithDerivative describes the services which have to be implemented for the function f which is to be used by a math_BissecNewton algorithm. The following definition corresponds to the header file of the abstract class math_FunctionWithDerivative:

class math_FunctionWithDerivative
{
public:
  virtual Standard_Boolean Value (const Standard_Real x, Standard_Real& f) = 0;
  virtual Standard_Boolean Derivative (const Standard_Real x, Standard_Real& d) = 0;
  virtual Standard_Boolean Values (const Standard_Real x, Standard_Real& f, Standard_Real& d) = 0;
};

Now the test sample uses the math_BissecNewton class to find the root of the equation f(x)=x^2+4 in the interval [1.5, 2.5]. The function to solve is implemented in the class myFunction which inherits from the class math_FunctionWithDerivative, then the main program finds the required root.

#include <math_BissecNewton.hxx>
#include <math_FunctionWithDerivative.hxx>
#include <iostream>
// 定义函数类,继承自 math_FunctionWithDerivative
class MyFunction : public math_FunctionWithDerivative {
public:
    // 计算函数值
    Standard_Boolean Value(const Standard_Real x, Standard_Real& f) override {
        f = x * x + 4; // f(x) = x^2 + 4
        return Standard_True;
    }

    // 计算导数值
    Standard_Boolean Derivative(const Standard_Real x, Standard_Real& df) override {
        df = 2 * x; // f'(x) = 2x
        return Standard_True;
    }

    // 计算函数值和导数值
    Standard_Boolean Values(const Standard_Real x, Standard_Real& f, Standard_Real& df) override {
        f = x * x + 4; // f(x) = x^2 + 4
        df = 2 * x;    // f'(x) = 2x
        return Standard_True;
    }
};

int main() {
    // 定义函数对象
    MyFunction func;
    // 定义求解区间 [1.5, 2.5]
    Standard_Real x1 = 1.5;
    Standard_Real x2 = 2.5;
    // 定义求解器,设置精度为 1e-6
    math_BissecNewton solver(func, x1, x2, 1e-6);
    // 检查是否求解成功
    if (solver.IsDone()) {
        Standard_Real root = solver.Root();
        std::cout << "方程的解为: " << root << std::endl;
    } else {
        std::cout << "求解失败,方程在给定区间内可能无解。" << std::endl;
    }

    return 0;
}

16.Precision

On the OCCT platform, each object stored in the database should carry its own precision value. This is important when dealing with systems where objects are imported from other systems as well as with various associated precision values.

The Precision package addresses the daily problem of the geometric algorithm developer: what precision setting to use to compare two numbers. Real number equivalence is clearly a poor choice. The difference between the numbers should be compared to a given precision setting.

Do not write if (X1 == X2), instead write if (Abs(X1-X2) < Precision).

Also, to order real numbers, keep in mind that if (X1 < X2 - Precision) is incorrect. if (X2 - X1 > Precision) is far better when X1 and X2 are high numbers.

This package proposes a set of methods providing precision settings for the most commonly encountered situations.

In Open CASCADE Technology, precision is usually not implicit; low-level geometric algorithms accept precision settings as arguments. Usually these should not refer directly to this package.

High-level modeling algorithms have to provide a precision setting to the low level geometric algorithms they call. One way is to use the settings provided by this package. The high-level modeling algorithms can also have their own strategy for managing precision. As an example the Topology Data Structure stores precision values which are later used by algorithms. When a new topology is created, it takes the stored value.

Different precision settings offered by this package cover the most common needs of geometric algorithms such as Intersection and Approximation. The choice of a precision value depends both on the algorithm and on the geometric space. The geometric space may be either:

  • a real space, 3d or 2d where the lengths are measured in meters, micron(微米), inches(英寸), etc.
  • a parametric space, 1d on a curve or 2d on a surface where numbers have no dimension.

The choice of precision value for parametric space depends not only on the accuracy of the machine, but also on the dimensions of the curve or the surface. This is because it is desirable to link parametric precision and real precision. If you are on a curve defined by the equation P(t), you would want to have equivalence between the following:

Abs (t1 - t2) < ParametricPrecision
Distance (P(t1), P(t2)) < RealPrecision

16.1.The Precision package

The Precision package offers a number of package methods and default precisions for use in dealing with angles, distances, intersections, approximations, and parametric space. It provides values to use in comparisons to test for real number equalities.

  • Angular precision compares angles.
  • Confusion precision compares distances.
  • Intersection precision is used by intersection algorithms.
  • Approximation precision is used by approximation algorithms.
  • Parametric precision gets a parametric space precision from a 3D precision.
  • Infinite returns a high number that can be considered to be infinite. Use -Infinite for a high negative number.

16.2.Standard Precision values

This package provides a set of real space precision values for algorithms. The real space precisions are designed for precision to 0.1 nanometers (in case if model is defined in millimeters).

The parametric precisions are derived from the real precisions by the Parametric function. This applies a scaling factor which is the length of a tangent to the curve or the surface. You, the user, provide this length. There is a default value for a curve with [0,1] parameter space and a length less than 100 meters.

The geometric packages provide Parametric precisions for the different types of curves. The Precision package provides methods to test whether a real number can be considered to be infinite.

Precision::Angular:

This method is used to compare two angles.

bool areEqualAngles (double theAngle1, double theAngle2)
{
  return Abs(theAngle1  - theAngle2) < Precision::Angular();
}
bool areParallelVectors (const gp_Vec& theVec1, const gp_Vec& theVec2)
{
  return theVec1.IsParallel (theVec2, Precision::Angular());
}

Note that Precision::Angular() can be used on both dot and cross products because for small angles the Sine and the Angle are equivalent. So to test if two directions of type gp_Dir are perpendicular, it is legal to use the following code:

bool arePerpendicular (const gp_Dir& theDir1, const gp_Dir& theDir2)
{
  return Abs(theDir1 * theDir2) < Precision::Angular();
}

Precision::Confusion:

This method is used to test 3D distances. The current value is 1.e-7, in other words, 1/10 micron(微米) if the unit used is the millimeter.

bool isNullVector (const gp_Vec& theVec)
{
  return theVec.Magnitude() < Precision::Confusion();
}

Precision::Intersection:

This is reasonable precision to pass to an Intersection process as a limit of refinement of Intersection Points. Intersection is high enough for the process to converge(收敛) quickly. Intersection is lower than Confusion so that you still get a point on the intersected geometries. The current value is Confusion() / 100.

Precision::Approximation:

This is a reasonable precision to pass to an approximation process as a limit of refinement of fitting. The approximation is greater than the other precisions because it is designed to be used when the time is at a premium(宝贵). It has been provided as a reasonable compromise by the designers of the Approximation algorithm. The current value is Confusion() * 10. Note that Approximation is greater than Confusion, so care must be taken when using Confusion in an approximation process.


http://www.kler.cn/a/456571.html

相关文章:

  • 聊聊 Mongod 以及 MongoDB 常用命令
  • 马原复习笔记
  • Python小括号( )、中括号[ ]和大括号{}代表什么
  • 5.最长回文子串
  • 爱思唯尔word模板
  • 钉钉h5微应用安卓报错error29 ios报错error3 加上报错52013,签名校验失败 (前端)
  • UE5玻璃材质
  • Rust编程与项目实战-箱
  • GDPU 数据库原理 期末复习(持续更新……)
  • 高级java每日一道面试题-2024年12月28日-并发篇-了解Semaphore吗?
  • 【Web】0基础学Web—js类和对象、json、js对象解构、js对象遍历、js深浅拷贝
  • HCIA-Access V2.5_6_3_GPON组网保护
  • mongodbredisneo4j 如何自己打造一个 web 数据库可视化客户端?
  • phidata快速开始
  • Docker--Bitnami/redis
  • Android9.x SurfaceView源码分析
  • 重学SpringBoot3-RestTemplate配置与使用详解
  • 7-Linux系统的磁盘基本管理
  • 代码思想之快慢路径
  • YOLO系列正传(五)YOLOv4论文精解(上):从CSPNet、SPP、PANet到CSPDarknet-53
  • 【论文阅读】MedCLIP: Contrastive Learning from Unpaired Medical Images and Text
  • apifox调用jar程序
  • 功能测试和接口测试
  • 总结-常见缓存替换算法
  • String的认识和使用
  • 【RK3568笔记】Android适配红外遥控器