文档的范围
•C/C++
•GLSL 程序
•OpenCL 内核
•TCL 脚本和测试用例
命名约定
一般命名规则
国际语言 [强制性]
有意义的名称
•包含单词 Geom 或 Geom2d 的包与几何数据和操作有关。
•包含单词 TopoDS 或 BRep 的包与拓扑数据和操作有关。
•以 ...Test 结尾的包定义了 Draw Harness 插件。
•以 Get... 和 Set... 开头的方法通常分别负责检索和存储数据。
相关名称
驼峰式大小写
Standard_Integer awidthofbox; // this is bad
Standard_Integer width_of_box; // this is bad
Standard_Integer aWidthOfBox; // this is OK
开发单元的名称
单元名称中不使用下划线 [强制性]
文件扩展名 [强制性]
•.cxx – C++ 源文件
•.hxx – C++ 头文件
•.lxx – 包含内联方法定义和辅助代码的附加头文件
工具包名称的前缀 [强制性]
工具包名称应以前缀 TK 开头,后面跟着一个有意义的部分,解释工具包所涵盖的功能领域(例如 TKOpenGl)。
公共类型的名称
<package-name>_<class-name>
typedef NCollection_IndexedDataMap<TCollection_AsciiString,TCollection_AsciiString,TCollection_AsciiString> TColStd_IndexedDataMapOfStringString;
函数名称
• 任何类方法
• 任何包方法
• 任何非成员过程或函数
class MyPackage_MyClass
{
public:
Standard_Integer Value() const;
void SetValue (const Standard_Integer theValue);
private:
void setIntegerValue (const Standard_Integer theValue);
};
变量名称
变量命名
Standard_Integer Elapsed_Time = 0; // this is bad - possible class name
Standard_Integer gp = 0; // this is bad - existing package name
Standard_Integer aGp = 0; // this is OK
Standard_Integer _KERNEL = 0; // this is bad
Standard_Integer THE_KERNEL = 0; // this is OK
函数参数名称
void Package_MyClass::MyFunction (const gp_Pnt& p); // this is bad
void Package_MyClass::MyFunction (const gp_Pnt& theP); // this is OK
void Package_MyClass::MyFunction (const gp_Pnt& thePoint); // this is preferred
类成员变量名称
Standard_Integer counter; // This is bad
Standard_Integer myC; // This is OK
Standard_Integer myCounter; // This is preferred
全局变量名称
Standard_Integer MyPackage_myGlobalVariable = 0;
Standard_Integer MyPackage_MyClass_myGlobalVariable = 0;
文件内的静态常量应使用大写字母编写,并以前缀 THE_ 开头:
namespace
{
static const Standard_Real THE_CONSTANT_COEF = 3.14;
};
局部变量名称
Standard_Integer theI; // this is bad
Standard_Integer i; // this is bad
Standard_Integer index; // this is bad
Standard_Integer anIndex; // this is OK
避免使用虚拟名称
避免使用虚拟名称,如 i、j、k。这样的名称没有意义,且容易混淆。
当多次使用这样的虚拟名称时,代码变得越来越复杂,或者在不同的迭代范围内使用时,等等。
以下是首选风格的一些示例:
void Average (const Standard_Real** theArray,
Standard_Integer theRowsNb,
Standard_Integer theRowLen,
theResult)
{
theResult = 0.0;
for (Standard_Integer aRow = 0; aRow < aRowsNb; ++aRow)
{
for (Standard_Integer aCol = 0; aCol < aRowLen; ++aCol)
{
theResult += theArray[aRow][aCol];
}
theResult /= Standard_Real(aRowsNb * aRowLen);
}
}
格式化规则
为了提高开源代码的可读性,从而提高可维护性,以下是应用的一组规则。
国际语言 [强制性]
所有源代码中的注释必须使用英文。
行长度
尽量在所有源代码中保持每行120个字符的限制。
C++风格注释
在 C++ 源代码中,推荐使用 C++ 风格的注释。
注释掉未使用的代码
删除未使用的代码,而不是注释掉或使用 #define。
源代码中的缩进 [强制性]
所有源代码的缩进应设置为两个空格字符。禁止使用制表符字符进行缩进。
分隔空格
标点规则遵循英语语言的规则。
•C/C++ 保留字、逗号、冒号和分号后面如果不是行尾,应跟一个空格字符。
•'(' 后面和 ')' 前面不应有空格字符。闭合和开放括号之间应有一个空格字符。
•为了更好的可读性,还建议在常规运算符周围加上一个空格字符。例如:
在布尔表达式中,建议在逻辑运算符周围使用空格:
while (true) // NOT: while( true ) ...
{
DoSomething (theA, theB, theC, theD); // NOT: DoSomething(theA,theB,theC,theD);
}
for (anIter = 0; anIter < 10; ++anIter) // NOT: for (anIter=0;anIter<10;++anIter){
{
theA = (theB + theC) * theD; // NOT: theA=(theB+theC)*theD
}
指针和引用的声明
Standard_Integer *theVariable; // not recommended
Standard_Integer * theVariable; // not recommended
Standard_Integer* theVariable; // this is OK
Standard_Integer *&theVariable; // not recommended
Standard_Integer *& theVariable; // not recommended
Standard_Integer*& theVariable; // this is OK
Standard_Integer **theVariable; // not recommended
Standard_Integer ** theVariable; // not recommended
Standard_Integer** theVariable; // this is OK
Standard_Integer *theA, theB, **theC; // not recommended (declare each variable independently)
分隔逻辑块
// check arguments
Standard_Integer anArgsNb = argCount();
if (anArgsNb < 3 || isSmthInvalid)
{
return THE_ARG_INVALID;
}
// read and check header
...
...
// do our job
...
...
注意应避免使用多个空行。
分隔函数体 [强制性]
// =======================================================================
// function : TellMeSmthGood
// purpose : Gives me good news
// =======================================================================
void TellMeSmthGood()
{
...
}
// =======================================================================
// function : TellMeSmthBad
// purpose : Gives me bad news
// =======================================================================
void TellMeSmthBad()
{
...
}
代码块布局 [强制性]
while (expression)
{
...
}
单行操作符
if (!myIsInit) return Standard_False; // bad
if (thePtr == NULL) // OK
return Standard_False;
if (!theAlgo.IsNull()) // preferred
{
DoSomething();
}
常量比较表达式
if (NULL != thePointer) // Yoda style, not recommended
if (thePointer != NULL) // OK
if (34 < anIter) // Yoda style, not recommended
if (anIter > 34) // OK
if (theNbValues >= anIter) // bad style (constant function argument vs. local variable)
if (anIter <= theNbValues) // OK
if (THE_LIMIT == theValue) // bad style (global constant vs. variable)
if (theValue == THE_LIMIT) // OK
对齐
MyPackage_MyClass anObject;
Standard_Real aMinimum = 0.0;
Standard_Integer aVal = theVal;
switch (aVal)
{
case 0: computeSomething(); break;
case 12: computeSomethingElse (aMinimum); break;
case 3:
default: computeSomethingElseYet(); break;
}
注释的缩进
while (expression) //bad comment
{
// this is a long multi-line comment
// which is really required
DoSomething(); // maybe, enough
DoSomethingMore(); // again
}
早期返回语句
Standard_Integer ComputeSumm (const Standard_Integer* theArray,
const Standard_Size theSize)
{
Standard_Integer aSumm = 0;
if (theArray == NULL || theSize == 0)
{
return 0;
}
... computing summ ...
return aSumm;
}
Standard_Integer ComputeSumm (const Standard_Integer* theArray,
const Standard_Size theSize)
{
Standard_Integer aSumm = 0;
if (theArray != NULL && theSize != 0)
{
... computing summ ...
}
return aSumm;
}
尾随空格
头文件顺序
// the header file of implemented class
// OCCT headers
// Qt headers
// system headers
文档规则
•注释易于获取 - 它们总是与源代码一起;
•在源代码修改时,很容易更新注释中的描述;
•源代码本身是描述各种细节的好上下文,这些细节在单独的文档中需要更多的解释;
•总之,这是最具成本效益的文档。
记录类 [强制性]
记录类方法 [强制性]
//! Method computes the square value.
//! @param theValue the input value
//! @return squared value
Standard_Export Standard_Real Square (Standard_Real theValue);
记录 C/C++ 源代码
应用程序设计
允许可能的继承
避免友元声明
设置/获取方法
隐藏虚拟函数 [强制性]
避免混合错误报告策略
最小化编译器警告 [强制性]
在编译源代码时注意并尽量最小化编译器警告。
避免不必要的包含
通用 C/C++ 规则
包装全局变量 [强制性]
避免私有成员
常量和内联函数超过定义 [强制性]
避免显式数值 [强制性]
三个强制性方法
虚拟析构函数
覆盖虚拟方法
class MyPackage_BaseClass
{
public:
Standard_EXPORT virtual Standard_Boolean Perform();
};
class MyPackage_MyClass : public MyPackage_BaseClass
{
public:
Standard_EXPORT virtual Standard_Boolean Perform() Standard_OVERRIDE;
};
默认参数值
不要在继承的函数中重新定义默认参数值。
使用 const 修饰符
尽可能地使用 const 修饰符(函数参数、返回值等)。
使用 goto 的情况 [强制性]
除非真的需要,否则避免使用 goto 语句。
在 for() 头声明变量
Standard_Real aMinDist = Precision::Infinite();
for (NCollection_Sequence<gp_Pnt>::Iterator aPntIter (theSequence);
aPntIter.More(); aPntIter.Next())
{
aMinDist = Min (aMinDist, theOrigin.Distance (aPntIter.Value()));
零值条件语句
void Function (Standard_Integer theValue,
Standard_Real* thePointer)
{
if (!theValue) // bad style - ambiguous logic
{
DoSome();
}
if (theValue == 0) // OK
{
DoSome();
}
if (thePointer != NULL) // OK, predefined NULL makes pointer comparison cleaner to reader
{ // (nullptr should be used instead as soon as C++11 will be available)
DoSome2();
}
}
可移植性问题
提供代码可移植性 [强制性]
避免使用全局变量 [强制性]
避免显式使用基本类型
使用 sizeof() 计算大小 [强制性]
文件末尾的空行 [强制性]
稳定性问题
使用 OSD::SetSignal() 捕获异常
交叉引用的句柄
class Slave;
class Master : public Standard_Transient
{
...
void SetSlave (const Handle(Slave)& theSlave)
{
mySlave = theSlave;
}
...
private:
Handle(Slave) theSlave; // smart pointer
...
}
class Slave : public Standard_Transient
{
...
void SetMaster (const Handle(Master)& theMaster)
{
myMaster = theMaster.get();
}
...
private:
Master* theMaster; // simple pointer
...
}
C++ 内存分配
匹配 new 和 delete [强制性]
aPtr1 = new TypeA[n]; ... ; delete[] aPtr1;
aPtr2 = new TypeB(); ... ; delete aPtr2;
aPtr3 = Standard::Allocate (4096); ... ; Standard::Free (aPtr3);
管理动态分配的方法 [强制性]
未初始化变量 [强制性]
Standard_Integer aTmpVar1; // bad
Standard_Integer aTmpVar2 = 0; // OK
不要隐藏全局 new
赋值运算符
浮点数比较
if (Abs (theFloat1 - theFloat2) < theTolerance)
{
DoSome();
}
•Precision::Confusion() 用于以米为单位的长度;
•Precision::Angular() 用于以弧度为单位的角度。
•Precision::Infinite()
•Precision::IsInfinite()
•Precision::IsPositiveInfinite()
•Precision::IsNegativeInfinite()
非索引迭代
不要在析构函数中抛出异常
赋值给引用 [强制性]
性能问题
类字段对齐
字段初始化顺序 [强制性]
class MyPackage_MyClass
{
public:
MyPackage_MyClass()
: myPropertyA (1),
myPropertyB (2) {}
// NOT
// : myPropertyB (2),
// myPropertyA (1) {}
private:
Standard_Integer myPropertyA;
Standard_Integer myPropertyB;
};
初始化优于赋值
MyPackage_MyClass()
: myPropertyA (1) // preferred
{
myPropertyB = 2; // not recommended
}
优化缓存
Standard_Real anArray[4096][2];
for (Standard_Integer anIter = 0; anIter < 4096; ++anIter)
{
anArray[anIter][0] = anArray[anIter][1];
}
Standard_Real anArray[2][4096];
for (Standard_Integer anIter = 0; anIter < 4096; ++anIter)
{
anArray[0][anIter] = anArray[1][anIter];
}
Draw Harness 命令
返回值
验证输入参数
验证输入参数的数量
if (theArgsNb != 3)
{
std::cout << "Syntax error - wrong number of arguments!\n";
return 1;
}
Standard_Integer anArgIter = 1;
Standard_CString aResName = theArgVec[anArgIter++];
Standard_CString aFaceName = theArgVec[anArgIter++];
TopoDS_Shape aFaceShape = DBRep::Get (aFaceName);
if (aFaceShape.IsNull()
|| aFaceShape.ShapeType() != TopAbs_FACE)
{
std::cout << "Shape " << aFaceName << " is empty or not a Face!\n";
return 1;
}
DBRep::Set (aResName, aFaceShape);
return 0;
消息打印
参数列表
myCommand -flag1 value1 value2 -flag2 value3
参数解析器
• 整数值应使用 Draw::Atoi() 函数读取。
• 实数值应使用 Draw::Atof() 函数读取。
• 标志名称应以不区分大小写的方式检查。
Standard_Real aPosition[3] = {0.0, 0.0, 0.0};
for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
{
Standard_CString anArg = theArgVec[anArgIter];
TCollection_AsciiString aFlag (anArg);
aFlag.LowerCase(); //!< for case insensitive comparison
if (aFlag == "position")
{
if ((anArgIt + 3) >= theArgsNb)
{
std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
return 1;
}
aPosition[0] = Draw::Atof (theArgVec[++anArgIt]);
aPosition[1] = Draw::Atof (theArgVec[++anArgIt]);
aPosition[2] = Draw::Atof (theArgVec[++anArgIt]);
}
else
{
std::cout << "Syntax error! Unknown flag '" << anArg << "'\n";
return 1;
}
}
示例
示例记录类
class Package_Class
{
public: //! @name public methods
//! Method computes the square value.
//! @param theValue the input value
//! @return squared value
Standard_Export Standard_Real Square (const Standard_Real theValue);
private: //! \@name private methods
//! Auxiliary method
void increment();
private: //! \@name private fields
Standard_Integer myCounter; //!< usage counter
};
// ==========================================================
// function : Square
// purpose : Method computes the square value
// ==========================================================
Standard_Real Package_Class::Square (const Standard_Real theValue)
{
increment();
return theValue * theValue;
}
// ==========================================================
// function : increment
// purpose :
// ==========================================================
void Package_Class::increment()
{
++myCounter;
}
Draw Harness 的 TCL 脚本
1 # show fragments (solids) in shading with different colors
2 proc DisplayColored {theShape} {
3 set aSolids [uplevel #0 explode $theShape so]
4 set aColorIter 0
5 set THE_COLORS {red green blue1 magenta1 yellow cyan1 brown}
6 foreach aSolIter $aSolids {
7 uplevel #0 vdisplay $aSolIter
8 uplevel #0 vsetcolor $aSolIter [lindex $THE_COLORS [expr [incr aColorIter] % [llength $THE_COLORS]]]
9 uplevel #0 vsetdispmode $aSolIter 1
10 uplevel #0 vsetmaterial $aSolIter plastic
11 uplevel #0 vsettransparency $aSolIter 0.5
12 }
13 }
14
15 # load modules
16 pload MODELING VISUALIZATION
17
18 # create boxes
19 box bc 0 0 0 1 1 1
20 box br 1 0 0 1 1 2
21 compound bc br c
22
23 # show fragments (solids) in shading with different colors
24 vinit View1
25 vclear
26 vaxo
27 vzbufftrihedron
28 DisplayColored c
29 vfit
30 vdump $imagedir/${casename}.png 512 512
GLSL 程序:
vec3 Ambient; //!< Ambient contribution of light sources
vec3 Diffuse; //!< Diffuse contribution of light sources
vec3 Specular; //!< Specular contribution of light sources
//! Computes illumination from light sources
vec4 ComputeLighting (in vec3 theNormal,
in vec3 theView,
in vec4 thePoint)
{
// clear the light intensity accumulators
Ambient = occLightAmbient.rgb;
Diffuse = vec3 (0.0);
Specular = vec3 (0.0);
vec3 aPoint = thePoint.xyz / thePoint.w;
for (int anIndex = 0; anIndex < occLightSourcesCount; ++anIndex)
{
int aType = occLight_Type (anIndex);
if (aType == OccLightType_Direct)
{
directionalLight (anIndex, theNormal, theView);
}
else if (aType == OccLightType_Point)
{
pointLight (anIndex, theNormal, theView, aPoint);
}
}
return vec4 (Ambient, 1.0) * occFrontMaterial_Ambient()
+ vec4 (Diffuse, 1.0) * occFrontMaterial_Diffuse()
+ vec4 (Specular, 1.0) * occFrontMaterial_Specular();
}
//! Entry point to the Fragment Shader
void main()
{
gl_FragColor = computeLighting (normalize (Normal),
normalize (View),
Position);
}
想了解更多
赶紧扫码关注
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.bianchenghao6.com/h6javajc/26380.html