基于PLY的STL文件基本信息统计方法

1、摘要

  STL文件是快速成型设备中常用的文件格式,随着3D打印技术的发展,STL格式文件的应用日益广泛。Python语言具有丰富和强大的类库,其语言简洁而清晰,因而Python语言越来越受欢迎。PLY是具名的LEX、YACC的Python版本,本文介绍了利用PLY模块对STL文件进行基本信息统计。

KeyWordPLY、语法分析、词法分析、STL

2、简介

  计算机语言是计算机软件的系统的基础,经过几十年的发展,实现了从低级语言到高级语言的转变。原始的机器语言,到低级的汇编语言,它们虽然可以运行,但是也存在很多问题,比如在程序移植的过程中,往往会出现不兼容的情况。高级语言的出现,使得计算机程序设计语言不再过度地依赖特定的机器或环境,从高级语言翻译成机器可执行的语言就显得相当重要。构造一个高级语言编译器,需要构造相应的此法及语法分析器,PLY模块可以帮助我们实现词法及语法的分析。

2.1 PLY简介

  PLY是LEX与YACC的Python版,包含了LEX与YACC的大部分特性。PLY模块包含两个独立的模块:lex.py和yacc.py。lex.py模块用来将输入字符通过一系列的正则表达式分解成标记序列,yacc.py通过一些上下文无关的文法来识别编程语言语法。yacc.py使用LR解析法,并使用LALR(1)算法(默认)或者SLR算法生成分析表。

2.1.1 PLY.LEX基本原理与实践

Lex.py用来将输入字符串标记化。首先,将字符串分割成独立的标记(token),这些token由不同的名称表示,然后将名称和值组合起来形成一个二元组。例如:

  tokens = (

      ‘NAME‘,‘NUMBER‘,

      )

  

  literals = [‘=‘,‘+‘,‘-‘,‘*‘,‘/‘, ‘(‘,‘)‘]

  

  # Tokens

  

  t_NAME    = r‘[a-zA-Z_][a-zA-Z0-9_]*‘ 
      #词法描述规则1

  

  def t_NUMBER(t):   
                                   
#词法描述规则2

      r‘\d+‘

      t.value = int(t.value)

      return t

  

  t_ignore = " \t"

  

  def t_newline(t):

      r‘\n+‘

      t.lexer.lineno += t.value.count("\n")

  

  def
t_error(t):                                                 
#出错处理

      print("Illegal character ‘%s‘" % t.value[0])

      t.lexer.skip(1)

  

  # Build the lexer

  import ply.lex as lex

  lex.lex()

  其中tokens是强制词法单元类型列表的名称,强制描述词法规则的变量名格式为t_[TOKENNAME],在此例中有两种类型:NUMBER和NAME。NUMBER定义为\d+,匹配整数,NAME定义为a-zA-Z_][a-zA-Z0-9_],匹配一般标识符。词法描述规则中,规则1不能自定义操作,规则2可以自定义操作,规则2中的参数列表必须为单个参数,并且只能返回t,若不返回则表示丢弃该token。最后调用lex()即可完成词法分析。

2.1.2 PLY.yacc 基本原理与实践

  YACC用于对语言进行语法分析。语法通常用BNF范式表达,用的分析技术是LALR分析法,LALR分析法是LR分析法的一种改进分析法。LR(K)分析,是指从左至右扫描和自底向上的语法分析,且在分析的每一步,只须根据分析栈当前已移进和归约出的全部文法符号,并至多再向前查看K个输入符号,就能确定相对于某一产生式左部符号的句柄是否已在分析栈的顶部形成,从而也就可以确定当前所应采取的分析动作
(是移进还是按某一产生式进行归约等)。例如:

简单算术表达式文法:

E    : E + T

| E - T

| T

T  : T * F

| T / F

| F

F  : N

| ( E )

  每个文法规则被描述为一个函数,这个函数的文档字符串描述了对应的上下文无关文法的规则。函数体用来实现规则的语义动作。每个函数都会接受一个参数p,这个参数是一个序列(sequence),包含了组成这个规则的所有的语法符号,p[i]是规则中的第i个语法符号。比如:

语法说明中的第一个为起始规则,也可以通过关键字参数传递给yacc以指定起始文法规则:

yacc.yacc(start = ‘rule_name‘)

2.2 STL文件简介

STL文件是在计算机图形应用系统中,用于表示三角形网格的一种文件格式。STL文件凭借其简单的格式,在许多领域得到应用,特别是在快速成型系统中的应用。STL文件有两种:一种为ASCII格式,另一种为二进制格式。在这里只介绍ASCII格式的STL文件。

STL的文件结构如下:

solid
filename                                   
//文件名

facet normal x y
z                      
//三角形法矢量

outer
loop

vertex x y
z                 
//第一个点

vertex x y
z                 
//第二个点

vertex x y
z                 
//第三个点

endloop

endfacet

……..

endsolid filename

3、词法分析

分析STL文件的文件结构,将词法单元类型分成5类:KEYWORD、RPARAM、LPARAM、NAME、NUMBER。词法采用正则表达式描述,详细定义分别如下:

KEYWORD:normal | outer | vertex

RPARAM:solid | facet | loop

LPARAM:endsolid | endfacet | endloop

NAME:[a-zA-Z_][a-zA-Z0-9_]*

NUMBER:(-?\d+)(\.\d+)?(e-?\d+)?

词法分析结果如下:

LexToken(RPARAM,‘solid‘,1,0)

LexToken(NAME,‘OBJECT‘,1,6)

LexToken(RPARAM,‘facet‘,2,15)

LexToken(KEYWORD,‘normal‘,2,21)

LexToken(NUMBER,-0.0,2,28)

LexToken(NUMBER,-1.0,2,31)

LexToken(NUMBER,0.0,2,34)

LexToken(KEYWORD,‘outer‘,3,40)

LexToken(RPARAM,‘loop‘,3,46)

LexToken(KEYWORD,‘vertex‘,4,57)

LexToken(NUMBER,-24.721731185913086,4,64)

LexToken(NUMBER,-6.938085079193115,4,84)

LexToken(NUMBER,0.0,4,104)

LexToken(KEYWORD,‘vertex‘,5,112)

LexToken(NUMBER,-21.674671173095703,5,119)

LexToken(NUMBER,-6.938085079193115,5,139)

……..

从词法分析结果中可以看出,扫描字符串的过程是从左至右依次进行。词法分析代码参见附录B

4、语法分析

STL文件格式比较简单,其文法也相应比较简单。采用BNF范式描述STL文件的文件结构:

Rule 0     S‘ -> start

Rule 1     start -> RPARAM NAME facet LPARAM NAME

Rule 2     facet -> facet facet

Rule 3     facet -> RPARAM norm out LPARAM

Rule 4     norm -> KEYWORD NUMBER NUMBER NUMBER

Rule 5     out -> KEYWORD lp

Rule 6     lp -> RPARAM vertex LPARAM

Rule 7     vertex -> point point point

Rule 8     point -> KEYWORD NUMBER NUMBER NUMBER

在采用LALR分析法时,出现移近规约冲突:

(2) facet -> facet facet .

(2) facet -> facet . facet

(2) facet -> . facet facet

(3) facet -> . RPARAM norm out LPARAM

! shift/reduce conflict for RPARAM resolved as shift

LPARAM          reduce using rule 2
(facet -> facet facet .)

RPARAM          shift and go to
state 4

! RPARAM          [
reduce using rule 2 (facet -> facet facet .) ]

facet                         
shift and go to state 9

默认采用移进解决这种移进规约冲突。

具体实现参见附录B

语法分析结果如下;

norm  : KEYWORD NUMBER NUMBER NUMBER

point : KEYWORD NUMBER NUMBER NUMBER

point : KEYWORD NUMBER NUMBER NUMBER

point : KEYWORD NUMBER NUMBER NUMBER

vertex : point point point

lp : RPARAM vertex LPARAM

out : KEYWORD lp

facet : RPARAM norm out LPARAM

…….

facet : facet facet

facet : facet facet

facet : facet facet

…..

start : RPARAM NAME facet LPARAM NAME

  从分析结果中可以看出语法分析中各规则归约顺序:首先是Rule 4,接着是3个Rule 8,然后Rule 7-> Rule 6-> Rule
5,跟着是Rule 3。如此分析完成一个三角形块。所有块分析完成后,应用Rule 2,最终应用Rule
1完成整个文件的分析。具体分析表参见附录C,分析过程参见附录D

5、信息统计

  在这里我们统计网格中的三角形个数和三角形的顶点数以及网格的表面积,虽然三角形顶点数可由三角形个数乘3得到,但是这里提供了语法分析时统计的手段。在每次对Rule
8进行规约时,顶点数加1,同时保存顶点用于表面积的计算;对Rule 3进行规约时,三角形个数加1,同时计算出三角形的面积,并对三角形面积进行累加。

由三角形的三个顶点A(x0,y0,z0),B(x1,y1,z1),C(x2,y2,z2)计算三角形的面积S。首先计算出三条边的长度:

,由海伦公式可得:

6、测试及分析


用计算机图形系统软件绘制一些三维文件,然后导出ASCII的STL格式文件作为测试用例。测试结果如下:

Cube.stl

---------------------------------------------------------------------------------------

object informatioin:

vertex:
84       facet: 28  surface area:
146.5441114077912

---------------------------------------------------------------------------------------

cy.stl

---------------------------------------------------------------------------------------

object informatioin:

vertex: 4740   facet:
1580     surface area: 1841.906043447056

---------------------------------------------------------------------------------------

shouji.stl

---------------------------------------------------------------------------------------

object informatioin:

vertex: 34542  facet:
11514    surface area: 1971.3863130454672

---------------------------------------------------------------------------------------

这三个测试用例都通过了测试。第一个、及第二个测试用例,内容较少,用于分析统计的时间可以忽略不计。第三个测试用例的容量较大,运行时有少许延时,若通过编译转换成C语言代码运行,可改善延时问题。

7、参考文献:

[1] 姚泽勤, 柏又青. 利用 LEX 及 YACC 实现嵌入式 SQL 分析器[J]. 航空计算技术, 2002, 32(1): 55-58.

[2] 肖任贤、张军舰、冯浩、潘海鹏, STL文件读取显示与操作, 陶瓷学报.2011(2)

[3]  Lesk M E, Schmidt E. lex: A lexical analyzer generator[M]. Bell
Laboratories, 1987.

[4]  Johnson S C. Yacc: Yet another compiler-compiler[M]. Murray Hill,
NJ: Bell Laboratories, 1975.

[5]  Beazley D M. Ply, python lex-yacc (2001)[J]. UR L http://www.
dabeaz. com/ply.

[6]  Amiguet M. Teaching compilers with python[J]. 2010.

8、附录:(代码)


8.1 附录A——stlcount.py

 1 #-------------------------------------------------------------
2 #stlcount.py
3 #
4 # STL文件信息统计
5 #-------------------------------------------------------------
6 import math
7
8 #小三角片数
9 c_facet=0
10
11 #表面积
12 s_all=0
13
14 #点数
15 c_vertex=0
16
17
18 #保存三个点
19 v_points=[]
20
21 b_print_yacc=False
22 b_print_lex=False
23
24 #初始化
25 def init_countstl():
26 global c_facet,s_all,c_vertex,v_points
27 c_facet=0
28 s_all=0
29 c_vertex=0
30 v_points=[]
31
32 def display(a,b,c):
33 print("--------------------------------------------------------------------------")
34 print("object informatioin:")
35 print("\tvertex: "+str(a)+"\tfacet: "+str(b)+"\tsurface area: "+str(c))
36 print("--------------------------------------------------------------------------")
37
38 def cal_area(p0,p1,p2):
39 A=[0,0,0]
40 B=[0,0,0]
41 C=[0,0,0]
42 A[0]=p1[0]-p0[0]
43 B[0]=p2[0]-p0[0]
44 C[0]=p2[0]-p1[0]
45 A[1]=p1[1]-p0[1]
46 B[1]=p2[1]-p0[1]
47 C[1]=p2[1]-p1[1]
48 A[2]=p1[2]-p0[2]
49 B[2]=p2[2]-p0[2]
50 C[2]=p2[2]-p1[2]
51 a=math.sqrt(A[0]**2+A[1]**2+A[2]**2)
52 b=math.sqrt(B[0]**2+B[1]**2+B[2]**2)
53 c=math.sqrt(C[0]**2+C[1]**2+C[2]**2)
54 p=(a+b+c)/2.0
55 return math.sqrt(p*(p-a)*(p-b)*(p-c))
56

8.2 附录B——stl.py

  1 # -----------------------------------------------------------------------------
2 # stl.py
3 #
4 # A simple calculator with variables. This is from O‘Reilly‘s
5 # "Lex and Yacc", p. 63.
6 # -----------------------------------------------------------------------------
7
8 import stlcount as cn
9
10 #------------------------------------------------------------------------------
11 #词法分析
12 #------------------------------------------------------------------------------
13
14
15
16 tokens = (
17 ‘KEYWORD‘,‘RPARAM‘,‘LPARAM‘,‘NAME‘,‘NUMBER‘
18 )
19
20 #literals = [‘=‘,‘+‘,‘-‘,‘*‘,‘/‘, ‘(‘,‘)‘]
21
22 # Tokens
23
24 def t_KEYWORD(t):
25 r"normal | outer | vertex"
26 return t
27
28 def t_RPARAM(t):
29 r"solid | facet | loop"
30 return t
31
32 def t_LPARAM(t):
33 r"endsolid | endfacet | endloop"
34 return t
35
36 def t_NAME(t):
37 r‘[a-zA-Z_][a-zA-Z0-9_]*‘
38 return t
39
40 def t_NUMBER(t):
41 r‘(-?\d+)(\.\d+)?(e-?\d+)?‘
42 t.value = float(t.value)
43 return t
44
45 t_ignore = " \t"
46
47 def t_newline(t):
48 r‘\n+‘
49 t.lexer.lineno += t.value.count("\n")
50
51 def t_error(t):
52 print("Illegal character ‘%s‘" % t.value[0])
53 t.lexer.skip(1)
54
55 # Build the lexer
56 import ply.lex as lex
57 lexer=lex.lex()
58
59 #======================================================================
60
61 def p_start(p):
62 r‘start : RPARAM NAME facet LPARAM NAME‘
63 if cn.b_print_yacc:
64 print("start : RPARAM NAME facet LPARAM NAME")
65 cn.display(cn.c_vertex,cn.c_facet,cn.s_all)
66
67 def p_facet(p):
68 r‘facet : facet facet‘
69 if cn.b_print_yacc:
70 print(‘facet : facet facet‘)
71
72 def p_facet1(p):
73 r‘facet : RPARAM norm out LPARAM‘
74 if cn.b_print_yacc:
75 print(‘facet : RPARAM norm out LPARAM‘)
76 cn.c_facet=cn.c_facet+1
77 s_single=cn.cal_area(cn.v_points[0],cn.v_points[1],cn.v_points[2])
78 if s_single<0:
79 print("****************************ERROR*******************************")
80 cn.s_all=cn.s_all+s_single
81 if cn.b_print_yacc:
82 print("area:",end=‘\t‘)
83 print(cn.s_all)
84 cn.v_points=[]
85
86
87 def p_norm(p):
88 r‘norm : KEYWORD NUMBER NUMBER NUMBER‘
89 if cn.b_print_yacc:
90 print("norm : KEYWORD NUMBER NUMBER NUMBER")
91
92 def p_out(p):
93 r‘out : KEYWORD lp‘
94 if cn.b_print_yacc:
95 print("out : KEYWORD lp")
96
97 def p_lp(p):
98 r‘lp : RPARAM vertex LPARAM‘
99 if cn.b_print_yacc:
100 print(‘lp : RPARAM vertex LPARAM‘)
101
102 def p_vertex(p):
103 r‘vertex : point point point‘
104 if cn.b_print_yacc:
105 print(‘vertex : point point point‘)
106
107 def p_point(p):
108 r‘point : KEYWORD NUMBER NUMBER NUMBER‘
109 if cn.b_print_yacc:
110 print(‘point : KEYWORD NUMBER NUMBER NUMBER‘)
111 cn.c_vertex=cn.c_vertex+1
112 cn.v_points.append([p[2],p[3],p[4]])
113
114
115 def p_error(p):
116 if p:
117 print("Syntax error at ‘%s‘" % p.value)
118 else:
119 print("Syntax error at EOF")
120
121 import ply.yacc as yacc
122 yacc.yacc()
123
124
125 def stl_exec(s,blex=False,byacc=False):
126 cn.b_print_lex=blex
127 cn.b_print_yacc=byacc
128 cn.init_countstl()
129 if cn.b_print_lex:
130 print("----------------------------------------------------------------------")
131 print("\t\tlex")
132 print("----------------------------------------------------------------------")
133 lexer.input(s)
134 for st in lexer:
135 print(st)
136 if cn.b_print_yacc:
137 print("----------------------------------------------------------------------")
138 print("\t\tyacc")
139 print("----------------------------------------------------------------------")
140 yacc.parse(s)

8.3 附录C——parsetab.py

 1 # parsetab.py
2 # This file is automatically generated. Do not edit.
3 _tabversion = ‘3.2‘
4
5 _lr_method = ‘LALR‘
6
7 _lr_signature = b‘|:{\[email protected]\x08\xce\xd8d\x055eAN\xff\x13‘
8
9 _lr_action_items = {‘NAME‘:([1,8,],[3,13,]),‘KEYWORD‘:([4,7,15,18,21,24,27,],[6,11,19,-4,19,19,-8,]),‘NUMBER‘:([6,10,14,19,22,25,],[10,14,18,22,25,27,]),‘LPARAM‘:([5,9,12,16,17,20,23,26,27,],[8,-2,17,-5,-3,23,-6,-7,-8,]),‘$end‘:([2,13,],[0,-1,]),‘RPARAM‘:([0,3,5,9,11,17,],[1,4,4,4,15,-3,]),}
10
11 _lr_action = { }
12 for _k, _v in _lr_action_items.items():
13 for _x,_y in zip(_v[0],_v[1]):
14 if not _x in _lr_action: _lr_action[_x] = { }
15 _lr_action[_x][_k] = _y
16 del _lr_action_items
17
18 _lr_goto_items = {‘norm‘:([4,],[7,]),‘start‘:([0,],[2,]),‘vertex‘:([15,],[20,]),‘point‘:([15,21,24,],[21,24,26,]),‘facet‘:([3,5,9,],[5,9,9,]),‘lp‘:([11,],[16,]),‘out‘:([7,],[12,]),}
19
20 _lr_goto = { }
21 for _k, _v in _lr_goto_items.items():
22 for _x,_y in zip(_v[0],_v[1]):
23 if not _x in _lr_goto: _lr_goto[_x] = { }
24 _lr_goto[_x][_k] = _y
25 del _lr_goto_items
26 _lr_productions = [
27 ("S‘ -> start","S‘",1,None,None,None),
28 (‘start -> RPARAM NAME facet LPARAM NAME‘,‘start‘,5,‘p_start‘,‘E:\\PY\\stl.py‘,65),
29 (‘facet -> facet facet‘,‘facet‘,2,‘p_facet‘,‘E:\\PY\\stl.py‘,71),
30 (‘facet -> RPARAM norm out LPARAM‘,‘facet‘,4,‘p_facet1‘,‘E:\\PY\\stl.py‘,76),
31 (‘norm -> KEYWORD NUMBER NUMBER NUMBER‘,‘norm‘,4,‘p_norm‘,‘E:\\PY\\stl.py‘,91),
32 (‘out -> KEYWORD lp‘,‘out‘,2,‘p_out‘,‘E:\\PY\\stl.py‘,96),
33 (‘lp -> RPARAM vertex LPARAM‘,‘lp‘,3,‘p_lp‘,‘E:\\PY\\stl.py‘,101),
34 (‘vertex -> point point point‘,‘vertex‘,3,‘p_vertex‘,‘E:\\PY\\stl.py‘,106),
35 (‘point -> KEYWORD NUMBER NUMBER NUMBER‘,‘point‘,4,‘p_point‘,‘E:\\PY\\stl.py‘,111),
36 ]

8.4 附录D——parser.out

  1 Created by PLY version 3.4 (http://www.dabeaz.com/ply)
2
3 Grammar
4
5 Rule 0 S‘ -> start
6 Rule 1 start -> RPARAM NAME facet LPARAM NAME
7 Rule 2 facet -> facet facet
8 Rule 3 facet -> RPARAM norm out LPARAM
9 Rule 4 norm -> KEYWORD NUMBER NUMBER NUMBER
10 Rule 5 out -> KEYWORD lp
11 Rule 6 lp -> RPARAM vertex LPARAM
12 Rule 7 vertex -> point point point
13 Rule 8 point -> KEYWORD NUMBER NUMBER NUMBER
14
15 Terminals, with rules where they appear
16
17 KEYWORD : 4 5 8
18 LPARAM : 1 3 6
19 NAME : 1 1
20 NUMBER : 4 4 4 8 8 8
21 RPARAM : 1 3 6
22 error :
23
24 Nonterminals, with rules where they appear
25
26 facet : 1 2 2
27 lp : 5
28 norm : 3
29 out : 3
30 point : 7 7 7
31 start : 0
32 vertex : 6
33
34 Parsing method: LALR
35
36 state 0
37
38 (0) S‘ -> . start
39 (1) start -> . RPARAM NAME facet LPARAM NAME
40
41 RPARAM shift and go to state 1
42
43 start shift and go to state 2
44
45 state 1
46
47 (1) start -> RPARAM . NAME facet LPARAM NAME
48
49 NAME shift and go to state 3
50
51
52 state 2
53
54 (0) S‘ -> start .
55
56
57
58 state 3
59
60 (1) start -> RPARAM NAME . facet LPARAM NAME
61 (2) facet -> . facet facet
62 (3) facet -> . RPARAM norm out LPARAM
63
64 RPARAM shift and go to state 4
65
66 facet shift and go to state 5
67
68 state 4
69
70 (3) facet -> RPARAM . norm out LPARAM
71 (4) norm -> . KEYWORD NUMBER NUMBER NUMBER
72
73 KEYWORD shift and go to state 7
74
75 norm shift and go to state 6
76
77 state 5
78
79 (1) start -> RPARAM NAME facet . LPARAM NAME
80 (2) facet -> facet . facet
81 (2) facet -> . facet facet
82 (3) facet -> . RPARAM norm out LPARAM
83
84 LPARAM shift and go to state 8
85 RPARAM shift and go to state 4
86
87 facet shift and go to state 9
88
89 state 6
90
91 (3) facet -> RPARAM norm . out LPARAM
92 (5) out -> . KEYWORD lp
93
94 KEYWORD shift and go to state 11
95
96 out shift and go to state 10
97
98 state 7
99
100 (4) norm -> KEYWORD . NUMBER NUMBER NUMBER
101
102 NUMBER shift and go to state 12
103
104
105 state 8
106
107 (1) start -> RPARAM NAME facet LPARAM . NAME
108
109 NAME shift and go to state 13
110
111
112 state 9
113
114 (2) facet -> facet facet .
115 (2) facet -> facet . facet
116 (2) facet -> . facet facet
117 (3) facet -> . RPARAM norm out LPARAM
118
119 ! shift/reduce conflict for RPARAM resolved as shift
120 LPARAM reduce using rule 2 (facet -> facet facet .)
121 RPARAM shift and go to state 4
122
123 ! RPARAM [ reduce using rule 2 (facet -> facet facet .) ]
124
125 facet shift and go to state 9
126
127 state 10
128
129 (3) facet -> RPARAM norm out . LPARAM
130
131 LPARAM shift and go to state 14
132
133
134 state 11
135
136 (5) out -> KEYWORD . lp
137 (6) lp -> . RPARAM vertex LPARAM
138
139 RPARAM shift and go to state 16
140
141 lp shift and go to state 15
142
143 state 12
144
145 (4) norm -> KEYWORD NUMBER . NUMBER NUMBER
146
147 NUMBER shift and go to state 17
148
149
150 state 13
151
152 (1) start -> RPARAM NAME facet LPARAM NAME .
153
154 $end reduce using rule 1 (start -> RPARAM NAME facet LPARAM NAME .)
155
156
157 state 14
158
159 (3) facet -> RPARAM norm out LPARAM .
160
161 RPARAM reduce using rule 3 (facet -> RPARAM norm out LPARAM .)
162 LPARAM reduce using rule 3 (facet -> RPARAM norm out LPARAM .)
163
164
165 state 15
166
167 (5) out -> KEYWORD lp .
168
169 LPARAM reduce using rule 5 (out -> KEYWORD lp .)
170
171
172 state 16
173
174 (6) lp -> RPARAM . vertex LPARAM
175 (7) vertex -> . point point point
176 (8) point -> . KEYWORD NUMBER NUMBER NUMBER
177
178 KEYWORD shift and go to state 19
179
180 vertex shift and go to state 18
181 point shift and go to state 20
182
183 state 17
184
185 (4) norm -> KEYWORD NUMBER NUMBER . NUMBER
186
187 NUMBER shift and go to state 21
188
189
190 state 18
191
192 (6) lp -> RPARAM vertex . LPARAM
193
194 LPARAM shift and go to state 22
195
196
197 state 19
198
199 (8) point -> KEYWORD . NUMBER NUMBER NUMBER
200
201 NUMBER shift and go to state 23
202
203
204 state 20
205
206 (7) vertex -> point . point point
207 (8) point -> . KEYWORD NUMBER NUMBER NUMBER
208
209 KEYWORD shift and go to state 19
210
211 point shift and go to state 24
212
213 state 21
214
215 (4) norm -> KEYWORD NUMBER NUMBER NUMBER .
216
217 KEYWORD reduce using rule 4 (norm -> KEYWORD NUMBER NUMBER NUMBER .)
218
219
220 state 22
221
222 (6) lp -> RPARAM vertex LPARAM .
223
224 LPARAM reduce using rule 6 (lp -> RPARAM vertex LPARAM .)
225
226
227 state 23
228
229 (8) point -> KEYWORD NUMBER . NUMBER NUMBER
230
231 NUMBER shift and go to state 25
232
233
234 state 24
235
236 (7) vertex -> point point . point
237 (8) point -> . KEYWORD NUMBER NUMBER NUMBER
238
239 KEYWORD shift and go to state 19
240
241 point shift and go to state 26
242
243 state 25
244
245 (8) point -> KEYWORD NUMBER NUMBER . NUMBER
246
247 NUMBER shift and go to state 27
248
249
250 state 26
251
252 (7) vertex -> point point point .
253
254 LPARAM reduce using rule 7 (vertex -> point point point .)
255
256
257 state 27
258
259 (8) point -> KEYWORD NUMBER NUMBER NUMBER .
260
261 KEYWORD reduce using rule 8 (point -> KEYWORD NUMBER NUMBER NUMBER .)
262 LPARAM reduce using rule 8 (point -> KEYWORD NUMBER NUMBER NUMBER .)
263
264 WARNING:
265 WARNING: Conflicts:
266 WARNING:
267 WARNING: shift/re

8.5 附录E——cstl.py

 1 import sys
2 largv=len(sys.argv)
3 bLex=False
4 bYacc=False
5 if largv==1:
6 filename=input(‘please input the name of file\n>>>‘)
7 else:
8 if largv>1:
9 filename=sys.argv[1]
10 if largv>2:
11 if sys.argv[2]==‘L‘:
12 bLex=True
13 bYacc=False
14 else:
15 if sys.argv[2]==‘Y‘:
16 bLex=False
17 bYacc=True
18 else:
19 if sys.argv[2]==‘YL‘ or sys.argv[2]==‘LY‘:
20 bLex=True
21 bYacc=True
22 def run():
23 try:
24 file=open(filename).read()
25 import stl
26 stl.stl_exec(file,bLex,bYacc)
27 except:
28 print(‘OPENFILE ERROR!‘)
29 exit()
30
31 run()

时间: 2024-11-10 07:29:53

基于PLY的STL文件基本信息统计方法的相关文章

打开本地STL文件并创建webgl使用的geometry

需求 打开本地STL文件 一个独立基于webgl的viewer,会被别的网站重用 将打开文件的数据传输给viewer,并且在文件加载的时候显示进度条 解决方案 #1可以使用传统的html5 api来打开, #2来说,可以通过iframe来提供独立的viewer, #3来说需要用web worker来实现. 实现细节 数据的流向是网站的main page->iframe中viewer的main page->web worker->iframe的main page 刚打开的数据类型是buff

Servlet3.0学习总结——基于Servlet3.0的文件上传

Servlet3.0学习总结(三)——基于Servlet3.0的文件上传 在Servlet2.5中,我们要实现文件上传功能时,一般都需要借助第三方开源组件,例如Apache的commons-fileupload组件,在Servlet3.0中提供了对文件上传的原生支持,我们不需要借助任何第三方上传组件,直接使用Servlet3.0提供的API就能够实现文件上传功能了. 一.使用Servlet3.0提供的API实现文件上传 1.1.编写上传页面 <%@ page language="java&

Servlet3.0学习总结(三)——基于Servlet3.0的文件上传

Servlet3.0学习总结(三)——基于Servlet3.0的文件上传 在Servlet2.5中,我们要实现文件上传功能时,一般都需要借助第三方开源组件,例如Apache的commons-fileupload组件,在Servlet3.0中提供了对文件上传的原生支持,我们不需要借助任何第三方上传组件,直接使用Servlet3.0提供的API就能够实现文件上传功能了. 一.使用Servlet3.0提供的API实现文件上传 1.1.编写上传页面 1 <%@ page language="jav

基于asp.net 的文件上传和下载~~~转

基于asp.net 的文件上传和下载 摘要: 文件的上传和下载是网络中非常重要的两种应用, 本文介绍了使用asp.net 控件实现文件上传的基本方法.解决了当上传大文件时出现各种问题, 并给出了几种解决方案和技巧.另外, 下载文件用二进制读写的方式实现. 1 引言          文件的上传和下载是网络中非常重要的两种应用.其实现方法主要有FTP 方式和HTTP 方式两种, FTP( File Transfer Protocol)是指文件传输协议, 主要用来在网络上传输文件.这种方式虽说文件传

服务器基于PHP CodeIgniter,Android基于Volley实现多文件/图片上传(含服务器,web版和android客户端完整代码)

问题背景:app在上传图片时,同时传递参数,支持传递多个图片.本文中的环境默认已经配好了服务器的CodeIgniter框架.事实上不使用这个框架也是可以的. 一,服务器部分 1,在controllers下的helpers新建文件upload_helper.php <?php /** * Make multifile array input complaint with CI_Upload.<br> * For use files[ ] input name you must use it

C++ 标准模板库STL 队列 queue 使用方法与应用介绍

C++ 标准模板库STL 队列 queue 使用方法与应用介绍 queue queue模板类的定义在<queue>头文件中. 与stack模板类很相似,queue模板类也需要两个模板参数,一个是元素类型,一个容器类型,元素类型是必要的,容器类型是可选的,默认为deque类型. 定义queue对象的示例代码如下: queue<int> q1; queue<double> q2; queue的基本操作有: 入队,如例:q.push(x); 将x接到队列的末端. 出队,如例:

linux下SVN忽略文件/文件夹的方法

linux下SVN忽略文件/文件夹的方法 假设想忽略文件temp 1. cd到temp所在的目录下: 2. svn propedit svn:ignore . 注意:请别漏掉最后的点(.表示当前目录),如果报错请看下面 3. 打开的文件就是忽略列表文件了(默认是空的),每一行是一项,在该文件中输入temp,保存退出 4. svn st查看状态,temp的?状态已经消除了 如果在svn propedit svn:ignore .时报错:svn: None of the environment va

linux找不到动态链接库 .so文件的解决方法

如果使用自己手动生成的动态链接库.so文件,但是这个.so文件,没有加入库文件搜索路劲中,程序运行时可能会出现找不到动态链接库的情形. 可以通过ldd命名来查看可执行文件依赖的动态链接库,如下(其中D为可执行程序): 其中的libjson_linux-gcc-4.6_libmt.so cannot found. 解决这个问题: (1)在系统中查找这个文件(当然要保证系统中已经有这个.so文件,只是查找路径没有设置正确而已): sudo find / -name libjson_linux-gcc

Linux服务器删除乱码文件和文件夹的方法

Linux服务器删除乱码文件和文件夹的方法 首页进入乱码文件所在文件夹由于php大势所趋,所以接触Linux服务器的机会越来越多.不同于Windows服务器,Linux服务器只支持数字.英文等字符,对中文字符没办法识别.所以导致我们打包上传文件解压之后出现中文乱码文件和文件夹.网上有很多解决的办法,但是今天亲测用find命令能快速删除乱码的文件和文件夹,所以跟大家分享一下. 使用ls -i命令找到文件或文件夹的节点编号 前面的就是节点号了,接下来使用find命令查询并且删除 -inum指根据节点