|
一、引言 . ?( D) u4 ?( S& ~+ S0 ]
; K. k! ~" n5 w0 a' L1 N
在进行产品设计时,很多时候只是设计出了产品的几何特征和属性,在图纸中很少涉及到其它非图形特征属性,如零件的材料、生产数量、拓扑关系等。这些非图形特征往往通过标注来实现,但在图纸本身的数据库中并没有保存这些有用的非图形特征信息。随着计算机技术的发展,尤其是网络和数据库的发展和成熟,图纸数据库中若不包含必要的非图形特征信息,就很难实现零件之间的关联及信息的相互利用,很难充分实现信息的共享。
! Z5 x) \& t- O# b' r' W, e$ n2 v4 _, q# c2 E; v. q) P
AutoCAD 2000 以其强大的功能及对二次开发的支持和开放性,成为众多设计人员采用的工作平台和二次开发平台。它不仅能存储所生成图形的几何信息和其它相关信息,而且还允许用户建立自己的“非图形特征信息”,以便在图形文件中提供必要的较完整的产品数据,实现零件信息的自动统计,不同零部件的关联设计,自动提取所需零件及图纸的相关特征参数等,为后续开发和生产提供保障。 " _- p/ P" d8 ~- I3 A. Q1 A9 A& S
' l7 I1 a. {, x2 l
二、 非图形特征的存储和提取方法 * F1 ?, W. G- |
& |5 G1 X2 i. S% J8 \1 ^' ]
在AutoCAD中,图形是指存储在数据库中的对象的集合。基本的数据库对象包括实体、符号表和字典。实体是一种指定类型的数据库对象,它在AutoCAD中有图形表示,如直线、圆、曲线和文字等;符号表和字典是用来存储数据库对象的容器对象。ObjectARX 使用户的应用程序能够访问这些数据库对象,另外,用户也可以为指定的应用程序创建新的数据库对象。
v! p) \, y3 _: a6 I3 c0 g8 M9 [; o* n9 D% r, W* U9 b
在通常的设计中,图纸中只包含了各种图形实体及实体的基本属性,如线型、图层和可见性等,一般都不包括基本属性以外的非图形特征属性,如实体的材料、加工方法等。我们可以利用扩展数据(Xdata)和扩展记录对象(Xrecord)来存储其非图形特征参数,为关联设计和CAPP等提供必要的信息。 # r. Y9 I& _$ u
/ ]9 C2 G. K3 E9 l
1.扩展实体数据(Xdata)
! ^) r. \- Q* p3 o5 ~3 e$ L/ j! U( ^/ r. b4 B- o5 j/ N
ObjectARX、Visual Lisp等应用程序都可以创建扩展实体数据(Xdata),扩展实体数据可以附在任何对象上,AutoCAD 只负责维护这些信息,但并不使用这些信息。一个实体的扩展数据由应用程序所建立,跟随在该实体的正常定义数据之后,包含一个或多个1001组。每一组均以一个互不相同的应用程序名开头,扩展数据的组码在1000至1071之间,不同组码对应不同类型的信息。可用以下方法为指定对象附加扩展实体数据,获取指定对象的扩展实体数据。 9 g0 g( W- U) D' D
$ ^% x3 |/ Y G' p (1)为指定对象附加扩展实体数据
$ K, [% m& A9 m9 P# D3 ?
% ?% W+ ~; y5 l1 Q! Y3 P" a! W( Z Acad::ErrorStatus AcDbObject::setXData(const resbuf* xdata);
7 [' v& j5 @/ }, E) _# J5 O
# `; X' E# t6 N: K 其中,xdata 为结果缓冲区链表,包含要添加的信息。 6 g% R5 ~) Q& X M s
7 d; D/ W$ q2 ]; T9 z- I
(2)获取指定对象的扩展实体数据
: v$ b' p% {6 y& ?. s% t
) r* l/ Q3 e. a2 c Acad::ErrorStatus AcDbObject::XData(const char* regappName); + f) s8 j* J( S8 y
) |; D6 p$ P: }1 {' R$ o
其中,regappName 欲获取信息所属的应用程序名。 o0 i$ @! t, U
6 l9 o3 {8 z. O r
2.扩展实体词典和扩展实体记录
0 F+ H! S& y' J3 C) z. G9 k8 |0 U* e- a$ p( @: i
词典用以存储用户自己定义的各类符号表及其他大量数据。扩展实体记录就是一个Resbuf链表。该链表是一个数据组的列表,链表中每一节点都包含一个DXF组码及相关数据。扩展实体记录的DXF组码的范围是1~369,其中的数据没有任何限制,可以被任何其它对象所拥有。我们可以通过以下方法来实现对非图形特征信息的存储和提取。
6 ^! x6 e) \$ j v! d8 ~- p
/ D. A9 D. n% c: a) c1 I (1)创建词典对象 : j9 w+ Z' b V
4 C% {2 d( |/ r; E Acad::ErrorStatus createExtensionDictionary();
8 K+ p5 J3 T5 y. ?! y0 l) g9 a& Q' \5 H, w8 q0 C
(2)添加对象到扩展数据词典 , J+ j- M1 j: M1 M& H
- p( W8 Z; g- @) v: B Acad::ErrorStatus;
5 {' G, a% W7 K) n" Z S$ K5 `- g( C6 Q7 @/ T! Q8 q3 l
setAt(char* Key,AcDbObject* obj,AcDbObjectId& retobjId); & N6 J9 u( Q. K8 o _
) B5 |. B3 G- r8 n" g# y5 R
其中,Key为加入到词典的新对象的索引关键字; 4 s5 I* {0 x6 W0 q! U2 |* r
, Q) b- V% t- E6 L/ B1 l obj为加入到词典的新对象指针;
f6 J! g% x" j2 `
6 a) |- S9 ]* X1 h1 }, _0 P. F retobjId为加入到词典的新对象Id。
: i* Q$ j" F9 t4 [( }: J: u, I8 t" J% I
(3)检索指定关键字的扩展数据词典记录
$ P+ f9 K! A' M) `
' v2 [3 q# D' E9 u; ] Acad::ErrorStatus getAt(const char* entryName,AcDbObject*&entryObj,AcDb::OpenMode mode) const; 6 }4 v8 ?5 d: \: p
j; {# e4 ^; H. R 其中,entryName为指定检索的关键字; * }8 g% o. y4 Q/ r: J& H
7 F2 h m6 b$ i2 ~: w entryObj为返回的检索到的对象指针;
3 [' y) U$ I7 c/ g+ o; m
5 t1 J) n1 b7 M3 X2 d* p* V* j' m mode为对象打开的方式。 / \# f5 l$ k' m) C7 ?& E! m
" O0 A( L( w9 E; M) H' Q
(4)添加数据到扩展数据记录 & ~% M. R5 I" x. k* L+ c
) Z% _. w, ]: O& C7 r/ L/ G% D
Acad::ErrorStatusAcDbXrecord::setFromRb
$ y: Z' W+ `; y& `8 S* {6 `' d/ i) q, X6 q) S
Chain(resbuf& pRb,AcDbDatabase*pDb=NULL); 8 |% T# h( |" Z) C/ T" R% s. L
, h/ K( W& i/ f. R' J9 V$ a
其中,pRb为包含特征信息的结果缓冲区链表。
$ `8 h4 O t, d1 R* {" S4 z! Z2 X# B+ Y9 }" M. b. p W1 ~" @
(5)获取扩展实体记录的内容 6 H" r+ `9 H8 F2 x N
: P1 u5 ^$ r1 u0 R
Acad::ErrorStatusAcDbXrecord::rbChain(resbuf**ppRb,AcDbDatabase*pAuxDb=NULL); + w: [$ i v. S
' ~3 H5 l1 z1 Y* k2 Y J6 b$ {
其中,ppRb为结果缓冲区结构指针。 ' @( V" _9 W0 V4 Q1 T. U/ m- F# c
0 L9 r, T' z$ d8 w 三、非图形特征存储提取方法的应用
. L/ [1 ]& ~8 H/ q& Y# r
* u8 d/ c4 R7 i+ I2 b+ R& Q S9 f 以上介绍了通过扩展实体数据和扩展实体记录对象来存储和提取非图形特征的方法。下面通过3个实例来介绍其应用。
2 U% b8 J1 m! E. d4 H% n
2 l5 y; n, V& f; [9 E: P* b0 I 1.利用扩展实体数据保存和提取实体非图形特征 ( p8 T. a9 f! _$ ~3 b5 D+ |
/ Y* o4 c& M$ l
在工厂电气布线中,需要对电缆设定代号、名称、产地等非几何特征,以便于对电缆等材料进行自动统计等后续工作。 8 m* Q( c/ \; N) i: r6 P
9 u# [# [5 K3 B7 V1 }* x7 X (1)为电缆实体设定非图形特征
( U$ g, P: d1 j, G8 {' o
' i6 N6 _ [+ _! A. h% y; D char appName[40];//应用程序名 ) n' P! {2 \. |6 j( V! q
2 G5 e/ { }" r9 h( i
char daihao[40];//电缆代号 : ^& }4 w4 z B! a% A8 Z9 ~, G
" R7 E* x% V6 [1 R4 T) N2 B char mingcheng[40];//电缆名称 8 Y! G' ?+ H1 q
# N; S1 ^% v3 X
ads_real length;//电缆长度
5 G4 x, g0 Y- @. k* [! N/ M" _- Y4 I+ b5 Y4 \' X3 d
struct resbuf *pRb,*pTemp;
* H+ G9 k4 \& L- E2 ^8 U# e i* Q+ N# ], [" T7 A, C y; Y
……//通过对话框等方式对daihao,mingcheng,length赋初值
- h* M% X H/ J5 N8 ~* _4 i& A0 `: ]. d+ `$ r" e
strcpy(appName,“diqibuxian”); , z' @( u" k. X' h9 I- s2 A1 U6 e
$ H+ L6 s3 _, g5 e/ k. D" s& U
acdbRegApp(appName);//以appName登记图形中一个应用程序名
4 e+ j% k, I. D6 M$ X/ ?! V
" l i, Y* W- K, @( r& a! e pRb = acutNewRb(AcDb::kDxfRegAppName);//分配结果缓冲器 ) g- i; h( b4 `; t
+ u+ |6 m1 o8 V p, {: I4 a( x5 s pTemp = pRb;
k2 q- ~, a( N4 X5 e4 H- ^0 I/ U9 a, H' ~8 i
pTemp->resval.rstring= (char*)malloc(strlen(appName)+1);
4 W' I; g, V. M ^. Q. _/ S u9 }3 N x- v5 J. O5 B3 w" S
strcpy(pTemp->resval.rstring, appName);//将数据存入结果缓冲器链表 0 d9 B1 x# G( B+ A
/ `" ^2 o. l1 g& @
pTemp->rbnext=acutNewRb(AcDb::kDxfXdAsciiString);
" p0 s% i+ {& D; X y) c
0 q* R& o1 H- S! } S g pTemp=pTemp->rbnext;
" l) q# c, T0 K0 }; _
% A; C5 R, R9 z5 [ pTemp->resval.rstring= (char*)malloc(strlen(daihao)+1); ?/ d0 B3 f! p5 w
0 e. y7 O9 s/ i2 S- e+ D strcpy(pTemp->resval.rstring, daihao); file://将[/COLOR]代号存入结果缓冲器链表 7 u3 E$ X4 U) @6 ?2 N* [1 X
# `+ U+ R w$ g0 \% c
……
; ]! `+ l3 ^0 k, a2 ?
/ z- E, A3 O5 z pTemp->rbnext=acutNewRb(AcDb::kDxfxdLong); ; h' B% M/ n/ D# \. {# H2 p
8 ]) k, b& m5 M8 h+ j: D
pTemp=pTemp->rbnext;
# B, D1 W0 j. N! Z0 N) l
3 g, o' A% d! \( w pTemp->resval.rreal=length;
6 W3 R# @8 ~' ]6 s2 X R3 I- e2 }7 r; l* x! M
AcdbObject *pObj;//通过一定的方式获取需要添加数据的对象 4 v% G6 @+ D w ~
/ Q: s" \1 p5 Z2 O8 t9 w3 [ pObj->SetXData(pRb);//为对象添加扩展实体数据
0 {5 S+ I6 T3 w/ d% N
9 g/ w: d8 c- ~% _ pObj->close();
+ F* I/ P7 G3 n% O" v( j8 R( K# d+ z9 R. n, {
acutRelRb(pRb); ! z1 g% u! ]3 k
0 N% O; L l9 t9 @
(2)获取指定对象的扩展实体数据 e+ j" s4 N4 o N6 S3 ?% L. W
, M6 |3 N4 Y+ Y# p AcDbObject* pObj;
: ?. u% d: G; F: D8 u" Q! A" }& i3 k
. `0 S+ x8 b2 q* h4 H7 F1 i char appName[40];//应用程序名
5 L0 K# |3 B% y" M. f) ?
) q! ^; X3 \$ e- W( \ char daihao[40];//电缆代号 " v( ~% v6 h, h' [) N: n' P
3 x5 c+ I* v0 w. K" H7 C) u4 f6 B; n char mingcheng[40];//电缆名称
6 Y# a! k7 m7 U4 [% p9 p3 n
1 z! e2 K7 V4 { ads_real length;//电缆长度 3 T' h: I# {$ _. ^! L
' G& M+ i8 K$ S! {' K struct resbuf *pRb; " l. P. g/ N5 h% g" X
3 k9 t+ q% o/ \! v0 ~' N: K strcpy(appName,“dianqibuxian”); 8 n( L% ^' r& v% H7 w
# b9 m* b2 a, n
pRb=pObj->xData(appName);//获取应用名appName指定的扩展数据 ' r5 z: P# w1 ~+ E) [+ i, T& @8 f
$ p( ^1 [. M' h, A) q J% Z5 I! B
if(pRb!=NULL) 3 x, P& X/ f& K2 u0 O
' v# b/ V1 z3 S' ~
{ int n=0;
& C5 v4 l+ @2 v$ f3 {2 M" h" i0 B) Z/ R& c _& R/ ^) F
for(;pRb!=NULL;pRb=pRb->rbnext)
' w; \9 ?, I: a1 K# E1 T; y4 z* c( g8 V+ [
{ if(pRb->restype==1000)
' K; S- p7 f* ^8 C: W
5 j3 }( o: n1 o9 i { n++;
" R2 b9 Q# n' O# C' p! o- K, Q/ m. c+ W! j" m6 X0 Z
if(n==1)
( f- M, d4 {" d' J9 i& N6 i
# c0 L$ Q% M$ ^% Q# `* @ L$ ` strcpy(daihao,pRb->resval.rstring);//得到电缆代号 . L, M' d+ s+ D7 N# D5 ?/ a
0 \% K* C5 m& _; t* Z* S if(n==2) % Y! D8 I w* T5 ]/ I
+ n! U5 d$ F. R; Q strcpy(mingcheng,pRb->resval.rstring);//得到电缆名称 . p% d1 I5 Z$ [! D; L- @# {
$ O+ ?5 e2 Q5 i0 m; h. y } 2 u- z. ? n* e3 _
+ S' Y, ]' E h if(pRb->restype==1040)
# C4 n" M' h; b! P$ b3 ^1 o& Q; }7 p1 D, U/ M) Y K ^
length=pRb->resval.rreal;
# i4 P! D& A k. s5 b% C- w O6 [. j2 m1 A# y c. t
}
; I$ A2 @4 a; F9 B4 N
$ P' t6 P4 o: e3 Z' O }
: h2 m; R t! k+ u8 H3 {
# P- u% B# ?9 ~: N acutRelRb(pRb); 9 ?" f, J( u# P3 U, J G$ c% H
( Z& |2 s# H/ k3 Z 2.利用扩展记录对象实现关联设计 ' ?* Y7 M* U& p; i. @
# ~1 c# q( X2 F( j& t s, m 在参数化设计过程中,零件甲中的某些参数与零件乙的设计有关联。我们设计零件乙时就需要从零件甲的图纸数据库中获取所需的参数,实现关联设计。
8 d+ z% i/ d2 @9 X. {: ~
+ \6 @$ V& ^# v/ S7 f! Y (1) 在零件甲的图纸空间中保存关联参数
$ U' F4 y7 k; w- E
: S+ w$ L- o6 I" J ads_real bl,fl;//零件甲与零件乙相关联的参数 3 U* h8 ` a- ^2 e# Z
/ |# e+ |# W7 t2 d4 f* S AcDbDictionary *pNamedobj, *pDict; 2 a" {7 J2 }5 c1 Y" Q) g
3 d7 @1 C* [0 c" \3 v acdbHostApplicationServices()->workingDatabase()
. B5 l1 E9 _0 D" L Q) D. l& J+ v. N9 V0 O) H
->getNamedObjectsDictionary(pNamedobj, AcDb::kForWrite); / d" i3 X5 d3 Z( g2 d' y$ T/ |" t8 l) a
1 o6 j0 ?* q8 Z3 p% T4 z
file://获[/COLOR]取当前数据库中的命名对象字典
+ S7 {2 c M( `& ^8 g' d" c& j( `( C$ ]' ?& x/ A1 b
pNamedobj->setAt("Guanliansheji", pDict, DictId);
2 c5 z. p) {9 o H6 U% {4 j$ E; B- f3 Q h+ P5 P/ r& M
pNamedobj->close();
# K3 I( N/ w' V+ T, A$ N m, Z: @% f9 d: n; R
AcDbXrecord *pXrec = new AcDbXrecord;
* E5 b: b% ]! ]. s; ?5 @5 _. Q6 a" ^* X) n' r$ h
AcDbObjectId xrecObjId; ; |: Y" q* h" V. T8 @1 Z5 I4 @' a( u9 y
0 D5 Y& r& Y" }4 R+ ?6 M6 {
pDict->setAt("XREC1", pXrec, xrecObjId);
- [* g7 Z6 L& x# S) R4 z1 G
0 B7 l6 |6 @! [. ` pDict->close(); . Q4 t! V u- P8 ?# I5 h
7 e3 m$ p: @% L" s; t `3 C6 Z, g9 e& n7 F
struct resbuf *pHead;
" c) B0 W- a# X' j4 z* t1 O) h, w! e( b
pHead = acutBuildList(AcDb::kDxfReal, bl,AcDb::kDxfReal,fl,0);
' x1 n+ D0 `+ h! n" O' Y5 m& \6 p0 Y! H) v- M. B+ D( x
file://设[/COLOR]置包含参数bl,fl的结果缓冲器链表
: `/ x2 H; X' t; C2 u9 u8 `7 j2 }9 @) F" T- {! U
pXrec->setFromRbChain(*pHead);//给扩展记录对象附加信息 7 w: z" Q. ~- R4 P
* r: [2 C. b% ^+ U0 l acutRelRb(pHead); 4 y% G6 q) X x# A( z$ [
K6 p1 G- O! h
pXrec->close(); ' d. q9 \/ B# w5 o$ P5 |
7 t4 }5 F( g J' J (2) 在设计零件乙的过程中,从零件甲的图形文件中获取所需的相关参数 " X. x: d; E9 E8 E {
, q6 N( s! X$ A3 k AcDbDatabase* pDb = new AcDbDatabase(false, true); 5 t4 y+ k5 k! V
/ d- v# K# W8 \2 i: [# @$ O
pDb->readDwgFile(fname);//fname为零件甲的图形文件名 ( t6 X& t5 e' b+ R3 e6 Y& h& B
' I* r$ D& ^+ J
AcDbDictionary *pNamedobj; : V" X1 Z# X+ [. U* E) S
7 O& a0 D& s" P8 Q pDb->getNamedObjectsDictionary(pNamedobj, AcDb::kForRead); 8 x7 @$ p# X1 O
* ~2 Z8 b+ Z% J4 y: j
AcDbDictionary *pDict;
# o3 y8 G' a( w$ z! D* R4 G4 v+ p) r0 w. Q# i+ y
pNamedobj->getAt("Guanliansheji", (AcDbObject*&)pDict, - P8 ~6 @4 k# p" M& P8 |
0 \ }+ h* P& N" i3 b, C
AcDb::kForRead);//获取名为Guanliansheji的数据词典 - q8 \0 W" y: T5 x( X# r
. \$ o1 x+ E w* y
pNamedobj->close();
H1 u# X# R* [% B. @
2 {1 G8 v: j2 I- R. n AcDbXrecord *pXrec;
+ G1 [( ^) i/ S, S4 a- [
& T) k1 J5 _4 Y0 w9 d- ]8 Q1 E pDict->getAt("XREC1", (AcDbObject*&) pXrec,AcDb::kForRead);
% m2 b: S1 W) r) `, c
# U- N+ M+ l7 @' j2 ] file://获[/COLOR]取关键字为XREC1的扩展记录对象
\ b" `% f; h* P0 M8 V' i2 g7 r4 d3 _ ~; k; I+ s
pDict->close(); % o1 r8 B9 K2 U$ S- ?
/ X3 K# X8 [+ _3 y, v8 X struct resbuf *pRbList;
. E' f. J. I/ j( S
7 H8 h* p. |6 H( J pXrec->rbChain(&pRbList);//获取包含特征信息的结果缓冲器链表
4 E. M- k& D: y" V! W6 {) Q+ E
pXrec->close();
0 y# p# F2 b$ O5 x, I v6 p0 n; ?8 ]4 E) N* \
bl=pRbList->resval.rreal;//获取关联参数bl
6 m! }* n7 r) q3 g: x( I7 f- o) B
5 r4 i" W' o' n5 |4 a# Z4 o pRbList=pRbList->rbnext; + s# l% \0 h2 J2 {
0 X, h6 b$ q1 K* T5 u6 \$ x) P1 a. d+ { fl=pRbList->resval.rreal; file://获[/COLOR]取关联参数fl & w5 Q5 S) E% ?) h7 E
% R4 E6 E* c3 ~ acutRelRb(pRbList); $ |( G" x F* w& s7 Q' z
' ^' J- |% V6 l+ p: c$ A" d 3. 其他应用
, ]7 @% k# V6 I1 F9 H8 }: q
2 O: i2 K% V4 c 前面介绍了如何利用扩展实体数据和扩展记录对象来存储和提取非图形特征,除此以外,还有更多的应用。例如,在CAPP中自动提取零件的一些特征参数供工艺设计用,可减少重复的工作,提高整个设计过程的效率。 8 ^% J$ X9 B! b" L
+ i' G! P0 N: M y8 e 四、结束语
! x! p3 B, `' v% B0 S
9 J+ ^. E: z0 L. }1 ?7 B 本文介绍了在AutoCAD中通过二次开发程序来实现非图形特征信息的存储和提取,这些方法可以大大提高图纸数据库中的信息含量,从而为后续的产品设计和开发工作提供基础,大大提高设计效率。
1 r N- J$ L5 L! R; J$ l" i8 ^) ?! M( R0 W( q+ L+ E
|
|