FreeCAD源码分析:FreeCADBase模块
济南友泉软件有限公司
FreeCADBase提供了FreeCAD软件开发的基础类库,具体来说,主要功能包括
- 公共功能
定义了工厂模式、观察者模式,以及数据持久化的接口。
- 数学几何
定义了三维空间几何的基本数据结构。
- 日志
定义了统一的接口完成软件运行时日志信息的输出与管理。
- 实用工具
提供了文件读写、内存检测、参数管理等主要工具。
- Python
调用Python C API嵌入Ptyhon代码;使用PyCXX扩展Python模块。
RTTI(Runtime Type Identification)是运行时类型识别。通过继承BaseClass类并利用提供的宏,可以非常方便地实现BaseClass子类支持RTTI。
为了使用户创建的类UserClass支持RTTI,可以按照下面的格式定义UserClass,
实际上,TYPESYSTEM_HEADER、TYPESYSTEM_SOURCE等宏用于定义下面的一系列的成员函数、成员变量等操作。
//UserClass.h
class UserClass : public Base::BaseClass
{
TYPESYSTEM_HEADER()
public:
/// Construction
UserClass();
/// Destruction
virtual ~UserClass();
};
//UserClass.cpp
TYPESYSTEM_SOURCE(UserClass, Base::BaseClass)
UserClass::UserClass()
{
}
UserClass::~UserClass()
{
}
- 获取类型
static Type BaseClass::getClassTypeId(void);
virtual Type BaseClass::getTypeId(void) const;
- 初始化类型信息数据结构
static void BaseClass::initSubclass(Base::Type &toInit,const char* ClassName, const char *ParentName, Type::instantiationMethod method=0);
- 类型判断
bool BaseClass::isDerivedFrom(const Type type) const
- 创建对象
static void * BaseClass::create(void)
- 关联Python
virtual PyObject * BaseClass::getPyObject(void);
virtual void BaseClass::setPyObject(PyObject *);
- 创建类对象
static void * BaseClass::create(void)
- 类型转换
template<typename T> T * freecad_dynamic_cast(Base::BaseClass * t)
template<typename T> const T * freecad_dynamic_cast(const Base::BaseClass * t)
Factory、AbstractProducer等类实现了工厂模式。Factory中包含一个AbstractProducer映射表,可以通过FactoryAddProducer向Factory注册对象生成的方法,
void Factory::AddProducer (const char* sClassName, AbstractProducer *pcProducer)
Observer、Subject等类实现了观察者模式。Subject类及其子类表示需要被观察的对象,需要绑定对应的观察者。
void Subject::Attach(Observer<_MessageType> *ToObserv)
void Subject::Detach(Observer<_MessageType> *ToObserv)
当Subject对象数据发生变化时,需要调用Subject::Notify通知Observer.
void Subject::Notify(_MessageType rcReason)
异常处理可以将逻辑代码与程序运行时的错误处理进行分离。Exception类是其他异常处理类的基类,其他派生类主要用于处理XML解析、文件读写等操作异常。
类名 |
功能 |
Exception |
异常类的基类,定义了异常信息输出等基本功能。 |
AbortException |
程序终止 |
XMLBaseException XMLParseException XMLAttributeError |
XML文件解析时异常 |
FileException |
文件I/O异常 |
FileSystemError |
文件系统操作异常(比如重命名) |
BadFormatError |
数据结构格式错误异常。 |
此外,ExceptionFactory、ExceptionProducer等类提供了针对异常对象的工厂模型实现。
Base::Reference类模板实现了引用计数风格的对象管理接口,
template <class T> class Reference
模板参数T必须是Base::Handled及其派生类。
数据持久化是把对象数据保存到存储介质或者从存储介质读取数据来创建对象。Base::Persistence定义了持久化对象的基本接口,Persistence::Save函数完成对象数据存储到XML文件中;Persistence::Restore完成从XML文件读取对象数据。
描述三维空间几何的基本数据结构。
Vector3D是一个类模板,由于表示三维空间的点或者矢量,原型为
template <class _Precision> class Vector3
模板参数_Precision可以是float或者double,不仅包含加、减、数乘、数除、内积、叉积等基本运算方法,而且还提供了点-线、点-面等几何关系比较的算法。
Axis类用于表示空间坐标轴,可以通过指定坐标原点Orig、坐标轴方向Dir来定义坐标轴,
Axis::Axis(const Vector3d& Orig, const Vector3d& Dir)
同时,提供了加、数乘、数除等基本运算方法。
BoundBox3用于表示三维包围盒,其内部实现是通过六个坐标值标定包围盒的范围,
template <class _Precision> class BoundBox3
模板参数_Precision可以是float或者double。
CoordinateSystem用于表示三维笛卡尔坐标系,根据右手法则,可以根据当前原点、其他两坐标轴方向,自动计算出第三个坐标轴的方向。
3.5 Builder3D & InventorBuilder
Builder3D用于保存点、线、三角形、文字等三维几何图元的创建信息。Builder3D首先将几何图元的创建信息保存为字符串,然后根据需要可以将其输出到文件或者日志中。
InventorBuilder可以用于保存点、线、三角形、文字、材质、颜色等几何图元信息。与Builder3D不同的是,InventorBuilder直接将几何图元信息存储到文件中。
由于计算机图形学中是以其次坐标来表示空间坐标的,因此定义了四阶矩阵Matrix4D以方便几何变换。
Placement定义了三维几何物体的几何变换信息,实际上表示一个其次坐标变换的Matrix4D矩阵。
3.8 Rotation
Rotation定义了三维几何物体的旋转变换。
投影变换是将三维几何信息投影到二维平面坐标上。ViewProjMethod提供了投影变换接口;ViewProjMatrix可以用于获取投影操作对应的投影矩阵。
日志输出是将程序运行过程中的信息、错误、警告等写入系统控制台或者文件。
调用ConsoleSingleton的成员函数输出消息、警告、错误等日志信息;LogLevel根据日志输出控制配置来调用ConsoleSingleton输出日志;ConsoleObserver派生类可以过滤日志信息。
FreeCAD提供了全局唯一的ConsoleSingleton对象,可以通过下面的函数获取这个对象,
ConsoleSingleton &Console(void)
ConsoleSingleton提供了类C printf方式的日志输出格式,主要包括消息、警告、错误、日志等输出。
- 消息
Base::Console().Message("Stage: %d", i);
- 警告
Base::Console().Warning ("Stage: %d", i+1);
- 错误
Base::Console().Error ("Stage: %d", i+2);
- 日志
Base::Console().Log("Stage: %d", i+3);
ConsoleSingleton提供了不同的成员函数用于控制输出。
方法 |
参数类型 |
描述 |
|
void SetConsoleMode(ConsoleMode m) void UnsetConsoleMode(ConsoleMode m) |
enum ConsoleMode { Verbose = 1, } |
当设置Verbose,则Log函数会输出日志信息,否则Log函数什么也不输出。 |
|
void SetConnectionMode(ConnectionMode mode) |
enum ConnectionMode { Direct = 0, Queued =1 } |
当设置为”Direct”模式,则会直接调用注册的ConsoleObserver派生类重载的函数。 比如,当调用Base::Console().Log(“FreeCAD”),则会调用所有ConsoleObserver派生类重载的Log函数。 |
|
ConsoleMsgFlags SetEnabledMsgType(const char* sObs, ConsoleMsgFlags type, bool b) |
enum FreeCAD_ConsoleMsgType { MsgType_Txt = 1, MsgType_Log = 2, MsgType_Wrn = 4, MsgType_Err = 8 } |
用于控制监测器sObs是否相应对应的输出。 例如: SetEnabledMsgType(“Log”,2,false); 则将关闭名字为Log的ConsoleObserver对象毁掉Log函数。 |
|
除了在ConsoleSingleton全局对象级别控制日志输出之外,LogLevel类可以个性化地设置日志输出以生成日志,然后可将生成的日志字符串流输出到ConsoleSingleton全局对象。
LogLevel::LogLevel(const char *tag, bool print_tag=true, bool print_src=false,
bool print_time=false, bool add_eol=true, bool refresh=false)
在创建LogLevel对象的时候,指定不同的输出控制,然后调用LogLevel::prefix来生成符合配置的字符串流。
std::stringstream &LogLevel::prefix(std::stringstream &str, const char *src, int line)
ConsoleObserver-ConsoleSingleton实现了一种简单的观察者模型。首先通过ConsoleSingleton:: AttachObserver(ConsoleObserver *pcObserver)向ConsoleSingleton注册观察者,当要用ConsoleSingleton的Message()、Log()等函数输出日志的时候,变回调用观察者实现的Message()、Log()等函数。
base64_encode是将指定长度的源字符串转换成另一个字符串;base64_decode的作用与此相反。
std::string BaseExport base64_encode(unsigned char const* , unsigned int len);
std::string BaseExport base64_decode(std::string const& s);
Debugger类提供了运行时调试程序的功能。
FileInfo类提供了访问文件路径、文件名、文件大小、文件权限等文件属性的功能,同时提供了创建文件夹、重命名文件、删除文件等操作。
fdostream、fdistream提供了输出、读入指定文件描述符关联的数据的操作。在构造的时候,需要指定一个文件描述符。
fdostream::fdostream (int fd)
fdistream::fdistream (int fd)
ogzstream、igzstream采用zlib库输出、读入gz格式的文件。
ogzstream::ogzstream( const char* name, int mode = std::ios_base::out, int comp = 1)
igzstream::igzstream( const char* name, int open_mode = std::ios_base::in, int comp = 1)
StdInputStream、StdInputSource使用Xerces读入二进制、文本格式的XML文件。
StdInputStream::StdInputStream ( std::istream& Stream, XERCES_CPP_NAMESPACE_QUALIFIER MemoryManager* const manager = XERCES_CPP_NAMESPACE_QUALIFIER XMLPlatformUtils::fgMemoryManager );
StdInputSource:: StdInputSource ( std::istream& Stream, const char* filePath, XERCES_CPP_NAMESPACE_QUALIFIER MemoryManager* const manager = XERCES_CPP_NAMESPACE_QUALIFIER XMLPlatformUtils::fgMemoryManager )
ConsoleSequencer类可以将操作进度输出到控制台窗口,而SequencerLauncher是为了简化使用ConsoleSequencer的使用而引入的,实际上会在堆上创建ConsoleSequencer对象,然后利用将ConsoleSequencer对象进度信息显示的控制台。
SequencerLauncher seq("my text", 10);
for (int i = 0; i < 10; i++)
{
// do something (e.g. here can be thrown an exception)
// ...
seq.next();
}
FutureWatcherProgress继承自QObjec,内部包含一个SequencerLauncher对象,提供了基于事件的进度显示功能。
void FutureWatcherProgress::progressValueChanged(int v)
UUID 是 通用唯一识别码(Universally Unique Identifier)的缩写,Uuid类用于生成UUID。
ParameterGrp基于观察者模式与引用计数功能用于表示软件运行参数。而且提供多种接口以方便的获取整形、浮点型、布尔类型的参数值。
ParameterManager继承自ParameterGrp,通过内部ParameterSerializer类型对象可以加载、导出DOM格式的参数文件,
MemCheck提供了Windows平台下内存检测的功能,主要包括内存泄漏、堆指针有效性分析等功能。
StackWalker用于输出函数调用栈的信息。
六、Python封装
首先,FreeCADMainPy、FreeCADGuiPy分别定义了FreeCAD、FreeCADGui的Python模块入口(同时提供FreeCADInit.py、FreeCADGuiInit.py两个脚本用于初始化FreeCAD、FreeCADGui模块),实现在Python解释器中导入FreeCAD、FreeCADGui模块相关功能。FreeCAD、FreeCADGui则使用Python C API、CXX对FreeCAD C++代码进行了包装。
其次,mod目录下的Python代码编写的扩展则在FreeCAD、FreeCADGui这两个模块基础之上,完成了具体的功能需求实现。
另外,FreeCADGui模块也内置了一个Python解释器,在FreeCAD界面程序中可以交互式地运行Python命令与代码。