1#!/usr/local/bin/python3.8 2""" 3 g_code_library 4 Copyright (C) <2017> <Scorch> 5 This program is free software: you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation, either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. 17""" 18import sys 19from math import * 20import os 21import re 22import binascii 23import getopt 24import webbrowser 25 26 27################# 28### START LIB ### 29################# 30############################################################################ 31class G_Code_Rip: 32 def __init__(self): 33 self.Zero = 0.0000001 34 self.g_code_data = [] 35 self.scaled_trans = [] 36 self.right_side = [] 37 self.left_side = [] 38 self.probe_gcode = [] 39 self.probe_coords = [] 40 self.arc_angle = 2 41 self.accuracy = .001 42 self.units = "in" 43 44 ################################################################################ 45 # Function for outputting messages to different locations # 46 # depending on what options are enabled # 47 ################################################################################ 48 def fmessage(self,text,newline=True): 49 if newline==True: 50 try: 51 sys.stdout.write(text) 52 sys.stdout.write("\n") 53 except: 54 pass 55 else: 56 try: 57 sys.stdout.write(text) 58 except: 59 pass 60 61 def Read_G_Code(self,filename, XYarc2line = False, arc_angle=2, units="in", Accuracy=""): 62 self.g_code_data = [] 63 self.scaled_trans = [] 64 self.right_side = [] 65 self.left_side = [] 66 self.probe_gcode = [] 67 self.probe_coords = [] 68 self.arc_angle = arc_angle 69 self.units = units 70 if Accuracy == "": 71 if units == "in": 72 self.accuracy = .001 73 else: 74 self.accuracy = .025 75 else: 76 self.accuracy = float(Accuracy) 77 78 READ_MSG = [] 79 80 # Try to open file for reading 81 try: 82 fin = open(filename,'r') 83 except: 84 READ_MSG.append("Unable to open file: %s" %(filename)) 85 return READ_MSG 86 87 scale = 1 88 variables = [] 89 line_number = 0 90 91 xind=0 92 yind=1 93 zind=2 94 95 mode_arc = "incremental" # "absolute" 96 mode_pos = "absolute" # "incremental" 97 98 mvtype = 1 # G0 (Rapid), G1 (linear), G2 (clockwise arc) or G3 (counterclockwise arc). 99 plane = "17" # G17 (Z-axis, XY-plane), G18 (Y-axis, XZ-plane), or G19 (X-axis, YZ-plane) 100 pos =['','',''] 101 pos_last=['','',''] 102 POS =[complex(0,1),complex(0,1),complex(0,1)] 103 feed = 0 104 spindle = 0 105 106 ######################### 107 for line in fin: 108 line_number = line_number + 1 109 #print line_number 110 line = line.replace("\n","") 111 line = line.replace("\r","") 112 code_line=[] 113 114 ##################### 115 ### FIND COMMENTS ### 116 ##################### 117 if line.find("(") != -1: 118 s = line.find("(") 119 while s != -1: 120 e = line.find(")") 121 code_line.append([ ";", line[s:e+1] ]) 122 line = self.rm_text(line,s,e) 123 s = line.find("(") 124 125 if line.find(";") != -1: 126 s = line.find(";") 127 e = len(line) 128 code_line.append([ ";", line[s:e] ]) 129 line = self.rm_text(line,s,e) 130 # If comment exists write it to output 131 if code_line!= []: 132 for comment in code_line: 133 self.g_code_data.append(comment) 134 code_line=[] 135 136 # Switch remaining non comment data to upper case 137 # and remove spaces 138 line = line.upper() 139 line = line.replace(" ","") 140 141 142 ##################################################### 143 # Find # chars and check for a variable definition # 144 ##################################################### 145 if line.find("#") != -1: 146 s = line.rfind("#") 147 while s != -1: 148 if line[s+1] == '<': 149 e = s+2 150 while line[e] != '>' and e <= len(line): 151 e = e+1 152 e = e+1 153 vname = line[s:e].lower() 154 else: 155 vname = re.findall(r'[-+]?\d+',line[s:])[0] 156 e = s + 1 + len(vname) 157 vname = line[s:e] 158 159 DEFINE = False 160 if e < len(line): 161 if line[e]=="=": 162 DEFINE = True 163 if DEFINE: 164 try: 165 vval = "%.4f" %(float(line[e+1:])) 166 line = '' 167 except: 168 try: 169 vval = self.EXPRESSION_EVAL(line[e+1:]) 170 line = '' 171 except: 172 READ_MSG.append(str(sys.exc_info()[1])) 173 return READ_MSG 174 175 variables.append([vname,vval]) 176 line = self.rm_text(line,s,e-1) 177 else: 178 line = self.rm_text(line,s,e-1) 179 VALUE = '' 180 for V in variables: 181 if V[0] == vname: 182 VALUE = V[1] 183 184 line = self.insert_text(line,VALUE,s) 185 186 s = line.rfind("#") 187 188 ######################### 189 ### FIND MATH REGIONS ### 190 ######################### 191 if line.find("[") != -1 and line.find("[") != 0: 192 ############################ 193 s = line.find("[") 194 while s != -1: 195 e = s + 1 196 val = 1 197 while val > 0: 198 if e >= len(line): 199 MSG = "ERROR: Unable to evaluate expression: G-Code Line %d" %(line_number) 200 raise ValueError(MSG) 201 if line[e]=="[": 202 val = val + 1 203 elif line[e] == "]": 204 val = val - 1 205 e = e + 1 206 207 new_val = self.EXPRESSION_EVAL(line[s:e]) 208 209 line = self.rm_text(line,s,e-1) 210 line = self.insert_text(line,new_val,s) 211 s = line.find("[") 212 ############################# 213 214 215 #################################### 216 ### FIND FULLY UNSUPPORTED CODES ### 217 #################################### 218 # D Tool radius compensation number 219 # E ... 220 # L ... 221 # O ... Subroutines 222 # Q Feed increment in G73, G83 canned cycles 223 # A A axis of machine 224 # B B axis of machine 225 # C C axis of machine 226 # U U axis of machine 227 # V V axis of machine 228 # W W axis of machine 229 230 UCODES = ("A","B","C","D","E","L","O","Q","U","V","W") 231 skip = False 232 for code in UCODES: 233 if line.find(code) != -1: 234 READ_MSG.append("Warning: %s Codes are not supported ( G-Code File Line: %d )" %(code,line_number)) 235 skip = True 236 if skip: 237 continue 238 239 240 ############################## 241 ### FIND ALL CODES ### 242 ############################## 243 # F Feed rate 244 # G General function 245 # I X offset for arcs and G87 canned cycles 246 # J Y offset for arcs and G87 canned cycles 247 # K Z offset for arcs and G87 canned cycles. Spindle-Motion Ratio for G33 synchronized movements. 248 # M Miscellaneous function (See table Modal Groups) 249 # P Dwell time in canned cycles and with G4. Key used with G10. Used with G2/G3. 250 # R Arc radius or canned cycle plane 251 # S Spindle speed 252 # T Tool selection 253 # X X axis of machine 254 # Y Y axis of machine 255 # Z Z axis of machine 256 257 ALL = ("A","B","C","D","E","F","G","H","I","J",\ 258 "K","L","M","N","O","P","Q","R","S","T",\ 259 "U","V","W","X","Y","Z","#","=") 260 temp = [] 261 line = line.replace(" ","") 262 for code in ALL: 263 index=-1 264 index = line.find(code,index+1) 265 while index != -1: 266 temp.append([code,index]) 267 index = line.find(code,index+1) 268 temp.sort(key=lambda a:a[1]) 269 270 code_line=[] 271 if temp != []: 272 x = 0 273 while x <= len(temp)-1: 274 s = temp[x][1]+1 275 if x == len(temp)-1: 276 e = len(line) 277 else: 278 e = temp[x+1][1] 279 280 CODE = temp[x][0] 281 VALUE = line[s:e] 282 code_line.append([ CODE, VALUE ]) 283 x = x + 1 284 285 ################################# 286 287 mv_flag = 0 288 POS_LAST = POS[:] 289 #CENTER = ['','',''] 290 CENTER = POS_LAST[:] 291 passthru = "" 292 for com in code_line: 293 if com[0] == "G": 294 Gnum = "%g" %(float(com[1])) 295 if Gnum == "0" or Gnum == "1": 296 mvtype = int(Gnum) 297 elif Gnum == "2" or Gnum == "3": 298 mvtype = int(Gnum) 299 #CENTER = POS_LAST[:] 300 elif Gnum == "17": 301 plane = Gnum 302 elif Gnum == "18": 303 plane = Gnum 304 elif Gnum == "19": 305 plane = Gnum 306 elif Gnum == "20": 307 if units == "in": 308 scale = 1 309 else: 310 scale = 25.4 311 elif Gnum == "21": 312 if units == "mm": 313 scale = 1 314 else: 315 scale = 1.0/25.4 316 elif Gnum == "81": 317 READ_MSG.append("Warning: G%s Codes are not supported ( G-Code File Line: %d )" %(Gnum,line_number)) 318 elif Gnum == "90.1": 319 mode_arc = "absolute" 320 321 elif Gnum == "90": 322 mode_pos = "absolute" 323 324 elif Gnum == "91": 325 mode_pos = "incremental" 326 327 elif Gnum == "91.1": 328 mode_arc = "incremental" 329 330 elif Gnum == "92": 331 #READ_MSG.append("Aborting G-Code Reading: G%s Codes are not supported" %(Gnum)) 332 READ_MSG.append("Warning: G%s Codes are not supported ( G-Code File Line: %d )" %(Gnum,line_number)) 333 #return READ_MSG 334 335 elif Gnum == "38.2": 336 READ_MSG.append("Warning: G%s Codes are not supported ( G-Code File Line: %d )" %(Gnum,line_number)) 337 #READ_MSG.append("Aborting G-Code Reading: G%s Codes are not supported" %(Gnum)) 338 #return READ_MSG 339 340 else: 341 passthru = passthru + "%s%s " %(com[0],com[1]) 342 343 elif com[0] == "X": 344 if mode_pos == "absolute": 345 POS[xind] = float(com[1])*scale 346 else: 347 POS[xind] = float(com[1])*scale + POS_LAST[xind] 348 mv_flag = 1 349 350 elif com[0] == "Y": 351 if mode_pos == "absolute": 352 POS[yind] = float(com[1])*scale 353 else: 354 POS[yind] = float(com[1])*scale + POS_LAST[yind] 355 mv_flag = 1 356 357 elif com[0] == "Z": 358 if mode_pos == "absolute": 359 POS[zind] = float(com[1])*scale 360 else: 361 POS[zind] = float(com[1])*scale + POS_LAST[zind] 362 mv_flag = 1 363 364 ################### 365 elif com[0] == "I": 366 if mode_arc == "absolute": 367 CENTER[xind] = float(com[1])*scale 368 else: 369 CENTER[xind] = float(com[1])*scale + POS_LAST[xind] 370 if (mvtype==2 or mvtype==3): 371 mv_flag = 1 372 373 elif com[0] == "J": 374 if mode_arc == "absolute": 375 CENTER[yind] = float(com[1])*scale 376 else: 377 CENTER[yind] = float(com[1])*scale + POS_LAST[yind] 378 if (mvtype==2 or mvtype==3): 379 mv_flag = 1 380 elif com[0] == "K": 381 if mode_arc == "absolute": 382 CENTER[zind] = float(com[1])*scale 383 else: 384 CENTER[zind] = float(com[1])*scale + POS_LAST[zind] 385 if (mvtype==2 or mvtype==3): 386 mv_flag = 1 387 388 elif com[0] == "R": 389 Rin= float(com[1])*scale 390 CENTER = self.get_center(POS,POS_LAST,Rin,mvtype,plane) 391 392 ################### 393 elif com[0] == "F": 394 feed = float(com[1]) * scale 395 396 elif com[0] == "S": 397 spindle = float(com[1]) 398 399 elif com[0] == ";": 400 passthru = passthru + "%s " %(com[1]) 401 402 elif com[0] == "P" and mv_flag == 1 and mvtype > 1: 403 READ_MSG.append("Aborting G-Code Reading: P word specifying the number of full or partial turns of arc are not supported") 404 return READ_MSG 405 406 elif com[0] == "M": 407 Mnum = "%g" %(float(com[1])) 408 if Mnum == "2": 409 self.g_code_data.append([ "M2", "(END PROGRAM)" ]) 410 passthru = passthru + "%s%s " %(com[0],com[1]) 411 412 elif com[0] == "N": 413 pass 414 #print "Ignoring Line Number %g" %(float(com[1])) 415 416 else: 417 passthru = passthru + "%s%s " %(com[0],com[1]) 418 419 pos = POS[:] 420 pos_last = POS_LAST[:] 421 center = CENTER[:] 422 423 # Most command on a line are executed prior to a move so 424 # we will write the passthru commands on the line before we found them 425 # only "M0, M1, M2, M30 and M60" are executed after the move commands 426 # there is a risk that one of these commands could stop the program before 427 # the move is completed 428 429 if passthru != '': 430 self.g_code_data.append("%s" %(passthru)) 431 432 433 ############################################################################### 434 if mv_flag == 1: 435 if mvtype == 0: 436 self.g_code_data.append([mvtype,pos_last[:],pos[:]]) 437 if mvtype == 1: 438 self.g_code_data.append([mvtype,pos_last[:],pos[:],feed,spindle]) 439 if mvtype == 2 or mvtype == 3: 440 if plane == "17": 441 if XYarc2line == False: 442 self.g_code_data.append([mvtype,pos_last[:],pos[:],center[:],feed,spindle]) 443 else: 444 data = self.arc2lines(pos_last[:],pos[:],center[:], mvtype, plane) 445 446 for line in data: 447 XY=line 448 self.g_code_data.append([1,XY[:3],XY[3:],feed,spindle]) 449 450 elif plane == "18": 451 data = self.arc2lines(pos_last[:],pos[:],center[:], mvtype, plane) 452 for line in data: 453 XY=line 454 self.g_code_data.append([1,XY[:3],XY[3:],feed,spindle]) 455 456 elif plane == "19": 457 data = self.arc2lines(pos_last[:],pos[:],center[:], mvtype, plane) 458 for line in data: 459 XY=line 460 self.g_code_data.append([1,XY[:3],XY[3:],feed,spindle]) 461 ############################################################################### 462 ################################# 463 fin.close() 464 465 ## Post process the g-code data to remove complex numbers 466 cnt = 0 467 firstx = complex(0,1) 468 firsty = complex(0,1) 469 firstz = complex(0,1) 470 first_sum = firstx + firsty + firstz 471 while ((cnt < len(self.g_code_data)) and (isinstance(first_sum, complex))): 472 line = self.g_code_data[cnt] 473 if line[0] == 0 or line[0] == 1 or line[0] == 2 or line[0] == 3: 474 if (isinstance(firstx, complex)): firstx = line[2][0] 475 if (isinstance(firsty, complex)): firsty = line[2][1] 476 if (isinstance(firstz, complex)): firstz = line[2][2] 477 cnt=cnt+1 478 first_sum = firstx + firsty + firstz 479 max_cnt = cnt 480 cnt = 0 481 ambiguousX = False 482 ambiguousY = False 483 ambiguousZ = False 484 while (cnt < max_cnt): 485 line = self.g_code_data[cnt] 486 if line[0] == 1 or line[0] == 2 or line[0] == 3: 487 # X Values 488 if (isinstance(line[1][0], complex)): 489 line[1][0] = firstx 490 ambiguousX = True 491 if (isinstance(line[2][0], complex)): 492 line[2][0] = firstx 493 ambiguousX = True 494 # Y values 495 if (isinstance(line[1][1], complex)): 496 line[1][1] = firsty 497 ambiguousY = True 498 if (isinstance(line[2][1], complex)): 499 line[2][1] = firsty 500 ambiguousY = True 501 # Z values 502 if (isinstance(line[1][2], complex)): 503 line[1][2] = firstz 504 ambiguousZ = True 505 if (isinstance(line[2][2], complex)): 506 line[2][2] = firstz 507 ambiguousZ = True 508 cnt=cnt+1 509 #if (ambiguousX or ambiguousY or ambiguousZ): 510 # MSG = "Ambiguous G-Code start location:\n" 511 # if (ambiguousX): MSG = MSG + "X position is not set by a G0(rapid) move prior to a G1,G2 or G3 move.\n" 512 # if (ambiguousY): MSG = MSG + "Y position is not set by a G0(rapid) move prior to a G1,G2 or G3 move.\n" 513 # if (ambiguousZ): MSG = MSG + "Z position is not set by a G0(rapid) move prior to a G1,G2 or G3 move.\n" 514 # MSG = MSG + "!! Review output files carefully !!" 515 # READ_MSG.append(MSG) 516 517 return READ_MSG 518 519 def get_center(self,POS,POS_LAST,Rin,mvtype,plane="17"): 520 if plane == "18": 521 xind=2 522 yind=0 523 zind=1 524 elif plane == "19": 525 xind=1 526 yind=2 527 zind=0 528 elif plane == "17": 529 xind=0 530 yind=1 531 zind=2 532 533 CENTER=["","",""] 534 cord = sqrt( (POS[xind]-POS_LAST[xind])**2 + (POS[yind]-POS_LAST[yind])**2 ) 535 v1 = cord/2.0 536 537 #print "rin=%f v1=%f (Rin**2 - v1**2)=%f" %(Rin,v1,(Rin**2 - v1**2)) 538 v2_sq = Rin**2 - v1**2 539 if v2_sq<0.0: 540 v2_sq = 0.0 541 v2 = sqrt( v2_sq ) 542 543 theta = self.Get_Angle2(POS[xind]-POS_LAST[xind],POS[yind]-POS_LAST[yind]) 544 545 if mvtype == 3: 546 dxc,dyc = self.Transform(-v2,v1,radians(theta-90)) 547 elif mvtype == 2: 548 dxc,dyc = self.Transform(v2,v1,radians(theta-90)) 549 else: 550 return "Center Error" 551 552 xcenter = POS_LAST[xind] + dxc 553 ycenter = POS_LAST[yind] + dyc 554 555 CENTER[xind] = xcenter 556 CENTER[yind] = ycenter 557 CENTER[zind] = POS_LAST[zind] 558 559 return CENTER 560 561 ####################################### 562 def split_code(self,code2split,shift=[0,0,0],angle=0.0): 563 xsplit=0.0 564 mvtype = -1 # G0 (Rapid), G1 (linear), G2 (clockwise arc) or G3 (counterclockwise arc). 565 566 passthru = "" 567 POS =[0,0,0] 568 feed = 0 569 spindle = 0 570 self.right_side = [] 571 self.left_side = [] 572 573 L = 0 574 R = 1 575 for line in code2split: 576 if line[0] == 1: 577 mvtype = line[0] 578 POS_LAST = line[1][:] 579 POS = line[2][:] 580 CENTER = ['','',''] 581 feed = line[3] 582 spindle = line[4] 583 584 elif line[0] == 3 or line[0] == 2: 585 mvtype = line[0] 586 POS_LAST = line[1][:] 587 POS = line[2][:] 588 CENTER = line[3][:] 589 feed = line[4] 590 spindle = line[5] 591 592 else: 593 mvtype = -1 594 passthru = line 595 596 ############################################################################### 597 if mvtype >= 1 and mvtype <= 3: 598 pos = self.coordop(POS,shift,angle) 599 pos_last = self.coordop(POS_LAST,shift,angle) 600 601 if CENTER[0]!='' and CENTER[1]!='': 602 center = self.coordop(CENTER,shift,angle) 603 else: 604 center = CENTER 605 606 this="" 607 other="" 608 609 if pos_last[0] > xsplit+self.Zero: 610 flag_side = R 611 elif pos_last[0] < xsplit-self.Zero: 612 flag_side = L 613 else: 614 if mvtype == 1: 615 if pos[0] >= xsplit: 616 flag_side = R 617 else: 618 flag_side = L 619 620 elif mvtype == 2: 621 622 if abs(pos_last[1]-center[1]) < self.Zero: 623 if center[0] > xsplit: 624 flag_side = R 625 else: 626 flag_side = L 627 else: 628 if pos_last[1] >= center[1]: 629 flag_side = R 630 else: 631 flag_side = L 632 633 else: #(mvtype == 3) 634 if abs(pos_last[1]-center[1]) < self.Zero: 635 if center[0] > xsplit: 636 flag_side = R 637 else: 638 flag_side = L 639 else: 640 if pos_last[1] >= center[1]: 641 flag_side = L 642 else: 643 flag_side = R 644 645 if flag_side == R: 646 this = 1 647 other = 0 648 else: 649 this = 0 650 other = 1 651 652 app=[self.apright, self.apleft] 653 654 ############################# 655 if mvtype == 0: 656 pass 657 658 if mvtype == 1: 659 A = self.coordunop(pos_last[:],shift,angle) 660 C = self.coordunop(pos[:] ,shift,angle) 661 cross = self.get_line_intersect(pos_last, pos, xsplit) 662 663 if len(cross) > 0: ### Line crosses boundary ### 664 B = self.coordunop(cross[0] ,shift,angle) 665 app[this] ( [mvtype,A,B,feed,spindle] ) 666 app[other]( [mvtype,B,C,feed,spindle] ) 667 else: 668 app[this] ( [mvtype,A,C,feed,spindle] ) 669 670 if mvtype == 2 or mvtype == 3: 671 A = self.coordunop(pos_last[:],shift,angle) 672 C = self.coordunop(pos[:] ,shift,angle) 673 D = self.coordunop(center ,shift,angle) 674 cross = self.get_arc_intersects(pos_last[:], pos[:], xsplit, center[:], "G%d" %(mvtype)) 675 676 if len(cross) > 0: ### Arc crosses boundary at least once ### 677 B = self.coordunop(cross[0] ,shift,angle) 678 #Check length of arc before writing 679 if sqrt((A[0]-B[0])**2 + (A[1]-B[1])**2) > self.accuracy: 680 app[this]( [mvtype,A,B,D,feed,spindle]) 681 682 if len(cross) == 1: ### Arc crosses boundary only once ### 683 #Check length of arc before writing 684 if sqrt((B[0]-C[0])**2 + (B[1]-C[1])**2) > self.accuracy: 685 app[other]([ mvtype,B,C,D, feed,spindle] ) 686 if len(cross) == 2: ### Arc crosses boundary twice ### 687 E = self.coordunop(cross[1],shift,angle) 688 #Check length of arc before writing 689 if sqrt((B[0]-E[0])**2 + (B[1]-E[1])**2) > self.accuracy: 690 app[other]([ mvtype,B,E,D, feed,spindle] ) 691 #Check length of arc before writing 692 if sqrt((E[0]-C[0])**2 + (E[1]-C[1])**2) > self.accuracy: 693 app[this] ([ mvtype,E,C,D, feed,spindle] ) 694 else: ### Arc does not cross boundary ### 695 app[this]([ mvtype,A,C,D, feed,spindle]) 696 697 ############################################################################### 698 else: 699 if passthru != '': 700 self.apboth(passthru) 701 702 ####################################### 703 def probe_code(self,code2probe,nX,nY,probe_istep,minx,miny,xPartitionLength,yPartitionLength): #,Xoffset,Yoffset): 704 #def probe_code(self,code2probe,nX,nY,probe_istep,minx,miny,xPartitionLength,yPartitionLength,Xoffset,Yoffset,Zoffset): 705 #print "nX,nY =",nX,nY 706 probe_coords = [] 707 BPN=500 708 POINT_LIST = [False for i in range(int((nY)*(nX)))] 709 710 if code2probe == []: 711 return 712 713 mvtype = -1 # G0 (Rapid), G1 (linear), G2 (clockwise arc) or G3 (counterclockwise arc). 714 passthru = "" 715 POS = [0,0,0] 716 feed = 0 717 spindle = 0 718 out = [] 719 720 min_length = min(xPartitionLength,yPartitionLength) / probe_istep 721 if (min_length < self.Zero): 722 min_length = max(xPartitionLength,yPartitionLength) / probe_istep 723 if (min_length < self.Zero): 724 min_length = 1 725 726 for line in code2probe: 727 if line[0] == 0 or line[0] == 1: 728 mvtype = line[0] 729 POS_LAST = line[1][:] 730 POS = line[2][:] 731 CENTER = ['','',''] 732 if line[0] == 1: 733 feed = line[3] 734 spindle = line[4] 735 736 elif line[0] == 3 or line[0] == 2: 737 mvtype = line[0] 738 POS_LAST = line[1][:] 739 POS = line[2][:] 740 CENTER = line[3][:] 741 feed = line[4] 742 spindle = line[5] 743 else: 744 mvtype = -1 745 passthru = line 746 747 ############################################################################### 748 if mvtype >= 0 and mvtype <=3: 749 pos = POS[:] 750 pos_last = POS_LAST[:] 751 center = CENTER[:] 752 753 ############################# 754 if mvtype == 0: 755 out.append( [mvtype,pos_last,pos] ) 756 757 if mvtype == 1: 758 dx = pos[0]-pos_last[0] 759 dy = pos[1]-pos_last[1] 760 dz = pos[2]-pos_last[2] 761 length = sqrt(dx*dx + dy*dy) 762 if (length <= min_length): 763 out.append( [mvtype,pos_last,pos,feed,spindle] ) 764 else: 765 Lsteps = max(2,int(ceil(length / min_length))) 766 xstp0 = float(pos_last[0]) 767 ystp0 = float(pos_last[1]) 768 zstp0 = float(pos_last[2]) 769 for n in range(1,Lsteps+1): 770 xstp1 = n/float(Lsteps)*dx + pos_last[0] 771 ystp1 = n/float(Lsteps)*dy + pos_last[1] 772 zstp1 = n/float(Lsteps)*dz + pos_last[2] 773 out.append( [mvtype,[xstp0,ystp0,zstp0],[xstp1,ystp1,zstp1],feed,spindle] ) 774 xstp0 = float(xstp1) 775 ystp0 = float(ystp1) 776 zstp0 = float(zstp1) 777 778 if mvtype == 2 or mvtype == 3: 779 out.append( [ mvtype,pos_last,pos,center, feed,spindle] ) 780 ############################################################################### 781 else: 782 if passthru != '': 783 out.append(passthru) 784 785 ################################ 786 ## Loop through output to ## 787 ## find needed probe points ## 788 ################################ 789 for i in range(len(out)): 790 line = out[i] 791 if line[0] == 0 or line[0] == 1: 792 mvtype = line[0] 793 POS_LAST = line[1][:] 794 POS = line[2][:] 795 CENTER = ['','',''] 796 if line[0] == 1: 797 feed = line[3] 798 spindle = line[4] 799 800 elif line[0] == 3 or line[0] == 2: 801 mvtype = line[0] 802 POS_LAST = line[1][:] 803 POS = line[2][:] 804 CENTER = line[3][:] 805 feed = line[4] 806 spindle = line[5] 807 else: 808 mvtype = -1 809 passthru = line 810 811 if mvtype >= 1 and mvtype <=3: 812 pos = POS[:] 813 pos_last = POS_LAST[:] 814 center = CENTER[:] 815 816 817 #### ADD ADDITIONAL DATA TO POS_LAST DATA #### 818 i_x,i_y = self.get_ix_iy((pos_last[0]-minx),(pos_last[1]-miny),xPartitionLength,yPartitionLength) 819 #i_x = i_x+Xoffset 820 #i_y = i_y+Yoffset 821 if i_x < 0: 822 i_x=0 823 if i_y < 0: 824 i_y=0 825 if (i_x+1 >= nX): 826 i_x = nX-2 827 #i_x = i_x-1 #commented 02/22 828 #print "adjust i_x POS_LAST" 829 i_x2 = i_x+1 830 if (i_y+1 >= nY): 831 i_y = nY-2 832 #i_y = i_y-1 #commented 02/22 833 #print "adjust i_y POS_LAST" 834 i_y2 = i_y+1 835 836 p_index_A = int(i_y* nX + i_x ) 837 p_index_B = int(i_y2*nX + i_x ) 838 p_index_C = int(i_y *nX + i_x2) 839 p_index_D = int(i_y2*nX + i_x2) 840 841 Xfraction=((pos_last[0]-minx)-(i_x*xPartitionLength))/xPartitionLength 842 Yfraction=((pos_last[1]-miny)-(i_y*yPartitionLength))/yPartitionLength 843 844 if Xfraction>1.0: 845 #print "ERROR POS_LAST: Xfraction = ", Xfraction 846 Xfraction = 1.0 847 if Xfraction <0.0: 848 #print "ERROR POS_LAST: Xfraction = ", Xfraction 849 Xfraction = 0.0 850 if Yfraction > 1.0: 851 #print "ERROR POS_LAST: Yfraction = ", Yfraction 852 Yfraction = 1.0 853 if Yfraction<0.0: 854 #print "ERROR POS_LAST: Yfraction = ", Yfraction 855 Yfraction = 0.0 856 857 BPN=500 858 out[i][1].append(p_index_A+BPN) 859 out[i][1].append(p_index_B+BPN) 860 out[i][1].append(p_index_C+BPN) 861 out[i][1].append(p_index_D+BPN) 862 out[i][1].append(Xfraction) 863 out[i][1].append(Yfraction) 864 865 try: 866 POINT_LIST[p_index_A ] = True 867 POINT_LIST[p_index_B ] = True 868 POINT_LIST[p_index_C ] = True 869 POINT_LIST[p_index_D ] = True 870 except: 871 pass 872 #### ADD ADDITIONAL DATA TO POS_LAST DATA #### 873 i_x,i_y = self.get_ix_iy((pos[0]-minx),(pos[1]-miny),xPartitionLength,yPartitionLength) 874 #i_x = i_x+Xoffset 875 #i_y = i_y+Yoffset 876 if i_x < 0: 877 i_x=0 878 if i_y < 0: 879 i_y=0 880 if (i_x+1 >= nX): 881 i_x = nX-2 882 #i_x = i_x-1 #commented 02/22 883 #print "adjust i_x POS" 884 i_x2 = i_x+1 885 if (i_y+1 >= nY): 886 i_y = nY-2 887 #i_y = i_y-1#commented 02/22 888 #print "adjust i_y POS" 889 i_y2 = i_y+1 890 891 p_index_A = int(i_y* nX + i_x ) 892 p_index_B = int(i_y2*nX + i_x ) 893 p_index_C = int(i_y *nX + i_x2) 894 p_index_D = int(i_y2*nX + i_x2) 895 Xfraction=((pos[0]-minx)-(i_x*xPartitionLength))/xPartitionLength 896 Yfraction=((pos[1]-miny)-(i_y*yPartitionLength))/yPartitionLength 897 898 if Xfraction>1.0: 899 Xfraction = 1.0 900 #print "ERROR POS: Xfraction = ", Xfraction 901 if Xfraction <0.0: 902 Xfraction = 0.0 903 #print "ERROR POS: Xfraction = ", Xfraction 904 if Yfraction > 1.0: 905 Yfraction = 1.0 906 #print "ERROR POS: Yfraction = ", Yfraction 907 if Yfraction<0.0: 908 Yfraction = 0.0 909 #print "ERROR POS: Yfraction = ", Yfraction 910 911 out[i][2].append(p_index_A+BPN) 912 out[i][2].append(p_index_B+BPN) 913 out[i][2].append(p_index_C+BPN) 914 out[i][2].append(p_index_D+BPN) 915 out[i][2].append(Xfraction) 916 out[i][2].append(Yfraction) 917 try: 918 POINT_LIST[p_index_A ] = True 919 POINT_LIST[p_index_B ] = True 920 POINT_LIST[p_index_C ] = True 921 POINT_LIST[p_index_D ] = True 922 except: 923 pass 924 self.probe_gcode = out 925 #for line in out: 926 # print line 927 928 ################################ 929 ## Generate Probing Code ## 930 ## For needed points ## 931 ################################ 932 933 for i in range(len(POINT_LIST)): 934 i_x = i % nX 935 i_y = int(i / nX) 936 xp = i_x * xPartitionLength + minx 937 yp = i_y * yPartitionLength + miny 938 probe_coords.append([POINT_LIST[i],i+BPN,xp,yp]) 939 940 self.probe_coords = probe_coords 941 return 942 943 def get_ix_iy(self,x,y,xPartitionLength,yPartitionLength): 944 i_x=int(x/xPartitionLength) 945 i_y=int(y/yPartitionLength) 946 return i_x,i_y 947 948 ####################################### 949 def scale_rotate_code(self,code2scale,scale=[1.0,1.0,1.0,1.0],angle=0.0): 950 if code2scale == []: 951 return code2scale,0,0,0,0,0,0 952 minx = 99999 953 maxx = -99999 954 miny = 99999 955 maxy = -99999 956 minz = 99999 957 maxz = -99999 958 mvtype = -1 # G0 (Rapid), G1 (linear), G2 (clockwise arc) or G3 (counterclockwise arc). 959 960 passthru = "" 961 POS =[0,0,0] 962 feed = 0 963 spindle = 0 964 out = [] 965 966 L = 0 967 R = 1 968 flag_side = 1 969 970 for line in code2scale: 971 if line[0] == 0 or line[0] == 1: 972 mvtype = line[0] 973 POS_LAST = line[1][:] 974 POS = line[2][:] 975 CENTER = ['','',''] 976 if line[0] == 1: 977 feed = line[3] * scale[3] 978 spindle = line[4] 979 980 elif line[0] == 3 or line[0] == 2: 981 mvtype = line[0] 982 POS_LAST = line[1][:] 983 POS = line[2][:] 984 CENTER = line[3][:] 985 feed = line[4] * scale[3] 986 spindle = line[5] 987 else: 988 mvtype = -1 989 passthru = line 990 991 ############################################################################### 992 if mvtype >= 0 and mvtype <=3: 993 994 pos = self.scale_rot_coords(POS,scale,angle) 995 pos_last = self.scale_rot_coords(POS_LAST,scale,angle) 996 997 998 if CENTER[0]!='' and CENTER[1]!='': 999 center = self.scale_rot_coords(CENTER,scale,angle) 1000 else: 1001 center = CENTER 1002 1003 ############################# 1004 try: 1005 minx = min( minx, min(pos[0],pos_last[0]) ) 1006 maxx = max( maxx, max(pos[0],pos_last[0]) ) 1007 except: 1008 pass 1009 try: 1010 miny = min( miny, min(pos[1],pos_last[1]) ) 1011 maxy = max( maxy, max(pos[1],pos_last[1]) ) 1012 except: 1013 pass 1014 try: 1015 minz = min( minz, min(pos[2],pos_last[2]) ) 1016 maxz = max( maxz, max(pos[2],pos_last[2]) ) 1017 except: 1018 pass 1019 1020 if mvtype == 0: 1021 out.append( [mvtype,pos_last,pos] ) 1022 1023 if mvtype == 1: 1024 out.append( [mvtype,pos_last,pos,feed, spindle] ) 1025 1026 if mvtype == 2 or mvtype == 3: 1027 out.append( [ mvtype,pos_last,pos,center, feed, spindle] ) 1028 1029 if mvtype == 3: 1030 ang1 = self.Get_Angle2(pos_last[0]-center[0],pos_last[1]-center[1]) 1031 xtmp,ytmp = self.Transform(pos[0]-center[0],pos[1]-center[1],radians(-ang1)) 1032 ang2 = self.Get_Angle2(xtmp,ytmp) 1033 1034 else: 1035 ang1 = self.Get_Angle2(pos[0]-center[0],pos[1]-center[1]) 1036 xtmp,ytmp = self.Transform(pos_last[0]-center[0],pos_last[1]-center[1],radians(-ang1)) 1037 ang2 = self.Get_Angle2(xtmp,ytmp) 1038 1039 if ang2 == 0: 1040 ang2=359.999 1041 1042 Radius = sqrt( (pos[0]-center[0])**2 +(pos[1]-center[1])**2 ) 1043 1044 if ang1 > 270: 1045 da = 270 1046 elif ang1 > 180: 1047 da = 180 1048 elif ang1 > 90: 1049 da = 90 1050 else: 1051 da = 0 1052 for side in [90,180,270,360]: 1053 spd = side + da 1054 if ang2 > (spd-ang1): 1055 if spd > 360: 1056 spd=spd-360 1057 if spd==90: 1058 maxy = max( maxy, center[1]+Radius ) 1059 if spd==180: 1060 minx = min( minx, center[0]-Radius) 1061 if spd==270: 1062 miny = min( miny, center[1]-Radius ) 1063 if spd==360: 1064 maxx = max( maxx, center[0]+Radius ) 1065 ############################################################################### 1066 else: 1067 if passthru != '': 1068 out.append(passthru) 1069 1070 return out,minx,maxx,miny,maxy,minz,maxz 1071 1072 1073 ####################################### 1074 def scale_translate(self,code2translate,translate=[0.0,0.0,0.0]): 1075 1076 if translate[0]==0 and translate[1]==0 and translate[2]==0: 1077 return code2translate 1078 1079 mvtype = -1 # G0 (Rapid), G1 (linear), G2 (clockwise arc) or G3 (counterclockwise arc). 1080 passthru = "" 1081 POS =[0,0,0] 1082 pos =[0,0,0] 1083 pos_last=[0,0,0] 1084 feed = 0 1085 spindle = 0 1086 out = [] 1087 1088 L = 0 1089 R = 1 1090 flag_side = 1 1091 1092 for line in code2translate: 1093 if line[0] == 1 or line[0] == 0: 1094 mvtype = line[0] 1095 POS_LAST = line[1][:] 1096 POS = line[2][:] 1097 CENTER = ['','',''] 1098 if line[0] == 1: 1099 feed = line[3] 1100 spindle = line[4] 1101 1102 elif line[0] == 3 or line[0] == 2: 1103 mvtype = line[0] 1104 POS_LAST = line[1][:] 1105 POS = line[2][:] 1106 CENTER = line[3][:] 1107 feed = line[4] 1108 spindle = line[5] 1109 else: 1110 mvtype = -1 1111 passthru = line 1112 1113 ############################################################################### 1114 if mvtype >= 0 and mvtype <=3: 1115 pos = self.scale_trans_coords(POS,translate) 1116 pos_last = self.scale_trans_coords(POS_LAST,translate) 1117 if CENTER[0]!='' and CENTER[1]!='': 1118 center = self.scale_trans_coords(CENTER,translate) 1119 else: 1120 center = CENTER[:] 1121 1122 ############################# 1123 if mvtype == 0: 1124 out.append( [mvtype,pos_last,pos] ) 1125 1126 if mvtype == 1: 1127 out.append( [mvtype,pos_last,pos,feed,spindle] ) 1128 1129 if mvtype == 2 or mvtype == 3: 1130 out.append( [ mvtype,pos_last,pos,center, feed,spindle] ) 1131 ############################################################################### 1132 else: 1133 if passthru != '': 1134 out.append(passthru) 1135 return out 1136 1137 def scale_trans_coords(self,coords,trans): 1138 x = coords[0] - trans[0] 1139 y = coords[1] - trans[1] 1140 z = coords[2] - trans[2] 1141 return [x,y,z] 1142 1143 def scale_rot_coords(self,coords,scale,rot): 1144 x = coords[0] * scale[0] 1145 y = coords[1] * scale[1] 1146 z = coords[2] * scale[2] 1147 1148 x,y = self.Transform(x,y, radians(rot) ) 1149 return [x,y,z] 1150 1151 def generategcode(self,side,z_safe=.5, 1152 plunge_feed=10.0, 1153 no_variables=False, 1154 Rstock=0.0, 1155 Wrap="XYZ", 1156 preamble="", 1157 postamble="", 1158 gen_rapids=False, 1159 PLACES_L=4, 1160 PLACES_R=3, 1161 PLACES_F=1, 1162 WriteAll=False, 1163 FSCALE="Scale-Rotary", 1164 Reverse_Rotary = False, 1165 NoComments=False): 1166 1167 g_code = [] 1168 1169 sign = 1 1170 if Reverse_Rotary: 1171 sign = -1 1172 1173 self.MODAL_VAL={'X':" ", 'Y':" ", 'Z':" ", 'F':" ", 'A':" ", 'B':" ", 'I':" ", 'J':" "} 1174 LASTX = 0 1175 LASTY = 0 1176 LASTZ = z_safe 1177 1178 g_code.append("( G-Code Modified by G-Code Ripper )") 1179 g_code.append("( by Scorch - 2017 www.scorchworks.com )") 1180 if Wrap == "XYZ": 1181 AXIS=["X" , "Y" , "Z" ] 1182 DECP=[PLACES_L, PLACES_L, PLACES_L] 1183 elif Wrap == "Y2A": 1184 AXIS=["X" , "A" , "Z" ] 1185 DECP=[PLACES_L, PLACES_R, PLACES_L] 1186 WriteAll=False 1187 g_code.append("(G-Code Ripper has mapped the Y-Axis to the A-Axis )") 1188 elif Wrap == "X2B": 1189 AXIS=["B" , "Y" , "Z" ] 1190 DECP=[PLACES_R, PLACES_L, PLACES_L] 1191 WriteAll=False 1192 g_code.append("(G-Code Ripper has mapped the X-Axis to the B-Axis )") 1193 elif Wrap == "Y2B": 1194 AXIS=["X" , "B" , "Z" ] 1195 DECP=[PLACES_L, PLACES_R, PLACES_L] 1196 WriteAll=False 1197 g_code.append("(G-Code Ripper has mapped the Y-Axis to the B-Axis )") 1198 elif Wrap == "X2A": 1199 AXIS=["A" , "Y" , "Z" ] 1200 DECP=[PLACES_R, PLACES_L, PLACES_L] 1201 WriteAll=False 1202 g_code.append("(G-Code Ripper has mapped the X-Axis to the A-Axis )") 1203 1204 if Wrap != "XYZ": 1205 g_code.append("(A nominal stock radius of %f was used. )" %(Rstock)) 1206 g_code.append("(Z-axis zero position is the surface of the round stock. )") 1207 g_code.append("(---------------------------------------------------------)") 1208 1209 g_code.append("G90 (set absolute distance mode)") 1210 g_code.append("G90.1 (set absolute distance mode for arc centers)") 1211 g_code.append("G17 (set active plane to XY)") 1212 1213 if self.units == "in": 1214 g_code.append("G20 (set units to inches)") 1215 else: 1216 g_code.append("G21 (set units to mm)") 1217 1218 if no_variables==False: 1219 g_code.append("#<z_safe> = % 5.3f " %(z_safe)) 1220 g_code.append("#<plunge_feed> = % 5.0f " %(plunge_feed)) 1221 1222 for line in preamble.split('|'): 1223 g_code.append(line) 1224 1225 g_code.append("(---------------------------------------------------------)") 1226 ################### 1227 ## GCODE WRITING ## 1228 ################### 1229 for line in side: 1230 if line[0] == 1 or line[0] == 2 or line[0] == 3 or (line[0] == 0 and gen_rapids == False): 1231 D0 = line[2][0]-line[1][0] 1232 D1 = line[2][1]-line[1][1] 1233 D2 = line[2][2]-line[1][2] 1234 D012 = sqrt((D0+0j).real**2+(D1+0j).real**2+(D2+0j).real**2) 1235 1236 coordA=[ line[1][0], line[1][1], line[1][2] ] 1237 coordB=[ line[2][0], line[2][1], line[2][2] ] 1238 if Wrap == "Y2A" or Wrap == "Y2B": 1239 #if line[1][1].imag == 0: 1240 if (not isinstance(line[1][1], complex)): 1241 coordA[1]=sign*degrees(line[1][1]/Rstock) 1242 #if line[2][1].imag == 0: 1243 if (not isinstance(line[2][1], complex)): 1244 coordB[1]=sign*degrees(line[2][1]/Rstock) 1245 elif Wrap == "X2B" or Wrap == "X2A": 1246 #if line[1][0].imag == 0: 1247 if (not isinstance(line[1][0], complex)): 1248 coordA[0]=sign*degrees(line[1][0]/Rstock) 1249 #if line[2][0].imag == 0: 1250 if (not isinstance(line[2][0], complex)): 1251 coordB[0]=sign*degrees(line[2][0]/Rstock) 1252 1253 dx = coordA[0]-LASTX 1254 dy = coordA[1]-LASTY 1255 dz = coordA[2]-LASTZ 1256 1257 # Check if next point is coincident with the 1258 # current point withing the set accuracy 1259 if sqrt((dx+0j).real**2 + (dy+0j).real**2 + (dz+0j).real**2) > self.accuracy and gen_rapids == True: 1260 ### Move tool to safe height (z_safe) ### 1261 if no_variables==False: 1262 g_code.append("G0 %c #<z_safe> " %(AXIS[2]) ) 1263 self.MODAL_VAL[AXIS[2]] = z_safe 1264 else: 1265 LINE = "G0" 1266 LINE = self.app_gcode_line(LINE,AXIS[2],z_safe,DECP[2],WriteAll) 1267 if len(LINE) > 2: g_code.append(LINE) 1268 1269 ### Move tool to coordinates of next cut ### 1270 LINE = "G0" 1271 LINE = self.app_gcode_line(LINE,AXIS[0],coordA[0],DECP[0],WriteAll) 1272 LINE = self.app_gcode_line(LINE,AXIS[1],coordA[1],DECP[1],WriteAll) 1273 if len(LINE) > 2: g_code.append(LINE) 1274 1275 if float(coordA[2]) < float(z_safe): 1276 if no_variables==False: 1277 LINE = "G1" 1278 LINE = self.app_gcode_line(LINE,AXIS[2],coordA[2],DECP[2],WriteAll) 1279 LINE = LINE + " F #<plunge_feed>" 1280 self.MODAL_VAL["F"] = plunge_feed 1281 if len(LINE) > 2: g_code.append(LINE) 1282 else: 1283 LINE = "G1" 1284 LINE = self.app_gcode_line(LINE,AXIS[2],coordA[2] ,DECP[2] , WriteAll) 1285 LINE = self.app_gcode_line(LINE,"F" ,plunge_feed,PLACES_F, WriteAll) 1286 if len(LINE) > 2: g_code.append(LINE) 1287 1288 LASTX = coordB[0] 1289 LASTY = coordB[1] 1290 LASTZ = coordB[2] 1291 1292 if (line[0] == 1) or (line[0] == 2) or (line[0] == 3) or (line[0] == 0 and (gen_rapids == False)): 1293 try: LAST0 = float(self.MODAL_VAL[AXIS[0]]) 1294 except: LAST0 = coordB[0] 1295 try: LAST1 = float(self.MODAL_VAL[AXIS[1]]) 1296 except: LAST1 = coordB[1] 1297 try: LAST2 = float(self.MODAL_VAL[AXIS[2]]) 1298 except: LAST2 = coordB[2] 1299 1300 LINE = "G%d" %(line[0]) 1301 LINE = self.app_gcode_line(LINE,AXIS[0],coordB[0],DECP[0],WriteAll) 1302 LINE = self.app_gcode_line(LINE,AXIS[1],coordB[1],DECP[1],WriteAll) 1303 LINE = self.app_gcode_line(LINE,AXIS[2],coordB[2],DECP[2],WriteAll) 1304 if (line[0] == 1): 1305 if ((LINE.find("A") > -1) or (LINE.find("B") > -1)) and (FSCALE == "Scale-Rotary") and (D012>self.Zero): 1306 if (LINE.find("X") > -1) or (LINE.find("Y") > -1) or (LINE.find("Z") > -1): 1307 if Wrap == "Y2A" or Wrap == "Y2B": 1308 Df = sqrt(D0**2 + D2**2) 1309 elif Wrap == "X2B" or Wrap == "X2A": 1310 Df = sqrt(D1**2 + D2**2) 1311 Feed_adj = abs(Df / (D012/line[3])) 1312 else: 1313 if Wrap == "Y2A" or Wrap == "Y2B": 1314 DAf = coordB[1]-LAST1 1315 Feed_adj = abs(DAf / (D012/line[3])) 1316 elif Wrap == "X2B" or Wrap == "X2A": 1317 DAf = coordB[0]-LAST0 1318 Feed_adj = abs(DAf / (D012/line[3])) 1319 else: 1320 Feed_adj = line[3] 1321 LINE = self.app_gcode_line(LINE,"F",Feed_adj ,PLACES_F,WriteAll) 1322 1323 elif (line[0] == 2) or (line[0] == 3): 1324 LINE = self.app_gcode_line(LINE,"I",line[3][0],DECP[0] ,WriteAll) 1325 LINE = self.app_gcode_line(LINE,"J",line[3][1],DECP[1] ,WriteAll) 1326 LINE = self.app_gcode_line(LINE,"F",Feed_adj ,PLACES_F,WriteAll) 1327 if len(LINE) > 2: g_code.append(LINE) 1328 1329 elif (line[0] == 0 and gen_rapids == True): 1330 pass 1331 1332 elif line[0] == ";": 1333 if not NoComments: 1334 g_code.append("%s" %(line[1])) 1335 1336 elif line[0] == "M2": 1337 if gen_rapids == True: 1338 if no_variables==False: 1339 g_code.append("G0 %c #<z_safe> " %(AXIS[2]) ) 1340 self.MODAL_VAL[AXIS[2]] = z_safe 1341 else: 1342 LINE = "G0" 1343 LINE = self.app_gcode_line(LINE,AXIS[2],z_safe,DECP[2],WriteAll) 1344 g_code.append(LINE) 1345 1346 for entry in postamble.split('|'): 1347 g_code.append(entry) 1348 #g_code.append(line[0]) 1349 else: 1350 g_code.append(line) 1351 ######################## 1352 ## END G-CODE WRITING ## 1353 ######################## 1354 return g_code 1355 1356 1357 def app_gcode_line(self,LINE,CODE,VALUE,PLACES,WriteAll): 1358 if isinstance(VALUE, complex): 1359 return LINE 1360 #if VALUE.imag != 0: 1361 # return LINE 1362 1363 if CODE == "F": 1364 if (VALUE*10**PLACES) < 1: 1365 # Fix Zero feed rate 1366 VALUE = 1.0/(10**PLACES) 1367 1368 if PLACES > 0: 1369 FORMAT="%% .%df" %(PLACES) 1370 else: 1371 FORMAT="%d" 1372 VAL = FORMAT %(VALUE) 1373 1374 if ( VAL != self.MODAL_VAL[CODE] )\ 1375 or ( CODE=="I" ) \ 1376 or ( CODE=="J" ) \ 1377 or (WriteAll): 1378 LINE = LINE + " %s%s" %(CODE, VAL) 1379 self.MODAL_VAL[CODE] = VAL 1380 1381 return LINE 1382 1383 def get_arc_intersects(self, p1, p2, xsplit, cent, code): 1384 xcross1= xsplit 1385 xcross2= xsplit 1386 1387 R = sqrt( (cent[0]-p1[0])**2 + (cent[1]-p1[1])**2 ) 1388 Rt= sqrt( (cent[0]-p2[0])**2 + (cent[1]-p2[1])**2 ) 1389 if abs(R-Rt) > self.accuracy: self.fmessage("Radius Warning: R1=%f R2=%f"%(R,Rt)) 1390 1391 val = R**2 - (xsplit - cent[0])**2 1392 if val >= 0.0: 1393 root = sqrt( val ) 1394 ycross1 = cent[1] - root 1395 ycross2 = cent[1] + root 1396 else: 1397 return [] 1398 1399 theta = self.Get_Angle2(p1[0]-cent[0],p1[1]-cent[1]) 1400 1401 xbeta,ybeta = self.Transform(p2[0]-cent[0],p2[1]-cent[1],radians(-theta)) 1402 beta = self.Get_Angle2(xbeta,ybeta,code) 1403 1404 if abs(beta) <= self.Zero: beta = 360.0 1405 1406 xt,yt = self.Transform(xsplit-cent[0],ycross1-cent[1],radians(-theta)) 1407 gt1 = self.Get_Angle2(xt,yt,code) 1408 1409 xt,yt = self.Transform(xsplit-cent[0],ycross2-cent[1],radians(-theta)) 1410 gt2 = self.Get_Angle2(xt,yt,code) 1411 1412 if gt1 < gt2: 1413 gamma1 = gt1 1414 gamma2 = gt2 1415 else: 1416 gamma1 = gt2 1417 gamma2 = gt1 1418 temp = ycross1 1419 ycross1 = ycross2 1420 ycross2 = temp 1421 1422 dz = p2[2] - p1[2] 1423 da = beta 1424 mz = dz/da 1425 zcross1 = p1[2] + gamma1 * mz 1426 zcross2 = p1[2] + gamma2 * mz 1427 1428 output=[] 1429 if gamma1 < beta and gamma1 > self.Zero and gamma1 < beta-self.Zero: 1430 output.append([xcross1,ycross1,zcross1]) 1431 if gamma2 < beta and gamma1 > self.Zero and gamma2 < beta-self.Zero: 1432 output.append([xcross2,ycross2,zcross2]) 1433 1434 #print(" start: x1 =%5.2f y1=%5.2f z1=%5.2f" %(p1[0], p1[1], p1[2])) 1435 #print(" end: x2 =%5.2f y2=%5.2f z2=%5.2f" %(p2[0], p2[1], p2[2])) 1436 #print("center: xc =%5.2f yc=%5.2f xsplit=%5.2f code=%s" %(cent[0],cent[1],xsplit,code)) 1437 #print("R = %f" %(R)) 1438 #print("theta =%5.2f" %(theta)) 1439 #print("beta =%5.2f gamma1=%5.2f gamma2=%5.2f\n" %(beta,gamma1,gamma2)) 1440 #cnt=0 1441 #for line in output: 1442 # cnt=cnt+1 1443 # print("arc cross%d: %5.2f, %5.2f, %5.2f" %(cnt, line[0], line[1], line[2])) 1444 #print(output) 1445 #print("----------------------------------------------\n") 1446 1447 return output 1448 1449 def arc2lines(self, p1, p2, cent, code, plane="17"): 1450 if plane == "18": 1451 xind=2 1452 yind=0 1453 zind=1 1454 elif plane == "19": 1455 xind=1 1456 yind=2 1457 zind=0 1458 elif plane == "17": 1459 xind=0 1460 yind=1 1461 zind=2 1462 1463 R = sqrt( (cent[xind]-p1[xind])**2 + (cent[yind]-p1[yind])**2 ) 1464 Rt= sqrt( (cent[xind]-p2[xind])**2 + (cent[yind]-p2[yind])**2 ) 1465 if abs(R-Rt) > self.accuracy: self.fmessage("Radius Warning: R1=%f R2=%f "%(R,Rt)) 1466 1467 if code == 3: 1468 theta = self.Get_Angle2(p1[xind]-cent[xind],p1[yind]-cent[yind]) 1469 xbeta,ybeta = self.Transform(p2[xind]-cent[xind],p2[yind]-cent[yind],radians(-theta)) 1470 X1 = p1[xind] 1471 Y1 = p1[yind] 1472 Z1 = p1[zind] 1473 zstart = Z1 1474 zend = p2[zind] 1475 if code == 2: 1476 theta = self.Get_Angle2(p2[xind]-cent[xind],p2[yind]-cent[yind]) 1477 xbeta,ybeta = self.Transform(p1[xind]-cent[xind],p1[yind]-cent[yind],radians(-theta)) 1478 X1 = p2[xind] 1479 Y1 = p2[yind] 1480 Z1 = p2[zind] 1481 zstart = Z1 1482 zend = p1[zind] 1483 1484 beta = self.Get_Angle2(xbeta,ybeta) #,code) 1485 1486 if abs(beta) <= self.Zero: beta = 360.0 1487 ########################################## 1488 arc_step=self.arc_angle 1489 1490 my_range=[] 1491 1492 at=arc_step 1493 while at < beta: 1494 my_range.append(at) 1495 at = at+arc_step 1496 my_range.append(beta) 1497 1498 1499 1500 new_lines=[] 1501 for at in my_range: 1502 xt,yt = self.Transform(R,0,radians(theta+at)) 1503 1504 X2 = cent[xind] + xt 1505 Y2 = cent[yind] + yt 1506 #Z2 = p1[zind] + at*(p2[zind]-p1[zind])/beta 1507 Z2 = zstart + at*(zend-zstart)/beta 1508 data = ["","","","","",""] 1509 1510 1511 if code == 3: 1512 data[xind]=X1 1513 data[yind]=Y1 1514 data[zind]=Z1 1515 data[3+xind]=X2 1516 data[3+yind]=Y2 1517 data[3+zind]=Z2 1518 new_lines.append(data) 1519 else: 1520 data[xind]=X2 1521 data[yind]=Y2 1522 data[zind]=Z2 1523 data[3+xind]=X1 1524 data[3+yind]=Y1 1525 data[3+zind]=Z1 1526 new_lines.insert(0, data) 1527 1528 X1=X2 1529 Y1=Y2 1530 Z1=Z2 1531 at = at+arc_step 1532 1533 return new_lines 1534 1535 def get_line_intersect(self,p1, p2, xsplit): 1536 dx = p2[0] - p1[0] 1537 dy = p2[1] - p1[1] 1538 dz = p2[2] - p1[2] 1539 1540 xcross = xsplit 1541 try: 1542 my = dy/dx 1543 by = p1[1] - my * p1[0] 1544 ycross = my*xsplit + by 1545 except: 1546 ycross = p1[1] 1547 try: 1548 mz = dz/dx 1549 bz = p1[2] - mz * p1[0] 1550 zcross = mz*xsplit + bz 1551 except: 1552 zcross = p1[2] 1553 1554 output=[] 1555 if xcross > min(p1[0],p2[0])+self.Zero and xcross < max(p1[0],p2[0])-self.Zero: 1556 output.append([xcross,ycross,zcross]) 1557 return output 1558 1559 1560 def apleft(self, gtext): 1561 self.left_side.append(gtext) 1562 1563 1564 def apright(self, gtext): 1565 self.right_side.append(gtext) 1566 1567 1568 def apboth(self, gtext): 1569 self.left_side.append(gtext) 1570 self.right_side.append(gtext) 1571 1572 1573 def rm_text(self,line,s,e): 1574 if e == -1: 1575 e = len(line) 1576 temp1 = line[0:s] 1577 temp2 = line[e+1:len(line)] 1578 return temp1+temp2 1579 1580 1581 def insert_text(self,line,itext,s): 1582 temp1 = line[0:s] 1583 temp2 = line[s:len(line)] 1584 return temp1+itext+temp2 1585 1586 1587 def coordop(self,coords,offset,rot): 1588 x = coords[0] 1589 y = coords[1] 1590 z = coords[2] 1591 x = x - offset[0] 1592 y = y - offset[1] 1593 z = z - offset[2] 1594 x,y = self.Transform(x,y, radians(rot) ) 1595 return [x,y,z] 1596 1597 1598 def coordunop(self,coords,offset,rot): 1599 x = coords[0] 1600 y = coords[1] 1601 z = coords[2] 1602 x,y = self.Transform(x,y, radians(-rot) ) 1603 x = x + offset[0] 1604 y = y + offset[1] 1605 z = z + offset[2] 1606 return [x,y,z] 1607 1608 ####################################### ####################################### 1609 ####################################### ####################################### 1610 ####################################### ####################################### 1611 ####################################### ####################################### 1612 1613 def FUNCTION_EVAL(self,list): 1614 #list consists of [name,val1,val2] 1615 name = list[0] 1616 val1 = float(list[1]) 1617 fval = float(val1) 1618 ############################################# 1619 ########### G-CODE FUNCTIONS ################ 1620 ############################################# 1621 # ATAN[Y]/[X] Four quadrant inverse tangent # 1622 # ABS[arg] Absolute value # 1623 # ACOS[arg] Inverse cosine # 1624 # ASIN[arg] Inverse sine # 1625 # COS[arg] Cosine # 1626 # EXP[arg] e raised to the given power # 1627 # FIX[arg] Round down to integer # 1628 # FUP[arg] Round up to integer # 1629 # ROUND[arg] Round to nearest integer # 1630 # LN[arg] Base-e logarithm # 1631 # SIN[arg] Sine # 1632 # SQRT[arg] Square Root # 1633 # TAN[arg] Tangent # 1634 # EXISTS[arg] Check named Parameter # 1635 ############################################# 1636 if name == "ATAN": 1637 fval2 = float(list[2]) 1638 atan2(fval1,fval2) 1639 if name == "ABS": 1640 return abs(fval) 1641 if name == "ACOS": 1642 return degrees(acos(fval)) 1643 if name == "ASIN": 1644 return degrees(asin(fval)) 1645 if name == "COS": 1646 return cos(radians(fval)) 1647 if name == "EXP": 1648 return exp(fval) 1649 if name == "FIX": 1650 return floor(fval) 1651 if name == "FUP": 1652 return ceil(fval) 1653 if name == "ROUND": 1654 return round(fval) 1655 if name == "LN": 1656 return log(fval) 1657 if name == "SIN": 1658 return sin(radians(fval)) 1659 if name == "SQRT": 1660 return sqrt(fval) 1661 if name == "TAN": 1662 return tan(radians(fval)) 1663 if name == "EXISTS": 1664 pass 1665 1666 def EXPRESSION_EVAL(self,line): 1667 ################################################### 1668 ### EVALUATE MATH IN REGION ### 1669 ################################################### 1670 line_in = line 1671 P = 0 1672 if P==1: self.fmessage("line=%s" %(line)) 1673 1674 if len(line)<2: 1675 MSG = "ERROR EXP-1: Unable to evaluate expression: %s\n" %(line_in) 1676 raise ValueError(MSG) 1677 1678 1679 line = line.replace(" ","") 1680 1681 ################################################# 1682 ### G-CODE OPPERATORS ### 1683 ### In Precedence Order ### 1684 ################################################# 1685 ## ** # 1686 ## * / MOD # 1687 ## + - # 1688 ## EQ NE GT GE LT LE # 1689 ## AND OR XOR # 1690 ################################################# 1691 1692 ################################################# 1693 ### Replace multiple +/- with single operator ### 1694 ################################################# 1695 cnt = 1 1696 while cnt > 0: 1697 if (not self.cmp_new(line[cnt],'+')) or (not self.cmp_new(line[cnt],'-')): 1698 sign = 1 1699 span = 0 1700 FLAG = True 1701 while FLAG: 1702 if not self.cmp_new(line[cnt+span],'+'): 1703 span = span + 1 1704 elif not self.cmp_new(line[cnt+span],'-'): 1705 sign = -sign 1706 span = span + 1 1707 else: 1708 FLAG = False 1709 tmp1=line[:(cnt)] 1710 tmp2=line[(cnt+span):] 1711 if sign > 0: 1712 line = tmp1+'+'+tmp2 1713 else: 1714 line = tmp1+'-'+tmp2 1715 cnt=cnt + 1 1716 if cnt >= len(line): 1717 cnt = -1 1718 1719 ######################################### 1720 ### Replace multi-character operators ### 1721 ### with single character identifiers ### 1722 ######################################### 1723 line = line.replace("XOR","|") 1724 line = line.replace("AND","&") 1725 line = line.replace("LE","l") 1726 line = line.replace("LT","<") 1727 line = line.replace("GE","g") 1728 line = line.replace("GT",">") 1729 line = line.replace("NE","!") 1730 line = line.replace("EQ","=") 1731 line = line.replace("**","^") 1732 1733 ######################################### 1734 ### Split the text into a list ### 1735 ######################################### 1736 line = re.split( "([\[,\],\^,\*,\/,\%,\+,\-,\| ,\& ,\l ,\< ,\g ,\> ,\! ,\= ])", line) 1737 1738 ######################################### 1739 ### Remove empty items from the list ### 1740 ######################################### 1741 for i in range(line.count('')): line.remove('') 1742 1743 ######################################### 1744 ### Find the last "[" in the list ### 1745 ######################################### 1746 s=-1 1747 for cnt in range(s+1,len(line)): 1748 if line[cnt] == '[': 1749 s = cnt 1750 if s == -1: 1751 MSG = "ERROR EXP-2: Unable to evaluate expression: %s" %(line_in) 1752 #self.fmessage(MSG) 1753 raise ValueError(MSG) 1754 1755 ################################################################# 1756 ### While there are still brackets "[...]" keep processing ### 1757 ################################################################# 1758 while s != -1: 1759 ############################################################## 1760 ### Find the first occurance of "]" after the current "[" ### 1761 ############################################################## 1762 e=-1 1763 for cnt in range(len(line)-1,s,-1): 1764 if line[cnt] == ']': 1765 e = cnt 1766 1767 ############################################# 1768 ### Find the items between the brackets ### 1769 ############################################# 1770 temp = line[s+1:e] 1771 1772 ############################################################## 1773 ### Fix Some Special Cases ### 1774 ############################################################## 1775 ### **- *- MOD- ### 1776 ############################################################## 1777 for cnt in range(0,len(temp)): 1778 if (not self.cmp_new(temp[cnt],'^')) or \ 1779 (not self.cmp_new(temp[cnt],'*')) or \ 1780 (not self.cmp_new(temp[cnt],'%')): 1781 if not self.cmp_new(temp[cnt+1],'-'): 1782 temp[cnt+1]='' 1783 temp[cnt+2]= -float(temp[cnt+2]) 1784 elif not self.cmp_new(temp[cnt+1],'+'): 1785 temp[cnt+1]='' 1786 temp[cnt+2]= float(temp[cnt+2]) 1787 for i in range(temp.count('')): temp.remove('') 1788 1789 ##################################### 1790 XOR_operation = self.list_split(temp,"|") #XOR 1791 for iXOR in range(0,len(XOR_operation)): 1792 ##################################### 1793 AND_operation = self.list_split(XOR_operation[iXOR],"&") #AND 1794 for iAND in range(0,len(AND_operation)): 1795 ##################################### 1796 LE_operation = self.list_split(AND_operation[iAND],"l") #LE 1797 for iLE in range(0,len(LE_operation)): 1798 ##################################### 1799 LT_operation = self.list_split(LE_operation[iLE],"<") #LT 1800 for iLT in range(0,len(LT_operation)): 1801 ##################################### 1802 GE_operation = self.list_split(LT_operation[iLT],"g") #GE 1803 for iGE in range(0,len(GE_operation)): 1804 ##################################### 1805 GT_operation = self.list_split(GE_operation[iGE],">") #GT 1806 for iGT in range(0,len(GT_operation)): 1807 ##################################### 1808 NE_operation = self.list_split(GT_operation[iGT],"!") #NE 1809 for iNE in range(0,len(NE_operation)): 1810 ##################################### 1811 EQ_operation = self.list_split(NE_operation[iNE],"=") #EQ 1812 for iEQ in range(0,len(EQ_operation)): 1813 ##################################### 1814 add = self.list_split(EQ_operation[iEQ],"+") 1815 for cnt in range(1,len(add)): 1816 if add[cnt-1]==[]: 1817 add[cnt-1] = '' 1818 for i in range(add.count('')): add.remove('') 1819 for iadd in range(0,len(add)): 1820 ##################################### 1821 subtract = self.list_split(add[iadd],"-") 1822 for cnt in range(1,len(subtract)): 1823 if subtract[cnt-1]==[]: 1824 subtract[cnt-1] = '' 1825 subtract[cnt][0] = -float(subtract[cnt][0]) 1826 for i in range(subtract.count('')): subtract.remove('') 1827 for isub in range(0,len(subtract)): 1828 ##################################### 1829 multiply = self.list_split(subtract[isub],"*") 1830 for imult in range(0,len(multiply)): 1831 ##################################### 1832 divide = self.list_split(multiply[imult],"/") 1833 for idiv in range(0,len(divide)): 1834 ##################################### 1835 mod = self.list_split(divide[idiv],"%") 1836 for imod in range(0,len(mod)): 1837 ##################################### 1838 power = self.list_split(mod[imod],"^") 1839 for ipow in range(0,len(power)): 1840 if power[ipow]==[]: 1841 MSG = "ERROR EXP-3: Unable to evaluate expression: %s" %(line_in) 1842 raise ValueError(MSG) 1843 1844 if type(power[0]) is list: 1845 power_len = len(power[0]) 1846 else: 1847 power_len = 1 1848 if power_len > 1: 1849 power[ipow] = self.FUNCTION_EVAL(power[0]) 1850 else: 1851 power[ipow] = float(power[ipow][0]) 1852 ##################################### 1853 res_power=power[0] 1854 for k in range(1,len(power)): 1855 res_power = res_power**power[k] 1856 if P==True: self.fmessage(" POWER"+str(power)+"="+str(res_power)) 1857 mod[imod]=res_power 1858 ##################################### 1859 #REVERSE MOD 1860 res_mod=mod[len(mod)-1] 1861 for k in range(len(mod),1,-1): 1862 res_mod = mod[k-2]%res_mod 1863 self.fmessage(" MOD"+str(mod)+"="+str(res_mod)) 1864 divide[idiv]=res_mod 1865 ##################################### 1866 res_divide=divide[0] 1867 for k in range(1,len(divide),1): 1868 res_divide = res_divide/divide[k] 1869 if P==True: self.fmessage(" DIVIDE"+str(divide)+"="+str(res_divide)) 1870 multiply[imult]=res_divide 1871 ##################################### 1872 res_multiply=multiply[0] 1873 for k in range(1,len(multiply)): 1874 res_multiply = res_multiply*multiply[k] 1875 if P==True: self.fmessage("MULTIPLY"+str(multiply)+"="+str(res_multiply)) 1876 subtract[isub]=res_multiply 1877 ##################################### 1878 res_subtract=subtract[0] 1879 for k in range(1,len(subtract)): 1880 res_subtract = res_subtract-subtract[k] 1881 if P==True: self.fmessage("SUBTRACT"+str(subtract)+"="+str(res_subtract)) 1882 add[iadd]=res_subtract 1883 ##################################### 1884 res_add=add[len(add)-1] 1885 for k in range(len(add),1,-1): 1886 res_add = add[k-2]+res_add 1887 if P==True: self.fmessage(" ADD"+str(add)+"="+str(res_add)) 1888 EQ_operation[iEQ]=res_add 1889 ##################### 1890 res_EQ=EQ_operation[0] 1891 for k in range(1,len(EQ_operation),1): 1892 if res_EQ == EQ_operation[k]: 1893 res_EQ = 1 1894 else: 1895 res_EQ = 0 1896 if P==True: self.fmessage(" EQ"+str(EQ_operation)+"="+str(res_EQ)) 1897 NE_operation[iNE]=res_EQ 1898 ##################### 1899 res_NE=NE_operation[0] 1900 for k in range(1,len(NE_operation),1): 1901 if res_NE != NE_operation[k]: 1902 res_NE = 1 1903 else: 1904 res_NE = 0 1905 if P==True: self.fmessage(" NE"+str(NE_operation)+"="+str(res_NE)) 1906 GT_operation[iGT]=res_NE 1907 ##################### 1908 res_GT=GT_operation[0] 1909 for k in range(1,len(GT_operation),1): 1910 if res_GT > GT_operation[k]: 1911 res_GT = 1 1912 else: 1913 res_GT = 0 1914 if P==True: self.fmessage(" GT"+str(GT_operation),"="+str(res_GT)) 1915 GE_operation[iGE]=res_GT 1916 ##################### 1917 res_GE=GE_operation[0] 1918 for k in range(1,len(GE_operation),1): 1919 if res_GE >= GE_operation[k]: 1920 res_GE = 1 1921 else: 1922 res_GE = 0 1923 if P==True: self.fmessage(" GE"+str(GE_operation)+"="+str(res_GE)) 1924 LT_operation[iLT]=res_GE 1925 ##################### 1926 res_LT=LT_operation[0] 1927 for k in range(1,len(LT_operation),1): 1928 if res_LT < LT_operation[k]: 1929 res_LT = 1 1930 else: 1931 res_LT = 0 1932 if P==True: self.fmessage(" LT"+str(LT_operation)+"="+str(res_LT)) 1933 LE_operation[iLE]=res_LT 1934 ##################### 1935 res_LE=LE_operation[0] 1936 for k in range(1,len(LE_operation),1): 1937 if res_LE <= LE_operation[k]: 1938 res_LE = 1 1939 else: 1940 res_LE = 0 1941 if P==True: self.fmessage(" LE"+str(LE_operation)+"="+str(res_LE)) 1942 AND_operation[iAND]=res_LE 1943 ##################### 1944 res_AND=AND_operation[0] 1945 for k in range(1,len(AND_operation),1): 1946 if res_AND and AND_operation[k]: 1947 res_AND = 1 1948 else: 1949 res_AND = 0 1950 if P==True: self.fmessage(" AND"+str(AND_operation)+"="+str(res_AND)) 1951 XOR_operation[iXOR]=res_AND 1952 ##################### 1953 res_XOR=XOR_operation[0] 1954 for k in range(1,len(XOR_operation),1): 1955 if bool(res_XOR) ^ bool(XOR_operation[k]): 1956 res_XOR = 1 1957 else: 1958 res_XOR = 0 1959 if P==True: self.fmessage(" XOR"+str(XOR_operation)+"="+str(res_XOR)) 1960 1961 ##################################### 1962 ### Return NEW VALUE to the list ### 1963 ##################################### 1964 for i in range(e,s-1,-1): line.pop(i) 1965 line.insert(int(s),res_XOR) 1966 1967 ############################# 1968 # Find Last "[" in the list # 1969 ############################# 1970 s=-1 1971 for cnt in range(s+1,len(line)): 1972 if line[cnt] == '[': 1973 s = cnt 1974 ################################################################# 1975 ### END of While there are still brackets "[...]" ### 1976 ################################################################# 1977 1978 if len(line) > 1: 1979 MSG = "ERROR EXP-5: Unable to evaluate expression: %s" %(line_in) 1980 raise ValueError(MSG) 1981 return "%.4f" %(line[0]) 1982 1983 1984 def list_split(self,lst,obj): 1985 loc=[] 1986 index = -1 1987 for cnt in range(0,len(lst)): 1988 if not self.cmp_new(lst[cnt],obj): 1989 loc.append( lst[index+1:cnt] ) 1990 index=cnt 1991 loc.append( lst[index+1:len(lst)]) 1992 return loc 1993 1994 1995 #Define self.cmp_new, cmp replacement for Python 3 compatability 1996 def cmp_new(self,A,B): 1997 if A==B: 1998 return False 1999 else: 2000 return True 2001 2002 ############################################################################ 2003 # routine takes an x and a y coords and does a cordinate transformation # 2004 # to a new coordinate system at angle from the initial coordinate system # 2005 # Returns new x,y tuple # 2006 ############################################################################ 2007 def Transform(self,x,y,angle): 2008 newx = x * cos(angle) - y * sin(angle) 2009 newy = x * sin(angle) + y * cos(angle) 2010 return newx,newy 2011 2012 ############################################################################ 2013 # routine takes an sin and cos and returnss the angle (between 0 and 360) # 2014 ############################################################################ 2015 def Get_Angle2(self,x,y,code=""): 2016 angle = 90.0-degrees(atan2(x,y)) 2017 if angle < 0: 2018 angle = 360 + angle 2019 if code == "G2": 2020 return (360.0 - angle) 2021 else: 2022 return angle 2023 2024 2025 ################################################## 2026 ### Generate paths for Laser cutter ### 2027 ################################################## 2028 def generate_laser_paths(self,side,Rapids=True): 2029 ecoords = [] 2030 ################################# 2031 xlast = -99999 2032 ylast = -99999 2033 loop = 1 2034 for line in side: 2035 #print line 2036 if line[0] == 1: 2037 feed = line[3] 2038 spindle = line[4] 2039 x1=(line[1][0]+0j).real 2040 y1=(line[1][1]+0j).real 2041 z1=(line[1][2]+0j).real 2042 2043 x2=(line[2][0]+0j).real 2044 y2=(line[2][1]+0j).real 2045 z2=(line[2][2]+0j).real 2046 2047 if xlast!=x1 or ylast!=y1: 2048 loop = loop+1 2049 ecoords.append([x1,y1,loop,feed,spindle]) 2050 2051 if x2!=x1 or y2!=y1: 2052 ecoords.append([x2,y2,loop,feed,spindle]) 2053 2054 xlast = x2 2055 ylast = y2 2056 ###################################### 2057 return ecoords 2058 ################################################## 2059 ### End Generate paths for Laser cutter ### 2060 ################################################## 2061 2062 2063 2064if __name__ == "__main__": 2065 g_rip = G_Code_Rip() 2066 filename="Z:\\text.ngc" 2067 MSG = g_rip.Read_G_Code(filename, XYarc2line = True, arc_angle=2, units="in", Accuracy="") 2068 print(MSG) 2069 ecoords = g_rip.generate_laser_paths(g_rip.g_code_data) 2070 for line in ecoords: 2071 print(line) 2072