用VC++读取DXF文件格式的源代码和相关资料.docx
《用VC++读取DXF文件格式的源代码和相关资料.docx》由会员分享,可在线阅读,更多相关《用VC++读取DXF文件格式的源代码和相关资料.docx(18页珍藏版)》请在冰豆网上搜索。
用VC++读取DXF文件格式的源代码和相关资料
我刚找到的:
大家先看看做好了
告诉我一声
我也正准备做这个!
!
我们使用?
Visual?
C++?
6.0?
来写一个读取DXF文件的小程序。
在实际应用中,模型中实体的数目以及实体中点和面的数目都是不定的,为
了有效地利用内存,我们选择MFC类库中的聚合类CobArray类所创建的对象
vertex,?
sequence来存储和管理实体的点坐标和点序。
CObArray类是一个用来存放数组类的聚合类,它能根据要存进来的数组(或
结构)多少自动进行自身大小的高速,而且这个类本身具有的成员函数使得我们
对它的对象的操作更加方便、快捷,用它编的程序也易于读懂。
三维实体模型的模型信息中的一部分信息可以在标题段中读出,通过读取变
量名为$UCSORG的三个变量,可以得到三维实体在世界坐标系中自身所定义的用
户坐标系原点的三维坐标。
通过读取$EXTMAX,$EXTMIN可以获知三维实体在世
界坐标系中的范围,而其它部分的信息只有读完了全部DXF文件后才可以通过计算
确定。
对于三维实体模型的全部点坐标、点序,可以在实体段中按照前面介绍的
DXF文件基本结构读出。
现在我们开始写这个程序。
先建立一个头文件HEAD.H定义如下的结构:
VERTEX,?
SEQUENCE和类CVertex,?
Csequence。
typedef?
struct?
{
float?
x,y,z;
}VERTEX;?
结构VERTEX用来存储点的坐标
typedef?
struct?
{
int?
a,b,c;
}SEQUENCE;?
结构SEQUENCE用来存储实体的面的组成
typedef?
struct?
{
char?
obName[20];?
定义结构myVertex来存储实体的名字,点的坐标以及面的组成,
CObArray?
Vertex;?
其中,点的坐标和面的组成是由聚合类CObArray定义的对象来
CObArray?
Sequence;?
在存储的,我们可以把VERTEX结构和SEQUENCE结构加入到
}myVertex;?
这两个对象中保存
class?
CVertex?
:
?
public?
CObject
{?
因为CObArray类的对象中只能加入由CObject派生的对象,所以
protected:
?
我们还需要建立一个由CObject类派生的CVertex类。
在CVertex类
CVertex();?
中有一个VERTEX结构的变量:
m_vertex,信息实际上是存储在这
DECLARE_DYNCREATE(CVertex)?
个变量中的。
virtual?
~CVertex();
//?
Attributes
public:
?
我们还需要建立一个由CObject类派生的CVertex类。
在CVertex类
CVertex(VERTEX&?
ver);?
中有一个VERTEX结构的变量:
m_vertex,信息实际
上是存储在这个变量中的,函数CVertex(VERTEX&?
ver)把VERTEX结构的变量
VERTEX?
m_vertex;?
存入CObArray对象中。
};
class?
CSequence?
:
?
public?
CObject
{?
这也是一个由CObject类派生的类,作用和刚才CVertex类一样,
protected:
?
只不过Csequence类是用来存储实体中面的组成(点序)的。
CSequence();
DECLARE_DYNCREATE(CSequence)
virtual?
~CSequence();
public:
CSequence(SEQUENCE&?
sequ);
SEQUENCE?
m_sequence;
};
声明好结构与类后,我们还需要建立一个.CPP文件,来定义几个函数。
IMPLEMENT_DYNCREATE(CVertex,CObject)
CVertex:
:
CVertex()
{
}
CVertex:
:
~CVertex()?
构造函数和销毁函数都是空的
{
}
CVertex:
:
CVertex(VERTEX&?
ver)
{?
这个函数的作用是:
把一个VERTEX结构的数据存入变量m_vertex中
m_vertex?
=?
ver;?
它是这个类中最重要的一环。
}
IMPLEMENT_DYNCREATE(CSequence,CObject)
CSequence:
:
CSequence()
{
}?
Csequence类的定义与CVertex类的定义差不多,只是其中的参数
m_sequence的类型和CVertex类中的参数my_vertex的类型不一样
CSequence:
:
~CSequence()
{
}
CSequence:
:
CSequence(SEQUENCE&?
sequ)
{
m_sequence=sequ;
}
对我有用[0]?
丢个板砖[0]?
引用?
|?
举报?
|?
管理
asd123asd
asd123asd
等级:
#7?
得分:
0回复于:
2004-12-1511:
45:
34
然后用结构myVertex(如前所定义)定义一个指针*myData,目的在于根据模
型中实体的多少来给指针分配合适的内存,使之成为结构数组。
定义一个函数,用于确定模型中有多少个实体,函数的返回值就是实体的个数。
int?
CJupiterView:
:
getObjectNumber()
{
char?
str1[10],str2[10];
char?
name[]="theFirst";
int?
num;
num=0;
FILE*?
fp;
fp=fopen("data.dxf","r");?
打开DXF文件,data.dxf
while(!
?
feof(fp)?
&&?
!
?
ferror(fp))?
这个函数是根据实体的名字来判断实体的个数的
{?
所以函数只读取实体的名字,一旦出现新的实体名字,
fscanf(fp,"%s",str1);?
实体数就加一。
if(strcmp(str1,"VERTEX")==0)
{
fscanf(fp,"%s",str2);?
打开DXF文件,data.dxf
fscanf(fp,"%s",str2)?
;这个函数是根据实体的名字来判断实体的个数的
if(strcmp(name,str2)?
!
=?
0)?
所以函数只读取实体的名字,一旦出现新的实体名字,
{实体数就加一。
strcpy(name,str2);
num++;
}
}
}
fclose(fp);
return?
num;
}
以下是读取实体点的坐标以及点序的程序代码,在这个程序中,读取了模型
中点的坐标的最大值与最小值、实体的名字、点的坐标,以及点序。
void?
CJupiterView:
:
OnFileInput()
{
//?
TODO:
?
Add?
your?
command?
handler?
code?
here
FILE*?
fp,*fp2;
int?
i,k,j;
float?
tempX,tempY,tempZ;
float?
xMin,yMin,zMin,xMax,yMax,zMax,Max;
int?
lab;
char?
str1[20],str2[20],str[20],HT;
char?
myName[20];
int?
myNumber;
VERTEX?
tempVertex;
SEQUENCE?
tempSequence;
typedef?
struct?
{
float?
x,y,z,max;
}MAX;
MAX?
max;
HT=9;
objectNumber=getObjectNumber();
myData=new?
myVertex[objectNumber];
fp=fopen(FileName,"r");
i=0;
j=0;
k=0;
myNumber=-1;
strcpy(myName,"ObjectName");
while(!
?
feof(fp)?
&&?
!
?
ferror(fp))
{
fscanf(fp,"%s",str);
if(strcmp(str,"$EXTMIN")==0)
{
fscanf(fp,"%s",str1);
fscanf(fp,"%f",&xMin);
fscanf(fp,"%s",str1);
fscanf(fp,"%f",&yMin);
fscanf(fp,"%s",str1);
fscanf(fp,"%f",&zMin);
}
if(strcmp(str,"$EXTMAX")==0)
{
fscanf(fp,"%s",str1);
fscanf(fp,"%f",&xMax);
fscanf(fp,"%s",str1);
fscanf(fp,"%f",&yMax);
fscanf(fp,"%s",str1);
fscanf(fp,"%f",&zMax);
max.x=max(abs(xMax),abs(xMin));
max.y=max(abs(yMax),abs(yMin));
max.z=max(abs(zMax),abs(zMin));
max.max=max(max.x,max.y);
max.max=max(max.max,max.z);
}
if(strcmp(str,"VERTEX")?
==0)
{
fscanf(fp,"%s",str1);
fscanf(fp,"%s",str1);
if(strcmp(myName,str1)?
!
=?
0)
{
myNumber++;
strcpy(myName,str1);
strcpy((myData+myNumber)->obName,myName);
}
fscanf(fp,"%s",str2);
fscanf(fp,"%f",&tempX);
fscanf(fp,"%s",str2);
fscanf(fp,"%f",&tempY);
fscanf(fp,"%s",str2);
fscanf(fp,"%f",&tempZ);
fscanf(fp,"%d",&lab);
fscanf(fp,"%d",&lab);
if(lab?
==?
192)
{
tempVertex.x=tempX?
/?
max.max;
tempVertex.y=tempY?
/?
max.max;
tempVertex.z=tempZ?
/?
max.max;
(myData+myNumber)->Vertex.Add(new?
CVertex(tempVertex));
}
if(lab?
==?
128)
{
fscanf(fp,"%s",str1);
fscanf(fp,"%f",&tempX);
fscanf(fp,"%s",str1);
fscanf(fp,"%f",&tempY);
fscanf(fp,"%s",str1);
fscanf(fp,"%f",&tempZ);
tempSequence.a=abs(tempX);
tempSequence.b=abs(tempY);
tempSequence.c=abs(tempZ);
(myData+myNumber)->Sequence.Add(new?
CSequence(tempSequence));
}
}
}
fclose(fp);
}?
?
对我有用[0]?
丢个板砖[0]?
引用?
|?
举报?
|?
管理
asd123asd
asd123asd
等级:
#8?
得分:
0回复于:
2004-12-1511:
45:
51
DXF数据接口
每个CAD系统都有自己的数据文件,数据文件分图形数据文件、几何模型文件和产品模型文件几种。
数据文件的格式与每个CAD系统自己的内部数据模式密切相关,而每个CAD系统自己内部的数据模式一般是不公开的,也是各不相同的。
由于用户使用的需要,就有数据交换文件概念的出现。
DXF为AutoCAD系统的图形数据文件,DXF虽然不是标准,但由于AutoCAD系统的普遍应用,使得DXF成为事实上的数据交换标准。
DXF是具有专门格式的ASCII码文本文件,它易于被其它程序处理,主要用于实现高级语言编写的程序与AutoCAD系统的连接,或其它CAD系统与AutoCAD系统交换图形文件。
1?
DXF文件结构?
一个完整的DXF文件是由四个段和一个文件结尾组成的。
其顺序如下:
(1)标题段,记录AutoCAD系统的所有标题变量的当前值或当前状态。
这些标题变量记录了AutoCAD系统的当前工作环境。
例如,AutoCAD版本号、插入基点、绘图界限、SNAP捕捉的当前状态、珊格间距、式样、当前图层名、当前线型和当前颜色等;
(2)表段,包含了四个表,每个表又包含可变数目的表项。
按照这些表在文件中出现的顺序,它们依次为线型表、图层表、字样表和视图表;
(3)块段,记录定义每一块时的块名、当前图层名、块的种类、块的插入基点及组成该块的所有成员。
块的种类分为图形块、带有属性的块和无名块三种。
无名块包括用HATCH命令生成的剖面线和用DIM命令完成的尺寸标注;
(4)元素段,记录了每个几何元素的名称、所在图层的名称、线型名、颜色号、基面高度、厚度以及有关几何数据;
(5)文件结束,标识文件结束。
DXF文件每个段由若干个组构成,每个组在DXF文件中占有两行。
组的第一行为组代码,它是一个非零的正整数,相当于数据类型代码,每个组代码的含义是由AutoCAD系统约定好的,以FORTRAN?
“I3”格式(即向右对齐并且用三字符字段填满空格的输出格式)输出。
组的第二行为组值,相当于数据的值,采用的格式取决于组代码指定的组的类型。
组代码和组值合起来表示一个数据的含义和它的值。
组代码范围见下表。
需要注意的是,在AutoCAD系统中组代码既用于指出如下表所示的组值的类型,又用来指出组的一般应用。
组代码的具体含义取决于实际变量、表项或元素描述,但“固定”的组代码总具有相同的含义,如组代码“8”总表示图层名。
组代码范围跟随值的类型
0-9串
10-59浮点
60-79整数
210-239浮点
999注释
1000-1009串
1010-1059浮点
1060-1079整数
表6.3?
组代码范围
一个DXF文件的框架如下:
0?
......段开始
SECTION?
2?
HEADER?
......该段为标题段
9
$ACADVER?
......下面依次描述所有标题变量
1
AC1003
.
.
.
0
ENDSEC?
......标题段结束
0
SECTION?
......段开始
2
TABLES?
......该段为表段
0
TABLE?
......表开始
2
LTYPE?
......该表为线型表
.
.
.
0
ENDTAB?
......线型表结束
0
TABLE?
2?
LAYER?
......图层表开始
.
.
.
0
ENDTAB?
......图层表结束
0
TABLE
2
STYLE?
......字样表开始
.
.
.
0
ENDTAB?
......字样表开始
0
TABLE
2
VIEW?
......视图表开始
.
.
.
0
ENDTAB?
......视图表结束
0
ENDSEC?
......表段结束
0
SECTION?
2
BLOCKS?
......块段开始
0
BLOCK?
......块开始
.
.
.
ENDBLK?
......块结束
.
.
.
0
ENDSEC?
......块段结束
0
SECTION
2
ENTITIES?
......元素表开始
0
xxxxxxx?
......开始的元素
.
.
.
0
xxxxxxx?
......又一个元素开始
.
.
.
0
ENDSEC?
......元素段结束
0
EOF?
......文件结束
2?
DXF文件接口程序设计
DXF文件格式的设计充分考虑了接口程序的需要,它能够容易地跳过没有必要关心的信息,同时又能方便地提取所需要的信息。
只要记住按何顺序处理各个组并跳过不关心的组即可。
但编写一个输出DXF文件的程序是比较困难的,因为必须保持图形的一致性以使AutoCAD系统接受它。
AutoCAD系统允许在一个DXF文件中省略许多项并且仍可获得一个合法的图形。
如果不需要设置任何标题变量,那么整个HEADER段都可以省略。
在TABLES段中的任何一个表,在不需要时也可以略去,并且事实上如果对它不作任何处理时,整个表段也可以去掉。
如果在LTYPE表中定义了线型,则该表必须在LAYER表之前出现。
如果图中没有使用块定义,则可以省略BLOCKS段。
如果有,那么它必须出现在ENTITIES段之前。
EOF必须出现在文件的末尾。
3?
DXF文件格式存在的问题
(1)由于DXF文件制定的较早,存在很多的不足。
不能完整地描述产品信息模型,产品的公差、材料等信息根本没有涉及。
即使产品的几何模型,由于仅仅保留了原有系统数据结构中的几何和部分属性信息,大量的拓扑信息已不复存在,也是不完整的;
(2)DXF文件格式也不合理,文件过于冗长,使得文件的处理、存放、传递和交换不方便。
另外,复杂的文件格式也使得编写一个读、写完整的DXF数据文件的程序接口是件不容易的工作。
随着CAD/CAM技术的发展和CAD/CAM系统应用的日益广泛,不同系统和系统不同子系统间的数据交换问题变得重要和迫切了,直接推动国家或国际上通用的数据交换文件标准的制定。