Inkscapeで描いたものをgcodeに変換の方法


お絵かきマシーンを動かすためにInkscapeでデータを作り、gcodeに変更する方法を書いておきます。

① inkscapeで何かを描くか、データをインポートします。

② ドローイングのデータがvectorであることを確認します。データを選択しパスに変更します。メニューのパスから、オブジェクトをパスへ、もしくはストロークをパスへでパスに変更できます。

③ メニューのエクステンションの中からgcodetoolsそしてその中のtool libraryに行きます。

④ Tools typeのdefaultを選び適用ボタンを押します。

⑤ 緑のボックスが出てきますので、中の文字を変更して調整することができます。

⑥ ’gcode before path’の'(None)’ を’M3 S040’に変更します。また ‘gcode after path’の ‘(None’)を’M5’へ変更します。これは後でパスの前後に ‘lower pen’と ‘raise pen’のためのこれらのコマンドを追加するようにエクスポートに指示しています。

⑦ 私は’penetration feed’を50に変更しています。コマンドM3 / M5は遅延がないので、ペンのサーボがまだ移動している間、プロッタは直接X / Yの移動を続けるからです。

⑧ Inkscapeでgcodeファイルにエクスポートする描画オブジェクトを選択するか、すべてを選択解除したままにします(すべてをエクスポートする場合)。

⑨ 
メニューから ‘ツール’ – > ‘gcodetools’ – > ‘Orientation points’を開きます。これにより、描画サイズとプロッタが実際の紙の上で行う作業のサイズを調整することができます。
設定をそのままにします(もちろん、リンクに変更することができます)。私はほとんどの場合2点モードを使います。
「適用」をクリックしてください。次に「閉じる」をクリックしてダイアログを閉じます。

⑩ これで、2つのマーカーが(グループ化されている別の名前付きオブジェクトとして)図面に追加されました。
マーカーまたは座標テキストをダブルクリックしてグループを開くことができます。その後は、マーカーを1つだけ個別に選択できるはずです。
0.0、0、0、0、0のマーカーはそのままにします(それはあなたのシートの角にあります)。シートに従って他のマーカー(100.0、0.0、-1.0)を正しい位置に移動します。これを行うには、トップバーのXボックスに「100」と入力して横軸の10 cmに直接移動します。
これは、Inkscapeの縮尺が、次のステップでgcodeがどのようにエクスポートされるかと一致することを確認するための重要なステップです。だからあなたの絵の中の10cmはあなたのプロッタのある現実の世界では実際に10cmです。

(mm XとYあたりのステップ数のGrblプロッタ設定も正しく設定されていることを確認してください。1/ 4マイクロステップではこれはおそらく約30です)

⑪ 
メニューを使って「ツール」 – >「gcodetools」 – >「Path to Gcode」を開きます。
あなたは好みに合わせて ‘切断順序’の設定を変更することができます、ほとんどの場合 ‘サブパスごとのサブパス’は丁度良いです。
ダイアログの[設定]タブで、[ファイル]と[ディレクトリ]ボックスでファイル名/パスを選択します。
今すぐ最初のタブ ‘Gcodeへのパス’が選択されている/アクティブであることを確認し、 ‘適用’ダイアログボタンを押してください。
ポップアップを表示されたらOKを押してください。
これにより、gcodeのエクスポートファイルが作成されます。

「閉じる」を押してダイアログを閉じます。

必要に応じて、図面上の「オーバーレイ」を選択してキーボードの「削除」キーを押すことで削除できます。

私は私のinkscape文書の上に描かれている ‘スパイラル’で上記の指示をしました、そしてこれは結果のgcodeファイルです( ‘————-‘行を除いて):

%
(Header)
(Generated by gcodetools from Inkscape.)
(Using default header. To add your own header create file "header" in the output dir.)
M3
(Header end.)
G21 (All units in mm)

(Start cutting path id: path3680)
(Change tool to Default tool)

G00 Z1.000000
G00 X75.044960 Y77.679670
M3 S040
G01 Z-1.000000 F100.0(Penetrate)
G02 X73.582637 Y73.540866 Z-1.000000 I-2.216997 J-1.544427 F400.000000
G02 X69.438316 Y73.773910 Z-1.000000 I-1.741969 J5.988446
G02 X64.592009 Y80.959687 Z-1.000000 I3.036743 J7.275208
G02 X67.233444 Y88.892960 Z-1.000000 I12.798031 J0.145191
G02 X79.556761 Y94.609429 Z-1.000000 I11.621145 J-8.911090
G02 X91.864893 Y89.396950 Z-1.000000 I-0.927838 J-19.328610
G02 X98.591733 Y71.963585 Z-1.000000 I-14.713436 J-15.691821
G02 X90.667992 Y55.253100 Z-1.000000 I-26.043697 J2.115470
G02 X68.128145 Y47.467120 Z-1.000000 I-19.676330 J20.442947
G02 X47.011739 Y58.150880 Z-1.000000 I3.325468 J32.782896
G02 X38.144472 Y85.796852 Z-1.000000 I26.131088 J23.626423
G02 X51.610413 Y111.319540 Z-1.000000 I39.523748 J-4.539290
G02 X84.362716 Y121.279975 Z-1.000000 I27.560021 J-31.795032
G02 X114.291470 Y105.019980 Z-1.000000 I-5.752760 J-46.262734
G02 X125.352177 Y67.161029 Z-1.000000 I-37.443922 J-31.484654
G02 X106.291020 Y32.826520 Z-1.000000 I-52.999571 J6.965005
G02 X63.325155 Y20.660952 Z-1.000000 I-35.403957 J43.082929
G02 X24.585161 Y42.527850 Z-1.000000 I8.175917 J59.734543
G02 X11.311610 Y90.600879 Z-1.000000 I48.715114 J39.319848
G02 X35.987381 Y133.746120 Z-1.000000 I66.468079 J-9.385702
G02 X89.167750 Y148.129884 Z-1.000000 I43.233439 J-54.342387
G02 X136.718050 Y120.643010 Z-1.000000 I-10.594508 J-73.200454
G02 X152.213675 Y62.355145 Z-1.000000 I-59.966054 J-47.145427
G02 X121.914050 Y10.399940 Z-1.000000 I-79.931895 J11.802496
G00 Z1.000000
M5
(End cutting path id: path3680)

(Footer)
M5
G00 X0.0000 Y0.0000
M2
(Using default footer. To add your own footer create file "footer" in the output dir.)
(end)
%

P5jsで簡単お絵かきアプリを作ろう!


作り方の解説はこちらから!

var stc = 0;
var stw = 1;
var slider;

function setup() {
	createCanvas(400, 400);
	slider = createSlider(1, 50, 1);
	slider.position(270, 10);
}

function draw() {
	//background(220);
	fill(100);
	stroke(100);
	strokeWeight(1);
	rect(0, 0, width, 60);
	button(0, 0, 50, 255);
	button(50, 0, 50, 0);
	button(100, 0, 50, color(255, 0, 0));


	stroke(stc);
	strokeWeight(stw);
	if (mouseIsPressed) {
		line(mouseX, mouseY, pmouseX, pmouseY);
	}

	stw = slider.value();
}

function button(x, y, s, c) {
	var bc = c;
	if (mouseX > x && mouseX < x + s && mouseY > y && mouseY < y + s && mouseIsPressed) {
		bc = 0;
		stc = c;
	}
	fill(bc);
	stroke(0);
	strokeWeight(1);
	rect(x, y, s, s);
}

P5jsでドラクエ風のゲーム作成しました!



P5jsでドラクエ風のゲーム作成しました!

var images = new Array(8);
var xoffset = 0;
var yoffset = 0;
var px = 0 * 25;
var py = 7 * 25;
var s = 25;
var suraimu;
var money = 0;
var item = false;
var item2 = false;
var item3 = false;
var item4 = false;
var mode = 0;
var button;
var teki1, teki2,teki3;
var kougeki = 20;
var bougyoz = 0;
var time = 0;
var zhp = 100;
var turn = true;

var array = [
  [5, 5, 5, 5, 1, 1, 1, 1, 1, 5, 5, 5, 1, 1, 1, 1, 5, 5, 5, 5],
  [5, 5, 5, 0, 1, 1, 0, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 5, 5, 5],
  [5, 5, 1, 0, 1, 1, 0, 0, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 5, 5],
  [5, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 11, 0, 1, 0, 1, 1, 5],
  [1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1],
  [1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1],
  [0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
  [0, 0, 0, 6, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1],
  [0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
  [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1],
  [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1],
  [1, 1, 1, 7, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 1, 0, 0, 0, 1, 1],
  [1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0],
  [1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1],
  [5, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 10, 0, 1, 0, 0, 1, 5],
  [5, 5, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 5, 5],
  [5, 5, 5, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 5, 5, 5],
  [5, 5, 5, 5, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 5, 5, 5, 5],
  [5, 5, 5, 5, 5, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5],
  [5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5]
];

function setup() {
  createCanvas(250, 250);
  background(0, 0, 255);
  //for (var k = 0; k < images.length; k++) {
  images[0] = loadImage("back0.png");
  images[1] = loadImage("back1.png");
  images[2] = loadImage("flower.png");
  images[3] = loadImage("flowerpod.png");
  images[4] = loadImage("Pot.PNG");
  images[5] = loadImage("");
  images[6] = loadImage("mig.jpg");
  images[7] = loadImage("teki.png");
  images[8] = loadImage("ryuo.jpg");
  images[9] = loadImage("ryuo2.jpg");
  images[10] = loadImage("ken.png");
  suraimu2 = loadImage("suraimu2.png");
  images[11] = loadImage("tate.png");
  //  }0
  suraimu = loadImage("back5.png");
  teki1 = new tatakai(images[6], 80, 80, 100, 100, "スライム", 0, 5);
  teki2 = new tatakai(images[7], 80, 80, 100, 100, "スライムナイト", 10, 8);
  teki3 = new tatakai(images[10], 80, 80, 100, 100, "りゅうおう", 20, 10);
  // teki4 = new tatakai(images[9], 80, 80, 100, 100, "竜王",17);
}

function draw() {
  //print(button);
  background(0, 0, 255);
  if (mode == 0) {
    xoffset = (px - width / 2);
    yoffset = (py - height / 2);
    print(px);
    for (var i = 0; i < 20; i++) {
      for (var j = 0; j < 20; j++) {
        var p = array[i][j];
        drawImage(images[p], j * s, i * s, s, s);
        //text(,10,230);

      }
    }

    drawImage(suraimu, px, py, 25, 25); //自分
    getItem();

  }

  if (mode == 1) {
    background(0);
    teki2.display();
  }

  if (mode == 2) {
    background(0);
    teki1.display();
  }

  if (mode == 3) {
    background(0);
    teki3.display();
  }
  /*
  if (mode == 4) {
    background(0);
    teki4.display();
  }
  */
  if (item == true) {
    sikaku();
    time++;
    if (time > 100) {
      item = false;
      time = 0;
    }
  }
  if (item4 == true) {
    sikaku2();
    time++;
  }
  if (time > 100) {
    item4 = false;
    time = 0;
  }
  if (item3 == true) {
    sikaku3();
    time++;
  }
  if (time > 100) {
    item3 = false;
    time = 0;
  }


}

function sikaku() {
  fill(0);
  rect(20, 210, 200, 30);
  fill(255);
  text("10円を拾った", 80, 230);
}

function sikaku2() {
  fill(0);
  rect(20, 210, 200, 30);
  fill(255);
  text("防御力が5アップした", 60, 230);
}

function sikaku3() {
  fill(0);
  rect(20, 210, 200, 30);
  fill(255);
  text("攻撃力が10アップした", 50, 230);
}

function getItem() {
  if (array1[px / s] == 2) {
    array1[px / s] = 0;
    money = money + 10;
    item = true;
  }
  if (array1[px / s] == 3) {
    array1[px / s] = 0;

  }
  if (array1[px / s] == 6) {
    mode = 2;
  }
  if (array1[px / s] == 7) {
    mode = 1;
  }
  if (array1[px / s] == 8) {
    mode = 3;
  }
  if (array1[px / s] == 9) {
    mode = 1;
  }
  if (array1[px / s] == 10) {
    array1[px / s] = 0;
    item3 = true;
  }
  if (array1[px / s] == 11) {
    array1[px / s] = 0;
    item4 = true;
  }

  if (array1[px / s] == 2 && item == true) {
    array1[px / s] = 0;
    item2 = true;
  }
  if (array1[px / s] == 4 && item == true) {

    array1[px / s] = 0;
  }

  if (item3 == true) {
    kougeki = 30;
    suraimu = suraimu2;
  }
  if (item4 == true) {
    bougyoz = 5;
  }
}




function drawImage(img, x, y, sx, sy) {
  x -= xoffset;
  y -= yoffset;
  image(img, x, y, sx, sy);
}

function keyPressed() {
  if (mode == 0) {


    if (keyCode == UP_ARROW && py > 0) {
      if (array1[px / 25] != 1) {
        if (array1[px / 25] != 5) {


          py = py - s;
        }
      }
    }
    if (keyCode == DOWN_ARROW && py < 475) {
      if (array1[px / 25] != 1) {
        if (array1[px / 25] != 5) {
          py = py + s;
        }
      }
    }
    if (keyCode == RIGHT_ARROW && px < 475) {
      if (array1[px / 25 + 1] != 1) {
        if (array1[px / 25 + 1] != 5) {
          px = px + s;
        }
      }
    }
    if (keyCode == LEFT_ARROW && px > 0) {
      if (array1[px / 25 - 1] != 1) {
        if (array1[px / 25 - 1] != 5) {
          px = px - s;
        }
      }
    }
  }
}

function tatakai(img, tx, ty, tss, thp, name, bougyo, tkogeki) {
  //  button = createButton('攻撃');
  print(turn)
  if (button == null) {

    exist = true;
  }
  var x = tx;
  var y = ty;
  var ts = tss;
  var S = 0;
  var hp = thp;
  var tbb = bougyo;
  var talk = false;
  var talk2 = false;
  var T = 0;
  var N = 0;
  var jikosyokai = true;
  var tekinokougeki = tkogeki;
  var tk = false;
  var teki=false;
  var zkougeki = true;
  this.display = function() {
    N++;
     
    image(img, x, y, ts, ts);
    fill(255);
    if (jikosyokai == true) {
      text(name + "が現れた", 75, 220);
    }
    if (N > 50) {
      jikosyokai = false;
      N = 0;
    }
    text(hp + "hp", 110, 70);
    //text(mode, 20, 20);
    text(money + "money", 180, 60);
    text("体力:" + zhp, 20, 20);


    text("攻撃力:" + kougeki, 180, 20);
    text("防御力:" + bougyoz, 180, 40);
    text(tbb, 100, 20);
    
    if(talk2==false){
this.buttonshow();
    }else{
    removeElements();
    }
    
    
    
    if (talk == true) {
      fill(255);
      text(kougeki + "ダメージを与えた", 70, 230);
      T++;
      zkougeki = false;

    }
    
    if (T > 25) {
      talk = false;
      T = 0;
      teki=true;
    }
    
    if (talk2 == true) {
      fill(255);
      text( tkogeki+ "ダメージをうけた", 70, 230);
      if(zhp<1){
         text("GameOver",120,220);
        noLoop();
         }
      
      T++;
    //zkougeki = false;
    }
    if (T > 25){
    talk2=false;
      T = 0;
    }
    

    if (tk == true) {
      fill(255);
      text(name + "を倒した", 80, 245);
      S++;
removeElements();
    }
    if (S > 50) {
      tk = false;
      mode = 0;

      array1[px / s] = 0;
      removeElements();
    }
    if (turn) { 
    
    } else {
      removeElements();
      this.tko();
    }

if(teki==true){
this.tekinokougeki();
  talk2=true;
  teki=false;
}
  }

  this.changeBG = function() {
    hp = hp - (kougeki - tbb);
    talk = true;

   



    if (hp < 1) {
      tk = true;
      //if(S>50){
      //	 tk=false;
      //		

    }

  }
this.tekinokougeki=function(){
   zhp = zhp - tkogeki;
  
}
  this.tko = function() {
    if (turn = true) {

      zkougeki = true;
    }
  }

this.buttonshow=function(){
   button = createButton('攻撃');
      button.position(20, 25);
      button.mousePressed(this.changeBG);
}


}

Monacaを利用してp5.jsで作ったsketchをスマホアプリにしてみました



電子工作教室の生徒さんがp5jsで作ったものをスマホでみたいとおっしゃいましたので、調べてみるとMonacaという便利な物がありました!

これでp5jsで作ったものをアンドロイドやiphoneで表示できます。

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <meta http-equiv="Content-Security-Policy" content="default-src * data: gap: content: https://ssl.gstatic.com; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'">
    <script src="components/loader.js"></script>
    <link rel="stylesheet" href="components/loader.css">
    <link rel="stylesheet" href="css/style.css">
    <script>
      <!-- この部分にsketch.js等を入れないと画面が二分割されて、結構ハマりました! -->
      <script src="components/p5js/lib/p5.js" type="text/javascript"></script>
      <script src="./sketch.js" type="text/javascript"></script>
      <style> body {padding: 0; margin: 0;} canvas {vertical-align: top;} </style>
    </script>
</head>
<body>

</body>
</html>

p5jsのコードはgenerative gestaltungからの引用。

'use strict';

var maxCount = 5000; // max count of the cirlces
var currentCount = 1;
var x = [];
var y = [];
var r = [];

function setup() {
  createCanvas(380, 680);
  strokeWeight(0.5);

  // first circle
  x[0] = width / 2;
  y[0] = height / 2;
  r[0] = 160;
}

function draw() {
  clear();

  // create a random set of parameters
  var newR = random(1, 7);
  var newX = random(newR, width - newR);
  var newY = random(newR, height - newR);

  var closestDist = Number.MAX_VALUE;
  var closestIndex = 0;
  // which circle is the closest?
  for (var i = 0; i < currentCount; i++) {
    var newDist = dist(newX, newY, x[i], y[i]);
    if (newDist < closestDist) {
      closestDist = newDist;
      closestIndex = i;
    }
  }

  // show original position of the circle and a line to the new position
     noFill();
  ellipse(newX, newY, newR * 2, newR * 2);
   line(newX, newY, x[closestIndex], y[closestIndex]);

  // aline it to the closest circle outline
  var angle = atan2(newY - y[closestIndex], newX - x[closestIndex]);

  x[currentCount] = x[closestIndex] + cos(angle) * (r[closestIndex] + newR);
  y[currentCount] = y[closestIndex] + sin(angle) * (r[closestIndex] + newR);
  r[currentCount] = newR;
  currentCount++;

  // draw them
  for (var i = 0; i < currentCount; i++) {
    
    ellipse(x[i], y[i], r[i] * 2, r[i] * 2);
  }

  if (currentCount >= maxCount) noLoop();
}

function keyReleased() {
  if (key == 's' || key == 'S') saveCanvas(gd.timestamp(), 'png');
}

Residence visualization


世界中からクラに来るレジデンスアーティストがどこから来たかのビジュアライゼーションを作成しました。
2007年から2018年まで表示させています。
p5.jsとmappa.jsをつかって制作しました。スマホでも見れますが、pcやタブレットで見るのをおすすめします!

https://editor.p5js.org/hirofumimatsuzaki/full/BJ4tFVBkN

二丈町をポイントし、クリアーでキャンバスを上書きしています。



二丈町をポイントし、クリアーでキャンバスを上書きしています。
https://editor.p5js.org/hirofumimatsuzaki/sketches/ByHZs4ryV