Máquina de perfuração para impressora 3D e conversor de cartão de perfuração PCAD para G-Code

Olá, querido habrozhitel.

Hoje, quero compartilhar um pouco de base projetada para converter os cartões de perfuração PCAD-s em código G. Flexível, simples e de código aberto. Verdade, desculpe, ospadi, no Qt. É claro que escrever nele é bom, mas implantar e coletar códigos de outras pessoas ...

Parte I A mecânica


Há algum tempo, adiei meu projeto na cabeça por um prius, e por isso:
Enquanto esperava chips, enquanto experimentava circuitos, percebi claramente que queria fazer placas de circuito impresso em casa. Sim, sim, existe experiência na tecnologia de passar a laser e até mesmo desenhar com verniz, mas eu queria algo real. Decidiu-se usar um filme fotorresistente e uma lâmpada UV para unhas. Naturalmente, surgiu o problema de fazer furos e galvanizar. E a partir daí, os furos precisam ser metalizados antes das faixas serem gravadas no quadro. Caso contrário, aplicar uma corrente a cada furo é uma história completa.

Acontece que a perfuração manual desaparece, porque simplesmente não há nada para navegar (não vamos oferecer papel com cartões de visita).

Decidiu-se pendurar um eixo em uma impressora 3D existente em vez de uma cabeça direta e viver assim. E aqui há soluções que eu gostaria de compartilhar hoje.

Cabeça intercambiável para RepRap


Para transformar facilmente a impressora em uma broca e vice-versa, foi decidido tornar a cabeça destacável. O controle deslizante preso aos cintos é separado e todo o resto é removível. Dado que isso não é uma boa notícia, que dificuldade, não faz sentido elaborar um artigo separado. Aqui estão apenas fotos e links para modelos STL , se alguém quiser fazer exatamente o mesmo. O arquivo morto também contém fontes SLDPRT, se houver algo para corrigir. Ele oscila lentamente - graças ao ADSL da Beltelecom, mas deve demorar muito.

O resultado é assim:









Cabeça do eixo


Tudo é simples aqui - depois de longas tentativas de criar meu próprio eixo, decidi comprar um no AliExpress e pendurá-lo no suporte. Nenhuma foto durante o processo.

Gerador de código G


E aqui começa a diversão.

Com o meu globalismo inerente, examinei as soluções disponíveis e percebi que cada uma delas não apenas criava um monte de problemas ao implantar a tecnologia em casa, mas também as fornecia regularmente e metodicamente, até a aposentadoria. Do que você não gostou? Inflexibilidade. Todos eles são mais para máquinas, com características predefinidas de modelos, etc. Sim, o assunto não é complicado. Mas eu realmente não queria encontrar um dia uma situação em que você precise modificar levemente o algoritmo e não possa fazê-lo. Por exemplo, eu não vi uma ferramenta que possa girar furos ao redor de um eixo. Mas depois da metalização, você não pode colocar uma placa 1: 1. Mas esses são pensamentos para o futuro. Ainda não preciso disso. Mas já é possível. Em geral, eu queria algo simples, leve, flexível e ... eficiente. Eu decidi polvilhar por conta própria.

As bibliotecas Qt 5.11 foram usadas como base. O aplicativo é escrito no estilo do console. A arquitetura do aplicativo é feita no estilo linux.

O aplicativo recebe um arquivo DRL retirado do PCAD ao criar o kit Geber. (Talvez você precise modificar o analisador se quiser alimentar algo do AltiumDesigner. Mas, pessoalmente, eu decidi tirar esse monstro do Altium do pecado. Pois agora ele está em sonhos terríveis e não me deixa esquecer o meu próprio nome).

Um arquivo XML é especificado como um parâmetro. O formato deste arquivo será descrito na segunda metade do artigo. Este arquivo, de fato, determina o mecanismo para gerar o Código G (e de fato qualquer arquivo de texto) para transferi-lo (Código G) para uma impressora 3D.

O mecanismo da aplicação


  1. O formato DRL (que é M48 ou Excellon ) é lido e reconhecido. O resultado são ferramentas que contêm uma lista de furos que são perfurados com essas ferramentas.
  2. Com os dados obtidos no item 1, vamos para XML, procuramos o nó de script lá e simplesmente executamos tudo o que está escrito lá. Existem cinco operadores, mas não precisamos de mais.
  3. Durante a execução da etapa 2, ocorreram instruções de impressão. O resultado é impresso no fluxo de saída.

Parte Dois Formato de arquivo XML


Para tornar o programa o mais flexível possível, foi utilizada a biblioteca ScriptEngine. Ele mesmo um pouco impressionado com o que agora pode realmente ser feito com a configuração. O postulado principal é o seguinte: existem muitos parâmetros calculados que são tratados da maneira mais transparente possível: o texto é passado para o módulo ScriptEngine e o resultado é usado. A mesma situação ocorre se a combinação $ {blá blá blá} for encontrada no modelo de código G. Além disso, tudo dentro dos colchetes será passado para o cálculo, e todo o modelo será substituído pelo resultado.

Código fonte

Arquivo de exemplo para minha impressora
<xml> <variables> <var name="ZChangeToolValue" value="30"/> <var name="ZTravelValue" value="10"/> <var name="ZDrillValue" value="0"/> </variables> <functions> <!-- predefined function with single parameter: a - source (requested) diameter returns - suggested tool diameter for give requested after halvanic if function nod defined, it assumed return=a --> <plate_increase_dia f="a+0.2"/> </functions> <tools> <!-- "tool" node defines a real drill tool for make a hole Depends on your technical process you can set up different tools for plated or not holes or join same holes in single tool. Required parameters for tool are: 1. range_min,range_max - diameters range to assign holes for this tool You can joun different diameters (f.ex. 0.31-0.4) to single tool 2. plated="yes|no|both" - defines plated property to Other parameters are optional and can be used later in G-Code patterns. For example, you can define tool position or toolbox coords for the tool. --> <tool description="0,3mm" range_min="0" range_max="0.3" plated="both" position="0" /> <tool description="0,4mm" range_min="0.3" range_max="0.4" plated="both" position="1" /> <tool description="0,5mm" range_min="0.4" range_max="0.5" plated="both" position="2" /> <tool description="0,6mm" range_min="0.5" range_max="0.6" plated="both" position="3" /> <tool description="0,7mm" range_min="0.6" range_max="0.7" plated="both" position="4" /> <tool description="0,8mm" range_min="0.7" range_max="0.8" plated="both" position="5" /> <tool description="0,9mm" range_min="0.8" range_max="0.9" plated="both" position="6" /> <tool description="1,0mm" range_min="0.9" range_max="1.0" plated="both" position="7" /> <tool description="1,1mm" range_min="1.0" range_max="1.1" plated="both" position="8" /> <tool description="1,2mm" range_min="1.1" range_max="5" plated="both" position="9" /> </tools> <patterns> <!-- in any pattern you can use any variable from context where it's printing Example (used inside 'tool' loop type): Mnnn Please, change tool to ${description} ; message to lcd Mnnn ; pause Note : here ${description} is optional tag defined in <tool> node Use this example outsite the tool loop will cause calculation error. --> <pattern name="start"> G90 ;${var hcnt=holesCount;var tcnt=toolsCount;"Hello"} M117 Homing G28 XY M117 Move Z to travel G0 X${minX} Y${minY} M76 G92 Z${ZTravelValue} </pattern> <pattern name="finish"> G0 Z${ZChangeToolValue} M104 S0 ; disable spindle G0 X0 Y220 M117 Drill finished M300 S600 P1 ; Stats: ; Holes : ${holesCount} ; Tools : ${toolsCount} </pattern> <pattern name="set_tool"> ; Tools rest: ${tcnt--} G0 Z${ZChangeToolValue} G0 X100 Y0 M104 S0 ; disable spindle M117 Change tool to ${description} M300 S600 P1 M76 ; pause job M117 Drilling M104 S100 ; enable spindle G28 X </pattern> <pattern name="go_drill"> ; Holes rest: ${hcnt--} ; Percent rest: ${var percent=Math.round(hcnt*100/holesCount); percent}% M73 P${100-percent} G0 Z${ZTravelValue} G0 X${Math.round(x*100)/100} Y${Math.round(y*100)/100} G0 Z${ZDrillValue} G0 Z${ZTravelValue} </pattern> </patterns> <script> <!-- "assign tools". No parameters Just assign all tools declared in DRL-file to tools described in <tools> node. For each DRL-defined tool will be selected FIRST compatible tool from <tools> node. Ie if range 0.3..0.8 will be defined early, <tool> node for diameter 0.4..0.5 will never be assigned. Except 'plated' property will be different. --> <command verb="assign tools" /> <!-- "assign tools". No parameters Join all DRL-file tools, assigned to same tool here to one tool (also holes) Just avoid multiply changing physical tool to same --> <command verb="join tools" /> <!-- "offset". Offset ALL holes by defined values xoffs, yoffs - values to offset. Before offset will be calculated ie here you can use global variables. --> <command verb="offset" xoffs="-minX+10" yoffs="-minY+10"/> <!-- loop for each DRL-tool (assigned and joined before). Context inside will be filled also with tool's properties and node's parameters --> <command verb="print" pattern="start"/> <loop type="tools"> <command verb="print" pattern="set_tool"/> <command verb="print context" line_begin=";"/> <!-- loop for each hole inside the tool. Context inside will be filled also with hole's properties(x&y) and node's parameters --> <loop type="toolholes"> <command verb="print" pattern="go_drill"/> <!-- "print context". Anwhere in script you can use this verb. It inserts all context variables available. Usefull for debug but completely useless for normal work --> <command verb="print context" line_begin=";"/> </loop> </loop> <command verb="print" pattern="finish"/> </script> </xml> 



E a versão do mesmo arquivo após testes práticos
 <xml> <variables> <var name="ZChangeToolValue" value="10"/> <var name="ZTravelValue" value="2"/> <var name="ZDrillValue" value="-3"/> <var name="FeedHorizontal" value="24000"/> <var name="FeedDown" value="100"/> <var name="FeedFree" value="2000"/> <var name="StartOffsX" value="20"/> <var name="StartOffsY" value="20"/> <var name="ZZeroPosition" value="0.1"/> <var name="first" value="0"/> </variables> <functions> <!-- predefined function with single parameter: a - source (requested) diameter returns - suggested tool diameter for give requested after halvanic if function nod defined, it assumed return=a --> <plate_increase_dia f="a+0.3"/> </functions> <tools> <!-- "tool" node defines a real drill tool for make a hole Depends on your technical process you can set up different tools for plated or not holes or join same holes in single tool. Required parameters for tool are: 1. range_min,range_max - diameters range to assign holes for this tool You can joun different diameters (f.ex. 0.31-0.4) to single tool 2. plated="yes|no|both" - defines plated property to Other parameters are optional and can be used later in G-Code patterns. For example, you can define tool position or toolbox coords for the tool. --> <tool description="0,3mm" range_min="0" range_max="0.3" plated="both" position="0" /> <tool description="0,4mm" range_min="0.3" range_max="0.4" plated="both" position="1" /> <tool description="0,5mm" range_min="0.4" range_max="0.5" plated="both" position="2" /> <tool description="0,6mm" range_min="0.5" range_max="0.6" plated="both" position="3" /> <tool description="0,7mm" range_min="0.6" range_max="0.7" plated="both" position="4" /> <tool description="0,8mm" range_min="0.7" range_max="0.8" plated="both" position="5" /> <tool description="0,9mm" range_min="0.8" range_max="0.9" plated="both" position="6" /> <tool description="1,0mm" range_min="0.9" range_max="1.0" plated="both" position="7" /> <tool description="1,1mm" range_min="1.0" range_max="1.1" plated="both" position="8" /> <tool description="1,2mm" range_min="1.1" range_max="5" plated="both" position="9" /> </tools> <patterns> <!-- in any pattern you can use any variable from context where it's printing Example (used inside 'tool' loop type): Mnnn Please, change tool to ${description} ; message to lcd Mnnn ; pause Note : here ${description} is optional tag defined in <tool> node Use this example outsite the tool loop will cause calculation error. --> <pattern name="start1"> ; Start </pattern> <pattern name="set_tool1"> ; Set tool ${description} </pattern> <pattern name="finish1"> ; Finish </pattern> <pattern name="go_drill1"> ; Drill X${Math.round(x*100)/100} Y${Math.round(y*100)/100} </pattern> <pattern name="start"> ;${var hcnt=holesCount;var tcnt=toolsCount;"Hello"} M117 Homing G28 G0 Z0 F${FeedFree} G92 Z1.6 </pattern> <pattern name="finish"> G0 Z${ZChangeToolValue} F${FeedFree} M400 M5 ; disable spindle G0 X0 Y220 F${FeedHorizontal} M117 Drill finished M300 S600 P100 ; Stats: ; Holes : ${holesCount} ; Tools : ${toolsCount} </pattern> <pattern name="set_tool"> ; Tools rest: ${tcnt--} G0 Z${ZChangeToolValue} F${FeedFree} M400 G0 X100 Y0 F${FeedHorizontal} M117 Stopping spindle M5 ; disable spindle M117 Change tool to ${description} M300 S600 P100 M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause M25 M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause G28 XY G0 X${StartOffsX-1} Y${StartOffsX-1} Z${ZTravelValue} F${FeedHorizontal} G0 Z${ZZeroPosition} F${FeedFree} M117 Check zero-hole M300 S600 P100 M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause M25 M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause M400 ; This strange line is just crutch to prevent Marlin from read-n-exec other commands begore do pause G92 Z${ZZeroPosition} F${FeedDown} M117 Starting spindle M3 ; enable spindle G0 Z${ZDrillValue} F${FeedDown/3} G0 Z${ZTravelValue} F${FeedFree} M117 Drilling M117 Starting spindle M3 ; enable spindle </pattern> <pattern name="go_drill"> ; Holes rest: ${hcnt--} ; Percent rest: ${var percent=Math.round(hcnt*100/holesCount); percent}% M73 P${100-percent} M117 Drilling X${Math.round(x*100)/100} Y${Math.round(y*100)/100} Z${ZTravelValue} G0 Z${ZTravelValue} F${FeedFree} G0 X${(Math.round(x*100)/100)-2} Y${(Math.round(y*100)/100)-2} F${FeedHorizontal} G0 X${Math.round(x*100)/100} Y${Math.round(y*100)/100} F${FeedHorizontal} M400 G0 Z${Math.round((ZZeroPosition+0.2)*100)/100} F${FeedFree} G0 Z${Math.round((ZZeroPosition-0.3)*100)/100} F${FeedDown/10} G0 Z${ZDrillValue} F${FeedDown} M117 Return G0 Z${ZTravelValue} F${FeedFree} </pattern> <pattern name="second_time"> ; ${var hcnt=holesCount;var tcnt=toolsCount;"SECOND!!!"} </pattern> </patterns> <script> <!-- "assign tools". No parameters Just assign all tools declared in DRL-file to tools described in <tools> node. For each DRL-defined tool will be selected FIRST compatible tool from <tools> node. Ie if range 0.3..0.8 will be defined early, <tool> node for diameter 0.4..0.5 will never be assigned. Except 'plated' property will be different. --> <command verb="assign tools" /> <!-- "assign tools". No parameters Join all DRL-file tools, assigned to same tool here to one tool (also holes) Just avoid multiply changing physical tool to same --> <command verb="join tools" /> <!-- "offset". Offset ALL holes by defined values xoffs, yoffs - values to offset. Before offset will be calculated ie here you can use global variables. --> <command verb="offset" xoffs="-minX+StartOffsX" yoffs="-minY+StartOffsY"/> <!-- loop for each DRL-tool (assigned and joined before). Context inside will be filled also with tool's properties and node's parameters --> <command verb="sort tools"/> <command verb="print" pattern="start"/> <loop type="tools"> <condition content="first++==0"> <command verb="print" pattern="set_tool"/> </condition> <command verb=";print context" line_begin=";"/> <!-- loop for each hole inside the tool. Context inside will be filled also with hole's properties(x&y) and node's parameters --> <loop type="toolholes"> <command verb="print" pattern="go_drill"/> <!-- "print context". Anwhere in script you can use this verb. It inserts all context variables available. Usefull for debug but completely useless for normal work --> <command verb=";print context" line_begin=";"/> </loop> </loop> <condition content="first=0"> <command verb=";dummy"/> </condition> <command verb="print" pattern="second_time"/> <loop type="tools"> <condition content="first++>0"> <command verb="print" pattern="set_tool"/> <command verb=";print context" line_begin=";"/> <!-- loop for each hole inside the tool. Context inside will be filled also with hole's properties(x&y) and node's parameters --> <loop type="toolholes"> <command verb="print" pattern="go_drill"/> <!-- "print context". Anwhere in script you can use this verb. It inserts all context variables available. Usefull for debug but completely useless for normal work --> <command verb=";print context" line_begin=";"/> </loop> </condition> </loop> <command verb="print" pattern="finish"/> </script> </xml> 



De fato, não há nada complicado, se você ler. Mas vamos analisar seção por seção:

  <variables> <var name=" " value=" "/> </variables> 

Na seção de variáveis, como o nome indica, podemos definir um conjunto arbitrário de variáveis ​​globais. Eles não afetam a operação do programa de forma alguma até que se encontrem em alguma expressão calculada.

  <functions> <plate_increase_dia f="a+0.2"/> </functions> 

Funções Bem, mais precisamente, uma função. Até o momento, é predeterminado um: o cálculo do diâmetro real da broca para furos metalizados. Sabe-se que a metalização rouba o diâmetro, e isso muitas vezes leva a incidentes ao tentar furar a perna do componente 0.8, que não entra no furo definido como 0,9. Para não me incomodar com isso ao projetar, decidi adicionar essa funcionalidade.

O significado desta seção é determinar as funções que o conversor pode usar para determinados fins. Essas funções não podem ser (ainda?) Usadas independentemente.

  <tools> <tool description="0,3mm" range_min="0" range_max="0.3" plated="both" position="0" /> </tools> 

Exercícios. Aqui você precisa fazer uma referência ao comando de script "align tools", sobre o qual abaixo. Cada elemento desta seção define uma célula na qual todas as ferramentas reconhecidas no arquivo de entrada serão coletadas. A idéia é que, muitas vezes, ao projetar, ocorrem diâmetros em polegadas e muitas ferramentas com valores de 0,478 ... 0,492 ... etc. Para não mexer com eles, definimos os parâmetros necessários range_min e range_max. Um sinal de metalização também é necessário. Os nós XML são varridos sequencialmente e, assim que a próxima ferramenta do DRL se encaixa na definição, o nó é reconhecido como adequado.
Você pode definir quaisquer outros parâmetros no nó. Seu valor pode ser usado posteriormente em modelos.

Você pode definir a posição no estojo ou nas coordenadas onde capturar a broca, se tiver uma máquina com uma ferramenta de troca automática. E você pode descrever a ferramenta com letras para exibição na tela da impressora, se você, como o meu, tiver o Marlin e a troca manual de brocas.

  <patterns> <pattern name="start"> G90 ;${var hcnt=holesCount;var tcnt=toolsCount;"Hello"} M117 Homing G28 XY M117 Move Z to travel G0 X${minX} Y${minY} M76 G92 Z${ZTravelValue} </pattern> 

E agora, aprecie todo o charme de uma máquina de script! Templates. O conversor, como eu já disse, trabalha com modelos simplesmente: ele procura todas as partes do formulário $ {...} e o envia para a máquina de script. E existe uma linguagem semelhante a JS. Portanto, de fato, você pode até programar um pouco. Neste exemplo, você pode ver como, ao exibir o padrão inicial, primeiro definimos um par de variáveis ​​aos quais foram atribuídos valores globais. Bem, só então eles escreveram uma constante, que será o valor da execução desta peça.

Quando este modelo é enviado para o arquivo de saída, veremos:

 G90 ;Hello M117 Homing G28 XY M117 Move Z to travel G0 X10 Y10 M76 G92 Z10 

Bem, eu não posso me gabar. Classifique a peça do modelo para perfurar cada furo:

  ; Holes rest: ${hcnt--} ; Percent rest: ${var percent=Math.round(hcnt*100/holesCount); percent}% M73 P${100-percent} 

sim ... toda vez que digitarmos um comentário no Holes rest, diminuiremos o valor hcnt. E, como lembramos, foi determinado enquanto digitamos start e, portanto, está localizado no contexto acima. E então calcularemos a variável percentual para usá-la em outra parte posteriormente - ao passar para o comando M73 (este comando força o marlin a mover a barra de progresso). Código G gerado por este fragmento:

 ; Holes rest: 6 ; Percent rest: 13% M73 P87 

a propósito, toolsCount, minX são nomes predefinidos de variáveis ​​globais.
Observo que os nomes dos modelos não são predefinidos, ou seja, você pode usar qualquer. O modelo será impresso quando o comando print e seu nome forem encontrados no script.

 <script> <command verb="assign tools" /> 

E a base é a seção de script


Nós com o comando e loop de nomes podem ser encontrados dentro de uma seção.

Formato do nó de comando :

  <command verb=" " ....    ... /> 

Uma declaração de ação é um dos poucos operadores. As opções para cada um são descritas abaixo. Eles podem ser complementados por outros que, como você já entendeu, podem ser usados ​​em modelos.

Formato do nó de loop:

 <loop type=" "> ..... </loop> 

um loop é uma seção cujo conteúdo será executado para cada elemento determinado pelo tipo de loop. Existem dois deles (por enquanto):

ferramentas - um loop será executado para cada ferramenta e
furos de ferramentas - um ciclo será executado para cada furo projetado para perfurar com esta ferramenta. Obviamente, o loop dos buracos das ferramentas só pode ser aninhado em ferramentas .
Ao mesmo tempo, ao executar um loop aninhado, todas as variáveis ​​da ferramenta atual estão disponíveis. Porque Eu não sei Acabei de dizer.

Operadores


atribuir ferramentas
Opções: nenhuma.

Atribui cada drill do arquivo da ferramenta de origem do XML. Sem ele, a maioria das outras ações não faz sentido.

juntar ferramentas
Opções: nenhuma.
Mais organizacional - combina todas as ferramentas que foram atribuídas da mesma forma no arquivo XML. Faz sentido logo após as ferramentas de atribuição, mas decidi dar ao usuário a oportunidade de realizar suas operações.

ferramentas de classificação
Parâmetros: nenhum (ainda).
Classifica as brocas aumentando os diâmetros

deslocamento
Parâmetros:
xoffs, yoffs - valores de deslocamento. A máquina de scripts está em execução.
Muda todos os furos para os valores especificados. Sim, muitas vezes acontece que o conselho não está muito distante na origem.

impressão
Parâmetro:
padrão O nome do padrão.
Imprime um modelo com o nome especificado no fluxo de saída.

contexto de impressão
Parâmetros:
line_begin, line_end - o início e o fim de cada linha.
Coisa de depuração - permite gerar todas as variáveis ​​disponíveis no momento e seus valores em qualquer lugar da saída. Cada variável é exibida em uma linha separada, o início e o fim são especificados nos parâmetros

Nomes predefinidos de variáveis ​​globais.


holesCount, toolsCount - Eu realmente espero que o significado dessas variáveis ​​não precise de explicação. Sim sim Este é o número de ferramentas e o número de furos.
minX, maxX, minY, maxY - e estes também. Não, bem, apenas no caso, essas são as coordenadas do campo de perfuração. Todos os furos estão dentro desse retângulo. Recalculado após o comando de deslocamento.

Conclusão


Aqui, de fato, tentei descrever brevemente, mas o mais completamente possível, descrever a tulza criada.

Honestamente, enquanto tentava imaginar cenários de uso, imaginei claramente quantas vezes o jugo tártaro-mongol apareceria em terras russas (acredita-se que eles nos trouxessem o tapete).

Daí a pergunta: vale a pena ficar confuso e criar uma página da Web simples onde você possa inserir a entrada e o script e obter o código G finalizado, ignorando os estágios de montagem da fonte?
UPD:
Obrigado a quem votou. Eu lavei tudo . E ... sim: eu escrevi que a página da web será simples? Se alguém não estiver com preguiça de trazer tudo isso para uma aparência mais estética - coloque HTML no PM.

Source: https://habr.com/ru/post/pt428534/


All Articles