G71 , ... (remap)

Обсуждение установки, настройки и использования LinuxCNC. Вопросы по Gкоду.
nkp
Мастер
Сообщения: 8340
Зарегистрирован: 28 ноя 2011, 00:25
Репутация: 1589
Контактная информация:

G71 , ... (remap)

Сообщение nkp »

вариант(один из)) определения кода G71(72) для токарки в "привязке" к файлу .dxf ...
Выделение_009.png (8282 просмотра) <a class='original' href='./download/file.php?id=75269&sid=9578190e895ab28330289bc83dd393a5&mode=view' target=_blank>Загрузить оригинал (94.18 КБ)</a>
вот такой формат:

Код: Выделить всё

G71.2 P1 Q9 D2.3 K1.3 I1.5   F400
ниже должны находиться строки самого контура :

Код: Выделить всё

( n1  g1 X 0.000  Z  0.000)
( N2  G1 X 10.600 Z -6.100)
( N3  G1 X 13.300 Z -9.300)
( N4  G1 X 13.600 Z -17.100)
( N5  G1 X 13.992 Z -19.690)
( N6  G2 X 18.649 Z -23.933 I4.944 K0.749)
( N7  G1 X 23.300 Z -24.200)
( N8  G1 X 23.3   Z -30)
( N9  G1 X 33     Z -32)
понятно,что они закомментированы и "обычным" способом не обрабатываются интерпретатором...
в ini :

Код: Выделить всё

[RS274NGC]
REMAP=G71.2 modalgroup=1 argspec=PQDKIF  py=g711
в remap.py :

Код: Выделить всё

def g711(self, **words):
    """ remap code G71.1 """
    p = int(words['p'])
    feed_rate = int(words['f'])
    q = int(words['q'])
    d = float(words['d'])
    l = float(words['k'])
    h = float(words['i'])
    s = linuxcnc.stat() 
    s.poll() 
    filename = s.file
    f = open(filename, "r")
    lines = f.readlines()
    x,v,i = 0,-1,0
    line_or_arc = []
    coordZ = []
    coordX = []
    coordI = []
    coordK = []
    s.poll() 
    while x < len(lines):
        if  re.search("^\s*[(]\s*N\d", lines[x], re.I):
            if not re.search("[^\(\)\.\-\+NGZXRIK\d\s]",lines[x].upper()):
                num = int(re.search("N\s*([0-9.]+)",lines[x], re.I).group(1))
                if num >= p and num <= q:
                    v+=1
                    g1 = line_or_arc.insert(0,(int(re.search("G\s*([0-4.]+)",lines[x], re.I).group(1))))
                    z1 = coordZ.insert(0,(float(re.search("Z\s*([-0-9.]+)",lines[x], re.I).group(1))))
                    x1 = coordX.insert(0,(float(re.search("X\s*([-0-9.]+)",lines[x], re.I).group(1))))                    
                    if  re.search("[I]", lines[x]):
                        i1 = coordI.insert(0,(float(re.search("I\s*([-0-9.]+)",lines[x], re.I).group(1))))
                        k1 = coordK.insert(0,(float(re.search("K\s*([-0-9.]+)",lines[x], re.I).group(1))))
                if num == p : # search Start_point
                    temp_x = x
                    a=2
                    while not re.search("^\s*.*Z", lines[temp_x-a].upper()):
                        a+=1
                    coordZ_start = float(re.search("Z\s*([-0-9.]+)",lines[temp_x-a], re.I).group(1))
        x+=1
    for n in range(v):
        COORDx0 =  coordX[n]
        COORDz0 =  coordZ[n]
        lengthZ = abs(COORDz0 - coordZ[n+1])
        lengthX = abs(COORDx0 - coordX[n+1])
        if lengthX == 0 :#горизонтальная линия
            delta = 0
            l = lengthZ +l
        elif lengthZ == 0 : #вертикальная линия
            delta = 0
            l = float(words['k'])
        else:  
            tan = lengthX/lengthZ
            delta = d/tan
            height_l = l*tan
            l = float(words['k'])
#            if  height_l < h:
#                l = h/tan
            if  tan < 0.3:
                l = 2l                         
        if line_or_arc[n] > 1:
            radius = sqrt((coordK[i])*(coordK[i]) + (coordI[i])*(coordI[i]))
            centreX = coordX[n+1] + coordI[i]
            centreZ = coordZ[n+1] + coordK[i]               
            i+=1                      
        while lengthX >= 0:
            try:
                self.execute("F%f" % feed_rate,lineno())
                self.execute("G21 G18",lineno())
                self.execute("G61",lineno())
                if (COORDz0 + l) <= coordZ_start:                             
                    self.execute(" G1  Z%f" % (COORDz0 + l),lineno())
                else:
                    self.execute(" G1  Z%f" % coordZ_start,lineno())
                if (COORDz0 + 0.5 +l) <= coordZ_start:
                    self.execute(" G0  X%f Z%f" % ((COORDx0 + 0.5),(COORDz0 + 0.5 + l)),lineno())# отход 45гр
               # else:
                    #self.execute(" G0  X%f Z%f" % ((COORDx0 + 0.5),(coordZ_start)),lineno())# отход 45гр
                self.execute(" G0  Z%f" % (coordZ_start),lineno())# выход в стартовую по Z
                if lengthX < d:
                    newX = COORDx0 - lengthX
                else:
                    newX = COORDx0 - d 
                self.execute(" G1  X%f" % (newX),lineno())# новая позиция по X
                COORDx0 = newX
                #просчитываем новую COORDz0 с учетом E(l) TODO пока без учета I(h):
                if line_or_arc[n] == 1:
                        COORDz0 = COORDz0 + delta  
                elif line_or_arc[n] >1:
                    b2 = sqrt(radius*radius - ((centreX-COORDx0)-d)*((centreX-COORDx0)-d))
                    b1 = sqrt(radius*radius - (centreX-COORDx0)*(centreX-COORDx0))
                    COORDz0 = COORDz0 + (abs(b2-b1))                                    
                lengthX = lengthX - d #d - съем за один проход
            except InterpreterException,e:
                msg = "%d: '%s' - %s" % (e.line_number,e.line_text, e.error_message)
                self.set_errormsg(msg) 
                return INTERP_ERROR    
    for w in lines:
        if  re.search("^\s*[(]\s*N\d", w.upper()):
            if not re.search("[^\(\)\.\-\+NGZXRIK\d\s]", w.upper()):
                num2 = int(re.findall("^\s*\d*",(re.split('N',w.upper())[1]))[0])
                if num2 >= p and num2 <= q:
                    try: 
                        contour=re.split('\)',(re.split('\(',w.upper())[1]))[0]
                        self.execute(contour,lineno())
                    except InterpreterException,e:
                        msg = "%d: '%s' - %s" % (e.line_number,e.line_text, e.error_message)
                        self.set_errormsg(msg) 
                        return INTERP_ERROR   
    self.execute("G91",lineno())
    self.execute(" G0  X0.5 Z0.5",lineno())# отход 45гр 
    self.execute("G90",lineno())
    self.execute(" G0  Z%f" % (coordZ_start),lineno())# выход в стартовую по Z                              
    f.close()                 
    return INTERP_OK
"подрихтовав" программку dxf2gcode ,чтоб она выводила строки в нужном нам формате,можно
открывать в емс сразу контур в .DXF :
https://www.youtube.com/watch?v=zq7rbsMW5ic
работает конечно только с монотонными контурами))
+ нужны еще чистовые проходы
+ ...
;)
https://github.com/nkp2169/G71
Последний раз редактировалось nkp 17 мар 2016, 12:58, всего редактировалось 1 раз.
nkp
Мастер
Сообщения: 8340
Зарегистрирован: 28 ноя 2011, 00:25
Репутация: 1589
Контактная информация:

Re: G71 , ... (remap)

Сообщение nkp »

деталь рисуется в такой проекции ,потому как в Canvas от Tkinter (в dxf2gcode) тяжко (для меня :) )переделать
в плоскость XZ ,да и простейшие чертилки (QCAD в данном случае) не умеют с ней работать
Аватара пользователя
aegis
Мастер
Сообщения: 3171
Зарегистрирован: 22 мар 2012, 06:59
Репутация: 1810
Настоящее имя: Михайло
Откуда: Україна, Конотоп=>Запоріжжя=>Харьків

Re: G71 , ... (remap)

Сообщение aegis »

nkp писал(а):( N6 G2 X 18.649 Z -23.933 I4.944 K0.749)
только в таком виде дуги принимает или с параметром R?
нікому нічого не нав'язую.
nkp
Мастер
Сообщения: 8340
Зарегистрирован: 28 ноя 2011, 00:25
Репутация: 1589
Контактная информация:

Re: G71 , ... (remap)

Сообщение nkp »

нет , R не принимает...
но поправить несложно...
просто dxf2gcode выдает с IJ (подправил через постпроцессор на IK)
Аватара пользователя
aegis
Мастер
Сообщения: 3171
Зарегистрирован: 22 мар 2012, 06:59
Репутация: 1810
Настоящее имя: Михайло
Откуда: Україна, Конотоп=>Запоріжжя=>Харьків

Re: G71 , ... (remap)

Сообщение aegis »

nkp, понятно. я просто из своей колокольни смотрю мне при ручном написании программы проще через R работать
нікому нічого не нав'язую.
Аватара пользователя
Nick
Мастер
Сообщения: 22776
Зарегистрирован: 23 ноя 2009, 16:45
Репутация: 1735
Заслуга: Developer
Откуда: Gatchina, Saint-Petersburg distr., Russia
Контактная информация:

Re: G71 , ... (remap)

Сообщение Nick »

Ого! Суперкул! :good:
Чистовой проход это просто - сдвиг контура +dx +dz и все...
nkp
Мастер
Сообщения: 8340
Зарегистрирован: 28 ноя 2011, 00:25
Репутация: 1589
Контактная информация:

Re: G71 , ... (remap)

Сообщение nkp »

если в Axis открывать файлы "по фильтру" ,то весьма удобная кнопочка "Edit" будет открывать не сам Gкод ,а
"файл-источник" (
чтоб не рыться где то во временных файлах , удобно ,когда скрипты,выводящие код в stdout(для емс),
будут дублировать его в файл - для непосредственного редактирования...
а в Axis:

Код: Выделить всё

  def edit_program(*event):
            .............
            ...........
            e = string.split(editor)
 [b]           if os.path.splitext(loaded_file)[1] == '.dxf':
                fs=os.path.join(open_directory, 'edit_dxf.ngc')
                e.append(fs)[/b]
            e.append(loaded_file)
            e.append("&")
            root_window.tk.call("exec", *e)
nkp
Мастер
Сообщения: 8340
Зарегистрирован: 28 ноя 2011, 00:25
Репутация: 1589
Контактная информация:

Re: G71 , ... (remap)

Сообщение nkp »

G72 из той же серии:
g71_72.png (8177 просмотров) <a class='original' href='./download/file.php?id=75351&sid=9578190e895ab28330289bc83dd393a5&mode=view' target=_blank>Загрузить оригинал (145.52 КБ)</a>
"переключение" 71-g72 при открытии .dxf в окне dxf2gcode
так же настройки всех параметров кода
примерно так:
Выделение_015.png (8175 просмотров) <a class='original' href='./download/file.php?id=75352&sid=9578190e895ab28330289bc83dd393a5&mode=view' target=_blank>Загрузить оригинал (101.03 КБ)</a>
nkp
Мастер
Сообщения: 8340
Зарегистрирован: 28 ноя 2011, 00:25
Репутация: 1589
Контактная информация:

Re: G71 , ... (remap)

Сообщение nkp »

Nick писал(а):Чистовой проход это просто - сдвиг контура +dx +dz и все...
задача:
есть gкод ,допустим:

Код: Выделить всё

G1 X  40.000 Z -60.000
G1 X  20.000 Z -40.000
G1 X  20.000 Z -20.000
G1 X   0.000 Z   0.000
(в идеале - с G2,G3)
требуется получить Gкод траектории-эквидистанты ...
как то не получается просто решить это ;) (то "бантики при <180гр,то дугу нужно вставлять при >180)
nkp
Мастер
Сообщения: 8340
Зарегистрирован: 28 ноя 2011, 00:25
Репутация: 1589
Контактная информация:

Re: G71 , ... (remap)

Сообщение nkp »

скоро в емс запилят G71 (обоих кстати типов) и это есть хорошо :good:
но так как я начал remap того же кода,то все равно трошки допилил его...
в связке с dxf2gcode это удобно и быстро...
тут писал человеку подобие талмуда по прикручиванию,решил выложить сюда тоже...
=============
Пару слов - как это все шевелится:
работа основана на remap( поэтому немного проще действовать,если remap
уже настроен в системе).
Еще желателен Qсad , по двум причинам: он работает под линукс(бесплатен) и проверен
для "нашей" работы)).
установка:
sudo apt-get install qcad
версия значения не имеет,так как наворотов нам не требуется(да и нет их в qcad)))
========================
Тут нужно сразу отметить одну особенность:
так как qcad заточен строго под оси X,Y (и перевернуть под токарку нет возможности),
то (как видно из видео) рисуем контур ,как бы расположив заготовку торцом вверх.
Для чертежа используем отрезки и дуги(окружности), скругления.
получили файл .dxf
=============================
Далее наш файл .dxf открываем в емс,
в котором настроен фильтр на то,чтоб dxf открывала программка dxf2gcode.
В ней меняем настройки обработки(из основных: глубина съема за один проход,припуск на чистовую
обработку)
Из недоделок:
контур,который отображается в окне предпросмотра dxf2gcode должен быть расположен
"сверху-вниз",то есть - как бы по ходу финишной обработки.
На направление указывают стрелки в начале и в конце контура(синяя и зеленая).
так вот - некоторые контуры нужно "переворачивать" - мышкой выделить контур,ПКМ(правая кн мыши),
пункт: "Switсh Direction"
-------------------------------------------------------------------------------------
правки в конфиге емс
добавить:

[FILTER]

PROGRAM_EXTENSION = .dxf Script
dxf = dxf2gcode/dxf2gcode_v01.py

[RS274NGC]

REMAP=G71.2 modalgroup=1 argspec=PQDKifjslt py=g712

это если "настроен" remap(если нет - допишу что нужно)
----------------------------------------------
папки dxf2gcode_v01 и dxf2gcode положить в папку с конфигом
( в принципе - без разницы ,если подправить пути)
---------------------
"основной " код в файле remap.py
если он есть и задействован реально ,то нужно дополнить его кодом из "моего" файла remap.py,
а если не задействован,то его можно и заменить полностью на "мой"
------------------
папка ngc с примерами контуров (это для проверки настроек)
все файлы из нее должны корректно открываться))
-----------------------------------
remap работает и без dxf2gcode , в папке ngc есть R_R.ngc
он открывается "напрямую"
то есть ,если мы напишем код G71 "ручками" - всё должно работать...
вот параметры кода: PQDKifjslt
PQDK - обязательные
ifjslt - необязательные
PQ - обозначают номер начальной строки кода и конечный(gкод контура обработки)
D - съем за проход
K- припуск на чистовую
необязательные параметры касаются чистовой обработки?
t - номер инструмента для чистовой
i - количество чистовых проходов(K/i)
f - подача для чистовой
j - позволяет "повторить" только чистовые проходы
s - резерв
l - резерв
G71.rar
(160.72 КБ) 449 скачиваний
nkp
Мастер
Сообщения: 8340
Зарегистрирован: 28 ноя 2011, 00:25
Репутация: 1589
Контактная информация:

Re: G71 , ... (remap)

Сообщение nkp »

что изменено:
теперь скриптик расчитывает эквидистанту и режет черновые проходы до нее,
то есть задаем один параметр - величину для чистового(ых) проходов
их количество тоже можно задать...
https://www.youtube.com/watch?v=qDyOuob4CTM
galexey
Опытный
Сообщения: 104
Зарегистрирован: 01 апр 2012, 21:35
Репутация: 9
Контактная информация:

Re: G71 , ... (remap)

Сообщение galexey »

nkp писал(а):скоро в емс запилят G71 (обоих кстати типов) и это есть хорошо :good:
А когда обещают поддержку G71?
nkp
Мастер
Сообщения: 8340
Зарегистрирован: 28 ноя 2011, 00:25
Репутация: 1589
Контактная информация:

Re: G71 , ... (remap)

Сообщение nkp »

galexey писал(а):А когда обещают поддержку G71?
в таких мероприятиях сроки никогда не присутствуют,ибо безоплатно люди работают ;)
nkp
Мастер
Сообщения: 8340
Зарегистрирован: 28 ноя 2011, 00:25
Репутация: 1589
Контактная информация:

Re: G71 , ... (remap)

Сообщение nkp »

при любом (пере)определении gкода ,(если траектория формируется именно remap),
траектория получается как бы единым массивом для Axis :
Выделение_156.png (7611 просмотров) <a class='original' href='./download/file.php?id=96649&sid=9578190e895ab28330289bc83dd393a5&mode=view' target=_blank>Загрузить оригинал (64.08 КБ)</a>
соответственно код:

Код: Выделить всё

N1 (FILE: /HOME/NKP/LINUXCNC/CONFIGS/G71/NGC/LINE_ARC_G2>.DXF)
N2 G21  G90 G64 P0.01 G18 G40 G49
N3 T2M6
N5 F1444
G1 X23.299  Z0.0 
G71.2 P6 Q8  D1.5 K0.3 I1.0 F1400.0 J0 S1000.0 L0.0 T1
(N6 G1 X   0.000 Z   0.000)
(N7 G1 X  19.259 Z -10.220)
(N8 G2 X  23.299 Z -19.853 I  19.824 K   2.650)
M2
=================================================================================
то есть - если мы хотим выделить отдельный участок - выделяется вся траектория...
добавил запись того же формирующегося Gкода в рядом_лежащий файл...
получаем "обычную" траекторию ,участки которой можно выделить ,перепрограмировать локально,редактировать,начать с нужной строки и тд
Выделение_155.png (7611 просмотров) <a class='original' href='./download/file.php?id=96648&sid=9578190e895ab28330289bc83dd393a5&mode=view' target=_blank>Загрузить оригинал (62.89 КБ)</a>
код:

Код: Выделить всё

G21 G18 G49  G90 G61 
F1444.000000 
M6 T2
G1 X23.535625
G1 Z-19.668860
G0 X24.035625 Z-19.168860
G0 Z0.264999
G1 X22.035625
G1 Z-17.443717
G0 X22.535625 Z-16.943717
G0 Z0.264999
G1 X20.535625
G1 Z-14.210645
G0 X21.035625 Z-13.710645
G0 Z0.264999
G1 X19.035625
G1 Z-9.761840
G0 X19.535625 Z-9.261840
G0 Z0.264999
G1 X17.535625
G1 Z-8.965849
G0 X18.035625 Z-8.465849
G0 Z0.264999
G1 X16.035625
G1 Z-8.169857
G0 X16.535625 Z-7.669857
G0 Z0.264999
G1 X14.535625
G1 Z-7.373866
G0 X15.035625 Z-6.873866
G0 Z0.264999
G1 X13.035625
G1 Z-6.577874
G0 X13.535625 Z-6.077874
G0 Z0.264999
G1 X11.535625
G1 Z-5.781883
G0 X12.035625 Z-5.281883
G0 Z0.264999
G1 X10.035625
G1 Z-4.985891
G0 X10.535625 Z-4.485891
G0 Z0.264999
G1 X8.535625
G1 Z-4.189900
G0 X9.035625 Z-3.689900
G0 Z0.264999
G1 X7.035625
G1 Z-3.393908
G0 X7.535625 Z-2.893908
G0 Z0.264999
G1 X5.535625
G1 Z-2.597917
G0 X6.035625 Z-2.097917
G0 Z0.264999
G1 X4.035625
G1 Z-1.801925
G0 X4.535625 Z-1.301925
G0 Z0.264999
G1 X2.535625
G1 Z-1.005934
G0 X3.035625 Z-0.505934
G0 Z0.264999
G1 X1.035625
G1 Z-0.209942
G0 X1.035625 Z0.264999
G1 X 0.1406248214 Z 0.264999357729
G1 X 19.3996248214 Z -9.95500064227
G3 X 19.5563549911 Z -10.1802506696 R 0.3
G2 X 23.535625204 Z -19.6688598973 R 19.7003368972
G0 Z0.264999
M6 T1
F1400.000000
N6 G1 X   0.000 Z   0.000
N7 G1 X  19.259 Z -10.220
N8 G2 X  23.299 Z -19.853 I  19.824 K   2.650
G0 Z0.264999
M02
remap.py:

Код: Выделить всё

# --*-- coding:utf-8 --*--
import linuxcnc
import re
from math import *
import traceback
from interpreter import *
from emccanon import MESSAGE

throw_exceptions = 1 # raises InterpreterException if execute() or read() fail
    
def pars(array,reg ,lines): 
    a=array.insert(0,(float(re.search(reg,lines, re.I).group(1))))
def cathetus(c,b):
    a = sqrt(abs(c*c - b*b))
    return a 
def hip(a,b):
    c = sqrt(abs(a*a + b*b))
    return c
def intersection_line_arc(G,Mz1,Mx1,Mz2,Mx2,centreZ,centreX,rad):    
    if (Mz2-Mz1)!=0:
        K=(Mx2-Mx1)/(Mz2-Mz1)
        B=-(K*Mz1-Mx1)           
        a = 1 + K**2 
        b = -2*centreZ + 2*K*B -2*K*centreX  
        c = -rad**2 + (B-centreX)**2 + centreZ**2 
        D = b**2 - 4*a*c 
        if D < 0: 
          print 'D<0' 
        z1 = (-b-sqrt(D))/(2*a) 
        z2 = (-b+sqrt(D))/(2*a)
        if G==3:
            if Mz2 < z1 < Mz1:
              pointZ1 = z1   
              pointX1 = K*z1+B
              return  pointZ1,pointX1
            else:
              pointZ1 = z2
              pointX1 = K*z2+B
              return  pointZ1,pointX1
        if G==2:
            if Mz2 < z1 < Mz1:
              pointZ1 = z2 
              pointX1 = K*z2+B
              return  pointZ1,pointX1
            else:
              pointZ1 = z1
              pointX1 = K*z1+B
              return  pointZ1,pointX1 
def intersection_arc_arc(x1,z1,r1,x2,z2,r2,Px,Pz):
    d=sqrt( pow(abs(x1-x2),2) + pow(abs(z1-z2),2))
    if(d > r1+r2): 
        return
    a= (r1*r1 - r2*r2 + d*d ) / (2*d)
    h= sqrt( pow(r1,2) - pow(a,2))
    x0 = x1 + a*( x2 - x1 ) / d
    z0 = z1 + a*( z2 - z1 ) / d;
    ix1= x0 + h*( z2 - z1 ) / d
    iz1= z0 - h*( x2 - x1 ) / d
    ix2= x0 - h*( z2 - z1 ) / d
    iz2= z0 + h*( x2 - x1 ) / d
    if(a == r1 ) :
        intscX = ix2
        intscZ = iz2
        return intscX , intscZ 

    l1= sqrt((Px - ix1)**2+(Pz - iz1)**2)
    l2= sqrt((Px - ix2)**2+(Pz - iz2)**2)
    if l1>l2:
        intscX = ix2
        intscZ = iz2
    else:
       intscX = ix1
       intscZ = iz1              
    return  intscX , intscZ 
                               
def papp(n,G,x,z,App=[],r=None,xc=None,zc=None):
    App.append([])
    App[n].append(G)
    App[n].append(App[n-1][3])
    App[n].append(App[n-1][4])                                               
    App[n].append(x)
    App[n].append(z)
    if G>1:
        App[n].append(r)
        App[n].append(xc)
        App[n].append(zc)
    return App 
def prog(array,G,x,z,r=None):
    ser=' '
    string=ser.join(['G1','X',str(x),'Z',str(z)])
    if G==2: 
        string=ser.join(['G2','X',str(x),'Z',str(z),'R',str(r)])
    if G==3: 
        string=ser.join(['G3','X',str(x),'Z',str(z),'R',str(r)])        
    return array.append(string)                
#################################################-----G71.2
def g712(self, **words):
    """ remap code G71.2 """
    p = int(words['p'])    
    q = int(words['q'])
    d = float(words['d'])
    offset = float(words['k'])
    
    if words.has_key('s'):
        rsv1 = float(words['s'])
    if words.has_key('l'):
        rsv2 = float(words['l'])
    only_finishing_cut = 0    
    if words.has_key('j'):
        only_finishing_cut = int(words['j'])
    quantity = 1    
    if words.has_key('i'):
        quantity = int(words['i'])
    tool = 2
    if words.has_key('t'):
        tool = int(words['t'])
    if words.has_key('f'):    
        feed_rate = float(words['f'])
    s = linuxcnc.stat() 
    s.poll()
    #backangle  =  s.tool_table #TODO 
    #frontangle =  s.tool_table
    filename = s.file
    f = open(filename, "r")
    lines = f.readlines()

    line_or_arc = []
    coordZ = []
    coordX = []
    coordI = []
    coordK = []
    coordR = []
    s.poll()
    x = 0 
    while x < len(lines):
        if re.search("\s*F\d", lines[x], re.I) and not re.search("G71",lines[x].upper()) :
            feed_rate=float(re.search("F\s*([0-9.]+)",lines[x], re.I).group(1))
            print 'feed_rate=', feed_rate
        if  re.search("^\s*[(]\s*N\d", lines[x], re.I):
            if not re.search("[^\(\)\.\-\+NGZXRIK\d\s]",lines[x].upper()):
                num = int(re.search("N\s*([0-9.]+)",lines[x], re.I).group(1))
                if num >= p and num <= q:
                    ins = line_or_arc.insert(0,(int(re.search("G\s*([0-4.]+)",lines[x], re.I).group(1))))
                    ins = pars(coordZ,"Z\s*([-0-9.]+)",lines[x])
                    ins = pars(coordX,"X\s*([-0-9.]+)",lines[x])                    
                    if  re.search("[I]", lines[x]):
                        ins = pars(coordI,"I\s*([-0-9.]+)",lines[x])
                        ins = pars(coordK,"K\s*([-0-9.]+)",lines[x])
                    else:
                        ins=coordI.insert(0,None)
                        ins=coordK.insert(0,None)                       
                    if  re.search("[R]", lines[x]):
                        ins = pars(coordR,"R\s*([-0-9.]+)",lines[x])
                    else:
                        ins=coordR.insert(0,None)
        x+=1     
    angle = [] 
    for n in range(len(coordZ)-1):
        lengthZ = abs(coordZ[n] - coordZ[n+1])
        lengthX = abs(coordX[n] - coordX[n+1])                    
        app = angle.append(atan2(lengthX,lengthZ))
        if line_or_arc[n]>1 and coordR[n]!=None:
            lh=(hip(lengthZ,lengthX))/2
            par=acos(lh/coordR[n])
            if line_or_arc[n]==2:
                ar=angle[n]+par
                indK=abs(cos(ar)*coordR[n])
            elif line_or_arc[n]==3:
                ar=angle[n]-par
                indK=-(cos(ar)*coordR[n])
            indI=sin(ar)*coordR[n] 
            pp=coordI.pop(n) 
            pp=coordK.pop(n) 
            ins=coordK.insert(n,indK) 
            ins=coordI.insert(n,indI)               
    app = angle.append(0.2914567944778671)                               
 ################################
    fn = '/home/nkp/fgcode.ngc'
    fgcode = open(fn, "w")
    self.execute("F%f" % feed_rate)#TODO

    part_n = -1
    flag_executed = 1 
    P = [] 
    program = [] 
    offset_mem=offset
    mm=len(angle)-2
  
    for i in range(quantity):
        print 'i=',i
        if i==1:
            if words.has_key('t'):
                self.execute("M6 T%d" % (tool))
                fgcode.write("M6 T%d\n" % (tool))
            if words.has_key('f'):
                feed_rate = float(words['f'])
                self.execute("F%f" % feed_rate)#TODO
                fgcode.write("F%f\n" % feed_rate)
        if line_or_arc[len(angle)-2] ==1:
            part_n+=1
            P.append([])
            P[part_n].append(1)
            P[part_n].append(round(coordX[mm+1]+(cos(angle[mm]))*offset,10))
            P[part_n].append(coordZ[mm+1]+(sin(angle[mm]))*offset)
            P[part_n].append(round(coordX[mm+1]+(cos(angle[mm]))*offset,10))
            P[part_n].append(coordZ[mm+1]+(sin(angle[mm]))*offset)
            FIRST_pointZ = coordZ[mm+1]+(sin(angle[mm]))*offset
            FIRST_pointX = round(coordX[mm+1]+(cos(angle[mm]))*offset,10)
            prog(program,1,FIRST_pointX,FIRST_pointZ)
        elif line_or_arc[len(angle)-2] ==3:
            FIRST_radius = sqrt((coordK[mm])*(coordK[mm]) + (coordI[mm])*(coordI[mm]))            
            FIRST_centreX = coordX[mm+1] + coordI[mm]            
            FIRST_centreZ = coordZ[mm+1] + coordK[mm]             
            FIRST_pointZ, FIRST_pointX=intersection_line_arc(3,coordZ[mm+1],coordX[mm+1],
                                                                coordZ[mm+1]+10,coordX[mm+1],
                                                                FIRST_centreZ,FIRST_centreX,
                                                                FIRST_radius+offset)
            part_n+=1
            P.append([])
            P[part_n].append(3)         
            P[part_n].append(FIRST_pointX)
            P[part_n].append(FIRST_pointZ)
            P[part_n].append(FIRST_pointX)
            P[part_n].append(FIRST_pointZ)
            prog(program,1,FIRST_pointX,FIRST_pointZ) 
        elif line_or_arc[len(angle)-2] ==2:
            FIRST_radius = sqrt((coordK[mm])*(coordK[mm]) + (coordI[mm])*(coordI[mm]))            
            FIRST_centreX = coordX[mm+1] + coordI[mm]            
            FIRST_centreZ = coordZ[mm+1] + coordK[mm]                     
            #FIRST_pointZ,FIRST_pointX=intersection_line_arc(2,coordZ[mm+1],coordX[mm+1],
                                                           #coordZ[mm+1],coordX[mm+1]+100,
                                                               # FIRST_centreZ,FIRST_centreX,
                                                               # FIRST_radius-offset
                                                                #)
            FIRST_pointZ = coordZ[mm+1]+(sin(angle[mm]))*offset
            FIRST_pointX = round(coordX[mm+1]+(cos(angle[mm]))*offset,10)
            part_n+=1
            P.append([])
            P[part_n].append(2)         
            P[part_n].append(FIRST_pointX)
            P[part_n].append(FIRST_pointZ)
            P[part_n].append(FIRST_pointX)
            P[part_n].append(FIRST_pointZ)
            prog(program,1,FIRST_pointX,FIRST_pointZ)
            
        coordZ_start =FIRST_pointZ                 
        for m in (reversed(range(len(angle)-1))):   
            if (line_or_arc[m] ==1): 
                if (line_or_arc[m-1] ==1): 
                    if angle[m-1] < angle[m]: 
                        print 'G01:LINE ANGLE:cw next:LINE'
                        if m==0:
                            prog(program,1,coordX[m]+cos(angle[m])*offset,
                                 coordZ[m]+sin(angle[m])*offset)
                            part_n+=1
                            papp(part_n,1,coordX[m]+cos(angle[m])*offset,
                                  coordZ[m]+sin(angle[m])*offset,P)                             
                        else:
                            prog(program,1,coordX[m]+cos(angle[m])*offset,
                                 coordZ[m]+sin(angle[m])*offset)
                            part_n+=1
                            papp(part_n,1,coordX[m]+cos(angle[m])*offset,coordZ[m]+sin(angle[m])*offset,P) 
                            part_n+=1
                            papp(part_n,3,coordX[m]+cos(angle[m-1])*offset,coordZ[m]+sin(angle[m-1])*offset,
                                   P,offset,coordX[m],coordZ[m])                 
                            prog(program,3,coordX[m]+cos(angle[m-1])*offset,
                                 coordZ[m]+sin(angle[m-1])*offset,offset)                           
                    else:                               
                        print 'G01:LINE ANGLE:ccw next:LINE'
                        angl = (angle[m] - angle[m-1])/2 
                        gg =  offset / cos(angl)
                        angl1 = angle[m] - angl
                        prog(program,1,coordX[m]+cos(angl1)*gg,
                                 coordZ[m]+sin(angl1)*gg)  
                        part_n+=1
                        papp(part_n,1,coordX[m]+cos(angl1)*gg,coordZ[m]+sin(angl1)*gg,P)
                else: #если СЛЕДУЮЩИЙ участок "дуга"
                    NEXT_radius = sqrt((coordK[m-1])*(coordK[m-1]) + (coordI[m-1])*(coordI[m-1]))
                    NEXT_centreX = coordX[m] + coordI[m-1]
                    NEXT_centreZ = coordZ[m] + coordK[m-1] 
                    NEXT_lengthZ = abs(NEXT_centreZ - coordZ[m])
                    NEXT_lengthX = abs(NEXT_centreX - coordX[m]) 
                    NEXT_alfa = atan2(NEXT_lengthZ,NEXT_lengthX)
                    cw_next_pointZ= coordZ[m]+sin(NEXT_alfa)*offset
                    cw_next_pointX= coordX[m]+cos(NEXT_alfa)*offset                    
                    if (line_or_arc[m-1] ==3): #если СЛЕДУЮЩИЙ участок "дуга" CW 
                        if (angle[m] - NEXT_alfa<-0.2): 
                            print '(G01:LINE)(ANGLE:angle[m]-NEXT_alfa < -0.2)(next:ARC_G03)'
                            radius_OFF = NEXT_radius+offset
                            NEXT_arc_itrs_lineZ,NEXT_arc_itrs_lineX = intersection_line_arc(3,coordZ[m+1]+sin(angle[m])*offset,
                                                                                  coordX[m+1]+cos(angle[m])*offset,
                                                                                  coordZ[m]+sin(angle[m])*offset,
                                                                                  coordX[m]+cos(angle[m])*offset,
                                                                                  NEXT_centreZ,NEXT_centreX,radius_OFF)
                            prog(program,1,NEXT_arc_itrs_lineX,NEXT_arc_itrs_lineZ)
                            part_n+=1
                            papp(part_n,1,NEXT_arc_itrs_lineX,NEXT_arc_itrs_lineZ,P)
                        elif (angle[m] - NEXT_alfa>0.2): 
                            print '(G01:LINE)(ANGLE:angle[m]-NEXT_alfa > 0.2)(next:ARC_G03)'
                            prog(program,1,coordX[m]+cos(angle[m])*offset,
                                 coordZ[m]+sin(angle[m])*offset)
                            part_n+=1
                            papp(part_n,1,coordX[m]+cos(angle[m])*offset,
                                 coordZ[m]+sin(angle[m])*offset,P)
                            prog(program,3,cw_next_pointX,cw_next_pointZ,offset)
                            part_n+=1 
                            papp(part_n,3,cw_next_pointX,cw_next_pointZ,P,offset,coordX[m],coordZ[m])                           
                        else: #angle[m] == NEXT_alfa 
                            print '(G01:LINE)  (ANGLE:angle[m] == NEXT_alfa)(next:ARC_G03)'
                            prog(program,1,coordX[m]+cos(angle[m])*offset,
                                 coordZ[m]+sin(angle[m])*offset)
                            part_n+=1
                            papp(part_n,1,coordX[m]+cos(angle[m])*offset,
                                 coordZ[m]+sin(angle[m])*offset,P)                                 
                    if (line_or_arc[m-1] ==2): #если СЛЕДУЮЩИЙ участок "дуга" CCW
                        if (angle[m] - NEXT_alfa<-0.2):
                            print '(G01:LINE) (angle[m] - NEXT_alfa<-0.2) (next:ARC_G02)'
                            NEXT_arc_itrs_lineZ,NEXT_arc_itrs_lineX = intersection_line_arc(3,coordZ[m+1]+sin(angle[m])*offset,
                                                                                  coordX[m+1]+cos(angle[m])*offset,
                                                                                  coordZ[m]+sin(angle[m])*offset,
                                                                                  coordX[m]+cos(angle[m])*offset,
                                                                                  NEXT_centreZ,NEXT_centreX,NEXT_radius-offset) 
                            prog(program,1,NEXT_arc_itrs_lineX,NEXT_arc_itrs_lineZ)
                            part_n+=1
                            papp(part_n,1,NEXT_arc_itrs_lineX,NEXT_arc_itrs_lineZ,P)

                        elif (angle[m] - NEXT_alfa>0.2): 
                            print '(G01:LINE) (angle[m] - NEXT_alfa>0.2) (next:ARC_G02)'#DXF line_arc_G2>.dxf
                            prog(program,1,coordX[m]+cos(angle[m])*offset,
                                 coordZ[m]+sin(angle[m])*offset)
                            part_n+=1
                            papp(part_n,1,coordX[m]+cos(angle[m])*offset,
                                 coordZ[m]+sin(angle[m])*offset,P)
                            prog(program,3,cw_next_pointX,cw_next_pointZ,offset)
                            part_n+=1
                            papp(part_n,3,cw_next_pointX,cw_next_pointZ,P,offset,coordX[m],coordZ[m]) 
                        else:       #angle[m] == NEXT_alfa
                            print '(G01:LINE)  (next:ARC_G02 angle[m] == NEXT_alfa) (next:ARC_G02)'
                            prog(program,1,coordX[m]+cos(angle[m])*offset,
                                 coordZ[m]+sin(angle[m])*offset)
                            part_n+=1
                            papp(part_n,1,coordX[m]+cos(angle[m])*offset,
                                 coordZ[m]+sin(angle[m])*offset,P)
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            else:  
                radius = sqrt((coordK[m])*(coordK[m]) + (coordI[m])*(coordI[m]))
                centreX = coordX[m+1] + coordI[m]
                centreZ = coordZ[m+1] + coordK[m]
                lengthZ = abs(centreZ - coordZ[m])
                lengthX = abs(centreX - coordX[m]) 
                alfa = atan2(lengthZ,lengthX) 
                zz= (radius-offset)*sin(alfa)
                xx= (radius-offset)*cos(alfa)
                pointZ=centreZ-zz
                if (coordX[m]<centreX):
                    pointX=centreX-xx
                else:
                    pointX=centreX+xx
                if (line_or_arc[m] == 3): 
                    if (line_or_arc[m-1] == 1): 
                        if (angle[m-1] - alfa < -0.2):
                            print '(G03:ARC)(ANGLE:angle[m-1] - alfa < -0.2)(next:LINE)'#DXF arc_G3_line<.dxf
                            cw_zz = (radius+offset)*sin(alfa)
                            cw_xx = (radius+offset)*cos(alfa)
                            cw_pointZ= centreZ+cw_zz
                            cw_pointX= centreX+cw_xx                                     
                            prog(program,3,cw_pointX,cw_pointZ,radius+offset)
                            
                            part_n+=1
                            papp(part_n,3,cw_pointX,cw_pointZ,P,radius+offset,centreX,centreZ)
                            prog(program,3,coordX[m]+cos(angle[m-1])*offset,
                                 coordZ[m]+sin(angle[m-1])*offset,offset)
                            part_n+=1
                            papp(part_n,3,coordX[m]+cos(angle[m-1])*offset,
                                  coordZ[m]+sin(angle[m-1])*offset,P,offset,coordX[m],coordZ[m]) 
                        elif (angle[m-1] - alfa > 0.2):
                            print '(G03:ARC)(ANGLE:angle[m-1] - alfa > 0.2)(next:LINE)'#DXF arc_G3_line>.dxf
                            radius_and_off = radius+offset
                            if m==0:
                                arc_itrs_lineZ,arc_itrs_lineX = coordZ[m],coordX[m]+offset
                            else:
                                arc_itrs_lineZ,arc_itrs_lineX = intersection_line_arc(3,coordZ[m]+sin(angle[m-1])*offset,
                                                                                     coordX[m]+cos(angle[m-1])*offset,
                                                                                     coordZ[m-1]+sin(angle[m-1])*offset,
                                                                                     coordX[m-1]+cos(angle[m-1])*offset,
                                                                                     centreZ,centreX,radius_and_off)
                            prog(program,3,arc_itrs_lineX,arc_itrs_lineZ,radius+offset)
                            part_n+=1 
                            papp(part_n,3,arc_itrs_lineX,arc_itrs_lineZ,P,radius_and_off,centreX,centreZ) 
                        else:      
                            print 'G03:ARC   next:LINE angle[m-1] == alfa' #DXF arc_G3_line=.dxf  
                            prog(program,3,coordX[m]+cos(angle[m-1])*offset,
                                 coordZ[m]+sin(angle[m-1])*offset,radius+offset)
                            part_n+=1
                            papp(part_n,3,coordX[m]+cos(angle[m-1])*offset,
                                 coordZ[m]+sin(angle[m-1])*offset,P,radius+offset,centreX,centreZ)                               
                    else:  #если дуга G3
                        NEXT_radius = sqrt((coordK[m-1])*(coordK[m-1]) + (coordI[m-1])*(coordI[m-1]))
                        NEXT_centreX = coordX[m] + coordI[m-1]
                        NEXT_centreZ = coordZ[m] + coordK[m-1]                      
                        if (line_or_arc[m-1] == 3):   # и следующая дуга G3 
                            print 'G03:ARC  next:ARC_G03'
                            NEXT_X,NEXT_Z=intersection_arc_arc(NEXT_centreX,NEXT_centreZ, 
                                                               NEXT_radius+offset,centreX,centreZ,radius+offset,
                                                               coordX[m],coordZ[m])                
                            prog(program,3,NEXT_X,NEXT_Z,radius+offset)
                            part_n+=1
                            papp(part_n,3,NEXT_X,NEXT_Z,P,radius+offset,centreX,centreZ)
                        if (line_or_arc[m-1] == 2): # и следующая дуга G2 
                            print 'G03:ARC ANGLE:ccw next:ARC_G02'
                            NEXT_X,NEXT_Z=intersection_arc_arc(NEXT_centreX,NEXT_centreZ, 
                                                               NEXT_radius-offset,centreX,centreZ,radius+offset,
                                                               coordX[m],coordZ[m])                
                            prog(program,3,NEXT_X,NEXT_Z,radius+offset)
                            part_n+=1
                            papp(part_n,3,NEXT_X,NEXT_Z,P,radius+offset,centreX,centreZ)
                else: #если участок "дуга" CCW  
                    if (line_or_arc[m-1] == 1): 
                        if (angle[m-1] - alfa < -0.2):
                            print '(G02:ARC) (angle[m-1] - alfa < -0.2) (next:LINE)'#DXF arc_G2_line<.dxf
                            prog(program,2,pointX,pointZ,radius-offset)
                            part_n+=1 
                            papp(part_n,2,pointX,pointZ,P,radius-offset,centreX,centreZ)
                            if m:
                                prog(program,3,coordX[m]+cos(angle[m-1])*offset,
                                     coordZ[m]+sin(angle[m-1])*offset,offset)
                                part_n+=1
                                papp(part_n,3,coordX[m]+cos(angle[m-1])*offset,
                                     coordZ[m]+sin(angle[m-1])*offset,P,offset,coordX[m],coordZ[m]) 
                        elif (angle[m-1] - alfa > 0.2):
                            '(G02:ARC)(ANGLE:angle[m-1] - alfa > 0.2)(next:LINE)'      
                            radius_and_off = radius-offset
                            if m==0:
                                arc_itrs_lineZ,arc_itrs_lineX = coordZ[m],coordX[m]+offset
                            else:
                                arc_itrs_lineZ,arc_itrs_lineX = intersection_line_arc(2,coordZ[m]+sin(angle[m-1])*offset,
                                                                                     coordX[m]+cos(angle[m-1])*offset,
                                                                                     coordZ[m-1]+sin(angle[m-1])*offset,
                                                                                     coordX[m-1]+cos(angle[m-1])*offset,
                                                                                     centreZ,centreX,radius_and_off)
                            prog(program,2,arc_itrs_lineX,arc_itrs_lineZ,radius-offset)
                            part_n+=1
                            papp(part_n,2,arc_itrs_lineX,arc_itrs_lineZ,P,radius_and_off,centreX,centreZ) 
 
                        else:
                            print 'G02:ARC   next:LINE angle[m-1] == alfa'
                            prog(program,2,coordX[m]+cos(angle[m-1])*offset,
                                     coordZ[m]+sin(angle[m-1])*offset,radius-offset)
                            part_n+=1
                            papp(part_n,2,coordX[m]+cos(angle[m-1])*offset,
                                 coordZ[m]+sin(angle[m-1])*offset,P,radius-offset,centreX,centreZ)                              
                            
                    else: 
                        NEXT_radius = sqrt((coordK[m-1])*(coordK[m-1]) + (coordI[m-1])*(coordI[m-1]))
                        NEXT_centreX = coordX[m] + coordI[m-1]
                        NEXT_centreZ = coordZ[m] + coordK[m-1]                  
                        if (line_or_arc[m-1] == 2): 
                            print 'G02:ARC  next:ARC_G02'
                            NEXT_X,NEXT_Z=intersection_arc_arc(NEXT_centreX,NEXT_centreZ, 
                                                               NEXT_radius-offset,centreX,centreZ,radius-offset,
                                                               coordX[m],coordZ[m])                
                            prog(program,2,NEXT_X,NEXT_Z,radius-offset)
                            part_n+=1
                            papp(part_n,2,NEXT_X,NEXT_Z,P,radius-offset,centreX,centreZ)
                            ########################################
                        if (line_or_arc[m-1] == 3): 
                            print 'G02:ARC ANGLE:ccw next:ARC_G03'
                            NEXT_X,NEXT_Z=intersection_arc_arc(NEXT_centreX,NEXT_centreZ, 
                                                               NEXT_radius+offset,centreX,centreZ,radius-offset,
                                                               coordX[m],coordZ[m])                
                            prog(program,2,NEXT_X,NEXT_Z,radius-offset)
                            part_n+=1
                            papp(part_n,2,NEXT_X,NEXT_Z,P,radius-offset,centreX,centreZ)
        flag_micro_part = 0        
        bounce = 0.5 
        self.execute("G21 G18 G49  G90 G61")
        
        fgcode.write("G21 G18 G49  G90 G61 \n")
        fgcode.write("F%f \n" % feed_rate)
        fgcode.write("M6 T2\n")
        COORDx0 = P[len(P)-1][3] 
        self.execute("G1 X%f" % (COORDx0))
        fgcode.write("G1 X%f\n" % (COORDx0))
        if flag_executed :
            i = len(P)-1
            if only_finishing_cut==0 :
                if COORDx0 - P[len(P)-1][1] <= d:
                    d=0
                while COORDx0 - P[i][1] >= d :
                    d = float(words['d'])  
                    if P[i][0] == 1:
                        Mz1 = P[i][2]
                        Mx1 = P[i][1]
                        Mz2 = P[i][4]
                        Mx2 = P[i][3]  
                        if (Mz2-Mz1)!=0:
                            K=(Mx2-Mx1)/(Mz2-Mz1)
                            B=-(K*Mz1-Mx1)
                            COORDz0 = (COORDx0 - B)/K
                        else:
                            COORDz0=P[i][2] 
                    elif P[i][0] == 2:
                        Mz1 = P[i][2]
                        Mx1 = P[i][3]
                        Mz2 = P[i][4]
                        Mx2 = P[i][3] 
                        B=COORDx0                           
                        center = [P[i][7],P[i][6]]
                        radius = P[i][5]                   
                        b = -2*center[0]   
                        c = -radius**2 + (B-center[1])**2 + center[0]**2  
                        D = b**2 - 4*c  
                        if D < 0:  
                            print 'D<0'
                        else:   
                            z1 = (-b-sqrt(D))/2 
                            z2 = (-b+sqrt(D))/2 
                            if Mz1 < z1 < Mz2:#TODO 
                                COORDz0=z2
                            else:
                                COORDz0=z1
                    elif P[i][0] == 3:
                        Mz1 = P[i][2]
                        Mx1 = P[i][3]
                        Mz2 = P[i][4]
                        Mx2 = P[i][3] 
                        B=COORDx0      
                        center = [P[i][7],P[i][6]]
                        radius = P[i][5] 
                        b = -2*center[0]  
                        c = -radius**2 + (B-center[1])**2 + center[0]**2  
                        D = b**2 - 4*c 
                        if D < 0: 
                            print 'D<0'
                        else:  
                            z1 = (-b-sqrt(D))/2 
                            z2 = (-b+sqrt(D))/2 
                            if Mz1 < z1 < Mz2:#TODO 
                                COORDz0=z1
                            else:
                                COORDz0=z2
                    self.execute("G1 Z%f" % ((COORDz0)))
                    fgcode.write("G1 Z%f\n" % ((COORDz0)))
                    if bounce > coordZ_start - COORDz0:
                        self.execute("G0 X%f Z%f" % ((COORDx0),(coordZ_start)))
                        fgcode.write("G0 X%f Z%f\n" % ((COORDx0),(coordZ_start)))
                    else:
                        self.execute("G0 X%f Z%f" % ((COORDx0+bounce),(COORDz0+bounce)))
                        fgcode.write("G0 X%f Z%f\n" % ((COORDx0+bounce),(COORDz0+bounce)))
                        self.execute("G0 Z%f" % (coordZ_start))
                        fgcode.write("G0 Z%f\n" % (coordZ_start))

                    COORDx0 = COORDx0 - d
                    for next_i in reversed(range(len(P))): 
                        if P[next_i][3] > COORDx0 > P[next_i][1]:
                            i=next_i                     
                    self.execute("G1 X%f" % (COORDx0))
                    fgcode.write("G1 X%f\n" % (COORDx0)) 
                    if flag_micro_part :                    
                        if COORDx0 - P[i][1] < d and P[i][3] > COORDx0 > P[i][1]:
                            d=0
                            flag_micro_part = 1
                        else:
                            flag_micro_part = 0
                        continue
                    if COORDx0 - P[i][1] < d:
                        if P[i][0] == 1:
                            Mz1 = P[i][2]
                            Mx1 = P[i][1]
                            Mz2 = P[i][4]
                            Mx2 = P[i][3]  
                            if (Mz2-Mz1)!=0:
                                K=(Mx2-Mx1)/(Mz2-Mz1)
                                B=-(K*Mz1-Mx1)
                                COORDz0 = (COORDx0 - B)/K
                            else:
                                COORDz0=P[i][2] 
                            self.execute("G1 Z%f" % ((COORDz0)))
                            fgcode.write("G1 Z%f\n" % ((COORDz0)))
                            if bounce > coordZ_start - COORDz0:
                                self.execute("G0 X%f Z%f" % ((COORDx0),(coordZ_start)))
                                fgcode.write("G0 X%f Z%f\n" % ((COORDx0),(coordZ_start)))
                            else:
                                self.execute("G0 X%f Z%f" % ((COORDx0+bounce),(COORDz0+bounce)))
                                fgcode.write("G0 X%f Z%f\n" % ((COORDx0+bounce),(COORDz0+bounce)))
                                self.execute("G0 Z%f" % (coordZ_start))
                                fgcode.write("G0 Z%f\n" % (coordZ_start))
                            if i>1:
                                COORDx0 = COORDx0 - d 
                                for next_i in reversed(range(len(P))): 
                                    if P[next_i][3] > COORDx0 > P[next_i][1]:
                                        i=next_i                                  
                                if COORDx0 - P[i][1] < d and P[i][3] > COORDx0 > P[i][1]:
                                    d=0
                                    flag_micro_part = 1   
                                self.execute("G1 X%f" % (COORDx0))
                                fgcode.write("G1 X%f\n" % (COORDx0))
                        elif P[i][0] == 2:
                            Mz1 = P[i][2]
                            Mx1 = P[i][3]
                            Mz2 = P[i][4]
                            Mx2 = P[i][3] 
                            B=COORDx0                           
                            center = [P[i][7],P[i][6]]
                            radius = P[i][5]  
                            b = -2*center[0]  
                            c = -radius**2 + (B-center[1])**2 + center[0]**2
                            D = b**2 - 4*c 
                            if D < 0:
                                print 'D<0'
                            else: 
                                z1 = (-b-sqrt(D))/2
                                z2 = (-b+sqrt(D))/2 
                                if Mz1 < z1 < Mz2:#TODO
                                    COORDz0=z2
                                else:
                                    COORDz0=z1
                            self.execute("G1 Z%f" % ((COORDz0)))
                            fgcode.write("G1 Z%f\n" % ((COORDz0)))                          
                            if bounce > coordZ_start - COORDz0:
                                self.execute("G0 X%f Z%f" % ((COORDx0),(coordZ_start)))
                                fgcode.write("G0 X%f Z%f\n" % ((COORDx0),(coordZ_start)))
                            else:
                                self.execute("G0 X%f Z%f" % ((COORDx0+bounce),(COORDz0+bounce)))
                                fgcode.write("G0 X%f Z%f\n" % ((COORDx0+bounce),(COORDz0+bounce)))
                                self.execute("G0 Z%f" % (coordZ_start))
                                fgcode.write("G0 Z%f\n" % (coordZ_start))
                            if i>1:
                                COORDx0 = COORDx0 - d 
                                for next_i in reversed(range(len(P))): 
                                    if P[next_i][3] > COORDx0 > P[next_i][1]:
                                        i=next_i                                  
                                if COORDx0 - P[i][1] < d and P[i][3] > COORDx0 > P[i][1]:
                                    d=0
                                    flag_micro_part = 1
                                self.execute("G1 X%f" % (COORDx0))
                                fgcode.write("G1 X%f\n" % (COORDx0))
                        elif P[i][0] == 3:
                            Mz1 = P[i][2]
                            Mx1 = P[i][3]
                            Mz2 = P[i][4]
                            Mx2 = P[i][3] 
                            B=COORDx0
                            center = [P[i][7],P[i][6]]
                            radius = P[i][5]
                            b = -2*center[0]
                            c = -radius**2 + (B-center[1])**2 + center[0]**2
                            D = b**2 - 4*c
                            if D < 0:  
                                print 'D<0'
                            else:   
                                z1 = (-b-sqrt(D))/2   
                                z2 = (-b+sqrt(D))/2 
                                if Mz1 < z1 < Mz2: #TODO сделать "умнее" расчет
                                    COORDz0=z1
                                else:
                                    COORDz0=z2
                            self.execute("G1 Z%f" % ((COORDz0)))
                            fgcode.write("G1 Z%f\n" % ((COORDz0)))
                            if bounce > coordZ_start - COORDz0:
                                self.execute("G0 X%f Z%f" % ((COORDx0),(coordZ_start)))
                                fgcode.write("G0 X%f Z%f\n" % ((COORDx0),(coordZ_start)))
                            else:
                                self.execute("G0 X%f Z%f" % ((COORDx0+bounce),(COORDz0+bounce)))
                                fgcode.write("G0 X%f Z%f\n" % ((COORDx0+bounce),(COORDz0+bounce)))
                                self.execute("G0 Z%f" % (coordZ_start))
                                fgcode.write("G0 Z%f\n" % (coordZ_start))
                            if i>1:
                                COORDx0 = COORDx0 - d 
                                for next_i in reversed(range(len(P))): 
                                    if P[next_i][3] > COORDx0 > P[next_i][1]:
                                        i=next_i                                  
                                if COORDx0 - P[i][1] < d and P[i][3] > COORDx0 > P[i][1]:
                                    d=0
                                    flag_micro_part = 1
                                self.execute("G1 X%f" % (COORDx0))
                                fgcode.write("G1 X%f\n" % (COORDx0))                         
            else:
                MESSAGE("Only finishing cut") 
                self.execute("M0")                          
##################################################### 
        print 'program =', program 
                                                        
        flag_executed = 0                                            
        for w in program:
            try:  
                self.execute(w)
                fgcode.write(w)
                fgcode.write("\n")
            except InterpreterException,e:
                        msg = "%d: '%s' - %s" % (e.line_number,e.line_text, e.error_message)
                        self.set_errormsg(msg) 
                        return INTERP_ERROR  
        offset-=offset_mem/quantity
        program = []
        self.execute("G0 Z%f" % (coordZ_start)) 
        fgcode.write("G0 Z%f\n" % (coordZ_start))   
#####################################################
    print 'P =', P 
    self.execute("G40 " )
 
    #self.execute("G42" )
 #   self.execute("G0 X%f Z%f" % ((FIRST_pointX),(coordZ_start)))
#    self.execute("G1 X%f " % FIRST_pointX)
    if words.has_key('t'):
        self.execute("M6 T%d" % (tool))
        fgcode.write("M6 T%d\n" % (tool))
    if words.has_key('f'):
        feed_rate = float(words['f'])
        self.execute("F%f" % feed_rate)#TODO
        fgcode.write("F%f\n" % feed_rate)                  
    for w in lines:
        if  re.search("^\s*[(]\s*N\d", w.upper()):
            if not re.search("[^\(\)\.\-\+NGZXRIK\d\s]", w.upper()):
                num2 = int(re.findall("^\s*\d*",(re.split('N',w.upper())[1]))[0])
                if num2 >= p and num2 <= q:
                    try: 
                        contour=re.split('\)',(re.split('\(',w.upper())[1]))[0]
                        self.execute(contour)
                        fgcode.write(contour)
                        fgcode.write("\n")
                    except InterpreterException,e:
                        msg = "%d: '%s' - %s" % (e.line_number,e.line_text, e.error_message)
                        self.set_errormsg(msg) 
                        return INTERP_ERROR 
    self.execute("G40" )   
    self.execute("G0 Z%f" % (coordZ_start))
    fgcode.write("G0 Z%f\n" % (coordZ_start))
    fgcode.write("M02\n")                             
    f.close() 
    fgcode.close()               
    return INTERP_OK
nkp
Мастер
Сообщения: 8340
Зарегистрирован: 28 ноя 2011, 00:25
Репутация: 1589
Контактная информация:

Re: G71 , ... (remap)

Сообщение nkp »

работает и для такой конфигурации:
Выделение_157.png (7590 просмотров) <a class='original' href='./download/file.php?id=96760&sid=9578190e895ab28330289bc83dd393a5&mode=view' target=_blank>Загрузить оригинал (82.73 КБ)</a>
nkp
Мастер
Сообщения: 8340
Зарегистрирован: 28 ноя 2011, 00:25
Репутация: 1589
Контактная информация:

Re: G71 , ... (remap)

Сообщение nkp »

такая вот мелочь ,как прорисовка заготовки (ну и патрона уже заодно))
можно задавать в комменте программы :
(AXIS,BLANK,145,100)
кстати - как правильно токарная заготовка в английском?(так ,для общего развития ;) )
ведь для себя можно прописать и так:
(AXIS,ZAGOTOVKA)145,100) :freak:
аргументы - диаметр,длина(длина от кулачка)
зы "досмотрел: "от кулачка " только для прямых кулачков)
Выделение_159.png (7554 просмотра) <a class='original' href='./download/file.php?id=96974&sid=9578190e895ab28330289bc83dd393a5&mode=view' target=_blank>Загрузить оригинал (62.6 КБ)</a>
третий аргумент(если прописать) - диам проточки
Выделение_158.png (7554 просмотра) <a class='original' href='./download/file.php?id=96973&sid=9578190e895ab28330289bc83dd393a5&mode=view' target=_blank>Загрузить оригинал (84.58 КБ)</a>
патрон 250-й в масштабе )
кулачки прямые (до д120) и обратные (свыше)
==============
конечно (openGL позволяет)) все это можно прорисовать и более "реалистично" ...

Код: Выделить всё

# -*- coding: utf-8 -*-
from rs274 import Translated, ArcsToSegmentsMixin, OpenGLTk
from minigl import *
import math
import glnav
import hershey
import linuxcnc
import array
import gcode

import hal



def minmax(*args):
    return min(*args), max(*args)

homeicon = array.array('B',
        [0x2, 0x00,   0x02, 0x00,   0x02, 0x00,   0x0f, 0x80,
        0x1e, 0x40,   0x3e, 0x20,   0x3e, 0x20,   0x3e, 0x20,
        0xff, 0xf8,   0x23, 0xe0,   0x23, 0xe0,   0x23, 0xe0,
        0x13, 0xc0,   0x0f, 0x80,   0x02, 0x00,   0x02, 0x00])

limiticon = array.array('B',
        [  0,   0,  128, 0,  134, 0,  140, 0,  152, 0,  176, 0,  255, 255,
         255, 255,  176, 0,  152, 0,  140, 0,  134, 0,  128, 0,    0,   0,
           0,   0,    0, 0])

class GLCanon(Translated, ArcsToSegmentsMixin):
    lineno = -1
    def __init__(self, colors, geometry, is_foam=0):
        # traverse list - [line number, [start position], [end position], [tlo x, tlo y, tlo z]]
        self.traverse = []; self.traverse_append = self.traverse.append
        # feed list - [line number, [start position], [end position], feedrate, [tlo x, tlo y, tlo z]]
        self.feed = []; self.feed_append = self.feed.append
        # arcfeed list - [line number, [start position], [end position], feedrate, [tlo x, tlo y, tlo z]]
        self.arcfeed = []; self.arcfeed_append = self.arcfeed.append
        # dwell list - [line number, color, pos x, pos y, pos z, plane]
        self.dwells = []; self.dwells_append = self.dwells.append
        self.choice = None
        self.feedrate = 1
        self.lo = (0,) * 9
        self.first_move = True
        self.geometry = geometry
        self.min_extents = [9e99,9e99,9e99]
        self.max_extents = [-9e99,-9e99,-9e99]
        self.min_extents_notool = [9e99,9e99,9e99]
        self.max_extents_notool = [-9e99,-9e99,-9e99]
        self.colors = colors
        self.in_arc = 0
        self.xo = self.yo = self.zo = self.ao = self.bo = self.co = self.uo = self.vo = self.wo = 0
        self.dwell_time = 0
        self.suppress = 0
        self.g92_offset_x = 0.0
        self.g92_offset_y = 0.0
        self.g92_offset_z = 0.0
        self.g92_offset_a = 0.0
        self.g92_offset_b = 0.0
        self.g92_offset_c = 0.0
        self.g92_offset_u = 0.0
        self.g92_offset_v = 0.0
        self.g92_offset_w = 0.0
        self.g5x_index = 1
        self.g5x_offset_x = 0.0
        self.g5x_offset_y = 0.0
        self.g5x_offset_z = 0.0
        self.g5x_offset_a = 0.0
        self.g5x_offset_b = 0.0
        self.g5x_offset_c = 0.0
        self.g5x_offset_u = 0.0
        self.g5x_offset_v = 0.0
        self.g5x_offset_w = 0.0
        self.is_foam = is_foam
        self.foam_z = 0
        self.foam_w = 1.5
        self.notify = 0
        self.notify_message = ""
        self.blank_f = 0
        self.blank_d = 0
        self.blank_l = 0
        self.blank_p = 0
    def comment(self, arg):   # -----------------------------------------------------------команды в G-коде
        if arg.startswith("AXIS,"):
            parts = arg.split(",")
            command = parts[1]
            if command == "stop": raise KeyboardInterrupt
            if command == "hide": self.suppress += 1
            if command == "show": self.suppress -= 1
            if command == "BLANK":
                self.blank_f = 1
                if len(parts) > 4 :
                    try:
                        self.blank_p = float(parts[4])
                        self.blank_d = float(parts[2])
                        self.blank_l = float(parts[3]) 
                    except:
                        self.blank_p = 0
                        self.blank_d = 0
                        self.blank_l = 0
                elif len(parts) > 3 :
                    try:
                        self.blank_d = float(parts[2])
                        self.blank_l = float(parts[3])
                    except:
                        self.blank_d = 0
                        self.blank_l = 0
                       
            if command == "XY_Z_POS": 
                if len(parts) > 2 :
                    try:
                        self.foam_z = float(parts[2])
                        if 210 in self.state.gcodes:
                            self.foam_z = self.foam_z / 25.4
                    except:
                        self.foam_z = 5.0/25.4
            if command == "UV_Z_POS": 
                if len(parts) > 2 :
                    try:
                        self.foam_w = float(parts[2])
                        if 210 in self.state.gcodes:
                            self.foam_w = self.foam_w / 25.4
                    except:
                        self.foam_w = 30.0
            if command == "notify":
                self.notify = self.notify + 1
                self.notify_message = "(AXIS,notify):" + str(self.notify)
                if len(parts) > 2:
                    if len(parts[2]): self.notify_message = parts[2]

    def message(self, message): pass

    def check_abort(self): pass

    def next_line(self, st):
        self.state = st
        self.lineno = self.state.sequence_number

    def draw_lines(self, lines, for_selection, j=0, geometry=None):
        return linuxcnc.draw_lines(geometry or self.geometry, lines, for_selection)

    def colored_lines(self, color, lines, for_selection, j=0):
        if self.is_foam:
            if not for_selection:
                self.color_with_alpha(color + "_xy")
            glPushMatrix()
            glTranslatef(0, 0, self.foam_z)
            self.draw_lines(lines, for_selection, 2*j, 'XY')
            glPopMatrix()
            if not for_selection:
                self.color_with_alpha(color + "_uv")
            glPushMatrix()
            glTranslatef(0, 0, self.foam_w)
            self.draw_lines(lines, for_selection, 2*j+len(lines), 'UV')
            glPopMatrix()
        else:
            if not for_selection:
                self.color_with_alpha(color)
            self.draw_lines(lines, for_selection, j)

    def draw_dwells(self, dwells, alpha, for_selection, j0=0):
        return linuxcnc.draw_dwells(self.geometry, dwells, alpha, for_selection, self.is_lathe())

    def calc_extents(self):#----------------------------------------------------------------------------вычисление размеров
        self.min_extents, self.max_extents, self.min_extents_notool, self.max_extents_notool = gcode.calc_extents(self.arcfeed, self.feed, self.traverse)

        if self.is_foam:
            min_z = min(self.foam_z, self.foam_w)
            max_z = max(self.foam_z, self.foam_w)
            self.min_extents = self.min_extents[0], self.min_extents[1], min_z
            self.max_extents = self.max_extents[0], self.max_extents[1], max_z
            self.min_extents_notool = \
                self.min_extents_notool[0], self.min_extents_notool[1], min_z
            self.max_extents_notool = \
                self.max_extents_notool[0], self.max_extents_notool[1], max_z
    def tool_offset(self, xo, yo, zo, ao, bo, co, uo, vo, wo):
        self.first_move = True
        x, y, z, a, b, c, u, v, w = self.lo
        self.lo = (x - xo + self.xo, y - yo + self.yo, z - zo + self.zo, a - ao + self.ao, b - bo + self.bo, c - bo + self.bo,
          u - uo + self.uo, v - vo + self.vo, w - wo + self.wo)
        self.xo = xo
        self.yo = yo
        self.zo = zo
        self.so = ao
        self.bo = bo
        self.co = co
        self.uo = uo
        self.vo = vo
        self.wo = wo

    def set_spindle_rate(self, arg): pass
    def set_feed_rate(self, arg): self.feedrate = arg / 60.
    def select_plane(self, arg): pass

    def change_tool(self, arg):
        self.first_move = True

    def straight_traverse(self, x,y,z, a,b,c, u, v, w): # ---------------------прямые перемещения
        if self.suppress > 0: return
        l = self.rotate_and_translate(x,y,z,a,b,c,u,v,w)
        if not self.first_move:
                self.traverse_append((self.lineno, self.lo, l, [self.xo, self.yo, self.zo]))
        self.lo = l


    def rigid_tap(self, x, y, z):
        if self.suppress > 0: return
        self.first_move = False
        l = self.rotate_and_translate(x,y,z,0,0,0,0,0,0)[:3]
        l += [self.lo[3], self.lo[4], self.lo[5],
               self.lo[6], self.lo[7], self.lo[8]]
        self.feed_append((self.lineno, self.lo, l, self.feedrate, [self.xo, self.yo, self.zo]))
#        self.dwells_append((self.lineno, self.colors['dwell'], x + self.offset_x, y + self.offset_y, z + self.offset_z, 0))
        self.feed_append((self.lineno, l, self.lo, self.feedrate, [self.xo, self.yo, self.zo]))

    def arc_feed(self, *args):
        if self.suppress > 0: return
        self.first_move = False
        self.in_arc = True
        try:
            ArcsToSegmentsMixin.arc_feed(self, *args)
        finally:
            self.in_arc = False

    def straight_arcsegments(self, segs):
        self.first_move = False
        lo = self.lo
        lineno = self.lineno
        feedrate = self.feedrate
        to = [self.xo, self.yo, self.zo]
        append = self.arcfeed_append
        for l in segs:
            append((lineno, lo, l, feedrate, to))
            lo = l
        self.lo = lo

    def straight_feed(self, x,y,z, a,b,c, u, v, w):
        if self.suppress > 0: return
        self.first_move = False
        l = self.rotate_and_translate(x,y,z,a,b,c,u,v,w)
        self.feed_append((self.lineno, self.lo, l, self.feedrate, [self.xo, self.yo, self.zo]))
        self.lo = l
    straight_probe = straight_feed

    def user_defined_function(self, i, p, q):
        if self.suppress > 0: return
        color = self.colors['m1xx']
        self.dwells_append((self.lineno, color, self.lo[0], self.lo[1], self.lo[2], self.state.plane/10-17))

    def dwell(self, arg):
        if self.suppress > 0: return
        self.dwell_time += arg
        color = self.colors['dwell']
        self.dwells_append((self.lineno, color, self.lo[0], self.lo[1], self.lo[2], self.state.plane/10-17))


    def highlight(self, lineno, geometry):
        glLineWidth(5)
        c = self.colors['selected']

        glColor3f(*c)
        glBegin(GL_LINES)
        coords = []
        for line in self.traverse:
            if line[0] != lineno: continue
            linuxcnc.line9(geometry, line[1], line[2])
            coords.append(line[1][:3])
            coords.append(line[2][:3])

        for line in self.arcfeed:
            if line[0] != lineno: continue
            linuxcnc.line9(geometry, line[1], line[2])
            coords.append(line[1][:3])
            coords.append(line[2][:3])
        for line in self.feed:
            if line[0] != lineno: continue
            linuxcnc.line9(geometry, line[1], line[2])
            coords.append(line[1][:3])
            coords.append(line[2][:3])
        glEnd()
        for line in self.dwells:
            if line[0] != lineno: continue
            self.draw_dwells([(line[0], c) + line[2:]], 2, 0)
            coords.append(line[2:5])
        glLineWidth(1)
        if coords:
            x = reduce(lambda x,y:x+y, [c[0] for c in coords]) / len(coords)
            y = reduce(lambda x,y:x+y, [c[1] for c in coords]) / len(coords)
            z = reduce(lambda x,y:x+y, [c[2] for c in coords]) / len(coords)
        else:
            x = (self.min_extents[0] + self.max_extents[0])/2
            y = (self.min_extents[1] + self.max_extents[1])/2
            z = (self.min_extents[2] + self.max_extents[2])/2     
        return x, y, z

    def color_with_alpha(self, name):
        glColor4f(*(self.colors[name] + (self.colors.get(name+'_alpha', 1/3.),)))
    def color(self, name):
        glColor3f(*self.colors[name])

    def draw(self, for_selection=0, no_traverse=True):
        if not no_traverse:
            glEnable(GL_LINE_STIPPLE)
            self.colored_lines('traverse', self.traverse, for_selection)
            glDisable(GL_LINE_STIPPLE)
        else:
            self.colored_lines('straight_feed', self.feed, for_selection, len(self.traverse))

            self.colored_lines('arc_feed', self.arcfeed, for_selection, len(self.traverse) + len(self.feed))

            glLineWidth(2)
            self.draw_dwells(self.dwells, self.colors.get('dwell_alpha', 1/3.), for_selection, len(self.traverse) + len(self.feed) + len(self.arcfeed))
            glLineWidth(1)

def with_context(f):
    def inner(self, *args, **kw):
        self.activate()
        try:
            return f(self, *args, **kw)
        finally:
            self.deactivate()
    return inner

def with_context_swap(f):
    def inner(self, *args, **kw):
        self.activate()
        try:
            return f(self, *args, **kw)
        finally:
            self.swapbuffers()
            self.deactivate()
    return inner


class GlCanonDraw:
    colors = {
        'traverse': (0.30, 0.50, 0.50),
        'traverse_alpha': 1/3.,
        'traverse_xy': (0.30, 0.50, 0.50),
        'traverse_alpha_xy': 1/3.,
        'traverse_uv': (0.30, 0.50, 0.50),
        'traverse_alpha_uv': 1/3.,
        'backplotprobing_alpha': 0.75,
        'backplotprobing': (0.63, 0.13, 0.94),
        'backplottraverse': (0.30, 0.50, 0.50),
        'label_ok': (1.00, 0.51, 0.53),
        'backplotjog_alpha': 0.75,
        'tool_diffuse': (0.60, 0.60, 0.60),
        'backplotfeed': (0.75, 0.25, 0.25),
        'back': (0.00, 0.00, 0.00),
        'lathetool_alpha': 0.10,
        'axis_x': (0.20, 1.00, 0.20),
        'cone': (1.00, 1.00, 1.00),
        'cone_xy': (0.00, 1.00, 0.00),
        'cone_uv': (0.00, 0.00, 1.00),
        'axis_z': (0.20, 0.20, 1.00),
        'label_limit': (1.00, 0.21, 0.23),
        'backplotjog': (1.00, 1.00, 0.00),
        'selected': (1.00, 1.00, 0.00),
        'lathetool': (0.80, 0.80, 0.80),
        'dwell': (1.00, 0.50, 0.50),
        'overlay_foreground': (1.00, 1.00, 1.00),
        'overlay_background': (0.00, 0.00, 0.00),
        'straight_feed': (1.00, 1.00, 1.00),
        'straight_feed_alpha': 1/3.,
        'straight_feed_xy': (0.20, 1.00, 0.20),
        'straight_feed_alpha_xy': 1/3.,
        'straight_feed_uv': (0.20, 0.20, 1.00),
        'straight_feed_alpha_uv': 1/3.,
        'small_origin': (0.00, 1.00, 1.00),
        'backplottoolchange_alpha': 0.25,
        'backplottraverse_alpha': 0.25,
        'overlay_alpha': 0.75,
        'tool_ambient': (0.40, 0.40, 0.40),
        'tool_alpha': 0.20,
        'backplottoolchange': (1.00, 0.65, 0.00),
        'backplotarc': (0.75, 0.25, 0.50),
        'm1xx': (0.50, 0.50, 1.00),
        'backplotfeed_alpha': 0.75,
        'backplotarc_alpha': 0.75,
        'arc_feed': (1.00, 1.00, 1.00),
        'arc_feed_alpha': .5,
        'arc_feed_xy': (0.20, 1.00, 0.20),
        'arc_feed_alpha_xy': 1/3.,
        'arc_feed_uv': (0.20, 0.20, 1.00),
        'arc_feed_alpha_uv': 1/3.,
        'axis_y': (1.00, 0.20, 0.20),
        'grid': (0.15, 0.15, 0.15),
    }
    def __init__(self, s, lp, g=None):
        self.stat = s
        self.lp = lp
        self.canon = g
        self._dlists = {}
        self.select_buffer_size = 100
        self.cached_tool = -1
        self.initialised = 0
        self.pincomp = hal.component('drawing')
        self.pincomp.newpin('begin_blank_horiz', hal.HAL_FLOAT, hal.HAL_IN)
        self.pincomp.newpin('begin_blank_vertical', hal.HAL_FLOAT, hal.HAL_IN)
        self.pincomp.newpin('height_blank', hal.HAL_FLOAT, hal.HAL_IN)
        self.pincomp.newpin('length_blank', hal.HAL_FLOAT, hal.HAL_IN)
        self.pincomp.ready()

    def realize(self):
        self.hershey = hershey.Hershey()
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
        self.basic_lighting()
        self.initialised = 1

    def set_canon(self, canon):
        self.canon = canon

    @with_context
    def basic_lighting(self):
        glLightfv(GL_LIGHT0, GL_POSITION, (1, -1, 1, 0))
        glLightfv(GL_LIGHT0, GL_AMBIENT, self.colors['tool_ambient'] + (0,))
        glLightfv(GL_LIGHT0, GL_DIFFUSE, self.colors['tool_diffuse'] + (0,))
        glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, (1,1,1,0))
        glEnable(GL_LIGHTING)
        glEnable(GL_LIGHT0)
        glDepthFunc(GL_LESS)
        glEnable(GL_DEPTH_TEST)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()

    def select(self, x, y):
        if self.canon is None: return
        pmatrix = glGetDoublev(GL_PROJECTION_MATRIX)
        glMatrixMode(GL_PROJECTION)
        glPushMatrix()
        glLoadIdentity()
        vport = glGetIntegerv(GL_VIEWPORT)
        gluPickMatrix(x, vport[3]-y, 5, 5, vport)
        glMultMatrixd(pmatrix)
        glMatrixMode(GL_MODELVIEW)

        while 1:
            glSelectBuffer(self.select_buffer_size)
            glRenderMode(GL_SELECT)
            glInitNames()
            glPushName(0)

            if self.get_show_rapids():
                glCallList(self.dlist('select_rapids', gen=self.make_selection_list))
            glCallList(self.dlist('select_norapids', gen=self.make_selection_list))

            try:
                buffer = list(glRenderMode(GL_RENDER))
            except OverflowError:
                self.select_buffer_size *= 2
                continue
            break

        if buffer:
            min_depth, max_depth, names = min(buffer)
            self.set_highlight_line(names[0])
        else:
            self.set_highlight_line(None)

        glMatrixMode(GL_PROJECTION)
        glPopMatrix()
        glMatrixMode(GL_MODELVIEW)

    def dlist(self, name, n=1, gen=lambda n: None):
        if name not in self._dlists:
            base = glGenLists(n)
            self._dlists[name] = base, n
            gen(base)
        return self._dlists[name][0]

    def stale_dlist(self, name):
        if name not in self._dlists: return
        base, count = self._dlists.pop(name)
        glDeleteLists(base, count)

    def __del__(self):
        for base, count in self._dlists.values():
            glDeleteLists(base, count)

    def set_current_line(self, line): pass
    def set_highlight_line(self, line):
        if line == self.get_highlight_line(): return
        highlight = self.dlist('highlight')
        glNewList(highlight, GL_COMPILE)
        if line is not None and self.canon is not None:
            if self.is_foam():
                glPushMatrix()
                glTranslatef(0, 0, self.get_foam_z()) 
                x, y, z = self.canon.highlight(line, "XY")
                glTranslatef(0, 0, self.get_foam_w()-self.get_foam_z())
                u, v, w = self.canon.highlight(line, "UV")
                glPopMatrix()
                x = (x+u)/2
                y = (y+v)/2
                z = (self.get_foam_z() + self.get_foam_w())/2
            else:
                x, y, z = self.canon.highlight(line, self.get_geometry())
        elif self.canon is not None:
            x = (self.canon.min_extents[0] + self.canon.max_extents[0])/2
            y = (self.canon.min_extents[1] + self.canon.max_extents[1])/2
            z = (self.canon.min_extents[2] + self.canon.max_extents[2])/2
        else:
            x, y, z = 0.0, 0.0, 0.0
        glEndList()
        self.set_centerpoint(x, y, z)#координаты центровки 
     

    @with_context_swap
    def redraw_perspective(self):

        w = self.winfo_width()
        h = self.winfo_height()
        glViewport(0, 0, w, h)

        # Clear the background and depth buffer.
        glClearColor(*(self.colors['back'] + (0,)))
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(self.fovy, float(w)/float(h), self.near, self.far + self.distance)

        gluLookAt(0, 0, self.distance,
            0, 0, 0,
            0., 1., 0.)
        glMatrixMode(GL_MODELVIEW)
        glPushMatrix()
        try:
            self.redraw()
        finally:
            glFlush()                               # Tidy up
            glPopMatrix()                   # Restore the matrix

    @with_context_swap
    def redraw_ortho(self):
        if not self.initialised: return

        w = self.winfo_width()
        h = self.winfo_height()
        glViewport(0, 0, w, h)

        # Clear the background and depth buffer.
        glClearColor(*(self.colors['back'] + (0,)))
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        ztran = self.distance
        k = (abs(ztran or 1)) ** .55555
        l = k * h / w
        glOrtho(-k, k, -l, l, -1000, 1000.)

        gluLookAt(0, 0, 1,
            0, 0, 0,
            0., 1., 0.)
        glMatrixMode(GL_MODELVIEW)
        glPushMatrix()
        try:
            self.redraw()
        finally:
            glFlush()                               # Tidy up
            glPopMatrix()                   # Restore the matrix

    def color_limit(self, cond):
        if cond:
            glColor3f(*self.colors['label_limit'])
        else:
            glColor3f(*self.colors['label_ok'])
        return cond
        ##################################################################### --показать заготовку 

     
    def blank (self):            
        s = self.stat
        g = self.canon
        if g is None: return
        self.color_limit(0)
        if self.canon.blank_f :            
            bp = self.pincomp['begin_blank_horiz'] /25.4
            ep = self.pincomp['begin_blank_vertical']/25.4
            hb = self.pincomp['height_blank']/25.4
            lb = self.pincomp['length_blank']/25.4
            
            hb = hb + self.canon.blank_d/25.4
            if hb < 0: hb = 0 
            lb = lb + self.canon.blank_l/25.4
            if lb < 0: lb = 0 
            glColor3f(0.4, 0.4, 0.4)
            rr=hb/2
            i_to_mm=1/25.4
            if rr <= 60*i_to_mm:
                #заготовка:
                glBegin(GL_LINE_LOOP)
                glVertex3f(-rr,0,(ep-lb-12*i_to_mm))
                glVertex3f(rr,0,(ep-lb-12*i_to_mm))
                glVertex3f(rr,0,ep)
                glVertex3f(-rr,0,(ep))
                glEnd()
                if self.canon.blank_p :
                    pb = self.canon.blank_p/2
                    glBegin(GL_LINE_LOOP)
                    glVertex3f(-pb*i_to_mm,0,0)
                    glVertex3f(-pb*i_to_mm,0,(ep-lb-12*i_to_mm))
                    
                    glVertex3f(pb*i_to_mm,0,(ep-lb-12*i_to_mm))
                    glVertex3f(pb*i_to_mm,0,0)
                    glEnd() 
                #патрон:
                #в.кулачок:
                glBegin(GL_LINE_LOOP) 
                glVertex3f(-rr,0,ep-lb)
                glVertex3f(-rr-25*i_to_mm,0,ep-lb)
                glVertex3f(-rr-25*i_to_mm,0,ep-lb-10*i_to_mm)
                glVertex3f(-rr-50*i_to_mm,0,ep-lb-10*i_to_mm)
                glVertex3f(-rr-50*i_to_mm,0,ep-lb-20*i_to_mm)
                glVertex3f(-rr-81*i_to_mm,0,ep-lb-20*i_to_mm)
                glVertex3f(-rr-81*i_to_mm,0,ep-lb-32*i_to_mm)
                glVertex3f(-rr,0,ep-lb-32*i_to_mm)          
                glEnd()
                #н.кулачок:
                glBegin(GL_LINE_LOOP) 
                glVertex3f(rr,0,ep-lb)
                glVertex3f(rr+25*i_to_mm,0,ep-lb)
                glVertex3f(rr+25*i_to_mm,0,ep-lb-10*i_to_mm)
                glVertex3f(rr+50*i_to_mm,0,ep-lb-10*i_to_mm)
                glVertex3f(rr+50*i_to_mm,0,ep-lb-20*i_to_mm)
                glVertex3f(rr+81*i_to_mm,0,ep-lb-20*i_to_mm)
                glVertex3f(rr+81*i_to_mm,0,ep-lb-32*i_to_mm)
                glVertex3f(rr,0,ep-lb-32*i_to_mm)
                glEnd()
                #корпус патрона (250mm):
                glBegin(GL_LINE_LOOP)
                glVertex3f(-125*i_to_mm,0,ep-lb-32*i_to_mm)
                glVertex3f(-125*i_to_mm,0,ep-lb-122*i_to_mm)
                glVertex3f(125*i_to_mm,0,ep-lb-122*i_to_mm)
                glVertex3f(125*i_to_mm,0,ep-lb-32*i_to_mm)         
                glEnd() 
            else:
                #заготовка:
                glBegin(GL_LINE_LOOP)
                glVertex3f(-rr,0,(ep-lb))
                glVertex3f(rr,0,(ep-lb))
                glVertex3f(rr,0,ep)
                glVertex3f(-rr,0,(ep))
                glEnd()
                if self.canon.blank_p :
                    pb = self.canon.blank_p/2
                    glBegin(GL_LINE_LOOP)
                    glVertex3f(-pb*i_to_mm,0,0)
                    glVertex3f(-pb*i_to_mm,0,(ep-lb))
                    
                    glVertex3f(pb*i_to_mm,0,(ep-lb))
                    glVertex3f(pb*i_to_mm,0,0)
                    glEnd() 
                #в.кулачок: <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                glBegin(GL_LINE_LOOP)
                glVertex3f(-rr,0,ep-lb)
                glVertex3f(-rr,0,ep-lb+10*i_to_mm)
                glVertex3f(-rr-25*i_to_mm,0,ep-lb+10*i_to_mm)
                glVertex3f(-rr-25*i_to_mm,0,ep-lb-22*i_to_mm)
                glVertex3f(-rr+62*i_to_mm,0,ep-lb-22*i_to_mm)
                glVertex3f(-rr+62*i_to_mm,0,ep-lb-10*i_to_mm)
                glVertex3f(-rr+25*i_to_mm,0,ep-lb-10*i_to_mm)
                glVertex3f(-rr+25*i_to_mm,0,ep-lb)
                glEnd() 
           #н.кулачок:
                glBegin(GL_LINE_LOOP)
                glVertex3f(rr,0,ep-lb)
                glVertex3f(rr,0,ep-lb+10*i_to_mm)
                glVertex3f(rr+25*i_to_mm,0,ep-lb+10*i_to_mm)
                glVertex3f(rr+25*i_to_mm,0,ep-lb-22*i_to_mm)
                glVertex3f(rr-62*i_to_mm,0,ep-lb-22*i_to_mm)
                glVertex3f(rr-62*i_to_mm,0,ep-lb-10*i_to_mm)
                glVertex3f(rr-25*i_to_mm,0,ep-lb-10*i_to_mm)
                glVertex3f(rr-25*i_to_mm,0,ep-lb)
                glEnd() 
               #корпус патрона:
                glBegin(GL_LINE_LOOP)
                glVertex3f(-125*i_to_mm,0,ep-lb-22*i_to_mm)
                glVertex3f(-125*i_to_mm,0,ep-lb-122*i_to_mm)
                glVertex3f(125*i_to_mm,0,ep-lb-122*i_to_mm)
                glVertex3f(125*i_to_mm,0,ep-lb-22*i_to_mm)         
                glEnd()               
                                  
            #осевая линия:                                                           
            kk = lb
            while kk>0:
                glBegin(GL_LINES)
                glVertex3f(bp,0,ep)
                glVertex3f(bp,0,(ep-lb*0.1))
                glVertex3f(bp,0,(ep-lb*0.14))
                glVertex3f(bp,0,(ep-lb*0.16))
                glEnd()
                kk-=lb*0.18
                ep-=lb*0.2
                     
        ######################################################################################
    def show_extents(self): # ------------------------------------------размеры
        s = self.stat
        g = self.canon

        if g is None: return

        # Dimensions
        x,y,z,p = 0,1,2,3
        view = self.get_view()
        is_metric = self.get_show_metric()
        dimscale = is_metric and 25.4 or 1.0
        fmt = is_metric and "%.1f" or "%.2f"

        machine_limit_min, machine_limit_max = self.soft_limits()

        pullback = max(g.max_extents[x] - g.min_extents[x],
                       g.max_extents[y] - g.min_extents[y],
                       g.max_extents[z] - g.min_extents[z],
                       2 ) * .1

        dashwidth = pullback/4
        charsize = dashwidth * 1.5
        halfchar = charsize * .5

        if view == z or view == p:
            z_pos = g.min_extents[z]
            zdashwidth = 0
        else:
            z_pos = g.min_extents[z] - pullback
            zdashwidth = dashwidth
        # x dimension

        self.color_limit(0)
        glBegin(GL_LINES)
        if view != x and g.max_extents[x] > g.min_extents[x]:
            y_pos = g.min_extents[y] - pullback
            glVertex3f(g.min_extents[x], y_pos, z_pos)
            glVertex3f(g.max_extents[x], y_pos, z_pos)

            #glVertex3f(g.min_extents[x], y_pos - dashwidth, z_pos - zdashwidth)
            #glVertex3f(g.min_extents[x], y_pos + dashwidth, z_pos + zdashwidth)

            #glVertex3f(g.max_extents[x], y_pos - dashwidth, z_pos - zdashwidth)
            #glVertex3f(g.max_extents[x], y_pos + dashwidth, z_pos + zdashwidth)

        # y dimension
        if view != y and g.max_extents[y] > g.min_extents[y]:
            x_pos = g.min_extents[x] - pullback
            glVertex3f(x_pos, g.min_extents[y], z_pos)
            glVertex3f(x_pos, g.max_extents[y], z_pos)

            #glVertex3f(x_pos - dashwidth, g.min_extents[y], z_pos - zdashwidth)
            #glVertex3f(x_pos + dashwidth, g.min_extents[y], z_pos + zdashwidth)

            #glVertex3f(x_pos - dashwidth, g.max_extents[y], z_pos - zdashwidth)
            #glVertex3f(x_pos + dashwidth, g.max_extents[y], z_pos + zdashwidth)

        # z dimension
        if view != z and g.max_extents[z] > g.min_extents[z]:
            x_pos = g.min_extents[x] - pullback
            y_pos = g.min_extents[y] - pullback
            glVertex3f(x_pos, y_pos, g.min_extents[z])
            glVertex3f(x_pos, y_pos, g.max_extents[z])

            glVertex3f(x_pos - dashwidth, y_pos - zdashwidth, g.min_extents[z])
            glVertex3f(x_pos + dashwidth, y_pos + zdashwidth, g.min_extents[z])

            glVertex3f(x_pos - dashwidth, y_pos - zdashwidth, g.max_extents[z])
            glVertex3f(x_pos + dashwidth, y_pos + zdashwidth, g.max_extents[z])

        glEnd()


        # Labels
        if self.get_show_relative():
            offset = self.to_internal_units(s.g5x_offset + s.g92_offset)
        else:
            offset = 0, 0, 0
        if view != z and g.max_extents[z] > g.min_extents[z]:
            if view == x:
                x_pos = g.min_extents[x] - pullback
                y_pos = g.min_extents[y] - 6.0*dashwidth
            else:
                x_pos = g.min_extents[x] - 6.0*dashwidth
                y_pos = g.min_extents[y] - pullback

            bbox = self.color_limit(g.min_extents[z] < machine_limit_min[z])
            glPushMatrix()
            f = fmt % ((g.min_extents[z]-offset[z]) * dimscale)
            glTranslatef(x_pos, y_pos, g.min_extents[z] - halfchar)
            glScalef(charsize, charsize, charsize)
            glRotatef(-90, 0, 1, 0)
            glRotatef(-90, 0, 0, 1)
            if view != x:
                glRotatef(-90, 0, 1, 0)
            self.hershey.plot_string(f, 0, bbox)
            glPopMatrix()

            bbox = self.color_limit(g.max_extents[z] > machine_limit_max[z])
            glPushMatrix()
            f = fmt % ((g.max_extents[z]-offset[z]) * dimscale)
            glTranslatef(x_pos, y_pos, g.max_extents[z] - halfchar)
            glScalef(charsize, charsize, charsize)
            glRotatef(-90, 0, 1, 0)
            glRotatef(-90, 0, 0, 1)
            if view != x:
                glRotatef(-90, 0, 1, 0)
            self.hershey.plot_string(f, 0, bbox)
            glPopMatrix()

            self.color_limit(0)
            glPushMatrix()
            f = fmt % ((g.max_extents[z] - g.min_extents[z]) * dimscale)
            glTranslatef(x_pos, y_pos, (g.max_extents[z] + g.min_extents[z])/2)
            glScalef(charsize, charsize, charsize)
            if view != x:
                glRotatef(-90, 0, 0, 1)
            glRotatef(-90, 0, 1, 0)
            self.hershey.plot_string(f, .5, bbox)
            glPopMatrix()

        if view != y and g.max_extents[y] > g.min_extents[y]:
            x_pos = g.min_extents[x] - 6.0*dashwidth

            bbox = self.color_limit(g.min_extents[y] < machine_limit_min[y])
            glPushMatrix()
            f = fmt % ((g.min_extents[y] - offset[y]) * dimscale)
            glTranslatef(x_pos, g.min_extents[y] + halfchar, z_pos)
            glRotatef(-90, 0, 0, 1)
            glRotatef(-90, 0, 0, 1)
            if view == x:
                glRotatef(90, 0, 1, 0)
                glTranslatef(dashwidth*1.5, 0, 0)
            glScalef(charsize, charsize, charsize)
            self.hershey.plot_string(f, 0, bbox)
            glPopMatrix()

            bbox = self.color_limit(g.max_extents[y] > machine_limit_max[y])
            glPushMatrix()
            f = fmt % ((g.max_extents[y] - offset[y]) * dimscale)
            glTranslatef(x_pos, g.max_extents[y] + halfchar, z_pos)
            glRotatef(-90, 0, 0, 1)
            glRotatef(-90, 0, 0, 1)
            if view == x:
                glRotatef(90, 0, 1, 0)
                glTranslatef(dashwidth*1.5, 0, 0)
            glScalef(charsize, charsize, charsize)
            self.hershey.plot_string(f, 0, bbox)
            glPopMatrix()

            self.color_limit(0)
            glPushMatrix()
            f = fmt % ((g.max_extents[y] - g.min_extents[y]) * dimscale)

            glTranslatef(x_pos, (g.max_extents[y] + g.min_extents[y])/2,
                        z_pos)
            glRotatef(-90, 0, 0, 1)
            if view == x:
                glRotatef(-90, 1, 0, 0)
                glTranslatef(0, halfchar, 0)
            glScalef(charsize, charsize, charsize)
            self.hershey.plot_string(f, .5)
            glPopMatrix()

        if view != x and g.max_extents[x] > g.min_extents[x]:
            y_pos = g.min_extents[y] - 6.0*dashwidth

            bbox = self.color_limit(g.min_extents[x] < machine_limit_min[x])
            glPushMatrix()
            f = fmt % ((g.min_extents[x] - offset[x]) * dimscale)
            glTranslatef(g.min_extents[x] - halfchar, y_pos, z_pos)
            glRotatef(-90, 0, 0, 1)
            if view == y:
                glRotatef(90, 0, 1, 0)
                glTranslatef(dashwidth*1.5, 0, 0)
            glScalef(charsize, charsize, charsize)
            self.hershey.plot_string(f, 0, bbox)
            glPopMatrix()

            bbox = self.color_limit(g.max_extents[x] > machine_limit_max[x])
            glPushMatrix()
            f = fmt % ((g.max_extents[x] - offset[x]) * dimscale)
            glTranslatef(g.max_extents[x] - halfchar, y_pos, z_pos)
            glRotatef(-90, 0, 0, 1)
            if view == y:
                glRotatef(90, 0, 1, 0)
                glTranslatef(dashwidth*1.5, 0, 0)
            glScalef(charsize, charsize, charsize)
            self.hershey.plot_string(f, 0, bbox)
            glPopMatrix()

            self.color_limit(0)
            glPushMatrix()
            f = fmt % ((g.max_extents[x] - g.min_extents[x]) * dimscale)

            glTranslatef((g.max_extents[x] + g.min_extents[x])/2, y_pos,
                        z_pos)
            if view == y:
                glRotatef(-90, 1, 0, 0)
                glTranslatef(0, halfchar, 0)
            glScalef(charsize, charsize, charsize)
            self.hershey.plot_string(f, .5)
            glPopMatrix()

    def to_internal_linear_unit(self, v, unit=None):
        if unit is None:
            unit = self.stat.linear_units
        lu = (unit or 1) * 25.4
        return v/lu


    def to_internal_units(self, pos, unit=None):
        if unit is None:
            unit = self.stat.linear_units
        lu = (unit or 1) * 25.4

        lus = [lu, lu, lu, 1, 1, 1, lu, lu, lu]
        return [a/b for a, b in zip(pos, lus)]

    def soft_limits(self):
        def fudge(x):
            if abs(x) > 1e30: return 0
            return x

        ax = self.stat.axis
        return (
            self.to_internal_units([fudge(ax[i]['min_position_limit'])
                for i in range(3)]),
            self.to_internal_units([fudge(ax[i]['max_position_limit'])
                for i in range(3)]))

    def get_foam_z(self):
        if self.canon: return self.canon.foam_z
        return 0

    def get_foam_w(self):
        if self.canon: return self.canon.foam_w
        return 1.5

    def get_grid(self):
        if self.canon and self.canon.grid: return self.canon.grid
        return 5./25.4

    def comp(self, (sx, sy), (cx, cy)):
        return -(sx*cx + sy*cy) / (sx*sx + sy*sy)

    def param(self, (x1, y1), (dx1, dy1), (x3, y3), (dx3, dy3)):
        den = (dy3)*(dx1) - (dx3)*(dy1)
        if den == 0: return 0
        num = (dx3)*(y1-y3) - (dy3)*(x1-x3)
        return num * 1. / den

    def draw_grid_lines(self, space, (ox, oy), (dx, dy), lim_min, lim_max,
            inverse_permutation):
        # draw a series of line segments of the form
        #   dx(x-ox) + dy(y-oy) + k*space = 0
        # for integers k that intersect the AABB [lim_min, lim_max]
        lim_pts = [
                (lim_min[0], lim_min[1]),
                (lim_max[0], lim_min[1]),
                (lim_min[0], lim_max[1]),
                (lim_max[0], lim_max[1])]
        od = self.comp((dy, -dx), (ox, oy))
        d0, d1 = minmax(*(self.comp((dy, -dx), i)-od for i in lim_pts))
        k0 = int(math.ceil(d0/space))
        k1 = int(math.floor(d1/space))
        delta = (dx, dy)
        for k in range(k0, k1+1):
            d = k*space
            # Now we're drawing the line dx(x-ox) + dx(y-oy) + d = 0
            p0 = (ox - dy * d, oy + dx * d)
            # which is the same as the line p0 + u * delta

            # but we only want the part that's inside the box lim_pts...
            if dx and dy:
                times = [
                        self.param(p0, delta, lim_min[:2], (0, 1)),
                        self.param(p0, delta, lim_min[:2], (1, 0)),
                        self.param(p0, delta, lim_max[:2], (0, 1)),
                        self.param(p0, delta, lim_max[:2], (1, 0))]
                times.sort()
                t0, t1 = times[1], times[2] # Take the middle two times
            elif dx:
                times = [
                        self.param(p0, delta, lim_min[:2], (0, 1)),
                        self.param(p0, delta, lim_max[:2], (0, 1))]
                times.sort()
                t0, t1 = times[0], times[1] # Take the only two times
            else:
                times = [
                        self.param(p0, delta, lim_min[:2], (1, 0)),
                        self.param(p0, delta, lim_max[:2], (1, 0))]
                times.sort()
                t0, t1 = times[0], times[1] # Take the only two times
            x0, y0 = p0[0] + delta[0]*t0, p0[1] + delta[1]*t0
            x1, y1 = p0[0] + delta[0]*t1, p0[1] + delta[1]*t1
            xm, ym = (x0+x1)/2, (y0+y1)/2
            # The computation of k0 and k1 above should mean that
            # the lines are always in the limits, but I observed
            # that this wasn't always the case...
            #if xm < lim_min[0] or xm > lim_max[0]: continue
            #if ym < lim_min[1] or ym > lim_max[1]: continue
            glVertex3f(*inverse_permutation((x0, y0, lim_min[2])))
            glVertex3f(*inverse_permutation((x1, y1, lim_min[2])))

    def draw_grid_permuted(self, rotation, permutation, inverse_permutation):
        grid_size=self.get_grid_size()
        if not grid_size: return

        glLineWidth(1)
        glColor3f(*self.colors['grid'])
        lim_min, lim_max = self.soft_limits()
        lim_min = permutation(lim_min)
        lim_max = permutation(lim_max)

        lim_pts = (
                (lim_min[0], lim_min[1]),
                (lim_max[0], lim_min[1]),
                (lim_min[0], lim_max[1]),
                (lim_max[0], lim_max[1]))
        s = self.stat
        g5x_offset = permutation(self.to_internal_units(s.g5x_offset)[:3])[:2]
        g92_offset = permutation(self.to_internal_units(s.g92_offset)[:3])[:2]
        if self.get_show_relative():
            cos_rot = math.cos(rotation)
            sin_rot = math.sin(rotation)
            offset = (
                    g5x_offset[0] + g92_offset[0] * cos_rot
                                  - g92_offset[1] * sin_rot,
                    g5x_offset[1] + g92_offset[0] * sin_rot
                                  + g92_offset[1] * cos_rot)
        else:
            offset = 0., 0.
            cos_rot = 1.
            sin_rot = 0.
        glDepthMask(False)
        glBegin(GL_LINES)
        self.draw_grid_lines(grid_size, offset, (cos_rot, sin_rot),
                lim_min, lim_max, inverse_permutation)
        self.draw_grid_lines(grid_size, offset, (sin_rot, -cos_rot),
                lim_min, lim_max, inverse_permutation)
        glEnd()
        glDepthMask(True)

    def draw_grid(self):
        x,y,z,p = 0,1,2,3
        view = self.get_view()
        if view == p: return
        rotation = math.radians(self.stat.rotation_xy % 90)
        if rotation != 0 and view != z and self.get_show_relative(): return
        permutations = [
                lambda (x, y, z): (z, y, x),  # YZ X
                lambda (x, y, z): (z, x, y),  # ZX Y
                lambda (x, y, z): (x, y, z),  # XY Z
        ]
        inverse_permutations = [
                lambda (z, y, x): (x, y, z),  # YZ X
                lambda (z, x, y): (x, y, z),  # ZX Y
                lambda (x, y, z): (x, y, z),  # XY Z
        ]
        self.draw_grid_permuted(rotation, permutations[view],
                inverse_permutations[view])

    def redraw(self):
        s = self.stat
        s.poll()

        machine_limit_min, machine_limit_max = self.soft_limits()

        glDisable(GL_LIGHTING)
        glMatrixMode(GL_MODELVIEW)
        self.draw_grid()
        if self.get_show_program():
            if self.get_program_alpha():
                glDisable(GL_DEPTH_TEST)
                glEnable(GL_BLEND)
                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

            if self.get_show_rapids():
                glCallList(self.dlist('program_rapids', gen=self.make_main_list))
            glCallList(self.dlist('program_norapids', gen=self.make_main_list))
            glCallList(self.dlist('highlight'))

            if self.get_program_alpha():
                glDisable(GL_BLEND)
                glEnable(GL_DEPTH_TEST)

            if self.get_show_extents():
                self.show_extents()
            self.blank()

        if self.get_show_live_plot() or self.get_show_program():
    
            alist = self.dlist(('axes', self.get_view()), gen=self.draw_axes)
            glPushMatrix()
            if self.get_show_relative() and (s.g5x_offset[0] or s.g5x_offset[1] or s.g5x_offset[2] or
                                             s.g92_offset[0] or s.g92_offset[1] or s.g92_offset[2] or
                                             s.rotation_xy):
                olist = self.dlist('draw_small_origin',
                                        gen=self.draw_small_origin)
                glCallList(olist)
                g5x_offset = self.to_internal_units(s.g5x_offset)[:3]
                g92_offset = self.to_internal_units(s.g92_offset)[:3]


                if self.get_show_offsets() and (g5x_offset[0] or g5x_offset[1] or g5x_offset[2]):
                    glBegin(GL_LINES)
                    glVertex3f(0,0,0)
                    glVertex3f(*g5x_offset)
                    glEnd()

                    i = s.g5x_index
                    if i<7:
                        label = "G5%d" % (i+3)
                    else:
                        label = "G59.%d" % (i-6)
                    glPushMatrix()
                    glScalef(0.2,0.2,0.2)
                    if self.is_lathe:
                        g5xrot=math.atan2(g5x_offset[0], -g5x_offset[2])
                        glRotatef(90, 1, 0, 0)
                        glRotatef(-90, 0, 0, 1)
                    else:
                        g5xrot=math.atan2(g5x_offset[1], g5x_offset[0])
                    glRotatef(math.degrees(g5xrot), 0, 0, 1)
                    glTranslatef(0.5, 0.5, 0)
                    self.hershey.plot_string(label, 0.1)
                    glPopMatrix()

                glTranslatef(*g5x_offset)
                glRotatef(s.rotation_xy, 0, 0, 1)

                
                if  self.get_show_offsets() and (g92_offset[0] or g92_offset[1] or g92_offset[2]):
                    glBegin(GL_LINES)
                    glVertex3f(0,0,0)
                    glVertex3f(*g92_offset)
                    glEnd()

                    glPushMatrix()
                    glScalef(0.2,0.2,0.2)
                    if self.is_lathe:
                        g92rot=math.atan2(g92_offset[0], -g92_offset[2])
                        glRotatef(90, 1, 0, 0)
                        glRotatef(-90, 0, 0, 1)
                    else:
                        g92rot=math.atan2(g92_offset[1], g92_offset[0])
                    glRotatef(math.degrees(g92rot), 0, 0, 1)
                    glTranslatef(0.5, 0.5, 0)
                    self.hershey.plot_string("G92", 0.1)
                    glPopMatrix()

                glTranslatef(*g92_offset)

            if self.is_foam():
                glTranslatef(0, 0, self.get_foam_z())
                glCallList(alist)
                uwalist = self.dlist(('axes_uw', self.get_view()), gen=lambda n: self.draw_axes(n, 'UVW'))
                glTranslatef(0, 0, self.get_foam_w()-self.get_foam_z())
                glCallList(uwalist)
            else:
                glCallList(alist)
            glPopMatrix()

        if self.get_show_limits(): # ==================================================================линии ограничивающие рабочий объём станка
            glLineWidth(1)
            glColor3f(1.0,0.0,0.0)
            glLineStipple(1, 0x1111)
            glEnable(GL_LINE_STIPPLE)
            glBegin(GL_LINES)

            glVertex3f(machine_limit_min[0], machine_limit_min[1], machine_limit_max[2])
            glVertex3f(machine_limit_min[0], machine_limit_min[1], machine_limit_min[2])

            glVertex3f(machine_limit_min[0], machine_limit_min[1], machine_limit_min[2])
            glVertex3f(machine_limit_min[0], machine_limit_max[1], machine_limit_min[2])

            glVertex3f(machine_limit_min[0], machine_limit_max[1], machine_limit_min[2])
            glVertex3f(machine_limit_min[0], machine_limit_max[1], machine_limit_max[2])

            glVertex3f(machine_limit_min[0], machine_limit_max[1], machine_limit_max[2])
            glVertex3f(machine_limit_min[0], machine_limit_min[1], machine_limit_max[2])


            glVertex3f(machine_limit_max[0], machine_limit_min[1], machine_limit_max[2])
            glVertex3f(machine_limit_max[0], machine_limit_min[1], machine_limit_min[2])

            glVertex3f(machine_limit_max[0], machine_limit_min[1], machine_limit_min[2])
            glVertex3f(machine_limit_max[0], machine_limit_max[1], machine_limit_min[2])

            glVertex3f(machine_limit_max[0], machine_limit_max[1], machine_limit_min[2])
            glVertex3f(machine_limit_max[0], machine_limit_max[1], machine_limit_max[2])

            glVertex3f(machine_limit_max[0], machine_limit_max[1], machine_limit_max[2])
            glVertex3f(machine_limit_max[0], machine_limit_min[1], machine_limit_max[2])


            glVertex3f(machine_limit_min[0], machine_limit_min[1], machine_limit_min[2])
            glVertex3f(machine_limit_max[0], machine_limit_min[1], machine_limit_min[2])

            glVertex3f(machine_limit_min[0], machine_limit_max[1], machine_limit_min[2])
            glVertex3f(machine_limit_max[0], machine_limit_max[1], machine_limit_min[2])

            glVertex3f(machine_limit_min[0], machine_limit_max[1], machine_limit_max[2])
            glVertex3f(machine_limit_max[0], machine_limit_max[1], machine_limit_max[2])

            glVertex3f(machine_limit_min[0], machine_limit_min[1], machine_limit_max[2])
            glVertex3f(machine_limit_max[0], machine_limit_min[1], machine_limit_max[2])

            glEnd()
            glDisable(GL_LINE_STIPPLE)
            glLineStipple(2, 0x5555)

        if self.get_show_live_plot():
            glDepthFunc(GL_LEQUAL)
            glLineWidth(3)
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
            glEnable(GL_BLEND)
            glPushMatrix()
            lu = 1/((s.linear_units or 1)*25.4)
            glScalef(lu, lu, lu)
            glMatrixMode(GL_PROJECTION)
            glPushMatrix()
            glTranslatef(0,0,.003)

            self.lp.call()

            glPopMatrix()
            glMatrixMode(GL_MODELVIEW)
            glPopMatrix()
            glDisable(GL_BLEND)
            glLineWidth(1)
            glDepthFunc(GL_LESS)

        if self.get_show_tool():#=========================================показать инструмент
            pos = self.lp.last(self.get_show_live_plot())
            if pos is None: pos = [0] * 6
            rx, ry, rz = pos[3:6]
            pos = self.to_internal_units(pos[:3])
            if self.is_foam():
                glEnable(GL_COLOR_MATERIAL)
                glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE)
                glPushMatrix()
                glTranslatef(pos[0], pos[1], self.get_foam_z())
                glRotatef(180, 1, 0, 0)
                cone = self.dlist("cone", gen=self.make_cone)
                glColor3f(*self.colors['cone_xy'])
                glCallList(cone)
                glPopMatrix()
                u = self.to_internal_linear_unit(rx)
                v = self.to_internal_linear_unit(ry)
                glPushMatrix()
                glTranslatef(u, v, self.get_foam_w())
                glColor3f(*self.colors['cone_uv'])
                glCallList(cone)
                glPopMatrix()
            else:
                glPushMatrix()
                glTranslatef(*pos)
                sign = 1
                for ch in self.get_geometry():
                    if ch == '-':
                        sign = -1
                    elif ch == 'A':
                        glRotatef(rx*sign, 1, 0, 0)
                        sign = 1
                    elif ch == 'B':
                        glRotatef(ry*sign, 0, 1, 0)
                        sign = 1
                    elif ch == 'C':
                        glRotatef(rz*sign, 0, 0, 1)
                        sign = 1
                glEnable(GL_BLEND)
                glEnable(GL_CULL_FACE)
                glBlendFunc(GL_ONE, GL_CONSTANT_ALPHA)

                current_tool = self.get_current_tool()
                if current_tool is None or current_tool.diameter == 0:
                    if self.canon:
                        g = self.canon
                        x,y,z = 0,1,2
                        cone_scale = max(g.max_extents[x] - g.min_extents[x],
                                       g.max_extents[y] - g.min_extents[y],
                                       g.max_extents[z] - g.min_extents[z],
                                       2 ) * .5
                    else:
                        cone_scale = 1
                    if self.is_lathe():
                        glRotatef(90, 0, 1, 0)
                    cone = self.dlist("cone", gen=self.make_cone)
                    glScalef(cone_scale, cone_scale, cone_scale)
                    glColor3f(*self.colors['cone'])
                    glCallList(cone)
                else:
                    if current_tool != self.cached_tool:
                        self.cache_tool(current_tool)
                    glColor3f(*self.colors['cone'])
                    glCallList(self.dlist('tool'))
                glPopMatrix()

        glMatrixMode(GL_PROJECTION)
        glPushMatrix()
        glLoadIdentity()
        ypos = self.winfo_height()
        glOrtho(0.0, self.winfo_width(), 0.0, ypos, -1.0, 1.0)
        glMatrixMode(GL_MODELVIEW)
        glPushMatrix()
        glLoadIdentity()

        limit, homed, posstrs, droposstrs = self.posstrs()

        charwidth, linespace, base = self.get_font_info()

        maxlen = max([len(p) for p in posstrs])
        pixel_width = charwidth * max(len(p) for p in posstrs)

        glDepthFunc(GL_ALWAYS)
        glDepthMask(GL_FALSE)
        glEnable(GL_BLEND)
        glBlendFunc(GL_ONE, GL_CONSTANT_ALPHA)
        glColor3f(*self.colors['overlay_background'])
        glBlendColor(0,0,0,1-self.colors['overlay_alpha'])
        glBegin(GL_QUADS)
        glVertex3f(0, ypos, 1)
        glVertex3f(0, ypos - 8 - linespace*len(posstrs), 1)
        glVertex3f(pixel_width+42, ypos - 8 - linespace*len(posstrs), 1)
        glVertex3f(pixel_width+42, ypos, 1)
        glEnd()
        glDisable(GL_BLEND)

        maxlen = 0
        ypos -= linespace+5
        i=0
        glColor3f(*self.colors['overlay_foreground'])
        if not self.get_show_offsets():
            for string in posstrs:
                maxlen = max(maxlen, len(string))
                glRasterPos2i(5, ypos)
                for char in string:
                    glCallList(base + ord(char))
                if i < len(homed) and homed[i]:
                    glRasterPos2i(pixel_width + 8, ypos)
                    glBitmap(13, 16, 0, 3, 17, 0, homeicon)
                if i < len(homed) and limit[i]:
                    glBitmap(13, 16, 0, 1, 17, 0, limiticon)
                ypos -= linespace
                i = i + 1
        if self.get_show_offsets():
            if self.is_lathe():
                homed.insert(0,homed[0])
            i=0
            for string in droposstrs:
                maxlen = max(maxlen, len(string))
                glRasterPos2i(5, ypos)
                for char in string:
                    glCallList(base + ord(char))
                if i < len(homed) and homed[i]:
                    glRasterPos2i(charwidth *3, ypos)
                    glBitmap(13, 16, 0, 3, 17, 0, homeicon)
                ypos -= linespace
                i = i + 1

        glDepthFunc(GL_LESS)
        glDepthMask(GL_TRUE)

        glPopMatrix()
        glMatrixMode(GL_PROJECTION)
        glPopMatrix()
        glMatrixMode(GL_MODELVIEW)

    def cache_tool(self, current_tool):
        self.cached_tool = current_tool
        glNewList(self.dlist('tool'), GL_COMPILE)
        if self.is_lathe() and current_tool and current_tool.orientation != 0:
            glBlendColor(0,0,0,self.colors['lathetool_alpha'])
            self.lathetool(current_tool)
        else:
            glBlendColor(0,0,0,self.colors['tool_alpha'])
            if self.is_lathe():
                glRotatef(90, 0, 1, 0)
            else:
                dia = current_tool.diameter
                r = self.to_internal_linear_unit(dia) / 2.
                q = gluNewQuadric()
                glEnable(GL_LIGHTING)
                gluCylinder(q, r, r, 8*r, 32, 1)
                glPushMatrix()
                glRotatef(180, 1, 0, 0)
                gluDisk(q, 0, r, 32, 1)
                glPopMatrix()
                glTranslatef(0,0,8*r)
                gluDisk(q, 0, r, 32, 1)
                glDisable(GL_LIGHTING)
                gluDeleteQuadric(q)
        glEndList()

    def posstrs(self):
        s = self.stat
        limit = []
        for i,l in enumerate(s.limit):
            if s.axis_mask & (1<<i):
                limit.append(l)

        homed = []
        for i,h in enumerate(s.homed):
            if s.axis_mask & (1<<i):
                homed.append(h)

        if self.is_lathe() and not s.axis_mask & 2:
            homed.insert(1, 0)
            limit.insert(1, 0)

        if not self.get_joints_mode():
            if self.get_show_commanded():
                positions = s.position
            else:
                positions = s.actual_position

            if self.get_show_relative():
                positions = [(i-j) for i, j in zip(positions, s.tool_offset)]
                positions = [(i-j) for i, j in zip(positions, s.g5x_offset)]

                t = -s.rotation_xy
                t = math.radians(t)
                x = positions[0]
                y = positions[1]
                positions[0] = x * math.cos(t) - y * math.sin(t)
                positions[1] = x * math.sin(t) + y * math.cos(t)
                positions = [(i-j) for i, j in zip(positions, s.g92_offset)]

            if self.get_a_axis_wrapped():
                positions[3] = math.fmod(positions[3], 360.0)
                if positions[3] < 0: positions[3] += 360.0

            if self.get_b_axis_wrapped():
                positions[4] = math.fmod(positions[4], 360.0)
                if positions[4] < 0: positions[4] += 360.0

            if self.get_c_axis_wrapped():
                positions[5] = math.fmod(positions[5], 360.0)
                if positions[5] < 0: positions[5] += 360.0

            positions = self.to_internal_units(positions)
            axisdtg = self.to_internal_units(s.dtg)
            g5x_offset = self.to_internal_units(s.g5x_offset)
            g92_offset = self.to_internal_units(s.g92_offset)
            tlo_offset = self.to_internal_units(s.tool_offset)

            if self.get_show_metric():
                positions = self.from_internal_units(positions, 1)
                axisdtg = self.from_internal_units(axisdtg, 1)
                g5x_offset = self.from_internal_units(g5x_offset, 1)
                g92_offset = self.from_internal_units(g92_offset, 1)
                tlo_offset = self.from_internal_units(tlo_offset, 1)
                format = "% 6s:% 9.3f"
                if self.get_show_distance_to_go():
                    droformat = " " + format + "  DTG %1s:% 9.3f"
                else:
                    droformat = " " + format
                offsetformat = "% 5s %1s:% 9.3f  G92 %1s:% 9.3f"
                rotformat = "% 5s %1s:% 9.3f"
            else:
                format = "% 6s:% 9.4f"
                if self.get_show_distance_to_go():
                    droformat = " " + format + "  DTG %1s:% 9.4f"
                else:
                    droformat = " " + format
                offsetformat = "% 5s %1s:% 9.4f  G92 %1s:% 9.4f"
                rotformat = "% 5s %1s:% 9.4f"
            diaformat = " " + format

            posstrs = []
            droposstrs = []
            for i in range(9):
                a = "XYZABCUVW"[i]
                if s.axis_mask & (1<<i):
                    posstrs.append(format % (a, positions[i]))
                    if self.get_show_distance_to_go():
                        droposstrs.append(droformat % (a, positions[i], a, axisdtg[i]))
                    else:
                        droposstrs.append(droformat % (a, positions[i]))
            droposstrs.append("")

            for i in range(9):
                index = s.g5x_index
                if index<7:
                    label = "G5%d" % (index+3)
                else:
                    label = "G59.%d" % (index-6)

                a = "XYZABCUVW"[i]
                if s.axis_mask & (1<<i):
                    droposstrs.append(offsetformat % (label, a, g5x_offset[i], a, g92_offset[i]))
            droposstrs.append(rotformat % (label, 'R', s.rotation_xy))

            droposstrs.append("")
            for i in range(9):
                a = "XYZABCUVW"[i]
                if s.axis_mask & (1<<i):
                    droposstrs.append(rotformat % ("TLO", a, tlo_offset[i]))


            if self.is_lathe():
                posstrs[0] = format % ("Rad", positions[0])
                posstrs.insert(1, format % ("Dia", positions[0]*2.0))
                if self.get_show_distance_to_go():
                    droposstrs[0] = droformat % ("Rad", positions[0], "R", axisdtg[0])
                    droposstrs.insert(1, droformat % ("Dia", positions[0]*2.0, "D", axisdtg[0]*2.0))
                else:
                    droposstrs[0] = droformat % ("Rad", positions[0])
                    droposstrs.insert(1, diaformat % ("Dia", positions[0]*2.0))

            if self.get_show_machine_speed():
                spd = self.to_internal_linear_unit(s.current_vel)
                if self.get_show_metric():
                    spd = spd * 25.4 * 60
                else:
                    spd = spd * 60
                posstrs.append(format % ("Vel", spd))
                pos=0
                for i in range(9):
                    if s.axis_mask & (1<<i): pos +=1
                if self.is_lathe():
                    pos +=1
                droposstrs.insert(pos, " " + format % ("Vel", spd))

            if self.get_show_distance_to_go():
                dtg = self.to_internal_linear_unit(s.distance_to_go)
                if self.get_show_metric():
                    dtg *= 25.4
                posstrs.append(format % ("DTG", dtg))
        else:
            # N.B. no conversion here because joint positions are unitless
            posstrs = ["  %s:% 9.4f" % i for i in
                zip(range(self.get_num_joints()), s.joint_actual_position)]
            droposstrs = posstrs
        return limit, homed, posstrs, droposstrs


    def draw_small_origin(self, n):
        glNewList(n, GL_COMPILE)
        r = 2.0/25.4
        glColor3f(*self.colors['small_origin'])

        glBegin(GL_LINE_STRIP)
        for i in range(37):
            theta = (i*10)*math.pi/180.0
            glVertex3f(r*math.cos(theta),r*math.sin(theta),0.0)
        glEnd()
        glBegin(GL_LINE_STRIP)
        for i in range(37):
            theta = (i*10)*math.pi/180.0
            glVertex3f(0.0, r*math.cos(theta), r*math.sin(theta))
        glEnd()
        glBegin(GL_LINE_STRIP)
        for i in range(37):
            theta = (i*10)*math.pi/180.0
            glVertex3f(r*math.cos(theta),0.0, r*math.sin(theta))
        glEnd()

        glBegin(GL_LINES)
        glVertex3f(-r, -r, 0.0)
        glVertex3f( r,  r, 0.0)
        glVertex3f(-r,  r, 0.0)
        glVertex3f( r, -r, 0.0)

        glVertex3f(-r, 0.0, -r)
        glVertex3f( r, 0.0,  r)
        glVertex3f(-r, 0.0,  r)
        glVertex3f( r, 0.0, -r)

        glVertex3f(0.0, -r, -r)
        glVertex3f(0.0,  r,  r)
        glVertex3f(0.0, -r,  r)
        glVertex3f(0.0,  r, -r)
        glEnd()
        glEndList()

    def draw_axes(self, n, letters="XYZ"):
        glNewList(n, GL_COMPILE)
        x,y,z,p = 0,1,2,3
        s = self.stat
        view = self.get_view()


        glColor3f(*self.colors['axis_x'])
        glBegin(GL_LINES)
        glVertex3f(1.0,0.0,0.0)
        glVertex3f(0.0,0.0,0.0)
        glEnd()

        if view != x:
            glPushMatrix()
            if self.is_lathe():
                glTranslatef(1.3, -0.1, 0)
                glTranslatef(0, 0, -0.1)
                glRotatef(-90, 0, 1, 0)
                glRotatef(90, 1, 0, 0)
                glTranslatef(0.1, 0, 0)
            else:
                glTranslatef(1.2, -0.1, 0)
                if view == y:
                    glTranslatef(0, 0, -0.1)
                    glRotatef(90, 1, 0, 0)
            glScalef(0.2, 0.2, 0.2)
            self.hershey.plot_string(letters[0], 0.5)
            glPopMatrix()

        glColor3f(*self.colors['axis_y'])
        glBegin(GL_LINES)
        glVertex3f(0.0,0.0,0.0)
        glVertex3f(0.0,1.0,0.0)
        glEnd()

        if view != y:
            glPushMatrix()
            glTranslatef(0, 1.2, 0)
            if view == x:
                glTranslatef(0, 0, -0.1)
                glRotatef(90, 0, 1, 0)
                glRotatef(90, 0, 0, 1)
            glScalef(0.2, 0.2, 0.2)
            self.hershey.plot_string(letters[1], 0.5)
            glPopMatrix()

        glColor3f(*self.colors['axis_z'])
        glBegin(GL_LINES)
        glVertex3f(0.0,0.0,0.0)
        glVertex3f(0.0,0.0,1.0)
        glEnd()

        if view != z:
            glPushMatrix()
            glTranslatef(0, 0, 1.2)
            if self.is_lathe():
                glRotatef(-90, 0, 1, 0)
            if view == x:
                glRotatef(90, 0, 1, 0)
                glRotatef(90, 0, 0, 1)
            elif view == y or view == p:
                glRotatef(90, 1, 0, 0)
            if self.is_lathe():
                glTranslatef(0, -.1, 0)
            glScalef(0.2, 0.2, 0.2)
            self.hershey.plot_string(letters[2], 0.5)
            glPopMatrix()

        glEndList()

    def make_cone(self, n):
        q = gluNewQuadric()
        glNewList(n, GL_COMPILE)
        glEnable(GL_LIGHTING)
        gluCylinder(q, 0, .1, .25, 32, 1)
        glPushMatrix()
        glTranslatef(0,0,.25)
        gluDisk(q, 0, .1, 32, 1)
        glPopMatrix()
        glDisable(GL_LIGHTING)
        glEndList()
        gluDeleteQuadric(q)


    lathe_shapes = [
        None,                           # 0
        (1,-1), (1,1), (-1,1), (-1,-1), # 1..4
        (0,-1), (1,0), (0,1), (-1,0),   # 5..8
        (0,0)                           # 9
    ]
    def lathetool(self, current_tool):
        glDepthFunc(GL_ALWAYS)
        diameter, frontangle, backangle, orientation = current_tool[-4:]
        w = 3/8.

        radius = self.to_internal_linear_unit(diameter) / 2.
        glColor3f(*self.colors['lathetool'])
        glBegin(GL_LINES)
        glVertex3f(-radius/2.0,0.0,0.0)
        glVertex3f(radius/2.0,0.0,0.0)
        glVertex3f(0.0,0.0,-radius/2.0)
        glVertex3f(0.0,0.0,radius/2.0)
        glEnd()

        glNormal3f(0,1,0)

        if orientation == 9:
            glBegin(GL_TRIANGLE_FAN)
            for i in range(37):
                t = i * math.pi / 18
                glVertex3f(radius * math.cos(t), 0.0, radius * math.sin(t))
            glEnd()
        else:
            dx, dy = self.lathe_shapes[orientation]

            min_angle = min(backangle, frontangle) * math.pi / 180
            max_angle = max(backangle, frontangle) * math.pi / 180

            sinmax = math.sin(max_angle)
            cosmax = math.cos(max_angle)
            tanmax = math.cos(max_angle)
            sinmin = math.sin(min_angle)
            cosmin = math.cos(min_angle)
            tanmin = math.cos(min_angle)

            circleminangle = - math.pi/2 + min_angle
            circlemaxangle = - 3*math.pi/2 + max_angle
            d0 = 0

            x1 = (w - d0)

            sz = max(w, 3*radius)

            glBegin(GL_TRIANGLE_FAN)
            glVertex3f(
                radius * dx + radius * math.sin(circleminangle) + sz * sinmin,
                0,
                radius * dy + radius * math.cos(circleminangle) + sz * cosmin)
            for i in range(37):
                #t = circleminangle + i * (circlemaxangle - circleminangle)/36.
                t = circleminangle + i * (circlemaxangle - circleminangle)/36.
                glVertex3f(radius*dx + radius * math.sin(t), 0.0, radius*dy + radius * math.cos(t))

            glVertex3f(
                radius * dx + radius * math.sin(circlemaxangle) + sz * sinmax,
                0,
                radius * dy + radius * math.cos(circlemaxangle) + sz * cosmax)

            glEnd()
        glDepthFunc(GL_LESS)

    def extents_info(self):
        if self.canon:
            mid = [(a+b)/2 for a, b in zip(self.canon.max_extents, self.canon.min_extents)]
            size = [(a-b) for a, b in zip(self.canon.max_extents, self.canon.min_extents)]
        else:
            mid = [0, 0, 0]
            size = [3, 3, 3]
        return mid, size

    def make_selection_list(self, unused=None):
        select_rapids = self.dlist('select_rapids')
        select_program = self.dlist('select_norapids')
        glNewList(select_rapids, GL_COMPILE)
        if self.canon: self.canon.draw(1, False)
        glEndList()
        glNewList(select_program, GL_COMPILE)
        if self.canon: self.canon.draw(1, True)
        glEndList()

    def make_main_list(self, unused=None):
        program = self.dlist('program_norapids')
        rapids = self.dlist('program_rapids')
        glNewList(program, GL_COMPILE)
        if self.canon: self.canon.draw(0, True)
        glEndList()

        glNewList(rapids, GL_COMPILE)
        if self.canon: self.canon.draw(0, False)
        glEndList()

    def load_preview(self, f, canon, unitcode, initcode, interpname=""):
        self.set_canon(canon)
        result, seq = gcode.parse(f, canon, unitcode, initcode, interpname)

        if result <= gcode.MIN_ERROR:
            self.canon.progress.nextphase(1)
            canon.calc_extents()
            self.stale_dlist('program_rapids')
            self.stale_dlist('program_norapids')
            self.stale_dlist('select_rapids')
            self.stale_dlist('select_norapids')
            

        return result, seq

    def from_internal_units(self, pos, unit=None):
        if unit is None:
            unit = self.stat.linear_units
        lu = (unit or 1) * 25.4

        lus = [lu, lu, lu, 1, 1, 1, lu, lu, lu]
        return [a*b for a, b in zip(pos, lus)]


# vim:ts=8:sts=4:sw=4:et:
pkasy
Мастер
Сообщения: 1139
Зарегистрирован: 15 мар 2013, 09:39
Репутация: 45
Откуда: Владивосток

Re: G71 , ... (remap)

Сообщение pkasy »

проверь код remap.py
G7 G8 путаешь
поставлю пока старый вариант
pkasy
Мастер
Сообщения: 1139
Зарегистрирован: 15 мар 2013, 09:39
Репутация: 45
Откуда: Владивосток

Re: G71 , ... (remap)

Сообщение pkasy »

и возврат на иходную у тебя происходит со скоростью финишной резки. а должен по Г0
а то устаешь ждать, пока резец по воздуху едет с пониженной подачей.
nkp
Мастер
Сообщения: 8340
Зарегистрирован: 28 ноя 2011, 00:25
Репутация: 1589
Контактная информация:

Re: G71 , ... (remap)

Сообщение nkp »

pkasy писал(а):проверь код remap.pyG7 G8 путаешь
спасибо ,что натолкнул на столь очевидную (наверно для многих,но не для меня :) ) вещь...
но вот (как лирическое отступление):
какие преимущества в режиме G7 ??
скрипт изначально задумывался в "связке" с кад-кам программами
рисуем нашу деталь в любой чертилке:
(для просмотра содержимого нажмите на ссылку)
Выделение_007.png
Выделение_007.png (10.31 КБ) 7455 просмотров
(заштриховано то ,что нужно проточить)
оставляем контур обработки(а для таких примитивов - сразу его непосредственно
и рисуем))
(для просмотра содержимого нажмите на ссылку)
Выделение_006.png
Выделение_006.png (6.5 КБ) 7455 просмотров
получаем нашу обработку в емс (с кодом G8)
Выделение_008.png (7455 просмотров) <a class='original' href='./download/file.php?id=97203&sid=9578190e895ab28330289bc83dd393a5&mode=view' target=_blank>Загрузить оригинал (64.04 КБ)</a>
а с G7 совсем другая деталь
вот что я имел в виду ,когда писал в лс ,что скрипт "внутри" работает с G8
Вложения
Выделение_005.png (7455 просмотров) <a class='original' href='./download/file.php?id=97200&sid=9578190e895ab28330289bc83dd393a5&mode=view' target=_blank>Загрузить оригинал (64.02 КБ)</a>
Аватара пользователя
aegis
Мастер
Сообщения: 3171
Зарегистрирован: 22 мар 2012, 06:59
Репутация: 1810
Настоящее имя: Михайло
Откуда: Україна, Конотоп=>Запоріжжя=>Харьків

Re: G71 , ... (remap)

Сообщение aegis »

nkp, естественно будет разная деталь ибо радиус и диаметр. можно множитель ввести, можно ограничить так как есть. я бы рекомендовал диаметр использовать - то что меряем (микрометром, штангелем), то и точим чтобы в голове не надо было делить на 2, особенно если размер с небольшими допусками вверх или вниз
нікому нічого не нав'язую.
Ответить

Вернуться в «LinuxCNC»