解析DXF文件代码为G代码
By
admin
at 2017-12-18 • 0人收藏 • 1395人看过
为了解析dxf代码,去网上下载了好多知网啊豆丁里面的文档,发现都是个坑.....
这些文档大部分都是只讲了dxf文档结构和解析的好处...然后,一笔带过怎么解析...
晕了...
这玩意解析其实也没那么难,敝帚自珍真的是够了..
怪不得国内开源的少的很,看看国外,唉......
dxf文件是cad的一种格式文本,里面包含了cad图的所有线条和属性,
G代码是数控里面用到的一种语言,具体百度.
思路很简单,就是读文本一行行处理,然后提取有用信息, 起始关键点是最后那个收尾排序.
因为dxf里面的线条是按照绘制过程中的顺序存储,所以需要排序,连接,这个才能产生G代码的刀路.
因为使用的图形都是一笔画,而且只包含线段和弧线,所以只做了line和arc判断.
由于编辑器字数限制, 以下代码分为两层楼
import win.ui;
/*DSG{{*/
var winform = win.form(text="aardio form";right=759;bottom=469;acceptfiles=1)
winform.add(
button={cls="button";text='\u2460获取有效数据';left=609;top=363;right=757;bottom=466;font=LOGFONT(h=-21);z=2};
button2={cls="button";text='\u2461生成ARC';left=5;top=363;right=138;bottom=466;font=LOGFONT(h=-21);z=3};
button3={cls="button";text='\u2464生成正序G';left=304;top=363;right=436;bottom=466;font=LOGFONT(h=-21);z=6};
button4={cls="button";text='\u2462排序';left=139;top=363;right=221;bottom=466;font=LOGFONT(h=-21);z=4};
button5={cls="button";text='\u2463结果';left=225;top=363;right=300;bottom=466;font=LOGFONT(h=-21);z=5};
button6={cls="button";text="生成反序G";left=442;top=363;right=579;bottom=466;font=LOGFONT(h=-21);z=7};
edit={cls="edit";left=0;top=0;right=760;bottom=362;edge=1;multiline=1;vscroll=1;z=1}
)
/*}}*/
var filePath,fileContents;
import console;
console.open()
winform.wndproc = function(hwnd,message,wParam,lParam){
select( message ) {
//拖拽文件到窗体里
case 0x233/*_WM_DROPFILES*/{
filePath = win.getDropFile(wParam )[1];
}
else{
}
}
}
class entitiesClass{
line = {};
arc = {};
}
class line{
//线段的第一个点
float x1 = 0.0;
float y1 = 0.0;
float z1 = 0.0;
//线段的第二个点
float x2 = 0.0;
float y2 = 0.0;
float z2 = 0.0;
};
class arc{
//弧形的第一个点
float x1 = 0.0;
float y1 = 0.0;
float z1 = 0.0;
//弧形第二个点
float x2 = 0.0;
float y2 = 0.0;
float z2 = 0.0;
//弧形半径
float R = 0.0;
//弧形圆心点
float xx = 0.0;
float yy = 0.0;
float zz = 0.0;
//弧形起始角度和终止角度
float startN = 0.0;
float endN = 0.0;
};
var G_line = line();
var G_arc = arc();
var entitiesTab = entitiesClass();
var entitiesStart = false;
winform.button.oncommand = function(id,event){
winform.edit.text = "";
fileContents = io.open(filePath,"r+");
fileContents.seek("set");
do{
//读取文件的一行
var stringLine = tostring(fileContents.read());
//去除该行的首尾空白字符之后进行判断
select( string.trim( stringLine ) ) {
case "ENTITIES" {
console.log("找到实体文件! 开始解析:");
entitiesStart = true;
}
case "LINE" {
//只有找到实体线条模块之后,线条类型解析才有效
if(entitiesStart == true){
//循环读取直到找到线属性这行
while( fileContents.read() != "AcDbLine" ){ };
//LINE线属性共有6组,其中每组第一行是特定属性名,第二行是属性值
for(i=1;6;1){
select( string.trim(tostring( fileContents.read() )) ) {
case "10" {
var pos = fileContents.read();
G_line.x1 = tonumber( string.format("%.3f",pos ) );
}
case "20" {
var pos = fileContents.read();
G_line.y1 = tonumber( string.format("%.3f",pos ) );
}
case "30" {
var pos = fileContents.read();
G_line.z1 = tonumber( string.format("%.3f",pos ) );
}
case "11" {
var pos = fileContents.read();
G_line.x2 = tonumber( string.format("%.3f",pos ) );
}
case "21" {
var pos = fileContents.read();
G_line.y2 = tonumber( string.format("%.3f",pos ) );
}
case "31" {
var pos = fileContents.read();
G_line.z2 = tonumber( string.format("%.3f",pos ) );;
}
else {
}
}
}
//每块LINE类型属性读取完毕,放入LINE表中,等待下一步操作
table.push(entitiesTab.line,table.clone(G_line));
}
}
case "ARC" {
if(entitiesStart == true){
//循环读取直到找到线属性这行
while( fileContents.read() != "AcDbCircle" ){ };
//ARC弧线属性共有6组,其中每组第一行是特定属性名,第二行是属性值
for(i=1;6;1){
select( string.trim(tostring( fileContents.read() )) ) {
case "10" {
var pos = fileContents.read();
G_arc.xx = tonumber( string.format("%.3f",pos ) );
}
case "20" {
var pos = fileContents.read();
G_arc.yy = tonumber( string.format("%.3f",pos ) );
}
case "30" {
var pos = fileContents.read();
G_arc.zz = tonumber( string.format("%.3f",pos ) );
}
case "40" {
var pos = fileContents.read();
G_arc.R = tonumber( string.format("%.3f",pos ) );
while( fileContents.read() != "AcDbArc" ){ };
}
case "50" {
var pos = fileContents.read();
G_arc.startN = tonumber( string.format("%.3f",pos ) );
}
case "51" {
var pos = fileContents.read();
G_arc.endN = tonumber( string.format("%.3f",pos ) );
}
else {
}
}
}
//每块ARC类型属性读取完毕,放入ARC表中,等待下一步操作
table.push(entitiesTab.arc,table.clone(G_arc));
}
}
//其他模块暂时不使用,检测到此模块即结束此次解析
case "CIRCLE","ELLIPSE","POLYLINE","VERTEX","SPLINE","INDERT","TEXT","DIMENSION" {
if(entitiesStart == true){
entitiesStart = false;
}
}
//文件末尾
case "EOF" {
console.dump(entitiesTab);
}
else {
}
}
}while( fileContents.read(0)/**是否是最后一行**/ )
}
//解析获得的ARC数据,求出弧线的起始点坐标和终止点坐标
winform.button2.oncommand = function(id,event){
for(i=1;#entitiesTab.arc;1){
if( (entitiesTab.arc[ i ].startN >= 0) && (entitiesTab.arc[ i ].startN <= 90) ){
//起始点在第一象限
entitiesTab.arc[ i ].x1 = tonumber( string.format("%.3f", entitiesTab.arc[ i ].R * math.cos(math.rad(entitiesTab.arc[ i ].startN)) + entitiesTab.arc[ i ].xx) );
entitiesTab.arc[ i ].y1 = tonumber( string.format("%.3f", entitiesTab.arc[ i ].R * math.sin(math.rad(entitiesTab.arc[ i ].startN)) + entitiesTab.arc[ i ].yy) );
}elseif( (entitiesTab.arc[ i ].startN > 90) && (entitiesTab.arc[ i ].startN <= 180) ){
//起始点在第二象限
entitiesTab.arc[ i ].x1 = tonumber( string.format("%.3f", entitiesTab.arc[ i ].xx - entitiesTab.arc[ i ].R * math.cos(math.rad(180 - entitiesTab.arc[ i ].startN))) );
entitiesTab.arc[ i ].y1 = tonumber( string.format("%.3f", entitiesTab.arc[ i ].R * math.sin(math.rad(180 - entitiesTab.arc[ i ].startN)) + entitiesTab.arc[ i ].yy) );
}elseif( (entitiesTab.arc[ i ].startN > 180) && (entitiesTab.arc[ i ].startN <= 270) ){
//起始点在第三象限
entitiesTab.arc[ i ].x1 = tonumber( string.format("%.3f", entitiesTab.arc[ i ].xx - entitiesTab.arc[ i ].R * math.cos(math.rad(entitiesTab.arc[ i ].startN - 180))) );
entitiesTab.arc[ i ].y1 = tonumber( string.format("%.3f", entitiesTab.arc[ i ].yy - entitiesTab.arc[ i ].R * math.sin(math.rad(entitiesTab.arc[ i ].startN - 180))) );
}elseif( (entitiesTab.arc[ i ].startN > 270) && (entitiesTab.arc[ i ].startN <=360) ){
//起始点在第四象限
entitiesTab.arc[ i ].x1 = tonumber( string.format("%.3f", entitiesTab.arc[ i ].xx + entitiesTab.arc[ i ].R * math.cos(math.rad(360 - entitiesTab.arc[ i ].startN))) );
entitiesTab.arc[ i ].y1 = tonumber( string.format("%.3f", entitiesTab.arc[ i ].yy - entitiesTab.arc[ i ].R * math.sin(math.rad(360 - entitiesTab.arc[ i ].startN))) );
}
if( (entitiesTab.arc[ i ].endN >= 0) && (entitiesTab.arc[ i ].endN <= 90) ){
//终止点在第一象限
entitiesTab.arc[ i ].x2 = tonumber( string.format("%.3f", entitiesTab.arc[ i ].R * math.cos(math.rad(entitiesTab.arc[ i ].endN)) + entitiesTab.arc[ i ].xx) );
entitiesTab.arc[ i ].y2 = tonumber( string.format("%.3f", entitiesTab.arc[ i ].R * math.sin(math.rad(entitiesTab.arc[ i ].endN)) + entitiesTab.arc[ i ].yy) );
}elseif( (entitiesTab.arc[ i ].endN > 90) && (entitiesTab.arc[ i ].endN <= 180) ){
//终止点在第二象限
entitiesTab.arc[ i ].x2 = tonumber( string.format("%.3f", entitiesTab.arc[ i ].xx - entitiesTab.arc[ i ].R * math.cos(math.rad(180 - entitiesTab.arc[ i ].endN))) );
entitiesTab.arc[ i ].y2 = tonumber( string.format("%.3f", entitiesTab.arc[ i ].R * math.sin(math.rad(180 - entitiesTab.arc[ i ].endN)) + entitiesTab.arc[ i ].yy) );
}elseif( (entitiesTab.arc[ i ].endN > 180) && (entitiesTab.arc[ i ].endN <= 270) ){
//终止点在第三象限
entitiesTab.arc[ i ].x2 = tonumber( string.format("%.3f", entitiesTab.arc[ i ].xx - entitiesTab.arc[ i ].R * math.cos(math.rad(entitiesTab.arc[ i ].endN - 180))) );
entitiesTab.arc[ i ].y2 = tonumber( string.format("%.3f", entitiesTab.arc[ i ].yy - entitiesTab.arc[ i ].R * math.sin(math.rad(entitiesTab.arc[ i ].endN - 180))) );
}elseif( (entitiesTab.arc[ i ].endN > 270) && (entitiesTab.arc[ i ].endN <=360) ){
//终止点在第四象限
entitiesTab.arc[ i ].x2 = tonumber( string.format("%.3f", entitiesTab.arc[ i ].xx + entitiesTab.arc[ i ].R * math.cos(math.rad(360 - entitiesTab.arc[ i ].endN))) );
entitiesTab.arc[ i ].y2 = tonumber( string.format("%.3f", entitiesTab.arc[ i ].yy - entitiesTab.arc[ i ].R * math.sin(math.rad(360 - entitiesTab.arc[ i ].endN))) );
}
}
}
1 个回复 | 最后更新于 2017-12-18
登录后方可回帖
下半部分:
//定义排序列表 class retClass{ str G_type; //类型 point G_content; //内容 } class lineClass{ float startX1; float startY1; float endX1; float endY1; } class arcClass{ float R; float startX1; float startY1; float endX1; float endY1; float centerX; float centerY; } var retTable = {}; var retType = retClass(); var lineType = lineClass(); var arcType = arcClass(); var 正常顺序 = function( tab , flag ){ if(flag == "line"){ retType.G_type = "line"; lineType.startX1 = tab.x1; lineType.startY1 = tab.y1; lineType.endX1 = tab.x2; lineType.endY1 = tab.y2; retType.G_content = table.clone( lineType ); }elseif( flag == "arc" ){ retType.G_type = "逆时针"; arcType.startX1 = tab.x1; arcType.startY1 = tab.y1; arcType.endX1 = tab.x2; arcType.endY1 = tab.y2; arcType.centerX = tab.xx; arcType.centerY = tab.yy; arcType.R = tab.R; retType.G_content = table.clone( arcType ); } return retType; } var 颠倒顺序 = function( tab , flag ){ if(flag == "line"){ retType.G_type = "line"; lineType.startX1 = tab.x2; lineType.startY1 = tab.y2; lineType.endX1 = tab.x1; lineType.endY1 = tab.y1; retType.G_content = table.clone( lineType ); }elseif( flag == "arc" ){ retType.G_type = "顺时针"; arcType.startX1 = tab.x2; arcType.startY1 = tab.y2; arcType.endX1 = tab.x1; arcType.endY1 = tab.y1; arcType.centerX = tab.xx; arcType.centerY = tab.yy; arcType.R = tab.R; retType.G_content = table.clone( arcType ); } return retType; } winform.button4.oncommand = function(id,event){ /* 取出排好序的表的第一元素的头点坐标,和最后一个元素的尾坐标, 拿其他没有对比过的线条的头坐标和尾坐标分别比较,然后就可以插入到相应的排序表的头和尾部 这样就形成一个连续的队列 难点在对比并放入排序列表的线条,应该放入后从原表中删除,防止多次重复对比,因为每根线条只有唯一的序号,无需再次判断 table貌似没有删除哪一条的指令 */ //首先把第一个线条作为第一序列 //console.dump(entitiesTab.line[1]) var tempTab = 正常顺序(entitiesTab.line[1],"line"); table.push(retTable, table.clone(tempTab) ); table.remove(entitiesTab.line,1); while( (#entitiesTab.arc + #entitiesTab.line) ){ for(k=1;#entitiesTab.arc;1){ if((retTable[1].G_content.startX1 == entitiesTab.arc[k].x1) && (retTable[1].G_content.startY1 == entitiesTab.arc[k].y1)){ var tempTab = 颠倒顺序(entitiesTab.arc[k],"arc"); table.insert(retTable,table.clone(tempTab));//插到前面 table.remove(entitiesTab.arc,k); break 1; } if((retTable[1].G_content.startX1 == entitiesTab.arc[k].x2) && (retTable[1].G_content.startY1 == entitiesTab.arc[k].y2)){ var tempTab = 正常顺序(entitiesTab.arc[k],"arc"); table.insert(retTable,table.clone(tempTab));//插到前面 table.remove(entitiesTab.arc,k); break 1; } if((retTable[#retTable].G_content.endX1 == entitiesTab.arc[k].x1) && (retTable[#retTable].G_content.endY1 == entitiesTab.arc[k].y1)){ var tempTab = 正常顺序(entitiesTab.arc[k],"arc"); table.push(retTable,table.clone(tempTab));//插到后面 table.remove(entitiesTab.arc,k); break 1; } if((retTable[#retTable].G_content.endX1 == entitiesTab.arc[k].x2) && (retTable[#retTable].G_content.endY1 == entitiesTab.arc[k].y2)){ var tempTab = 颠倒顺序(entitiesTab.arc[k],"arc"); table.push(retTable,table.clone(tempTab));//插到后面 table.remove(entitiesTab.arc,k); break 1; } } //----------------------------------------------------- for(j=1;#entitiesTab.line;1){ //起始点有没重合 if((retTable[1].G_content.startX1 == entitiesTab.line[j].x1) && (retTable[1].G_content.startY1 == entitiesTab.line[j].y1)){ var tempTab = 颠倒顺序(entitiesTab.line[j],"line"); table.insert(retTable,table.clone(tempTab));//插到前面 table.remove(entitiesTab.line,j); break 1; } if((retTable[1].G_content.startX1 == entitiesTab.line[j].x2) && (retTable[1].G_content.startY1 == entitiesTab.line[j].y2)){ var tempTab = 正常顺序(entitiesTab.line[j],"line"); table.insert(retTable,table.clone(tempTab));//插到前面 table.remove(entitiesTab.line,j); break 1; } if((retTable[#retTable].G_content.endX1 == entitiesTab.line[j].x1) && (retTable[#retTable].G_content.endY1 == entitiesTab.line[j].y1)){ var tempTab = 正常顺序(entitiesTab.line[j],"line"); table.push(retTable,table.clone(tempTab));//插到后面 table.remove(entitiesTab.line,j); break 1; } if((retTable[#retTable].G_content.endX1 == entitiesTab.line[j].x2) && (retTable[#retTable].G_content.endY1 == entitiesTab.line[j].y2)){ var tempTab = 颠倒顺序(entitiesTab.line[j],"line"); table.push(retTable,table.clone(tempTab));//插到后面 table.remove(entitiesTab.line,j); break 1; } } } console.log("转换完成!"); } winform.button5.oncommand = function(id,event){ console.dump(retTable) } winform.button3.oncommand = function(id,event){ var GcodeStr; for(k,v in retTable){ if(GcodeStr == null){ GcodeStr = string.concat(GcodeStr,"G00 ","X",v.G_content.startX1," Y",v.G_content.startY1,'\r\n'); } select(v.G_type) { case "line" { GcodeStr = string.concat(GcodeStr,"G01 ","X",v.G_content.endX1," Y",v.G_content.endY1,'\r\n'); } case "顺时针" { GcodeStr = string.concat(GcodeStr,"G02 ","X",v.G_content.endX1," Y",v.G_content.endY1," R",v.G_content.R,'\r\n'); } case "逆时针" { GcodeStr = string.concat(GcodeStr,"G03 ","X",v.G_content.endX1," Y",v.G_content.endY1," R",v.G_content.R,'\r\n'); } else { console.log("rrrrrrrrrrrrr") } } } console.log( GcodeStr ); string.save("/cnctest.nc",GcodeStr) } winform.button6.oncommand = function(id,event){ var GcodeStr; table.reverse(retTable); for(k,v in retTable){ if(GcodeStr == null){ GcodeStr = string.concat(GcodeStr,"G00 ","X",v.G_content.endX1," Y",v.G_content.endY1,'\r\n'); } select(v.G_type) { case "line" { GcodeStr = string.concat(GcodeStr,"G01 ","X",v.G_content.startX1," Y",v.G_content.startY1,'\r\n'); } case "顺时针" { GcodeStr = string.concat(GcodeStr,"G03 ","X",v.G_content.startX1," Y",v.G_content.startY1," R",v.G_content.R,'\r\n'); } case "逆时针" { GcodeStr = string.concat(GcodeStr,"G02 ","X",v.G_content.startX1," Y",v.G_content.startY1," R",v.G_content.R,'\r\n'); } else { console.log("rrrrrrrrrrrrr") } } } console.log( GcodeStr ); string.save("/cnctestFFFF.nc",GcodeStr) } winform.show() win.loopMessage();