{"id":511,"date":"2017-09-12T20:42:40","date_gmt":"2017-09-12T18:42:40","guid":{"rendered":"http:\/\/www.joanillo.org\/?p=511"},"modified":"2020-09-24T20:43:28","modified_gmt":"2020-09-24T18:43:28","slug":"script-cncstroke-mejorando-la-conversion-dxf-a-g-code-i","status":"publish","type":"post","link":"https:\/\/www.joanillo.org\/?p=511&lang=es","title":{"rendered":"script cncstroke: mejorando la conversi\u00f3n DXF a G-Code, I"},"content":{"rendered":"<p><a href=\"http:\/\/www.joanillo.org\/wp-content\/uploads\/2017\/09\/einstein.jpg\"><img loading=\"lazy\" src=\"http:\/\/www.joanillo.org\/wp-content\/uploads\/2017\/09\/einstein-300x296.jpg\" alt=\"\" title=\"einstein black and white\" width=\"300\" height=\"296\" class=\"alignright size-medium wp-image-1505\"><\/a>Uno de los trabajos t\u00edpicos que se hacen con la <strong>CNC<\/strong> es el retrato de personajes en formato blanco y negro. Por ejemplo, son conocidos los retratos del Che Guevara o Albert Einstein. Estos d\u00edas estoy trabajando con la imagen de <strong>Ovidi Montllor<\/strong> [1].<\/p>\n<p>La idea es sencilla y conocida. Importo la imagen en <strong>LibreCAD<\/strong> [2] (el software CAD que utilizo, que es open source), defino la silueta, y defino unas \u00e1reas de <em>hatching<\/em> que seran fresades (rebajadas). Utilizo el programa <em>dxf2gcode<\/em> [3] para exportar a G-Code, y freso todo el trabajo a una profundidad de 1.5mm. La limitaci\u00f3n que tengo es que la fresa que utilizo es de 2mm de di\u00e1metro, y esto limita la resoluci\u00f3n final que pudo alcanzar.<\/p>\n<p>Estoy programando un peque\u00f1o script (<strong>cncstroke<\/strong> [4]) para mejorar la resoluci\u00f3n de mis trabajos. Imaginemos por ejemplo los cabellos de Albert Einstein. Lo ideal es que las mechas de cabello acaben en punta, haciendo un trazo que pase de grueso a fino. Esto se consigue haciendo que la profundidad de ataque de la broca sea variable, desde 1.5mm de profundidad en el inicio del trazo hasta 0mm al final del trazo. Pero para que el invento funcione, no he de utilizar una broca normal, sino una broca <a href=\"https:\/\/www.google.es\/search?q=V-Shape+bit&amp;safe=strict&amp;client=ubuntu&amp;hs=U6T&amp;channel=fs&amp;dcr=0&amp;source=lnms&amp;tbm=isch&amp;sa=X&amp;ved=0ahUKEwimuriG7Z_WAhVGBBoKHeJQCiwQ_AUICigB&amp;biw=1366&amp;bih=591\">V-Shape<\/a> (con punta de 40 grados). De esta manera conseguir\u00e9 el efecto de hacer un trazo que pase de 2mm de ancho en el origen a 0 mm en el extremo. Esta t\u00e9cnica tambi\u00e9n ser\u00e1 muy \u00fatil para fresar letras que simulen trazos variables.<\/p>\n<p>La idea es que en els mis proyectos de LibreCAD tendr\u00e9 una capa con la silueta b\u00e1sica (que fresar\u00e9 con una broca de 2mm), y una capa (que siempre nombrar\u00e9 <em>stroke<\/em>) que constar\u00e1 de <em>polil\u00edneas<\/em> que representar\u00e1n el trazo variable desde 2mm hasta a 0 mm de ancho. Con esta segunda capa podr\u00e9 hacer los detalles como cabellos o caligraf\u00eda de letras.<\/p>\n<p>En este primer art\u00edculo s\u00f3lo expongo la estructura de datos que me permitir\u00e1 gestionar la generaci\u00f3n del G-Code a partir del proyecto de LibreCAD. Cuando recorra (program\u00e1ticamente) el contenido de un proyecto LibreCAD (formato <em>dxf<\/em>), tendr\u00e9 que buscar la definici\u00f3n de la capa <em>stroke<\/em> y de los puntos que contiene. Esto es relativamente f\u00e1cil de hacer. Esta sucesi\u00f3n de puntos se pueden agrupar en polil\u00edneas, entendiendo que una polil\u00ednea es un conjunto de l\u00edneas que van empalmadas.<\/p>\n<p>Como el n\u00famero de poli\u00edneas es variable, y el n\u00famero de l\u00edneas que contiene una polil\u00ednea tambi\u00e9n es variable, la mejor manera de programar esta estructura con lenguaje C++ es utilizar vectores.<br \/>\n<code><br \/>\nstruct linia {<br \/>\n\\tint x0;<br \/>\n\\tint y0;<br \/>\n\\tint x1;<br \/>\n\\tint y1;<br \/>\n\\tdouble dist;<br \/>\n};<\/code><\/p>\n<p><code>struct polilinia {<br \/>\n\\tstd::vector  \t<linia> vlinia;<br \/>\n\\tdouble dist;<br \/>\n};<\/linia>\n<p><\/code><code>std::vector <polilinia> vpolilinia;\n<\/polilinia><\/code><\/p>\n<p>Una l\u00ednea consta de un punto origen y de un punto final (f\u00e1cilmente se podr\u00e1 calcular la longitud de esta l\u00ednea). Una polil\u00ednea consta de un conjunto de l\u00edneas, y la longitud de la polil\u00ednea ser\u00e1 la suma de les longitudes individuales.<\/p>\n<p>A continuaci\u00f3n mostramos el ejemplo m\u00ednimo de c\u00f3mo se pueden gestionar diferentes polil\u00edneas, cada una con un n\u00famero variable de l\u00edneas.<br \/>\n<code><br \/>\n\/\/ g++ -o polilinia polilinia.cpp<br \/>\n#include <iostream><br \/>\n#include <string><br \/>\n#include <sstream><br \/>\n#include <vector><br \/>\n#include <math.h>\n<\/math.h><\/vector><\/sstream><\/string><\/iostream><\/code><\/p>\n<p><code>struct linia {<br \/>\n\\tint x0;<br \/>\n\\tint y0;<br \/>\n\\tint x1;<br \/>\n\\tint y1;<br \/>\n\\tdouble length;<br \/>\n};<\/code><\/p>\n<p><code>struct polilinia {<br \/>\n\\tstd::vector  \t<linia> vlinia;<br \/>\n\\tdouble length;<br \/>\n};<\/linia>\n<p>std::vector <polilinia> vpolilinia;<\/polilinia>\n<p>using namespace std;<\/p>\n<p>int main() {<br \/>\n\\t<br \/>\n\\tdouble lengthlinia,lengthpolilinia;<br \/>\n\\tpolilinia polilinia1;\\t<br \/>\n\\tlinia linia1;<\/p>\n<p>\\tlengthpolilinia=0;<\/p>\n<p>\\tlinia1.x0=34;<br \/>\n\\tlinia1.y0=30;<br \/>\n\\tlinia1.x1=120;<br \/>\n\\tlinia1.y1=122;<br \/>\n\\tlengthlinia = sqrt(pow(linia1.x1-linia1.x0,2) + pow(linia1.y1-linia1.y0,2));<br \/>\n\\tlinia1.length=lengthlinia;<br \/>\n\\tlengthpolilinia += lengthlinia;<\/p>\n<p>\\tpolilinia1.vlinia.push_back(linia1);<\/p>\n<p>\\tlinia1.x0=320;<br \/>\n\\tlinia1.y0=322;<br \/>\n\\tlinia1.x1=420;<br \/>\n\\tlinia1.y1=422;<br \/>\n\\tlengthlinia = sqrt(pow(linia1.x1-linia1.x0,2) + pow(linia1.y1-linia1.y0,2));<br \/>\n\\tlinia1.length=lengthlinia;<br \/>\n\\tlengthpolilinia += lengthlinia;<\/p>\n<p>\\tpolilinia1.vlinia.push_back(linia1);<br \/>\n\\t<br \/>\n\\tpolilinia1.length = lengthpolilinia;<br \/>\n\\t<br \/>\n\\tvpolilinia.push_back(polilinia1);<br \/>\n\\t<br \/>\n\\t\/\/cout &lt;&lt; vpolilinia.at(0).vlinia.size() &lt;&lt; endl;<\/p>\n<p>\\t\/\/anem per una altra polilinia<br \/>\n\\tpolilinia1.vlinia.clear();<br \/>\n\\tlengthpolilinia=0;<\/p>\n<p>\\tlinia1.x0=134;<br \/>\n\\tlinia1.y0=130;<br \/>\n\\tlinia1.x1=220;<br \/>\n\\tlinia1.y1=222;<br \/>\n\\tlengthlinia = sqrt(pow(linia1.x1-linia1.x0,2) + pow(linia1.y1-linia1.y0,2));<br \/>\n\\tlinia1.length=lengthlinia;<br \/>\n\\tlengthpolilinia += lengthlinia;<\/p>\n<p>\\tpolilinia1.vlinia.push_back(linia1);<\/p>\n<p>\\tlinia1.x0=220;<br \/>\n\\tlinia1.y0=222;<br \/>\n\\tlinia1.x1=320;<br \/>\n\\tlinia1.y1=322;<br \/>\n\\tlengthlinia = sqrt(pow(linia1.x1-linia1.x0,2) + pow(linia1.y1-linia1.y0,2));<br \/>\n\\tlinia1.length=lengthlinia;<br \/>\n\\tlengthpolilinia += lengthlinia;<\/p>\n<p>\\tpolilinia1.vlinia.push_back(linia1);<\/p>\n<p>\\tlinia1.x0=220;<br \/>\n\\tlinia1.y0=222;<br \/>\n\\tlinia1.x1=320;<br \/>\n\\tlinia1.y1=322;<br \/>\n\\tlengthlinia = sqrt(pow(linia1.x1-linia1.x0,2) + pow(linia1.y1-linia1.y0,2));<br \/>\n\\tlinia1.length=lengthlinia;<br \/>\n\\tlengthpolilinia += lengthlinia;<\/p>\n<p>\\tpolilinia1.vlinia.push_back(linia1);<\/p>\n<p>\\tpolilinia1.length = lengthpolilinia;<\/p>\n<p>\\tvpolilinia.push_back(polilinia1);\\t<\/p>\n<p>\\t\/\/cout &lt;&lt; vpolilinia.at(1).vlinia.size() &lt;&lt; endl;<br \/>\n\\t\/\/cout &lt;&lt; vpolilinia.size() &lt;&lt; endl;<\/p>\n<p>\\t\/\/recorrem totes les polil\u00ednies<br \/>\n\\tfor (int i=0; i<vpolilinia.size(); i++)=\"\" {=\"\" \\t\\tcout=\"\" <<=\"\" \"polilinia=\"\" #\"=\"\" i=\"\" \".=\"\" length:=\"\" \"=\"\" vpolilinia.at(i).length=\"\" endl;=\"\" \\t\\t=\"\" dins=\"\" de=\"\" cada=\"\" polilinia,=\"\" recorrem=\"\" les=\"\" l\u00ednies:=\"\" \\t\\tfor=\"\" (int=\"\" j=\"0;\" j<vpolilinia.at(i).vlinia.size();=\"\" j++)=\"\" \\t\\t\\tcout=\"\" \"linia=\"\" vpolilinia.at(i).vlinia.at(j).length=\"\" endl;\\t\\t\\t=\"\" \\t\\t}=\"\" \\t}=\"\" }=\"\" <=\"\" code=\"\"><br \/>\nI la sortida per pantalla:<br \/>\n<code><br \/>\n$ .\/polilinia<br \/>\npolilinia #0. length: 267.358<br \/>\nlinia #0. length: 125.936<br \/>\nlinia #1. length: 141.421<br \/>\npolilinia #1. length: 408.779<br \/>\nlinia #0. length: 125.936<br \/>\nlinia #1. length: 141.421<br \/>\nlinia #2. length: 141.421<br \/>\n<\/code><\/vpolilinia.size();><\/p>\n<p>En el siguiente <a href=\"http:\/\/www.joanillo.org\/?p=1493\">art\u00edculo<\/a> [5] se explica la implementaci\u00f3n del proyecto <strong>cncstroke<\/strong> para generar G-Code con <em>z-depth<\/em> variable.<\/p>\n<p>Referencias:<\/p>\n<ul>\n\\t<\/p>\n<li>[1]. <a href=\"https:\/\/ca.wikipedia.org\/wiki\/Ovidi_Montllor_i_Mengual\" title=\"Ovidi Montllor\">https:\/\/ca.wikipedia.org\/wiki\/Ovidi_Montllor_i_Mengual<\/a><\/li>\n<p>\\t<\/p>\n<li>[2]. <a href=\"http:\/\/librecad.org\/cms\/home.html\" title=\"LibreCAD\">LibreCAD<\/a><\/li>\n<p>\\t<\/p>\n<li>[3]. <a href=\"https:\/\/sourceforge.net\/projects\/dxf2gcode\" title=\"dfx2gcode\">dfx2gcode<\/a><\/li>\n<p>\\t<\/p>\n<li>[4]. <a href=\"http:\/\/wiki.joanillo.org\/index.php\/Script_CNC_stroke\" title=\"cncstroke en wik.joanillo.org\">cncstroke en wiki.joanillo.org<\/a><\/li>\n<p>\\t<\/p>\n<li>[5]. <a href=\"http:\/\/www.joanillo.org\/?p=1493\">Mejorando la conversi\u00f3n DXF a G-Code, II<\/a><\/li>\n<\/ul>\n<p><strong>Nota aclarativa<\/strong>:  En el proyecto <strong>cncstroke<\/strong> utilizamos el t\u00e9rmino <em>polil\u00ednea<\/em> como sucesi\u00f3n de l\u00edneas enlazadas. Ahora bien, para generar estas l\u00edneas enlazadas, en LibreCAD, utilizamos la herramienta <em>l\u00ednea<\/em> (y no la herramienta <em>polil\u00ednea<\/em>) (En una futura versi\u00f3n se estudiar\u00e1 la posibilidad de utilizar la herramienta <em>polil\u00ednea<\/em>, o ambas).<\/p>\n<p><\/code><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Uno de los trabajos t\u00edpicos que se hacen con la CNC es el retrato de personajes en formato blanco y negro. Por ejemplo, son conocidos los retratos del Che Guevara o Albert Einstein. Estos d\u00edas estoy trabajando con la imagen de Ovidi Montllor [1]. La idea es sencilla y conocida. Importo la imagen en LibreCAD [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[302,310,324,192],"tags":[],"_links":{"self":[{"href":"https:\/\/www.joanillo.org\/index.php?rest_route=\/wp\/v2\/posts\/511"}],"collection":[{"href":"https:\/\/www.joanillo.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.joanillo.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.joanillo.org\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.joanillo.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=511"}],"version-history":[{"count":1,"href":"https:\/\/www.joanillo.org\/index.php?rest_route=\/wp\/v2\/posts\/511\/revisions"}],"predecessor-version":[{"id":512,"href":"https:\/\/www.joanillo.org\/index.php?rest_route=\/wp\/v2\/posts\/511\/revisions\/512"}],"wp:attachment":[{"href":"https:\/\/www.joanillo.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=511"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.joanillo.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=511"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.joanillo.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=511"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}