├── .gitignore ├── README.md ├── axiplot ├── carriage.scad ├── go-xy ├── nycr.pjl ├── pdf2vec ├── peano.pjl ├── polargraph ├── pulley.scad ├── serial-monitor ├── smoothie.config ├── smoothiecat └── vecsort.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.pdf 2 | *.gcode 3 | *.pjl 4 | *.svg 5 | *.stl 6 | .*.sw[op] 7 | *.zip 8 | *.ai 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Polargraph plotting program 2 | ![Gosper curve](https://farm2.static.flickr.com/1531/25435298340_7cefb92d62.jpg) 3 | 4 | This is a total hack that was built and written in just a few hours. 5 | It is not robust, generic, usable, etc. But perhaps it could be 6 | improved! 7 | 8 | More info: https://trmm.net/Polargraph 9 | 10 | 11 | TSV-6 12 | 118.5" diagonal to zero == 3010 mm 13 | 165" side to side == 4191 mm 14 | 15 | ./polargraph --scale 1.25 -F 6000 -w 4191 -l 3010 --offset-x 500 --offset-y 400 < paris-crop.pjl > paris-crop.gcode 2>/tmp/p 16 | 17 | TSV lobby 18 | 3m high 19 | 7m wide 20 | diagonal 4609.7722 21 | ./polargraph -F 6000 -f 4000 -w 7000 -l 4609 --offset-x 0 --offset-y 0 22 | -------------------------------------------------------------------------------- /axiplot: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | from pyaxidraw import axidraw 3 | from math import sqrt 4 | import sys 5 | 6 | verbose = False 7 | 8 | ad = axidraw.AxiDraw() 9 | ad.interactive() 10 | ad.options.units = 2 # mm instead of inches 11 | ad.options.model = 2 # AxiDraw V3/A3 12 | ad.options.speed_penup = 100 # full speed MOVETO 13 | ad.options.speed_pendown = 50 # half speed LINETO 14 | 15 | ad.connect() 16 | 17 | # The output of vecsort is ASCII lines of the format 18 | # P r g b -- Power level, or layer change (could pause here) 19 | # M x y -- Move to x y coordinate 20 | # L x y -- Line from the current positoin to the new coordinates 21 | lines = sys.stdin.readlines() 22 | total_draw = 0 23 | total_move = 0 24 | ox = 0 25 | oy = 0 26 | for line in lines: 27 | words = line.split(' ') 28 | if len(words) < 3: 29 | continue 30 | 31 | cmd = words[0] 32 | x = float(words[1]) 33 | y = float(words[2]) 34 | dx = x - ox 35 | dy = y - oy 36 | dist = sqrt(dx*dx + dy*dy) 37 | 38 | if cmd == 'M': 39 | total_move += dist 40 | ox = x 41 | oy = y 42 | elif cmd =='L': 43 | total_draw += dist 44 | ox = x 45 | oy = y 46 | 47 | print("Distance %.2f + %.2f\n" % (total_draw, total_move)) 48 | 49 | ox = 0 50 | oy = 0 51 | draw = 0 52 | move = 0 53 | for line in lines: 54 | words = line.split(' ') 55 | if len(words) < 3: 56 | #print(len(words), words) 57 | continue 58 | cmd = words[0] 59 | x = float(words[1]) 60 | y = float(words[2]) 61 | dx = x - ox 62 | dy = y - oy 63 | ox = x 64 | oy = y 65 | dist = sqrt(dx*dx + dy*dy) 66 | 67 | if cmd == 'M': 68 | if verbose: print("MOVE %.3f %.3f" % (x,y), file=sys.stderr) 69 | move += dist 70 | ad.moveto(x,y) 71 | elif cmd =='L': 72 | if verbose: print("LINE %.3f %.3f" % (x,y), file=sys.stderr) 73 | draw += dist 74 | ad.lineto(x,y) 75 | 76 | print("%6.2f%%: draw %9.2f / %6.0f move %9.2f / %6.0f " % ( 77 | 100.0 * (draw + move) / (total_draw + total_move), 78 | draw, 79 | total_draw, 80 | move, 81 | total_move 82 | ), file=sys.stderr, end='\r'); 83 | 84 | 85 | print("", file=sys.stderr) 86 | 87 | ad.moveto(0,0) 88 | ad.usb_command("EM,0,0\r") # Turn off the motors 89 | ad.disconnect() 90 | -------------------------------------------------------------------------------- /carriage.scad: -------------------------------------------------------------------------------- 1 | // Holds a standard Expo whiteboard marker 2 | // tapers from 16 to 17 mm 3 | 4 | $fn=60; 5 | 6 | // Pen holder in the middle 7 | module holder(d1, d2, endcap) 8 | { 9 | render() difference() 10 | { 11 | // outside 12 | cylinder(d=d2+4, h=20); 13 | 14 | // shaft 15 | translate([0,0,endcap ? 1 : -1]) 16 | cylinder(d1=d1, d2=d2, h=22); 17 | 18 | // M3 set screw, just in case 19 | if(false) 20 | translate([0,5,5]) 21 | rotate([-90,0,0]) 22 | cylinder(d=3.25, h=10); 23 | 24 | // string holes 25 | translate([0,0,10]) 26 | for(angle=[-60,60]) 27 | { 28 | rotate([90,0,angle]) { 29 | translate([-3,0,0]) cylinder(d=3.25, h=20); 30 | translate([+3,0,0]) cylinder(d=3.25, h=20); 31 | } 32 | } 33 | } 34 | } 35 | 36 | translate([-13,0,0]) holder(20,21, true); 37 | translate([+13,0,0]) holder(18,19, false); 38 | 39 | 40 | /* 41 | // outer ring 42 | render() difference() 43 | { 44 | cylinder(d=100, h=2); 45 | translate([0,0,-1]) cylinder(d=90, h=4); 46 | } 47 | 48 | 49 | // spokes 50 | for(a=[0,120,240]) 51 | rotate([0,0,a]) 52 | render() difference() 53 | { 54 | translate([0,55/2,1]) cube([10,38,2], center=true); 55 | 56 | // mounting holes for the wires 57 | for(i=[20,30,40]) 58 | translate([0,i,-1]) cylinder(d=2, h=4); 59 | } 60 | */ 61 | -------------------------------------------------------------------------------- /go-xy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # Send the polargraph to a known location. 3 | # This will attempt to iterate to draw straight (not curved) lines, 4 | # but the tinyg doesn't seem to handle it well. 5 | use warnings; 6 | use strict; 7 | 8 | # origin is at l1=800 l2=800 9 | # xy = 600,500 or so 10 | # separation between the two is 1120 11 | 12 | my $w = 1120; 13 | my $feed = 10000; 14 | my $step_size = 40; 15 | 16 | my $x0 = shift; 17 | my $y0 = shift; 18 | 19 | my $x1 = shift; 20 | my $y1 = shift; 21 | 22 | unless($x1) 23 | { 24 | # go straight to the positoin 25 | goxy($x0,$y0); 26 | } else { 27 | # iterate from x0,y0 to x1,y1 28 | my $dx = $x1 - $x0; 29 | my $dy = $y1 - $y0; 30 | my $dist = sqrt($dx*$dx+$dy*$dy); 31 | 32 | my $steps = int($dist/$step_size); 33 | for(my $i = 0 ; $i < $steps ; $i++) 34 | { 35 | $x0 += $dx / $steps; 36 | $y0 += $dy / $steps; 37 | goxy($x0,$y0); 38 | #sleep(1); 39 | } 40 | 41 | goxy($x1,$y1); 42 | } 43 | 44 | 45 | sub goxy 46 | { 47 | my $x = shift; 48 | my $y = shift; 49 | 50 | my $l1 = sqrt(($w-$x)*($w-$x) + $y*$y); 51 | my $l2 = sqrt($x*$x + $y*$y); 52 | 53 | printf STDERR "%.3f %.3f -> %.3f %.3f\n", $x, $y, $l1, $l2; 54 | printf "G1 X%.3f Y%.3f F%d\n", $l1, $l2, $feed; 55 | } 56 | -------------------------------------------------------------------------------- /nycr.pjl: -------------------------------------------------------------------------------- 1 | PU1390,1391 2 | PD1311,1472,1234,1554,1159,1639,1086,1725,1015,1814,946,1904,879,1995,815,2088,752,2183,692,2280,634,2378,579,2477,525,2578,474,2680,426,2784,380,2889,336,2996,296,3103,257,3212,221,3322,188,3434,158,3546,130,3660,105,3774,83,3890,64,4007,47,4124,34,4242,23,4362,16,4482,11,4603,9,4725,11,4846,16,4967,23,5087,34,5207,47,5325,64,5443,83,5559,105,5675,130,5789,158,5903,188,6015,221,6127,257,6237,296,6346,336,6453,380,6560,426,6665,474,6769,525,6871,579,6972,634,7071,692,7169,752,7266,815,7361,879,7454,946,7546,1015,7636,1086,7724,1159,7810,1234,7895,1311,7978,1390,8059,1471,8138,1554,8215,1639,8290,1725,8363,1813,8434,1903,8503,1995,8570,2088,8634,2183,8697,2280,8757,2378,8815,2477,8870,2578,8924,2680,8975,2784,9023,2889,9069,2996,9112,3103,9153,3212,9192,3322,9228,3434,9261,3546,9291,3660,9319,3774,9344,3890,9366,4006,9385,4124,9402,4242,9415,4362,9426,4482,9433,4603,9438,4724,9440,4846,9438,4967,9433,5087,9426,5206,9415,5325,9402,5442,9385,5559,9366,5675,9344,5789,9319,5903,9291,6015,9261,6126,9228,6237,9192,6346,9153,6453,9112,6560,9069,6665,9023,6769,8975,6871,8924,6972,8870,7071,8815,7169,8757,7266,8697,7361,8634,7454,8570,7545,8503,7635,8434,7724,8363,7810,8290,7895,8215,7977,8138,8058,8059,8137,7978,8215,7895,8290,7810,8363,7724,8434,7636,8503,7546,8569,7454,8634,7361,8697,7266,8757,7169,8815,7071,8870,6972,8924,6871,8974,6769,9023,6665,9069,6560,9112,6453,9153,6346,9192,6237,9227,6127,9261,6015,9291,5903,9319,5789,9344,5675,9366,5559,9385,5443,9401,5325,9415,5207,9426,5087,9433,4967,9438,4846,9439,4725,9438,4603,9433,4482,9426,4362,9415,4242,9401,4124,9385,4007,9366,3890,9344,3774,9319,3660,9291,3546,9261,3434,9227,3322,9192,3212,9153,3103,9112,2996,9069,2889,9023,2784,8974,2680,8924,2578,8870,2477,8815,2378,8757,2280,8697,2183,8634,2088,8569,1995,8503,1904,8434,1814,8363,1725,8290,1639,8215,1554,8137,1472,8058,1391,7977,1312,7895,1234,7810,1159,7724,1086,7635,1015,7545,946,7454,879,7361,815,7266,752,7169,692,7071,634,6972,579,6871,525,6769,475,6665,426,6560,380,6453,337,6346,296,6237,257,6126,222,6015,188,5903,158,5789,130,5675,105,5559,83,5442,64,5325,47,5206,34,5087,23,4967,16,4846,11,4724,10,4603,11,4482,16,4362,23,4242,34,4124,47,4006,64,3890,83,3774,105,3660,130,3546,158,3434,188,3322,222,3212,257,3103,296,2996,337,2889,380,2784,426,2680,475,2578,525,2477,579,2378,634,2280,692,2183,752,2088,815,1995,879,1903,946,1813,1015,1725,1086,1639,1159,1554,1234,1471,1312,1390,1391 3 | PU2723,1611 4 | PD2989,1611,3636,2832,3636,1611,3827,1611,3827,3070,3561,3070,2914,1849,2914,3070,2723,3070,2723,1611 5 | PU4020,1611 6 | PD4232,1611,4637,2211,5039,1611,5251,1611,4735,2375,4735,3070,4536,3070,4536,2375,4020,1611 7 | PU5298,2027 8 | PD5287,2062,5278,2099,5269,2136,5263,2175,5257,2215,5254,2256,5252,2298,5251,2342,5252,2385,5254,2427,5257,2468,5263,2508,5269,2547,5278,2584,5287,2621,5298,2656,5311,2690,5325,2723,5341,2755,5358,2785,5377,2815,5397,2843,5418,2870,5441,2896,5466,2921,5491,2944,5518,2965,5546,2985,5574,3003,5604,3019,5635,3034,5667,3048,5700,3060,5735,3070,5770,3079,5807,3086,5844,3091,5883,3095,5923,3098,5963,3098,6027,3096,6089,3090,6149,3079,6208,3063,6265,3043,6321,3019,6375,2991,6428,2958,6428,2751,6377,2795,6325,2833,6271,2864,6215,2890,6158,2910,6099,2925,6038,2933,5975,2936,5944,2936,5914,2934,5885,2931,5857,2927,5830,2921,5804,2915,5779,2907,5754,2898,5731,2888,5708,2877,5687,2864,5666,2850,5646,2836,5627,2819,5609,2802,5592,2784,5576,2764,5561,2743,5547,2721,5534,2698,5522,2675,5511,2650,5501,2624,5492,2596,5484,2568,5478,2539,5472,2509,5467,2478,5464,2445,5461,2412,5460,2377,5459,2342,5460,2306,5461,2272,5464,2238,5467,2206,5472,2174,5478,2144,5484,2115,5492,2087,5501,2060,5511,2034,5522,2009,5534,1985,5547,1962,5561,1940,5576,1920,5592,1900,5609,1881,5627,1864,5646,1848,5666,1833,5687,1819,5708,1806,5731,1795,5754,1785,5779,1776,5804,1768,5830,1761,5857,1756,5885,1752,5914,1749,5944,1747,5975,1746,6038,1749,6099,1758,6158,1772,6215,1792,6271,1818,6325,1850,6377,1888,6428,1931,6428,1723,6376,1690,6322,1662,6267,1639,6210,1619,6151,1604,6091,1593,6028,1586,5963,1584,5923,1585,5883,1587,5844,1591,5807,1597,5770,1604,5735,1613,5700,1623,5667,1635,5635,1648,5604,1664,5574,1680,5546,1699,5518,1718,5491,1740,5466,1763,5441,1788,5418,1813,5397,1840,5377,1869,5358,1898,5341,1929,5325,1960,5311,1993,5298,2027 9 | PU5078,3651 10 | PD5984,5742,6710,3652,7241,4880,7889,4880 11 | PU7912,4884 12 | PD7912,4859,7912,4835,7914,4810,7917,4786,7921,4763,7927,4739,7933,4716,7941,4694,7949,4672,7959,4651,7970,4630,7981,4610,7994,4591,8007,4572,8021,4554,8037,4536,8053,4519,8069,4503,8087,4488,8105,4474,8124,4461,8143,4448,8163,4436,8184,4426,8205,4416,8227,4408,8250,4400,8272,4394,8296,4388,8319,4384,8343,4381,8368,4379,8393,4378,8417,4379,8442,4381,8466,4384,8490,4388,8513,4394,8536,4400,8558,4408,8580,4416,8601,4426,8622,4436,8642,4448,8662,4461,8680,4474,8699,4488,8716,4503,8733,4519,8749,4536,8764,4554,8778,4572,8792,4591,8804,4610,8816,4630,8826,4651,8836,4672,8844,4694,8852,4716,8859,4739,8864,4763,8868,4786,8871,4810,8873,4835,8874,4859,8873,4884,8871,4909,8868,4933,8864,4956,8859,4980,8852,5003,8844,5025,8836,5047,8826,5068,8816,5089,8804,5109,8792,5128,8778,5147,8764,5165,8749,5183,8733,5200,8716,5216,8699,5231,8680,5245,8662,5258,8642,5271,8622,5282,8601,5293,8580,5303,8558,5311,8536,5319,8513,5325,8490,5331,8466,5335,8442,5338,8417,5340,8393,5341,8368,5340,8343,5338,8319,5335,8296,5331,8272,5325,8250,5319,8227,5311,8205,5303,8184,5293,8163,5282,8143,5271,8124,5258,8105,5245,8087,5231,8069,5216,8053,5200,8037,5183,8021,5165,8007,5147,7994,5128,7981,5109,7970,5089,7959,5068,7949,5047,7941,5025,7933,5003,7927,4980,7921,4956,7917,4933,7914,4909,7912,4884 13 | PU8121,4859 14 | PD8123,4832,8127,4805,8134,4779,8143,4754,8154,4730,8168,4708,8183,4687,8201,4668,8220,4650,8241,4634,8263,4621,8287,4609,8312,4600,8338,4594,8365,4590,8393,4588,8420,4590,8447,4594,8473,4600,8498,4609,8522,4621,8544,4634,8565,4650,8585,4668,8602,4687,8618,4708,8631,4730,8643,4754,8652,4779,8658,4805,8663,4832,8664,4859,8663,4887,8658,4914,8652,4940,8643,4965,8631,4989,8618,5011,8602,5032,8585,5051,8565,5069,8544,5084,8522,5098,8498,5110,8473,5119,8447,5125,8420,5129,8393,5131,8365,5129,8338,5125,8312,5119,8287,5110,8263,5098,8241,5084,8220,5069,8201,5051,8183,5032,8168,5011,8154,4989,8143,4965,8134,4940,8127,4914,8123,4887,8121,4859 15 | PU7821,6505 16 | PD7785,6500,7747,6497,7707,6495,7407,6495,7407,7475,7540,7475,7540,7061,7684,7061,7703,7062,7722,7063,7739,7066,7755,7069,7770,7074,7784,7079,7797,7086,7808,7093,7820,7103,7832,7114,7843,7127,7855,7142,7867,7160,7879,7179,7891,7200,7903,7224,8028,7475,8171,7475,8036,7208,8016,7169,7995,7134,7975,7104,7955,7078,7935,7056,7914,7039,7893,7025,7872,7016,7892,7009,7911,7002,7928,6993,7944,6983,7959,6972,7973,6959,7985,6946,7997,6931,8007,6916,8016,6899,8023,6881,8029,6862,8034,6843,8037,6822,8039,6800,8040,6778,8039,6743,8035,6711,8028,6681,8019,6654,8008,6628,7994,6605,7977,6584,7957,6566,7935,6549,7911,6535,7883,6523,7853,6513,7821,6505 17 | PU7791,6615 18 | PD7808,6622,7824,6629,7838,6638,7851,6648,7863,6660,7873,6673,7881,6687,7888,6702,7893,6719,7897,6737,7899,6757,7900,6778,7899,6799,7897,6818,7893,6836,7888,6853,7881,6869,7873,6883,7863,6897,7851,6908,7838,6919,7824,6928,7808,6935,7791,6941,7772,6946,7752,6950,7730,6952,7707,6952,7540,6952,7540,6604,7707,6604,7730,6605,7752,6607,7772,6611,7791,6615 19 | PU7169,6778 20 | PD7152,6733,7130,6691,7105,6652,7076,6616,7044,6584,7010,6556,6972,6532,6932,6512,6890,6497,6845,6486,6797,6480,6747,6478,6697,6480,6649,6486,6604,6497,6561,6512,6521,6532,6483,6556,6448,6584,6416,6616,6387,6652,6362,6691,6341,6733,6324,6778,6310,6825,6300,6876,6295,6930,6293,6986,6295,7043,6300,7097,6310,7147,6324,7195,6341,7240,6362,7282,6387,7321,6416,7357,6448,7389,6483,7417,6521,7441,6561,7460,6604,7475,6649,7486,6697,7492,6747,7495,6797,7492,6845,7486,6890,7475,6932,7460,6972,7441,7010,7417,7044,7389,7076,7357,7105,7321,7130,7282,7152,7240,7169,7195,7183,7147,7192,7096,7198,7043,7200,6986,7198,6930,7192,6876,7183,6825,7169,6778 21 | PU7039,6820 22 | PD7048,6858,7055,6898,7059,6941,7060,6986,7059,7032,7055,7074,7048,7114,7039,7152,7027,7188,7012,7221,6995,7251,6975,7279,6953,7304,6930,7326,6904,7345,6876,7360,6847,7372,6815,7380,6782,7385,6747,7387,6712,7385,6678,7380,6647,7372,6617,7360,6590,7345,6564,7326,6539,7304,6517,7279,6497,7251,6480,7221,6466,7188,6454,7152,6444,7114,6438,7074,6434,7032,6433,6986,6434,6941,6438,6898,6444,6858,6454,6820,6466,6785,6480,6752,6497,6721,6517,6693,6539,6668,6564,6646,6590,6627,6617,6612,6647,6601,6678,6592,6712,6587,6747,6585,6782,6587,6815,6592,6847,6601,6876,6612,6904,6627,6930,6646,6953,6668,6975,6693,6995,6721,7012,6752,7027,6785,7039,6820 23 | PU6221,6607 24 | PD6221,6495,5391,6495,5391,6607,5739,6607,5739,7475,5873,7475,5873,6607,6221,6607 25 | PU5262,6657 26 | PD5262,6528,5188,6506,5115,6490,5044,6481,4975,6478,4936,6479,4899,6482,4864,6488,4831,6496,4801,6507,4772,6520,4746,6535,4722,6553,4701,6572,4682,6593,4666,6616,4654,6641,4644,6668,4636,6696,4632,6726,4631,6757,4632,6785,4635,6810,4640,6835,4647,6857,4657,6878,4668,6898,4681,6916,4697,6933,4715,6948,4735,6962,4758,6975,4784,6987,4812,6998,4843,7008,4876,7017,4912,7025,4992,7041,5017,7046,5039,7052,5060,7059,5079,7066,5096,7074,5112,7083,5126,7092,5137,7102,5148,7113,5157,7124,5165,7137,5171,7151,5176,7165,5179,7181,5181,7197,5182,7215,5181,7235,5178,7254,5173,7272,5167,7288,5158,7303,5147,7318,5135,7330,5120,7342,5104,7353,5086,7362,5067,7369,5046,7376,5023,7381,4999,7384,4973,7386,4945,7387,4908,7385,4870,7381,4831,7374,4793,7364,4754,7351,4715,7335,4675,7317,4635,7296,4635,7432,4676,7447,4717,7459,4757,7470,4797,7479,4836,7486,4873,7491,4910,7494,4945,7495,4990,7493,5032,7490,5071,7484,5107,7476,5141,7466,5172,7453,5200,7438,5225,7421,5247,7402,5267,7380,5283,7356,5297,7330,5307,7302,5315,7272,5319,7240,5321,7205,5319,7176,5316,7148,5311,7122,5303,7098,5293,7075,5281,7053,5266,7033,5250,7015,5231,6997,5210,6982,5186,6967,5160,6954,5131,6942,5100,6932,5067,6923,5031,6915,4951,6898,4925,6893,4901,6888,4879,6881,4859,6875,4842,6868,4827,6861,4814,6853,4803,6845,4794,6836,4786,6827,4779,6816,4774,6804,4769,6791,4766,6777,4765,6763,4764,6747,4765,6728,4768,6710,4772,6694,4779,6678,4787,6664,4797,6651,4809,6638,4822,6627,4838,6618,4855,6609,4874,6602,4894,6596,4915,6591,4939,6588,4963,6586,4990,6585,5021,6586,5053,6590,5086,6595,5119,6603,5153,6613,5188,6625,5224,6640,5262,6657 27 | PU4410,6495 28 | PD4410,7475,4278,7475,4278,6495,4410,6495 29 | PU4012,6528 30 | PD4012,6657,3974,6640,3938,6625,3903,6613,3869,6603,3836,6595,3803,6590,3771,6586,3740,6585,3714,6586,3689,6588,3666,6591,3644,6596,3624,6602,3605,6609,3588,6618,3573,6627,3559,6638,3547,6651,3537,6664,3529,6678,3522,6694,3518,6710,3515,6728,3514,6747,3515,6763,3517,6777,3520,6791,3524,6804,3529,6816,3536,6827,3544,6836,3553,6845,3564,6853,3577,6861,3592,6868,3610,6875,3629,6881,3651,6888,3675,6893,3701,6898,3781,6915,3817,6923,3851,6932,3882,6942,3910,6954,3936,6967,3960,6982,3981,6997,4000,7015,4017,7033,4031,7053,4043,7075,4053,7098,4061,7122,4066,7148,4070,7176,4071,7205,4069,7240,4065,7272,4057,7302,4047,7330,4033,7356,4017,7380,3997,7402,3975,7421,3950,7438,3922,7453,3891,7466,3857,7476,3821,7484,3782,7490,3740,7493,3695,7495,3660,7494,3623,7491,3586,7486,3547,7479,3508,7470,3467,7459,3426,7447,3385,7432,3385,7296,3425,7317,3465,7335,3504,7351,3543,7364,3582,7374,3620,7381,3658,7385,3695,7387,3723,7386,3749,7384,3773,7381,3796,7376,3817,7369,3837,7362,3854,7353,3871,7342,3885,7330,3898,7318,3908,7303,3917,7288,3924,7272,3928,7254,3931,7235,3932,7215,3932,7197,3930,7181,3926,7165,3921,7151,3915,7137,3907,7124,3898,7113,3888,7102,3876,7092,3862,7083,3847,7074,3829,7066,3810,7059,3790,7052,3767,7046,3743,7041,3662,7025,3626,7017,3593,7008,3562,6998,3534,6987,3508,6975,3485,6962,3465,6948,3447,6933,3432,6916,3418,6898,3407,6878,3397,6857,3390,6835,3385,6810,3382,6785,3381,6757,3382,6726,3387,6696,3394,6668,3404,6641,3417,6616,3432,6593,3451,6572,3472,6553,3496,6535,3522,6520,3551,6507,3581,6496,3614,6488,3649,6482,3686,6479,3725,6478,3794,6481,3865,6490,3938,6506,4012,6528 31 | PU3193,6495 32 | PD2574,6495,2574,7475,3205,7475,3205,7364,2706,7364,2706,7009,3173,7009,3173,6897,2706,6897,2706,6607,3193,6607,3193,6495 33 | PU2722,5742 34 | PD2191,4515,1505,4515 35 | PU1520,4511 36 | PD1520,4535,1520,4560,1518,4585,1515,4609,1511,4632,1505,4656,1499,4678,1491,4701,1483,4723,1473,4744,1462,4765,1451,4785,1438,4804,1425,4823,1411,4841,1395,4859,1379,4876,1363,4891,1345,4907,1327,4921,1308,4934,1289,4947,1269,4958,1248,4969,1227,4979,1205,4987,1182,4995,1160,5001,1136,5007,1113,5011,1089,5014,1064,5016,1039,5016,1015,5016,990,5014,966,5011,942,5007,919,5001,896,4995,874,4987,852,4979,831,4969,810,4958,790,4947,770,4934,752,4921,733,4907,716,4891,699,4876,683,4859,668,4841,654,4823,640,4804,628,4785,616,4765,606,4744,596,4723,587,4701,580,4678,573,4656,568,4632,564,4609,561,4585,559,4560,558,4535,559,4511,561,4486,564,4462,568,4438,573,4415,580,4392,587,4370,596,4348,606,4327,616,4306,628,4286,640,4266,654,4248,668,4229,683,4212,699,4195,716,4179,733,4164,752,4150,770,4136,790,4124,810,4112,831,4102,852,4092,874,4084,896,4076,919,4069,942,4064,966,4060,990,4057,1015,4055,1039,4054,1064,4055,1089,4057,1113,4060,1136,4064,1160,4069,1182,4076,1205,4084,1227,4092,1248,4102,1269,4112,1289,4124,1308,4136,1327,4150,1345,4164,1363,4179,1379,4195,1395,4212,1411,4229,1425,4248,1438,4266,1451,4286,1462,4306,1473,4327,1483,4348,1491,4370,1499,4392,1505,4415,1511,4438,1515,4462,1518,4486,1520,4511 37 | PU1311,4535 38 | PD1309,4563,1305,4590,1298,4616,1289,4641,1278,4665,1264,4687,1249,4708,1231,4727,1212,4745,1191,4760,1169,4774,1145,4785,1120,4795,1094,4801,1067,4805,1039,4807,1012,4805,985,4801,959,4795,934,4785,910,4774,888,4760,867,4745,847,4727,830,4708,814,4687,801,4665,789,4641,780,4616,773,4590,769,4563,768,4535,769,4508,773,4481,780,4455,789,4430,801,4406,814,4384,830,4363,847,4344,867,4326,888,4310,910,4297,934,4285,959,4276,985,4270,1012,4265,1039,4264,1067,4265,1094,4270,1120,4276,1145,4285,1169,4297,1191,4310,1212,4326,1231,4344,1249,4363,1264,4384,1278,4406,1289,4430,1298,4455,1305,4481,1309,4508,1311,4535 39 | PU2722,5742 40 | PD3448,3652,4352,5742,5078,3651 41 | PU2208,6584 42 | PD2189,6566,2167,6549,2142,6535,2115,6523,2085,6513,2052,6505,2017,6500,1979,6497,1938,6495,1639,6495,1639,7475,1771,7475,1771,7061,1916,7061,1935,7062,1953,7063,1970,7066,1986,7069,2001,7074,2015,7079,2028,7086,2040,7093,2051,7103,2063,7114,2075,7127,2086,7142,2098,7160,2110,7179,2122,7200,2134,7224,2260,7475,2402,7475,2268,7208,2247,7169,2227,7134,2207,7104,2186,7078,2166,7056,2146,7039,2125,7025,2104,7016,2123,7009,2142,7002,2160,6993,2176,6983,2191,6972,2204,6959,2217,6946,2228,6931,2238,6916,2247,6899,2255,6881,2261,6862,2265,6843,2269,6822,2271,6800,2272,6778,2270,6743,2266,6711,2260,6681,2251,6654,2239,6628,2225,6605,2208,6584 43 | PU2104,6673 44 | PD2113,6687,2119,6702,2125,6719,2129,6737,2131,6757,2132,6778,2131,6799,2129,6818,2125,6836,2119,6853,2113,6869,2104,6883,2094,6897,2083,6908,2070,6919,2055,6928,2039,6935,2022,6941,2003,6946,1983,6950,1961,6952,1938,6952,1771,6952,1771,6604,1938,6604,1961,6605,1983,6607,2003,6611,2022,6615,2039,6622,2055,6629,2070,6638,2083,6648,2094,6660,2104,6673 45 | -------------------------------------------------------------------------------- /pdf2vec: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # Convert a PDF file into a list of vectors. 3 | use warnings; 4 | use strict; 5 | use IPC::Open2; 6 | use Data::Dumper; 7 | use File::Temp 'tempfile'; 8 | 9 | my $file = shift || '-'; 10 | my $dpi = 600; 11 | my $scale = 25.4 / $dpi; 12 | 13 | # Postscript code to extract numbers 14 | my $ps_code = <) 120 | { 121 | # convert M and L positions from pixels to positions 122 | if(/^([ML])\s*(\d+)\s+(\d+)$/) 123 | { 124 | printf "%s %.3f %.3f\n", $1, $2*$scale, $3*$scale; 125 | next; 126 | } 127 | 128 | print; 129 | } 130 | 131 | __END__ 132 | -------------------------------------------------------------------------------- /peano.pjl: -------------------------------------------------------------------------------- 1 | PU89,15 2 | PD15,90,15,164,89,239,15,314,15,389,89,463,164,463,239,389,388,538,314,613,239,688,164,613,89,613,15,688,15,762,89,837,15,912,15,987,89,1061,164,1061,239,987,314,1061,388,1061,463,987,463,912,388,837,538,688,613,762,687,837,613,912,613,987,687,1061,762,1061,837,987,912,1061,986,1136,912,1211,837,1286,762,1211,687,1211,613,1286,613,1360,687,1435,613,1510,538,1585,388,1435,463,1360,463,1286,388,1211,314,1211,239,1286,164,1211,89,1211,15,1286,15,1360,89,1435,15,1510,15,1585,89,1659,164,1659,239,1585,314,1659,388,1734,239,1884,164,1809,89,1809,15,1884,15,1959,89,2033,15,2108,15,2183,89,2258,164,2258,239,2183,314,2258,388,2258,463,2183,463,2108,388,2033,463,1959,538,1884,613,1959,687,2033,613,2108,613,2183,687,2258,762,2258,837,2183,912,2258,986,2258,1061,2183,1061,2108,986,2033,1061,1959,1061,1884,986,1809,912,1809,837,1884,687,1734,762,1659,837,1585,912,1659,986,1659,1061,1585,1061,1510,986,1435,1061,1360,1136,1286,1211,1360,1285,1435,1211,1510,1211,1585,1285,1659,1360,1659,1435,1585,1510,1659,1585,1734,1435,1884,1360,1809,1285,1809,1211,1884,1211,1959,1285,2033,1211,2108,1211,2183,1285,2258,1360,2258,1435,2183,1510,2258,1585,2258,1659,2183,1659,2108,1585,2033,1659,1959,1734,1884,1809,1959,1884,2033,1809,2108,1809,2183,1884,2258,1958,2258,2033,2183,2108,2258,2183,2332,2108,2407,2033,2482,1958,2407,1884,2407,1809,2482,1809,2557,1884,2631,1809,2706,1734,2781,1585,2631,1659,2557,1659,2482,1585,2407,1510,2407,1435,2482,1360,2407,1285,2407,1211,2482,1211,2557,1285,2631,1211,2706,1211,2781,1285,2856,1360,2856,1435,2781,1510,2856,1585,2930,1435,3080,1360,3005,1285,3005,1211,3080,1211,3155,1285,3229,1136,3379,1061,3304,986,3229,1061,3155,1061,3080,986,3005,912,3005,837,3080,687,2930,762,2856,837,2781,912,2856,986,2856,1061,2781,1061,2706,986,2631,1061,2557,1061,2482,986,2407,912,2407,837,2482,762,2407,687,2407,613,2482,613,2557,687,2631,538,2781,463,2706,388,2631,463,2557,463,2482,388,2407,314,2407,239,2482,164,2407,89,2407,15,2482,15,2557,89,2631,15,2706,15,2781,89,2856,164,2856,239,2781,314,2856,388,2930,239,3080,164,3005,89,3005,15,3080,15,3155,89,3229,15,3304,15,3379,89,3454,164,3454,239,3379,314,3454,388,3454,463,3379,463,3304,388,3229,463,3155,538,3080,687,3229,613,3304,613,3379,687,3454,762,3454,837,3379,986,3528,912,3603,837,3678,762,3603,687,3603,613,3678,613,3753,687,3828,613,3902,538,3977,463,3902,388,3828,463,3753,463,3678,388,3603,314,3603,239,3678,164,3603,89,3603,15,3678,15,3753,89,3828,15,3902,15,3977,89,4052,164,4052,239,3977,388,4127,314,4201,239,4276,164,4201,89,4201,15,4276,15,4351,89,4426,15,4500,15,4575,89,4650,164,4650,239,4575,314,4650,388,4650,463,4575,463,4500,388,4426,538,4276,613,4351,687,4426,613,4500,613,4575,687,4650,762,4650,837,4575,912,4650,986,4650,1061,4575,1061,4500,986,4426,1061,4351,1061,4276,986,4201,912,4201,837,4276,762,4201,687,4127,837,3977,912,4052,986,4052,1061,3977,1061,3902,986,3828,1061,3753,1136,3678,1285,3828,1211,3902,1211,3977,1285,4052,1360,4052,1435,3977,1585,4127,1510,4201,1435,4276,1360,4201,1285,4201,1211,4276,1211,4351,1285,4426,1211,4500,1211,4575,1285,4650,1360,4650,1435,4575,1510,4650,1585,4650,1659,4575,1659,4500,1585,4426,1659,4351,1734,4276,1884,4426,1809,4500,1809,4575,1884,4650,1958,4650,2033,4575,2108,4650,2183,4650,2257,4575,2257,4500,2183,4426,2257,4351,2257,4276,2183,4201,2108,4201,2033,4276,1958,4201,1884,4127,2033,3977,2108,4052,2183,4052,2257,3977,2257,3902,2183,3828,2257,3753,2257,3678,2183,3603,2108,3603,2033,3678,1958,3603,1884,3603,1809,3678,1809,3753,1884,3828,1809,3902,1734,3977,1659,3902,1585,3828,1659,3753,1659,3678,1585,3603,1510,3603,1435,3678,1360,3603,1285,3528,1435,3379,1510,3454,1585,3454,1659,3379,1659,3304,1585,3229,1734,3080,1809,3155,1884,3229,1809,3304,1809,3379,1884,3454,1958,3454,2033,3379,2108,3454,2183,3454,2257,3379,2257,3304,2183,3229,2257,3155,2257,3080,2183,3005,2108,3005,2033,3080,1884,2930,1958,2856,2033,2781,2108,2856,2183,2856,2257,2781,2257,2706,2183,2631,2257,2557,2332,2482,2482,2631,2407,2706,2407,2781,2482,2856,2556,2856,2631,2781,2706,2856,2781,2930,2706,3005,2631,3080,2556,3005,2482,3005,2407,3080,2407,3155,2482,3229,2407,3304,2407,3379,2482,3454,2556,3454,2631,3379,2706,3454,2781,3454,2855,3379,2855,3304,2781,3229,2855,3155,2930,3080,3005,3155,3080,3229,3005,3304,3005,3379,3080,3454,3154,3454,3229,3379,3304,3454,3379,3528,3229,3678,3154,3603,3080,3603,3005,3678,3005,3753,3080,3828,2930,3977,2781,3828,2855,3753,2855,3678,2781,3603,2706,3603,2631,3678,2556,3603,2482,3603,2407,3678,2407,3753,2482,3828,2407,3902,2407,3977,2482,4052,2556,4052,2631,3977,2706,4052,2781,4127,2631,4276,2556,4201,2482,4201,2407,4276,2407,4351,2482,4426,2407,4500,2407,4575,2482,4650,2556,4650,2631,4575,2706,4650,2781,4650,2855,4575,2855,4500,2781,4426,2855,4351,2930,4276,3005,4351,3080,4426,3005,4500,3005,4575,3080,4650,3154,4650,3229,4575,3304,4650,3379,4650,3453,4575,3453,4500,3379,4426,3453,4351,3453,4276,3379,4201,3304,4201,3229,4276,3080,4127,3154,4052,3229,3977,3304,4052,3379,4052,3453,3977,3453,3902,3379,3828,3453,3753,3528,3678,3603,3753,3678,3828,3603,3902,3603,3977,3678,4052,3753,4052,3827,3977,3902,4052,3977,4127,3902,4201,3827,4276,3753,4201,3678,4201,3603,4276,3603,4351,3678,4426,3603,4500,3603,4575,3678,4650,3753,4650,3827,4575,3902,4650,3977,4650,4052,4575,4052,4500,3977,4426,4052,4351,4126,4276,4201,4351,4276,4426,4201,4500,4201,4575,4276,4650,4351,4650,4425,4575,4500,4650,4575,4725,4500,4799,4425,4874,4351,4799,4276,4799,4201,4874,4201,4949,4276,5024,4201,5098,4126,5173,3977,5024,4052,4949,4052,4874,3977,4799,3902,4799,3827,4874,3753,4799,3678,4799,3603,4874,3603,4949,3678,5024,3603,5098,3603,5173,3678,5248,3753,5248,3827,5173,3902,5248,3977,5323,3902,5397,3827,5472,3753,5397,3678,5397,3603,5472,3603,5547,3678,5622,3603,5696,3528,5771,3453,5696,3379,5622,3453,5547,3453,5472,3379,5397,3304,5397,3229,5472,3080,5323,3229,5173,3304,5248,3379,5248,3453,5173,3453,5098,3379,5024,3453,4949,3453,4874,3379,4799,3304,4799,3229,4874,3154,4799,3080,4799,3005,4874,3005,4949,3080,5024,2930,5173,2781,5024,2855,4949,2855,4874,2781,4799,2706,4799,2631,4874,2556,4799,2482,4799,2407,4874,2407,4949,2482,5024,2407,5098,2407,5173,2482,5248,2556,5248,2631,5173,2781,5323,2631,5472,2556,5397,2482,5397,2407,5472,2407,5547,2482,5622,2407,5696,2407,5771,2482,5846,2556,5846,2631,5771,2706,5846,2781,5846,2855,5771,2855,5696,2781,5622,2930,5472,3080,5622,3005,5696,3005,5771,3080,5846,3154,5846,3229,5771,3304,5846,3379,5921,3304,5996,3229,6070,3154,5996,3080,5996,3005,6070,3005,6145,3080,6220,3005,6295,2930,6369,2855,6295,2781,6220,2855,6145,2855,6070,2781,5996,2706,5996,2631,6070,2556,5996,2482,5996,2407,6070,2407,6145,2482,6220,2407,6295,2407,6369,2482,6444,2556,6444,2631,6369,2706,6444,2781,6519,2706,6594,2631,6668,2556,6594,2482,6594,2407,6668,2407,6743,2482,6818,2407,6893,2332,6967,2183,6818,2257,6743,2257,6668,2183,6594,2108,6594,2033,6668,1884,6519,1958,6444,2033,6369,2108,6444,2183,6444,2257,6369,2257,6295,2183,6220,2257,6145,2257,6070,2183,5996,2108,5996,2033,6070,1958,5996,1884,5996,1809,6070,1809,6145,1884,6220,1809,6295,1734,6369,1585,6220,1659,6145,1659,6070,1585,5996,1510,5996,1435,6070,1285,5921,1360,5846,1435,5771,1510,5846,1585,5846,1659,5771,1659,5696,1585,5622,1659,5547,1734,5472,1809,5547,1884,5622,1809,5696,1809,5771,1884,5846,1958,5846,2033,5771,2108,5846,2183,5846,2257,5771,2257,5696,2183,5622,2257,5547,2257,5472,2183,5397,2108,5397,2033,5472,1958,5397,1884,5323,1958,5248,2033,5173,2108,5248,2183,5248,2257,5173,2257,5098,2183,5024,2257,4949,2257,4874,2183,4799,2108,4799,2033,4874,1958,4799,1884,4799,1809,4874,1809,4949,1884,5024,1809,5098,1734,5173,1659,5098,1585,5024,1659,4949,1659,4874,1585,4799,1510,4799,1435,4874,1360,4799,1285,4799,1211,4874,1211,4949,1285,5024,1211,5098,1211,5173,1285,5248,1360,5248,1435,5173,1510,5248,1585,5323,1510,5397,1435,5472,1360,5397,1285,5397,1211,5472,1211,5547,1285,5622,1211,5696,1136,5771,986,5622,1061,5547,1061,5472,986,5397,912,5397,837,5472,762,5397,687,5323,762,5248,837,5173,912,5248,986,5248,1061,5173,1061,5098,986,5024,1061,4949,1061,4874,986,4799,912,4799,837,4874,762,4799,687,4799,613,4874,613,4949,687,5024,613,5098,538,5173,463,5098,388,5024,463,4949,463,4874,388,4799,314,4799,239,4874,164,4799,89,4799,15,4874,15,4949,89,5024,15,5098,15,5173,89,5248,164,5248,239,5173,314,5248,388,5323,314,5397,239,5472,164,5397,89,5397,15,5472,15,5547,89,5622,15,5696,15,5771,89,5846,164,5846,239,5771,314,5846,388,5846,463,5771,463,5696,388,5622,463,5547,538,5472,613,5547,687,5622,613,5696,613,5771,687,5846,762,5846,837,5771,912,5846,986,5921,837,6070,762,5996,687,5996,613,6070,613,6145,687,6220,538,6369,463,6295,388,6220,463,6145,463,6070,388,5996,314,5996,239,6070,164,5996,89,5996,15,6070,15,6145,89,6220,15,6295,15,6369,89,6444,164,6444,239,6369,314,6444,388,6519,239,6668,164,6594,89,6594,15,6668,15,6743,89,6818,15,6893,15,6967,89,7042,164,7042,239,6967,314,7042,388,7042,463,6967,463,6893,388,6818,463,6743,538,6668,687,6818,613,6893,613,6967,687,7042,762,7042,837,6967,912,7042,986,7042,1061,6967,1061,6893,986,6818,1061,6743,1061,6668,986,6594,912,6594,837,6668,687,6519,762,6444,837,6369,912,6444,986,6444,1061,6369,1061,6295,986,6220,1061,6145,1136,6070,1211,6145,1285,6220,1211,6295,1211,6369,1285,6444,1360,6444,1435,6369,1510,6444,1585,6519,1435,6668,1360,6594,1285,6594,1211,6668,1211,6743,1285,6818,1211,6893,1211,6967,1285,7042,1360,7042,1435,6967,1510,7042,1585,7042,1659,6967,1659,6893,1585,6818,1734,6668,1809,6743,1884,6818,1809,6893,1809,6967,1884,7042,1958,7042,2033,6967,2108,7042,2183,7117,2108,7192,2033,7266,1958,7192,1884,7192,1809,7266,1809,7341,1884,7416,1809,7491,1734,7565,1585,7416,1659,7341,1659,7266,1585,7192,1510,7192,1435,7266,1360,7192,1285,7192,1211,7266,1211,7341,1285,7416,1211,7491,1211,7565,1285,7640,1360,7640,1435,7565,1585,7715,1510,7790,1435,7865,1360,7790,1285,7790,1211,7865,1211,7939,1285,8014,1211,8089,1136,8164,1061,8089,986,8014,1061,7939,1061,7865,986,7790,912,7790,837,7865,762,7790,687,7715,837,7565,912,7640,986,7640,1061,7565,1061,7491,986,7416,1061,7341,1061,7266,986,7192,912,7192,837,7266,762,7192,687,7192,613,7266,613,7341,687,7416,538,7565,463,7491,388,7416,463,7341,463,7266,388,7192,314,7192,239,7266,164,7192,89,7192,15,7266,15,7341,89,7416,15,7491,15,7565,89,7640,164,7640,239,7565,388,7715,314,7790,239,7865,164,7790,89,7790,15,7865,15,7939,89,8014,15,8089,15,8164,89,8238,164,8238,239,8164,314,8238,388,8238,463,8164,463,8089,388,8014,463,7939,538,7865,687,8014,613,8089,613,8164,687,8238,762,8238,837,8164,986,8313,912,8388,837,8463,762,8388,687,8388,613,8463,613,8537,687,8612,613,8687,538,8762,463,8687,388,8612,463,8537,463,8463,388,8388,314,8388,239,8463,164,8388,89,8388,15,8463,15,8537,89,8612,15,8687,15,8762,89,8836,164,8836,239,8762,314,8836,388,8911,314,8986,239,9061,164,8986,89,8986,15,9061,15,9135,89,9210,15,9285,15,9360,89,9434,164,9434,239,9360,314,9434,388,9434,463,9360,463,9285,388,9210,463,9135,538,9061,613,9135,687,9210,613,9285,613,9360,687,9434,762,9434,837,9360,912,9434,986,9434,1061,9360,1061,9285,986,9210,1061,9135,1061,9061,986,8986,912,8986,837,9061,762,8986,687,8911,762,8836,837,8762,912,8836,986,8836,1061,8762,1061,8687,986,8612,1136,8463,1211,8537,1285,8612,1211,8687,1211,8762,1285,8836,1360,8836,1435,8762,1510,8836,1585,8911,1510,8986,1435,9061,1360,8986,1285,8986,1211,9061,1211,9135,1285,9210,1211,9285,1211,9360,1285,9434,1360,9434,1435,9360,1510,9434,1585,9434,1659,9360,1659,9285,1585,9210,1659,9135,1734,9061,1809,9135,1884,9210,1809,9285,1809,9360,1884,9434,1958,9434,2033,9360,2108,9434,2183,9434,2257,9360,2257,9285,2183,9210,2257,9135,2257,9061,2183,8986,2108,8986,2033,9061,1958,8986,1884,8911,1958,8836,2033,8762,2108,8836,2183,8836,2257,8762,2257,8687,2183,8612,2257,8537,2257,8463,2183,8388,2108,8388,2033,8463,1958,8388,1884,8388,1809,8463,1809,8537,1884,8612,1809,8687,1734,8762,1659,8687,1585,8612,1659,8537,1659,8463,1585,8388,1510,8388,1435,8463,1360,8388,1285,8313,1435,8164,1510,8238,1585,8238,1659,8164,1659,8089,1585,8014,1734,7865,1809,7939,1884,8014,1809,8089,1809,8164,1884,8238,1958,8238,2033,8164,2108,8238,2183,8238,2257,8164,2257,8089,2183,8014,2257,7939,2257,7865,2183,7790,2108,7790,2033,7865,1958,7790,1884,7715,2033,7565,2108,7640,2183,7640,2257,7565,2257,7491,2183,7416,2332,7266,2407,7341,2482,7416,2407,7491,2407,7565,2482,7640,2556,7640,2631,7565,2706,7640,2781,7715,2706,7790,2631,7865,2556,7790,2482,7790,2407,7865,2407,7939,2482,8014,2407,8089,2407,8164,2482,8238,2556,8238,2631,8164,2706,8238,2781,8238,2855,8164,2855,8089,2781,8014,2855,7939,2930,7865,3005,7939,3080,8014,3005,8089,3005,8164,3080,8238,3154,8238,3229,8164,3304,8238,3379,8313,3304,8388,3229,8463,3154,8388,3080,8388,3005,8463,3005,8537,3080,8612,2930,8762,2781,8612,2855,8537,2855,8463,2781,8388,2706,8388,2631,8463,2556,8388,2482,8388,2407,8463,2407,8537,2482,8612,2407,8687,2407,8762,2482,8836,2556,8836,2631,8762,2781,8911,2631,9061,2556,8986,2482,8986,2407,9061,2407,9135,2482,9210,2407,9285,2407,9360,2482,9434,2556,9434,2631,9360,2706,9434,2781,9434,2855,9360,2855,9285,2781,9210,2930,9061,3080,9210,3005,9285,3005,9360,3080,9434,3154,9434,3229,9360,3304,9434,3379,9434,3453,9360,3453,9285,3379,9210,3453,9135,3453,9061,3379,8986,3304,8986,3229,9061,3080,8911,3229,8762,3304,8836,3379,8836,3453,8762,3453,8687,3379,8612,3453,8537,3528,8463,3603,8537,3678,8612,3603,8687,3603,8762,3678,8836,3753,8836,3827,8762,3902,8836,3977,8911,3902,8986,3827,9061,3753,8986,3678,8986,3603,9061,3603,9135,3678,9210,3603,9285,3603,9360,3678,9434,3753,9434,3827,9360,3902,9434,3977,9434,4052,9360,4052,9285,3977,9210,4126,9061,4201,9135,4276,9210,4201,9285,4201,9360,4276,9434,4351,9434,4425,9360,4500,9434,4575,9434,4650,9360,4650,9285,4575,9210,4650,9135,4650,9061,4575,8986,4500,8986,4425,9061,4276,8911,4425,8762,4500,8836,4575,8836,4650,8762,4650,8687,4575,8612,4650,8537,4650,8463,4575,8388,4500,8388,4425,8463,4351,8388,4276,8388,4201,8463,4201,8537,4276,8612,4201,8687,4126,8762,3977,8612,4052,8537,4052,8463,3977,8388,3902,8388,3827,8463,3678,8313,3753,8238,3827,8164,3902,8238,3977,8238,4052,8164,4052,8089,3977,8014,4052,7939,4126,7865,4276,8014,4201,8089,4201,8164,4276,8238,4351,8238,4425,8164,4500,8238,4575,8238,4650,8164,4650,8089,4575,8014,4650,7939,4650,7865,4575,7790,4500,7790,4425,7865,4351,7790,4276,7715,4351,7640,4425,7565,4500,7640,4575,7640,4650,7565,4650,7491,4575,7416,4650,7341,4650,7266,4575,7192,4500,7192,4425,7266,4351,7192,4276,7192,4201,7266,4201,7341,4276,7416,4126,7565,4052,7491,3977,7416,4052,7341,4052,7266,3977,7192,3902,7192,3827,7266,3753,7192,3678,7192,3603,7266,3603,7341,3678,7416,3603,7491,3603,7565,3678,7640,3753,7640,3827,7565,3902,7640,3977,7715,3827,7865,3753,7790,3678,7790,3603,7865,3603,7939,3678,8014,3528,8164,3379,8014,3453,7939,3453,7865,3379,7790,3304,7790,3229,7865,3154,7790,3080,7715,3154,7640,3229,7565,3304,7640,3379,7640,3453,7565,3453,7491,3379,7416,3453,7341,3453,7266,3379,7192,3304,7192,3229,7266,3154,7192,3080,7192,3005,7266,3005,7341,3080,7416,3005,7491,2930,7565,2855,7491,2781,7416,2855,7341,2855,7266,2781,7192,2706,7192,2631,7266,2482,7117,2556,7042,2631,6967,2706,7042,2781,7042,2855,6967,2855,6893,2781,6818,2855,6743,2930,6668,3005,6743,3080,6818,3005,6893,3005,6967,3080,7042,3154,7042,3229,6967,3304,7042,3379,7042,3453,6967,3453,6893,3379,6818,3453,6743,3453,6668,3379,6594,3304,6594,3229,6668,3154,6594,3080,6519,3154,6444,3229,6369,3304,6444,3379,6444,3453,6369,3453,6295,3379,6220,3528,6070,3678,6220,3603,6295,3603,6369,3678,6444,3753,6444,3827,6369,3977,6519,3902,6594,3827,6668,3753,6594,3678,6594,3603,6668,3603,6743,3678,6818,3603,6893,3603,6967,3678,7042,3753,7042,3827,6967,3902,7042,3977,7042,4052,6967,4052,6893,3977,6818,4052,6743,4126,6668,4276,6818,4201,6893,4201,6967,4276,7042,4351,7042,4425,6967,4500,7042,4575,7042,4650,6967,4650,6893,4575,6818,4650,6743,4650,6668,4575,6594,4500,6594,4425,6668,4351,6594,4276,6519,4351,6444,4425,6369,4500,6444,4575,6444,4650,6369,4650,6295,4575,6220,4650,6145,4650,6070,4575,5996,4500,5996,4425,6070,4351,5996,4276,5996,4201,6070,4201,6145,4276,6220,4126,6369,4052,6295,3977,6220,4052,6145,4052,6070,3977,5996,3902,5996,3827,6070,3753,5996,3678,5921,3827,5771,3902,5846,3977,5846,4052,5771,4052,5696,3977,5622,4126,5472,4201,5547,4276,5622,4201,5696,4201,5771,4276,5846,4351,5846,4425,5771,4500,5846,4575,5846,4650,5771,4650,5696,4575,5622,4650,5547,4650,5472,4575,5397,4500,5397,4425,5472,4276,5323,4425,5173,4500,5248,4575,5248,4650,5173,4650,5098,4575,5024,4724,4874,4799,4949,4874,5024,4799,5098,4799,5173,4874,5248,4949,5248,5023,5173,5098,5248,5173,5323,5098,5397,5023,5472,4949,5397,4874,5397,4799,5472,4799,5547,4874,5622,4799,5696,4799,5771,4874,5846,4949,5846,5023,5771,5098,5846,5173,5846,5248,5771,5248,5696,5173,5622,5248,5547,5322,5472,5397,5547,5472,5622,5397,5696,5397,5771,5472,5846,5547,5846,5622,5771,5771,5921,5696,5996,5622,6070,5547,5996,5472,5996,5397,6070,5397,6145,5472,6220,5397,6295,5322,6369,5173,6220,5248,6145,5248,6070,5173,5996,5098,5996,5023,6070,4949,5996,4874,5996,4799,6070,4799,6145,4874,6220,4799,6295,4799,6369,4874,6444,4949,6444,5023,6369,5098,6444,5173,6519,5023,6668,4949,6594,4874,6594,4799,6668,4799,6743,4874,6818,4799,6893,4799,6967,4874,7042,4949,7042,5023,6967,5098,7042,5173,7042,5248,6967,5248,6893,5173,6818,5322,6668,5397,6743,5472,6818,5397,6893,5397,6967,5472,7042,5547,7042,5622,6967,5696,7042,5771,7042,5846,6967,5846,6893,5771,6818,5846,6743,5846,6668,5771,6594,5696,6594,5622,6668,5472,6519,5547,6444,5622,6369,5696,6444,5771,6444,5846,6369,5846,6295,5771,6220,5846,6145,5921,6070,6070,6220,5995,6295,5995,6369,6070,6444,6145,6444,6220,6369,6294,6444,6369,6519,6294,6594,6220,6668,6145,6594,6070,6594,5995,6668,5995,6743,6070,6818,5995,6893,5995,6967,6070,7042,6145,7042,6220,6967,6294,7042,6369,7042,6444,6967,6444,6893,6369,6818,6519,6668,6593,6743,6668,6818,6593,6893,6593,6967,6668,7042,6743,7042,6818,6967,6892,7042,6967,7117,6892,7192,6818,7266,6743,7192,6668,7192,6593,7266,6593,7341,6668,7416,6593,7491,6519,7565,6369,7416,6444,7341,6444,7266,6369,7192,6294,7192,6220,7266,6145,7192,6070,7192,5995,7266,5995,7341,6070,7416,5995,7491,5995,7565,6070,7640,6145,7640,6220,7565,6294,7640,6369,7715,6294,7790,6220,7865,6145,7790,6070,7790,5995,7865,5995,7939,6070,8014,5921,8164,5846,8089,5771,8014,5846,7939,5846,7865,5771,7790,5696,7790,5622,7865,5547,7790,5472,7715,5622,7565,5696,7640,5771,7640,5846,7565,5846,7491,5771,7416,5846,7341,5846,7266,5771,7192,5696,7192,5622,7266,5547,7192,5472,7192,5397,7266,5397,7341,5472,7416,5397,7491,5322,7565,5173,7416,5248,7341,5248,7266,5173,7192,5098,7192,5023,7266,4949,7192,4874,7192,4799,7266,4799,7341,4874,7416,4799,7491,4799,7565,4874,7640,4949,7640,5023,7565,5173,7715,5098,7790,5023,7865,4949,7790,4874,7790,4799,7865,4799,7939,4874,8014,4799,8089,4799,8164,4874,8238,4949,8238,5023,8164,5098,8238,5173,8238,5248,8164,5248,8089,5173,8014,5322,7865,5397,7939,5472,8014,5397,8089,5397,8164,5472,8238,5547,8238,5622,8164,5696,8238,5771,8313,5622,8463,5547,8388,5472,8388,5397,8463,5397,8537,5472,8612,5397,8687,5322,8762,5248,8687,5173,8612,5248,8537,5248,8463,5173,8388,5098,8388,5023,8463,4949,8388,4874,8388,4799,8463,4799,8537,4874,8612,4799,8687,4799,8762,4874,8836,4949,8836,5023,8762,5098,8836,5173,8911,5098,8986,5023,9061,4949,8986,4874,8986,4799,9061,4799,9135,4874,9210,4799,9285,4799,9360,4874,9434,4949,9434,5023,9360,5098,9434,5173,9434,5248,9360,5248,9285,5173,9210,5248,9135,5322,9061,5397,9135,5472,9210,5397,9285,5397,9360,5472,9434,5547,9434,5622,9360,5696,9434,5771,9434,5846,9360,5846,9285,5771,9210,5846,9135,5846,9061,5771,8986,5696,8986,5622,9061,5547,8986,5472,8911,5547,8836,5622,8762,5696,8836,5771,8836,5846,8762,5846,8687,5771,8612,5846,8537,5921,8463,5995,8537,6070,8612,5995,8687,5995,8762,6070,8836,6145,8836,6220,8762,6369,8911,6220,9061,6145,8986,6070,8986,5995,9061,5995,9135,6070,9210,5995,9285,5995,9360,6070,9434,6145,9434,6220,9360,6294,9434,6369,9434,6444,9360,6444,9285,6369,9210,6444,9135,6519,9061,6668,9210,6593,9285,6593,9360,6668,9434,6743,9434,6818,9360,6892,9434,6967,9434,7042,9360,7042,9285,6967,9210,7042,9135,7042,9061,6967,8986,6892,8986,6818,9061,6743,8986,6668,8911,6743,8836,6818,8762,6892,8836,6967,8836,7042,8762,7042,8687,6967,8612,7042,8537,7042,8463,6967,8388,6892,8388,6818,8463,6743,8388,6668,8388,6593,8463,6593,8537,6668,8612,6519,8762,6444,8687,6369,8612,6444,8537,6444,8463,6369,8388,6294,8388,6220,8463,6145,8388,6070,8313,6145,8238,6220,8164,6294,8238,6369,8238,6444,8164,6444,8089,6369,8014,6519,7865,6593,7939,6668,8014,6593,8089,6593,8164,6668,8238,6743,8238,6818,8164,6892,8238,6967,8238,7042,8164,7042,8089,6967,8014,7042,7939,7042,7865,6967,7790,6892,7790,6818,7865,6668,7715,6743,7640,6818,7565,6892,7640,6967,7640,7042,7565,7042,7491,6967,7416,7042,7341,7117,7266,7191,7341,7266,7416,7191,7491,7191,7565,7266,7640,7341,7640,7416,7565,7490,7640,7565,7715,7416,7865,7341,7790,7266,7790,7191,7865,7191,7939,7266,8014,7191,8089,7191,8164,7266,8238,7341,8238,7416,8164,7490,8238,7565,8238,7640,8164,7640,8089,7565,8014,7640,7939,7715,7865,7864,8014,7790,8089,7790,8164,7864,8238,7939,8238,8014,8164,8163,8313,8089,8388,8014,8463,7939,8388,7864,8388,7790,8463,7790,8537,7864,8612,7790,8687,7715,8762,7565,8612,7640,8537,7640,8463,7565,8388,7490,8388,7416,8463,7341,8388,7266,8388,7191,8463,7191,8537,7266,8612,7191,8687,7191,8762,7266,8836,7341,8836,7416,8762,7490,8836,7565,8911,7490,8986,7416,9061,7341,8986,7266,8986,7191,9061,7191,9135,7266,9210,7191,9285,7191,9360,7266,9434,7341,9434,7416,9360,7490,9434,7565,9434,7640,9360,7640,9285,7565,9210,7715,9061,7790,9135,7864,9210,7790,9285,7790,9360,7864,9434,7939,9434,8014,9360,8089,9434,8163,9434,8238,9360,8238,9285,8163,9210,8238,9135,8238,9061,8163,8986,8089,8986,8014,9061,7864,8911,8014,8762,8089,8836,8163,8836,8238,8762,8238,8687,8163,8612,8313,8463,8388,8537,8462,8612,8388,8687,8388,8762,8462,8836,8537,8836,8612,8762,8687,8836,8761,8911,8687,8986,8612,9061,8537,8986,8462,8986,8388,9061,8388,9135,8462,9210,8388,9285,8388,9360,8462,9434,8537,9434,8612,9360,8687,9434,8761,9434,8836,9360,8836,9285,8761,9210,8836,9135,8911,9061,8986,9135,9060,9210,8986,9285,8986,9360,9060,9434,9135,9434,9210,9360,9285,9434,9360,9434,9434,9360,9434,9285,9360,9210,9434,9135,9434,9061,9360,8986,9285,8986,9210,9061,9135,8986,9060,8911,9135,8836,9210,8762,9285,8836,9360,8836,9434,8762,9434,8687,9360,8612,9434,8537,9434,8463,9360,8388,9285,8388,9210,8463,9135,8388,9060,8388,8986,8463,8986,8537,9060,8612,8986,8687,8911,8762,8836,8687,8761,8612,8836,8537,8836,8463,8761,8388,8687,8388,8612,8463,8537,8388,8462,8313,8612,8164,8687,8238,8761,8238,8836,8164,8836,8089,8761,8014,8836,7939,8911,7865,9060,8014,8986,8089,8986,8164,9060,8238,9135,8238,9210,8164,9285,8238,9360,8238,9434,8164,9434,8089,9360,8014,9434,7939,9434,7865,9360,7790,9285,7790,9210,7865,9135,7790,9060,7715,9210,7565,9285,7640,9360,7640,9434,7565,9434,7491,9360,7416,9434,7341,9434,7266,9360,7192,9285,7192,9210,7266,9135,7192,9060,7192,8986,7266,8986,7341,9060,7416,8911,7565,8836,7491,8761,7416,8836,7341,8836,7266,8761,7192,8687,7192,8612,7266,8537,7192,8462,7192,8388,7266,8388,7341,8462,7416,8388,7491,8388,7565,8462,7640,8537,7640,8612,7565,8761,7715,8687,7790,8612,7865,8537,7790,8462,7790,8388,7865,8388,7939,8462,8014,8388,8089,8313,8164,8238,8089,8163,8014,8238,7939,8238,7865,8163,7790,8089,7790,8014,7865,7939,7790,7864,7715,7939,7640,8014,7565,8089,7640,8163,7640,8238,7565,8238,7491,8163,7416,8238,7341,8238,7266,8163,7192,8089,7192,8014,7266,7939,7192,7864,7192,7790,7266,7790,7341,7864,7416,7715,7565,7640,7491,7565,7416,7640,7341,7640,7266,7565,7192,7490,7192,7416,7266,7341,7192,7266,7117,7341,7042,7416,6967,7490,7042,7565,7042,7640,6967,7640,6893,7565,6818,7640,6743,7715,6668,7864,6818,7790,6893,7790,6967,7864,7042,7939,7042,8014,6967,8089,7042,8163,7042,8238,6967,8238,6893,8163,6818,8238,6743,8238,6668,8163,6594,8089,6594,8014,6668,7939,6594,7864,6519,7939,6444,8014,6369,8089,6444,8163,6444,8238,6369,8238,6295,8163,6220,8238,6145,8313,6070,8388,6145,8462,6220,8388,6295,8388,6369,8462,6444,8537,6444,8612,6369,8687,6444,8761,6519,8612,6668,8537,6594,8462,6594,8388,6668,8388,6743,8462,6818,8388,6893,8388,6967,8462,7042,8537,7042,8612,6967,8687,7042,8761,7042,8836,6967,8836,6893,8761,6818,8836,6743,8911,6668,9060,6818,8986,6893,8986,6967,9060,7042,9135,7042,9210,6967,9285,7042,9360,7042,9434,6967,9434,6893,9360,6818,9434,6743,9434,6668,9360,6594,9285,6594,9210,6668,9060,6519,9135,6444,9210,6369,9285,6444,9360,6444,9434,6369,9434,6295,9360,6220,9434,6145,9434,6070,9360,5996,9285,5996,9210,6070,9135,5996,9060,5996,8986,6070,8986,6145,9060,6220,8911,6369,8836,6295,8761,6220,8836,6145,8836,6070,8761,5996,8687,5996,8612,6070,8462,5921,8537,5846,8612,5771,8687,5846,8761,5846,8836,5771,8836,5696,8761,5622,8836,5547,8911,5472,8986,5547,9060,5622,8986,5696,8986,5771,9060,5846,9135,5846,9210,5771,9285,5846,9360,5846,9434,5771,9434,5696,9360,5622,9434,5547,9434,5472,9360,5397,9285,5397,9210,5472,9135,5397,9060,5323,9135,5248,9210,5173,9285,5248,9360,5248,9434,5173,9434,5098,9360,5024,9434,4949,9434,4874,9360,4799,9285,4799,9210,4874,9135,4799,9060,4799,8986,4874,8986,4949,9060,5024,8986,5098,8911,5173,8836,5098,8761,5024,8836,4949,8836,4874,8761,4799,8687,4799,8612,4874,8537,4799,8462,4799,8388,4874,8388,4949,8462,5024,8388,5098,8388,5173,8462,5248,8537,5248,8612,5173,8687,5248,8761,5323,8687,5397,8612,5472,8537,5397,8462,5397,8388,5472,8388,5547,8462,5622,8388,5696,8313,5771,8163,5622,8238,5547,8238,5472,8163,5397,8089,5397,8014,5472,7864,5323,8014,5173,8089,5248,8163,5248,8238,5173,8238,5098,8163,5024,8238,4949,8238,4874,8163,4799,8089,4799,8014,4874,7939,4799,7864,4799,7790,4874,7790,4949,7864,5024,7790,5098,7715,5173,7565,5024,7640,4949,7640,4874,7565,4799,7490,4799,7416,4874,7341,4799,7266,4799,7191,4874,7191,4949,7266,5024,7191,5098,7191,5173,7266,5248,7341,5248,7416,5173,7490,5248,7565,5323,7490,5397,7416,5472,7341,5397,7266,5397,7191,5472,7191,5547,7266,5622,7191,5696,7191,5771,7266,5846,7341,5846,7416,5771,7490,5846,7565,5846,7640,5771,7640,5696,7565,5622,7715,5472,7790,5547,7864,5622,7790,5696,7790,5771,7864,5846,7939,5846,8014,5771,8089,5846,8163,5921,8014,6070,7939,5996,7864,5996,7790,6070,7790,6145,7864,6220,7715,6369,7640,6295,7565,6220,7640,6145,7640,6070,7565,5996,7490,5996,7416,6070,7341,5996,7266,5996,7191,6070,7191,6145,7266,6220,7191,6295,7191,6369,7266,6444,7341,6444,7416,6369,7565,6519,7490,6594,7416,6668,7341,6594,7266,6594,7191,6668,7191,6743,7266,6818,7191,6893,7117,6967,7042,6893,6967,6818,7042,6743,7042,6668,6967,6594,6892,6594,6818,6668,6743,6594,6668,6519,6818,6369,6892,6444,6967,6444,7042,6369,7042,6295,6967,6220,7042,6145,7042,6070,6967,5996,6892,5996,6818,6070,6743,5996,6668,5996,6593,6070,6593,6145,6668,6220,6593,6295,6519,6369,6369,6220,6444,6145,6444,6070,6369,5996,6294,5996,6220,6070,6145,5996,6070,5921,6145,5846,6220,5771,6294,5846,6369,5846,6444,5771,6444,5696,6369,5622,6444,5547,6519,5472,6668,5622,6593,5696,6593,5771,6668,5846,6743,5846,6818,5771,6892,5846,6967,5846,7042,5771,7042,5696,6967,5622,7042,5547,7042,5472,6967,5397,6892,5397,6818,5472,6743,5397,6668,5323,6743,5248,6818,5173,6892,5248,6967,5248,7042,5173,7042,5098,6967,5024,7042,4949,7042,4874,6967,4799,6892,4799,6818,4874,6743,4799,6668,4799,6593,4874,6593,4949,6668,5024,6519,5173,6444,5098,6369,5024,6444,4949,6444,4874,6369,4799,6294,4799,6220,4874,6145,4799,6070,4799,5995,4874,5995,4949,6070,5024,5995,5098,5995,5173,6070,5248,6145,5248,6220,5173,6369,5323,6220,5472,6145,5397,6070,5397,5995,5472,5995,5547,6070,5622,5995,5696,5921,5771,5846,5696,5771,5622,5846,5547,5846,5472,5771,5397,5696,5397,5622,5472,5547,5397,5472,5323,5547,5248,5622,5173,5696,5248,5771,5248,5846,5173,5846,5098,5771,5024,5846,4949,5846,4874,5771,4799,5696,4799,5622,4874,5547,4799,5472,4799,5397,4874,5397,4949,5472,5024,5397,5098,5322,5173,5248,5098,5173,5024,5248,4949,5248,4874,5173,4799,5098,4799,5023,4874,4949,4799,4874,4725,4949,4650,5023,4575,5098,4650,5173,4650,5248,4575,5248,4500,5173,4426,5248,4351,5322,4276,5472,4426,5397,4500,5397,4575,5472,4650,5547,4650,5622,4575,5696,4650,5771,4650,5846,4575,5846,4500,5771,4426,5846,4351,5846,4276,5771,4201,5696,4201,5622,4276,5547,4201,5472,4127,5622,3977,5696,4052,5771,4052,5846,3977,5846,3902,5771,3828,5921,3678,5995,3753,6070,3828,5995,3902,5995,3977,6070,4052,6145,4052,6220,3977,6294,4052,6369,4127,6220,4276,6145,4201,6070,4201,5995,4276,5995,4351,6070,4426,5995,4500,5995,4575,6070,4650,6145,4650,6220,4575,6294,4650,6369,4650,6444,4575,6444,4500,6369,4426,6444,4351,6519,4276,6593,4351,6668,4426,6593,4500,6593,4575,6668,4650,6743,4650,6818,4575,6892,4650,6967,4650,7042,4575,7042,4500,6967,4426,7042,4351,7042,4276,6967,4201,6892,4201,6818,4276,6743,4201,6668,4127,6743,4052,6818,3977,6892,4052,6967,4052,7042,3977,7042,3902,6967,3828,7042,3753,7042,3678,6967,3603,6892,3603,6818,3678,6743,3603,6668,3603,6593,3678,6593,3753,6668,3828,6519,3977,6444,3902,6369,3828,6444,3753,6444,3678,6369,3603,6294,3603,6220,3678,6070,3528,6145,3454,6220,3379,6294,3454,6369,3454,6444,3379,6444,3304,6369,3229,6519,3080,6593,3155,6668,3229,6593,3304,6593,3379,6668,3454,6743,3454,6818,3379,6892,3454,6967,3454,7042,3379,7042,3304,6967,3229,7042,3155,7042,3080,6967,3005,6892,3005,6818,3080,6743,3005,6668,2930,6818,2781,6892,2856,6967,2856,7042,2781,7042,2706,6967,2631,7117,2482,7266,2631,7191,2706,7191,2781,7266,2856,7341,2856,7416,2781,7565,2930,7490,3005,7416,3080,7341,3005,7266,3005,7191,3080,7191,3155,7266,3229,7191,3304,7191,3379,7266,3454,7341,3454,7416,3379,7490,3454,7565,3454,7640,3379,7640,3304,7565,3229,7640,3155,7715,3080,7864,3229,7790,3304,7790,3379,7864,3454,7939,3454,8014,3379,8163,3528,8089,3603,8014,3678,7939,3603,7864,3603,7790,3678,7790,3753,7864,3828,7790,3902,7715,3977,7565,3828,7640,3753,7640,3678,7565,3603,7490,3603,7416,3678,7341,3603,7266,3603,7191,3678,7191,3753,7266,3828,7191,3902,7191,3977,7266,4052,7341,4052,7416,3977,7490,4052,7565,4127,7490,4201,7416,4276,7341,4201,7266,4201,7191,4276,7191,4351,7266,4426,7191,4500,7191,4575,7266,4650,7341,4650,7416,4575,7490,4650,7565,4650,7640,4575,7640,4500,7565,4426,7640,4351,7715,4276,7790,4351,7864,4426,7790,4500,7790,4575,7864,4650,7939,4650,8014,4575,8089,4650,8163,4650,8238,4575,8238,4500,8163,4426,8238,4351,8238,4276,8163,4201,8089,4201,8014,4276,7864,4127,7939,4052,8014,3977,8089,4052,8163,4052,8238,3977,8238,3902,8163,3828,8238,3753,8313,3678,8462,3828,8388,3902,8388,3977,8462,4052,8537,4052,8612,3977,8761,4127,8687,4201,8612,4276,8537,4201,8462,4201,8388,4276,8388,4351,8462,4426,8388,4500,8388,4575,8462,4650,8537,4650,8612,4575,8687,4650,8761,4650,8836,4575,8836,4500,8761,4426,8911,4276,8986,4351,9060,4426,8986,4500,8986,4575,9060,4650,9135,4650,9210,4575,9285,4650,9360,4650,9434,4575,9434,4500,9360,4426,9434,4351,9434,4276,9360,4201,9285,4201,9210,4276,9135,4201,9060,4127,9210,3977,9285,4052,9360,4052,9434,3977,9434,3902,9360,3828,9434,3753,9434,3678,9360,3603,9285,3603,9210,3678,9135,3603,9060,3603,8986,3678,8986,3753,9060,3828,8986,3902,8911,3977,8836,3902,8761,3828,8836,3753,8836,3678,8761,3603,8687,3603,8612,3678,8537,3603,8462,3528,8612,3379,8687,3454,8761,3454,8836,3379,8836,3304,8761,3229,8836,3155,8911,3080,9060,3229,8986,3304,8986,3379,9060,3454,9135,3454,9210,3379,9285,3454,9360,3454,9434,3379,9434,3304,9360,3229,9434,3155,9434,3080,9360,3005,9285,3005,9210,3080,9060,2930,9135,2856,9210,2781,9285,2856,9360,2856,9434,2781,9434,2706,9360,2631,9434,2557,9434,2482,9360,2407,9285,2407,9210,2482,9135,2407,9060,2407,8986,2482,8986,2557,9060,2631,8911,2781,8836,2706,8761,2631,8836,2557,8836,2482,8761,2407,8687,2407,8612,2482,8537,2407,8462,2407,8388,2482,8388,2557,8462,2631,8388,2706,8388,2781,8462,2856,8537,2856,8612,2781,8687,2856,8761,2930,8612,3080,8537,3005,8462,3005,8388,3080,8388,3155,8462,3229,8313,3379,8238,3304,8163,3229,8238,3155,8238,3080,8163,3005,8089,3005,8014,3080,7939,3005,7864,2930,7939,2856,8014,2781,8089,2856,8163,2856,8238,2781,8238,2706,8163,2631,8238,2557,8238,2482,8163,2407,8089,2407,8014,2482,7939,2407,7864,2407,7790,2482,7790,2557,7864,2631,7715,2781,7640,2706,7565,2631,7640,2557,7640,2482,7565,2407,7490,2407,7416,2482,7341,2407,7266,2332,7341,2258,7416,2183,7490,2258,7565,2258,7640,2183,7640,2108,7565,2033,7715,1884,7790,1959,7864,2033,7790,2108,7790,2183,7864,2258,7939,2258,8014,2183,8089,2258,8163,2258,8238,2183,8238,2108,8163,2033,8238,1959,8238,1884,8163,1809,8089,1809,8014,1884,7939,1809,7864,1734,8014,1585,8089,1659,8163,1659,8238,1585,8238,1510,8163,1435,8238,1360,8313,1286,8388,1360,8462,1435,8388,1510,8388,1585,8462,1659,8537,1659,8612,1585,8687,1659,8761,1734,8612,1884,8537,1809,8462,1809,8388,1884,8388,1959,8462,2033,8388,2108,8388,2183,8462,2258,8537,2258,8612,2183,8687,2258,8761,2258,8836,2183,8836,2108,8761,2033,8836,1959,8911,1884,8986,1959,9060,2033,8986,2108,8986,2183,9060,2258,9135,2258,9210,2183,9285,2258,9360,2258,9434,2183,9434,2108,9360,2033,9434,1959,9434,1884,9360,1809,9285,1809,9210,1884,9060,1734,9135,1659,9210,1585,9285,1659,9360,1659,9434,1585,9434,1510,9360,1435,9434,1360,9434,1286,9360,1211,9285,1211,9210,1286,9135,1211,9060,1211,8986,1286,8986,1360,9060,1435,8986,1510,8911,1585,8761,1435,8836,1360,8836,1286,8761,1211,8687,1211,8612,1286,8537,1211,8462,1136,8537,1061,8612,987,8687,1061,8761,1061,8836,987,8836,912,8761,837,8911,688,8986,762,9060,837,8986,912,8986,987,9060,1061,9135,1061,9210,987,9285,1061,9360,1061,9434,987,9434,912,9360,837,9434,762,9434,688,9360,613,9285,613,9210,688,9135,613,9060,538,9210,389,9285,463,9360,463,9434,389,9434,314,9360,239,9434,164,9434,90,9360,15,9285,15,9210,90,9135,15,9060,15,8986,90,8986,164,9060,239,8986,314,8911,389,8836,314,8761,239,8836,164,8836,90,8761,15,8687,15,8612,90,8537,15,8462,15,8388,90,8388,164,8462,239,8388,314,8388,389,8462,463,8537,463,8612,389,8761,538,8687,613,8612,688,8537,613,8462,613,8388,688,8388,762,8462,837,8388,912,8313,987,8238,912,8163,837,8238,762,8238,688,8163,613,8089,613,8014,688,7864,538,7939,463,8014,389,8089,463,8163,463,8238,389,8238,314,8163,239,8238,164,8238,90,8163,15,8089,15,8014,90,7939,15,7864,15,7790,90,7790,164,7864,239,7790,314,7715,389,7565,239,7640,164,7640,90,7565,15,7490,15,7416,90,7341,15,7266,15,7191,90,7191,164,7266,239,7191,314,7191,389,7266,463,7341,463,7416,389,7490,463,7565,538,7490,613,7416,688,7341,613,7266,613,7191,688,7191,762,7266,837,7191,912,7191,987,7266,1061,7341,1061,7416,987,7490,1061,7565,1061,7640,987,7640,912,7565,837,7640,762,7715,688,7790,762,7864,837,7790,912,7790,987,7864,1061,7939,1061,8014,987,8089,1061,8163,1136,8089,1211,8014,1286,7939,1211,7864,1211,7790,1286,7790,1360,7864,1435,7790,1510,7715,1585,7640,1510,7565,1435,7640,1360,7640,1286,7565,1211,7490,1211,7416,1286,7341,1211,7266,1211,7191,1286,7191,1360,7266,1435,7191,1510,7191,1585,7266,1659,7341,1659,7416,1585,7490,1659,7565,1734,7490,1809,7416,1884,7341,1809,7266,1809,7191,1884,7191,1959,7266,2033,7191,2108,7117,2183,7042,2108,6967,2033,7042,1959,7042,1884,6967,1809,6892,1809,6818,1884,6743,1809,6668,1734,6743,1659,6818,1585,6892,1659,6967,1659,7042,1585,7042,1510,6967,1435,7042,1360,7042,1286,6967,1211,6892,1211,6818,1286,6743,1211,6668,1211,6593,1286,6593,1360,6668,1435,6593,1510,6519,1585,6444,1510,6369,1435,6444,1360,6444,1286,6369,1211,6294,1211,6220,1286,6145,1211,6070,1136,6145,1061,6220,987,6294,1061,6369,1061,6444,987,6444,912,6369,837,6444,762,6519,688,6593,762,6668,837,6593,912,6593,987,6668,1061,6743,1061,6818,987,6892,1061,6967,1061,7042,987,7042,912,6967,837,7042,762,7042,688,6967,613,6892,613,6818,688,6743,613,6668,538,6743,463,6818,389,6892,463,6967,463,7042,389,7042,314,6967,239,7042,164,7042,90,6967,15,6892,15,6818,90,6743,15,6668,15,6593,90,6593,164,6668,239,6519,389,6444,314,6369,239,6444,164,6444,90,6369,15,6294,15,6220,90,6145,15,6070,15,5995,90,5995,164,6070,239,5995,314,5995,389,6070,463,6145,463,6220,389,6294,463,6369,538,6220,688,6145,613,6070,613,5995,688,5995,762,6070,837,5921,987,5846,912,5771,837,5846,762,5846,688,5771,613,5696,613,5622,688,5547,613,5472,538,5622,389,5696,463,5771,463,5846,389,5846,314,5771,239,5846,164,5846,90,5771,15,5696,15,5622,90,5547,15,5472,15,5397,90,5397,164,5472,239,5397,314,5322,389,5248,314,5173,239,5248,164,5248,90,5173,15,5098,15,5023,90,4949,15,4874,15,4799,90,4799,164,4874,239,4799,314,4799,389,4874,463,4949,463,5023,389,5173,538,5098,613,5023,688,4949,613,4874,613,4799,688,4799,762,4874,837,4799,912,4799,987,4874,1061,4949,1061,5023,987,5098,1061,5173,1061,5248,987,5248,912,5173,837,5248,762,5322,688,5472,837,5397,912,5397,987,5472,1061,5547,1061,5622,987,5771,1136,5622,1286,5547,1211,5472,1211,5397,1286,5397,1360,5472,1435,5322,1585,5248,1510,5173,1435,5248,1360,5248,1286,5173,1211,5098,1211,5023,1286,4949,1211,4874,1211,4799,1286,4799,1360,4874,1435,4799,1510,4799,1585,4874,1659,4949,1659,5023,1585,5098,1659,5173,1734,5023,1884,4949,1809,4874,1809,4799,1884,4799,1959,4874,2033,4799,2108,4799,2183,4874,2258,4949,2258,5023,2183,5098,2258,5173,2258,5248,2183,5248,2108,5173,2033,5248,1959,5322,1884,5397,1959,5472,2033,5397,2108,5397,2183,5472,2258,5547,2258,5622,2183,5696,2258,5771,2258,5846,2183,5846,2108,5771,2033,5846,1959,5846,1884,5771,1809,5696,1809,5622,1884,5472,1734,5547,1659,5622,1585,5696,1659,5771,1659,5846,1585,5846,1510,5771,1435,5846,1360,5921,1286,6070,1435,5995,1510,5995,1585,6070,1659,6145,1659,6220,1585,6369,1734,6294,1809,6220,1884,6145,1809,6070,1809,5995,1884,5995,1959,6070,2033,5995,2108,5995,2183,6070,2258,6145,2258,6220,2183,6294,2258,6369,2258,6444,2183,6444,2108,6369,2033,6444,1959,6519,1884,6668,2033,6593,2108,6593,2183,6668,2258,6743,2258,6818,2183,6892,2258,6967,2332,6892,2407,6818,2482,6743,2407,6668,2407,6593,2482,6593,2557,6668,2631,6593,2706,6519,2781,6369,2631,6444,2557,6444,2482,6369,2407,6294,2407,6220,2482,6145,2407,6070,2407,5995,2482,5995,2557,6070,2631,5995,2706,5995,2781,6070,2856,6145,2856,6220,2781,6294,2856,6369,2930,6294,3005,6220,3080,6145,3005,6070,3005,5995,3080,5995,3155,6070,3229,5995,3304,5921,3379,5771,3229,5846,3155,5846,3080,5771,3005,5696,3005,5622,3080,5472,2930,5547,2856,5622,2781,5696,2856,5771,2856,5846,2781,5846,2706,5771,2631,5846,2557,5846,2482,5771,2407,5696,2407,5622,2482,5547,2407,5472,2407,5397,2482,5397,2557,5472,2631,5397,2706,5322,2781,5173,2631,5248,2557,5248,2482,5173,2407,5098,2407,5023,2482,4949,2407,4874,2407,4799,2482,4799,2557,4874,2631,4799,2706,4799,2781,4874,2856,4949,2856,5023,2781,5098,2856,5173,2930,5023,3080,4949,3005,4874,3005,4799,3080,4799,3155,4874,3229,4799,3304,4799,3379,4874,3454,4949,3454,5023,3379,5098,3454,5173,3454,5248,3379,5248,3304,5173,3229,5322,3080,5397,3155,5472,3229,5397,3304,5397,3379,5472,3454,5547,3454,5622,3379,5696,3454,5771,3528,5696,3603,5622,3678,5547,3603,5472,3603,5397,3678,5397,3753,5472,3828,5397,3902,5322,3977,5248,3902,5173,3828,5248,3753,5248,3678,5173,3603,5098,3603,5023,3678,4949,3603,4874,3603,4799,3678,4799,3753,4874,3828,4799,3902,4799,3977,4874,4052,4949,4052,5023,3977,5173,4127,5098,4201,5023,4276,4949,4201,4874,4201,4799,4276,4799,4351,4874,4426,4799,4500,4724,4575,4650,4500,4575,4426,4650,4351,4650,4276,4575,4201,4500,4201,4425,4276,4276,4127,4351,4052,4425,3977,4500,4052,4575,4052,4650,3977,4650,3902,4575,3828,4650,3753,4650,3678,4575,3603,4500,3603,4425,3678,4351,3603,4276,3603,4201,3678,4201,3753,4276,3828,4201,3902,4126,3977,3977,3828,4052,3753,4052,3678,3977,3603,3902,3603,3827,3678,3753,3603,3678,3528,3753,3454,3827,3379,3902,3454,3977,3454,4052,3379,4052,3304,3977,3229,4052,3155,4126,3080,4276,3229,4201,3304,4201,3379,4276,3454,4351,3454,4425,3379,4500,3454,4575,3454,4650,3379,4650,3304,4575,3229,4650,3155,4650,3080,4575,3005,4500,3005,4425,3080,4351,3005,4276,2930,4351,2856,4425,2781,4500,2856,4575,2856,4650,2781,4650,2706,4575,2631,4650,2557,4650,2482,4575,2407,4500,2407,4425,2482,4351,2407,4276,2407,4201,2482,4201,2557,4276,2631,4126,2781,4052,2706,3977,2631,4052,2557,4052,2482,3977,2407,3902,2407,3827,2482,3753,2407,3678,2407,3603,2482,3603,2557,3678,2631,3603,2706,3603,2781,3678,2856,3753,2856,3827,2781,3977,2930,3902,3005,3827,3080,3753,3005,3678,3005,3603,3080,3603,3155,3678,3229,3603,3304,3528,3379,3453,3304,3379,3229,3453,3155,3453,3080,3379,3005,3304,3005,3229,3080,3154,3005,3080,2930,3154,2856,3229,2781,3304,2856,3379,2856,3453,2781,3453,2706,3379,2631,3453,2557,3453,2482,3379,2407,3304,2407,3229,2482,3154,2407,3080,2407,3005,2482,3005,2557,3080,2631,3005,2706,2930,2781,2855,2706,2781,2631,2855,2557,2855,2482,2781,2407,2706,2407,2631,2482,2556,2407,2482,2332,2631,2183,2706,2258,2781,2258,2855,2183,2855,2108,2781,2033,2930,1884,3080,2033,3005,2108,3005,2183,3080,2258,3154,2258,3229,2183,3304,2258,3379,2258,3453,2183,3453,2108,3379,2033,3453,1959,3453,1884,3379,1809,3304,1809,3229,1884,3154,1809,3080,1734,3229,1585,3304,1659,3379,1659,3453,1585,3453,1510,3379,1435,3528,1286,3678,1435,3603,1510,3603,1585,3678,1659,3753,1659,3827,1585,3902,1659,3977,1734,3902,1809,3827,1884,3753,1809,3678,1809,3603,1884,3603,1959,3678,2033,3603,2108,3603,2183,3678,2258,3753,2258,3827,2183,3902,2258,3977,2258,4052,2183,4052,2108,3977,2033,4126,1884,4201,1959,4276,2033,4201,2108,4201,2183,4276,2258,4351,2258,4425,2183,4500,2258,4575,2258,4650,2183,4650,2108,4575,2033,4650,1959,4650,1884,4575,1809,4500,1809,4425,1884,4351,1809,4276,1734,4425,1585,4500,1659,4575,1659,4650,1585,4650,1510,4575,1435,4650,1360,4650,1286,4575,1211,4500,1211,4425,1286,4351,1211,4276,1211,4201,1286,4201,1360,4276,1435,4201,1510,4126,1585,4052,1510,3977,1435,4052,1360,4052,1286,3977,1211,3902,1211,3827,1286,3678,1136,3827,987,3902,1061,3977,1061,4052,987,4052,912,3977,837,4052,762,4126,688,4201,762,4276,837,4201,912,4201,987,4276,1061,4351,1061,4425,987,4500,1061,4575,1061,4650,987,4650,912,4575,837,4650,762,4650,688,4575,613,4500,613,4425,688,4276,538,4351,463,4425,389,4500,463,4575,463,4650,389,4650,314,4575,239,4650,164,4650,90,4575,15,4500,15,4425,90,4351,15,4276,15,4201,90,4201,164,4276,239,4201,314,4126,389,3977,239,4052,164,4052,90,3977,15,3902,15,3827,90,3753,15,3678,15,3603,90,3603,164,3678,239,3603,314,3603,389,3678,463,3753,463,3827,389,3902,463,3977,538,3902,613,3827,688,3753,613,3678,613,3603,688,3603,762,3678,837,3528,987,3379,837,3453,762,3453,688,3379,613,3304,613,3229,688,3080,538,3154,463,3229,389,3304,463,3379,463,3453,389,3453,314,3379,239,3453,164,3453,90,3379,15,3304,15,3229,90,3154,15,3080,15,3005,90,3005,164,3080,239,2930,389,2781,239,2855,164,2855,90,2781,15,2706,15,2631,90,2556,15,2482,15,2407,90,2407,164,2482,239,2407,314,2407,389,2482,463,2556,463,2631,389,2706,463,2781,538,2631,688,2556,613,2482,613,2407,688,2407,762,2482,837,2407,912,2407,987,2482,1061,2556,1061,2631,987,2706,1061,2781,1061,2855,987,2855,912,2781,837,2855,762,2930,688,3005,762,3080,837,3005,912,3005,987,3080,1061,3154,1061,3229,987,3304,1061,3379,1136,3304,1211,3229,1286,3154,1211,3080,1211,3005,1286,3005,1360,3080,1435,3005,1510,2930,1585,2855,1510,2781,1435,2855,1360,2855,1286,2781,1211,2706,1211,2631,1286,2556,1211,2482,1211,2407,1286,2407,1360,2482,1435,2407,1510,2407,1585,2482,1659,2556,1659,2631,1585,2781,1734,2706,1809,2631,1884,2556,1809,2482,1809,2407,1884,2407,1959,2482,2033,2407,2108,2332,2183,2183,2033,2257,1959,2257,1884,2183,1809,2108,1809,2033,1884,1884,1734,1958,1659,2033,1585,2108,1659,2183,1659,2257,1585,2257,1510,2183,1435,2257,1360,2257,1286,2183,1211,2108,1211,2033,1286,1958,1211,1884,1211,1809,1286,1809,1360,1884,1435,1734,1585,1659,1510,1585,1435,1659,1360,1659,1286,1585,1211,1510,1211,1435,1286,1360,1211,1285,1136,1360,1061,1435,987,1510,1061,1585,1061,1659,987,1659,912,1585,837,1659,762,1734,688,1884,837,1809,912,1809,987,1884,1061,1958,1061,2033,987,2108,1061,2183,1061,2257,987,2257,912,2183,837,2257,762,2257,688,2183,613,2108,613,2033,688,1958,613,1884,538,2033,389,2108,463,2183,463,2257,389,2257,314,2183,239,2257,164,2257,90,2183,15,2108,15,2033,90,1958,15,1884,15,1809,90,1809,164,1884,239,1809,314,1734,389,1659,314,1585,239,1659,164,1659,90,1585,15,1510,15,1435,90,1360,15,1285,15,1211,90,1211,164,1285,239,1211,314,1211,389,1285,463,1360,463,1435,389,1585,538,1510,613,1435,688,1360,613,1285,613,1211,688,1211,762,1285,837,1211,912,1136,987,1061,912,986,837,1061,762,1061,688,986,613,912,613,837,688,762,613,687,538,837,389,912,463,986,463,1061,389,1061,314,986,239,1061,164,1061,90,986,15,912,15,837,90,762,15,687,15,613,90,613,164,687,239,613,314,538,389,463,314,388,239,463,164,463,90,388,15,314,15,239,90,164,15,89,15 3 | -------------------------------------------------------------------------------- /polargraph: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # Translate the vectors from a PJL file into gcode for the polargraph. 3 | # There is probably a better way to do this. 4 | # origin is at l1=2032 l2=2032 5 | # separation between the two is 2.5m 6 | use warnings; 7 | use strict; 8 | use Getopt::Long qw/:config no_ignore_case/; 9 | 10 | my $usage = <<""; 11 | $0: Plot a set of vectors on the polargraph. 12 | Options: 13 | -H | --home Send the set-home command in the gcode 14 | -w | --width N Separation between the pulleys in mm 15 | -l | --length N Length of the two strings at the home position in mm 16 | -f | --feed N Feed rate for the motors in mm/sec 17 | -F | --transit N Transit rate for the motors in mm/sec 18 | -n | --step N Interpolation step size for straight lines in mm 19 | -a | --accel Acceleration in mm/s/s (override config) 20 | -M | --motors-on Leave the motors on after the plot (default off) 21 | -r | --rotate Rotate the PDF 90 degrees 22 | -p | --pause Seconds to pause between layers 23 | --offset x,y Shift the origin to x,y in mm 24 | --scale N Scale the plot by this factor 25 | --steps N Adjust the steps/mm to deal with maljusted printers 26 | 27 | my $width = 2501.9; 28 | my $home_length = 2032.0; 29 | my $feed = 2000; 30 | my $transit_feed = 2500; 31 | my $acceleration; 32 | my $step_size = 10; 33 | my $motor_on = 0; 34 | my $send_home = 0; 35 | my $offset_x = 0; 36 | my $offset_y = 0; 37 | my $steps_per_step = 1; 38 | my $rotate = 0; 39 | my $pause_seconds = 1; 40 | 41 | my $scale = 1; 42 | 43 | my $total_dist = 0; 44 | my $total_time = 0; 45 | my $transit_dist = 0; 46 | my $transit_time = 0; 47 | 48 | GetOptions( 49 | "H|home+" => \$send_home, 50 | "r|rotate+" => \$rotate, 51 | "w|width=f" => \$width, 52 | "l|length=f" => \$home_length, 53 | "f|feed=f" => \$feed, 54 | "F|transit=f" => \$transit_feed, 55 | "a|accel=f" => \$acceleration, 56 | "n|step=f" => \$step_size, 57 | "p|pause=f" => \$pause_seconds, 58 | "x|offset-x=f" => \$offset_x, 59 | "y|offset-y=f" => \$offset_y, 60 | "scale=f" => \$scale, 61 | "steps=f" => \$steps_per_step, 62 | "h|?|help" => sub { print $usage; exit 0; } 63 | ) or die $usage; 64 | 65 | # assume the zero-zero point is in the center (width/2) and 66 | # the triangles are right. length^2 = (width/2)^2 + height^2 67 | my $height = $home_length*$home_length - $width*$width/4.0; 68 | die "Width $width is too wide for length $home_length!\n" 69 | if $height <= 0; 70 | $height = sqrt($height); 71 | printf STDERR "Computed height: %0.2fmm\n", $height; 72 | printf STDERR "0 0\n"; 73 | printf STDERR "%.2f %.2f\n", $width, 0; 74 | printf STDERR "%.2f %.2f\n", $width, $height; 75 | printf STDERR "%.2f %.2f\n", 0, $height; 76 | printf STDERR "0 0\n\n"; 77 | 78 | my $points_file = "/tmp/p"; 79 | open POINTS, ">$points_file" 80 | or die "$points_file: Unable to open temp file $!\n"; 81 | 82 | 83 | print "M999\n"; # reset any error condition 84 | printf "M204 S%.0f\n", $acceleration if $acceleration; 85 | 86 | print "G90\nG92 X0 Y0\n"; 87 | print "G92 X$home_length Y$home_length\n" 88 | if $send_home; 89 | 90 | 91 | my @transit_old = (0,0); 92 | my @old; 93 | my $old_file = $ARGV[0] || "stdin"; 94 | my $ol1 = 0; 95 | my $ol2 = 0; 96 | 97 | 98 | while(<>) 99 | { 100 | if($ARGV ne $old_file) 101 | { 102 | $old_file = $ARGV; 103 | print "M72 P2\n"; 104 | print "M71 (Marker Change)\n"; 105 | } 106 | 107 | chomp; 108 | 109 | # ignore anything other than pen up/down commands 110 | next unless /^[MPLZZ]/; 111 | 112 | # a "P" by itself is a layer change or end of file 113 | if(/^P\s*(\d+)\s+(\d+)\s+(\d+)$/) 114 | { 115 | print STDERR "layer $1 $2 $3\n"; 116 | printf "G4 S%.2f\n", $pause_seconds; 117 | next; 118 | } 119 | 120 | my ($cmd,$x,$y) = /^([ML])\s*([-+\d.]+)\s+([-+\d.]+)$/ 121 | or next; 122 | 123 | # swap the axis if we are rotating the image 124 | ($x,$y) = ($width - $y,$x) if $rotate; 125 | 126 | # if the $x and $y are outside of our bounding box, 127 | # warn that this might not work 128 | if ($x < 0 || $x > $width || $y < 0 || $y > $height) 129 | { 130 | printf STDERR "!!! %.02f,%.02f out of bounds\n", $x, $y; 131 | } 132 | 133 | my $dist = len(@old, $x, $y); 134 | 135 | if ($cmd eq 'M') 136 | { 137 | goxy($x,$y, $transit_feed); 138 | $transit_dist += $dist; 139 | $transit_time += $dist / ($transit_feed / 60.0); 140 | } else { 141 | goxy_step(@old, $x,$y, $feed); 142 | $total_dist += $dist; 143 | $total_time += $dist / ($feed / 60.0); 144 | } 145 | 146 | @old = ($x,$y); 147 | } 148 | 149 | sub len 150 | { 151 | my ($x1,$y1,$x2,$y2) = @_; 152 | my $dx = $x2 - $x1; 153 | my $dy = $y2 - $y1; 154 | return sqrt($dx*$dx + $dy*$dy); 155 | } 156 | 157 | sub compute_lengths 158 | { 159 | my ($x,$y) = @_; 160 | 161 | my $l1 = sqrt($x*$x + $y*$y); 162 | my $l2 = sqrt(($width-$x)*($width-$x) + $y*$y); 163 | 164 | # fix for the makerbot software 165 | $l1 = ($l1 - $home_length) * $steps_per_step; 166 | $l2 = ($l2 - $home_length) * $steps_per_step; 167 | 168 | # compute how far this is in motor space from our last point 169 | my $dl1 = $l1 - $ol1; 170 | my $dl2 = $l2 - $ol2; 171 | my $ldist = sqrt($dl1*$dl1 + $dl2*$dl2); 172 | $ol1 = $l1; 173 | $ol2 = $l2; 174 | 175 | return ($l1,$l2,$ldist); 176 | } 177 | 178 | 179 | sub goxy_step 180 | { 181 | my ($x0,$y0,$x1,$y1,$feed) = @_; 182 | 183 | # iterate from x0,y0 to x1,y1 184 | my $dx = $x1 - $x0; 185 | my $dy = $y1 - $y0; 186 | my $dist = sqrt($dx*$dx+$dy*$dy); 187 | 188 | my $steps = int($dist/$step_size) + 1; 189 | my $step_dist = $dist / $steps; 190 | 191 | for(my $i = 0 ; $i < $steps ; $i++) 192 | { 193 | $x0 += $dx / $steps; 194 | $y0 += $dy / $steps; 195 | 196 | # compute the desired motor speed for this step 197 | # so that the cartesian speed is constant. 198 | my $step_feed = $feed; 199 | 200 | #goxy($x0,$y0,$step_feed); 201 | 202 | # compute how far we are moving in motor space 203 | my ($l1,$l2,$ldist) = compute_lengths($x0,$y0); 204 | 205 | # and compute how fast we have to move that distance 206 | # to equal moving $dist/$steps at the feed rate 207 | my $lfeed = $feed * $ldist / $step_dist; 208 | 209 | printf POINTS "%.3f %.3f -> %.3f %.3f @ %.3f %.3f\n", $x0, $y0, $l1, $l2, $lfeed, $step_dist; 210 | printf "G1 X%.3f Y%.3f F%d\n", $l1, $l2, $lfeed; 211 | } 212 | 213 | # we had better be at x1,y1, or close enough for floating point 214 | # so this goxy is not necessary 215 | #goxy($x1,$y1,$feed); 216 | } 217 | 218 | 219 | # Move the pen somewhere, quickly 220 | sub goxy 221 | { 222 | # convert from pts to something 223 | my $x = shift; 224 | my $y = shift; 225 | my $feed = shift || 1000; 226 | 227 | my ($l1,$l2) = compute_lengths($x,$y); 228 | printf POINTS "%.3f %.3f -> %.3f %.3f @ %.3f\n", $x, $y, $l1, $l2, $feed; 229 | printf "G0 X%.3f Y%.3f F%d\n", $l1, $l2, $feed; 230 | } 231 | 232 | # Send the marker back to home at the high speed 233 | printf "G1 X%.3f Y%.3f F%d\n", 0, 0, $transit_feed; 234 | 235 | # Turn off the motors if requested 236 | print "M18 X Y\n" unless $motor_on; 237 | print "M72 P1\n"; 238 | print "M137\n"; 239 | 240 | # Report some stats 241 | printf STDERR "Drawing %8.02fm %7.0f:%02.0f\n", 242 | $total_dist / 1000.0, 243 | $total_time / 60, 244 | $total_time % 60; 245 | printf STDERR "Transit %8.02fm %7.0f:%02.0f\n", 246 | $transit_dist / 1000.0, 247 | $transit_time / 60, 248 | $transit_time % 60; 249 | printf STDERR "Total %8.02fm %7.0f:%02.0f\n", 250 | ($total_dist+$transit_dist) / 1000.0, 251 | ($total_time+$transit_time) / 60, 252 | ($total_time+$transit_time) % 60; 253 | 254 | 255 | -------------------------------------------------------------------------------- /pulley.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Pulley for the polargraph motors. 3 | * You will need two. 4 | */ 5 | 6 | circumference = 120; 7 | height = 10; 8 | shank_height = 8; 9 | radius = circumference / (2 * PI); 10 | 11 | render() difference() 12 | { 13 | 14 | union() 15 | { 16 | // the two pieces of the pulley 17 | { 18 | translate([0,0,height*2/3]) 19 | cylinder(r1=radius, r2=radius+height*0.5, h=height/3, $fn=90); 20 | 21 | translate([0,0,height/3]) 22 | cylinder(r=radius, h=height/3, $fn=90); 23 | 24 | cylinder(r2=radius, r1=radius+height*0.5, h=height/3, $fn=90); 25 | } 26 | 27 | // the shank 28 | rotate([0,0,-10]) translate([0,0,height]) cylinder(r=8, h=shank_height, $fn=7); 29 | } 30 | 31 | // shaft for the 5mm nema23 stepper motor 32 | cylinder(r=5.0/2 + 0.25, h=30, $fn=30); 33 | cylinder(r1=5.0/2 + 1, r2=5.0/2 + 0.25, h=2, $fn=30); 34 | 35 | translate([0,-5.0/2+1.2,height+shank_height/2]) 36 | rotate([90,0,0]) { 37 | // m3 mounting screw 38 | cylinder(r=3.0/2 + 0.2, h=30, $fn=30); 39 | // m3 nut to capture it 40 | rotate([0,0,30]) cylinder(r=6.0/2+0.5, h=2, $fn=6); 41 | translate([0,3.5,0.5]) cube([5.5,10,2],center=true); 42 | } 43 | 44 | // string hole 45 | translate([radius,0,height*2/3]) cylinder(r=1, h=height+2, $fn=12); 46 | } 47 | 48 | -------------------------------------------------------------------------------- /serial-monitor: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Run this to initialize the serial port and provide feedback 3 | # as the polargraph plots. 4 | # 5 | # FLOW CONTROL MUST BE TURNED ON. 6 | # Enable it with $ex 2 7 | # Otherwise the plot command will over-run the buffers. 8 | # 9 | exec picocom \ 10 | --flow hard \ 11 | --echo \ 12 | --imap lfcrlf \ 13 | -b 115200 \ 14 | /dev/ttyUSB2 15 | -------------------------------------------------------------------------------- /smoothie.config: -------------------------------------------------------------------------------- 1 | # map a switch to start the drawing 2 | #switch.player.input_pin 1.25^ 3 | #switch.player.input_pin_behaviour momentary 4 | #switch.player.output_off_command play /sd/calibration.gcode 5 | 6 | # NOTE Lines must not exceed 132 characters 7 | # Robot module configurations : general handling of movement G-codes and slicing into moves 8 | default_feed_rate 1000 # Default rate ( mm/minute ) for G1/G2/G3 moves 9 | default_seek_rate 4000 # Default rate ( mm/minute ) for G0 moves 10 | mm_per_arc_segment 0.5 # Arcs are cut into segments ( lines ), this is the length for 11 | # these segments. Smaller values mean more resolution, 12 | # higher values mean faster computation 13 | mm_per_line_segment 5 # Lines can be cut into segments ( not usefull with cartesian 14 | # coordinates robots ). 15 | 16 | # Arm solution configuration : Cartesian robot. Translates mm positions into stepper positions 17 | # this is using 10mm diameter pulleys on 200 steps/rev motors 18 | # 3200 steps/rev / (10mm * 3.14 / rev) = 101.4 19 | # 3200 steps/rev / (22mm * 3.14 / rev) = 46.32 20 | # 3200 steps/rev / (100mm circumference) = 32.00 21 | # 3200 steps/rev / (120mm circumference) = 26.66 22 | alpha_steps_per_mm 26.666 # Steps per mm for alpha stepper 23 | beta_steps_per_mm 26.666 # Steps per mm for beta stepper 24 | gamma_steps_per_mm 1600 # Steps per mm for gamma stepper 25 | 26 | # Planner module configuration : Look-ahead and acceleration configuration 27 | planner_queue_size 32 # DO NOT CHANGE THIS UNLESS YOU KNOW EXACTLY WHAT YOU ARE DOING 28 | acceleration 1000 # Acceleration in mm/second/second. 29 | #z_acceleration 500 # Acceleration for Z only moves in mm/s^2, 0 uses acceleration which is the default. DO NOT SET ON A DELTA 30 | acceleration_ticks_per_second 1000 # Number of times per second the speed is updated 31 | junction_deviation 0.01 # Similar to the old "max_jerk", in millimeters, 32 | # see https://github.com/grbl/grbl/blob/master/planner.c 33 | # and https://github.com/grbl/grbl/wiki/Configuring-Grbl-v0.8 34 | # Lower values mean being more careful, higher values means being 35 | # faster and have more jerk 36 | #z_junction_deviation 0.0 # for Z only moves, -1 uses junction_deviation, zero disables junction_deviation on z moves DO NOT SET ON A DELTA 37 | #minimum_planner_speed 0.0 # sets the minimum planner speed in mm/sec 38 | 39 | # Stepper module configuration 40 | microseconds_per_step_pulse 1 # Duration of step pulses to stepper drivers, in microseconds 41 | base_stepping_frequency 100000 # Base frequency for stepping, higher gives smoother movement 42 | 43 | # Cartesian axis speed limits 44 | x_axis_max_speed 30000 # mm/min 45 | y_axis_max_speed 30000 # mm/min 46 | z_axis_max_speed 300 # mm/min 47 | 48 | # Stepper module pins ( ports, and pin numbers, appending "!" to the number will invert a pin ) 49 | alpha_step_pin 2.0 # Pin for alpha stepper step signal 50 | alpha_dir_pin 0.5 # Pin for alpha stepper direction 51 | alpha_en_pin 0.4 # Pin for alpha enable pin 52 | alpha_current 0.5 # X stepper motor current 53 | alpha_max_rate 30000.0 # mm/min 54 | 55 | beta_step_pin 2.1 # Pin for beta stepper step signal 56 | beta_dir_pin 0.11! # Pin for beta stepper direction 57 | beta_en_pin 0.10 # Pin for beta enable 58 | beta_current 0.5 # Y stepper motor current 59 | beta_max_rate 30000.0 # mm/min 60 | 61 | gamma_step_pin 2.2 # Pin for gamma stepper step signal 62 | gamma_dir_pin 0.20 # Pin for gamma stepper direction 63 | gamma_en_pin 0.19 # Pin for gamma enable 64 | gamma_current 1.5 # Z stepper motor current 65 | gamma_max_rate 300.0 # mm/min 66 | 67 | # Serial communications configuration ( baud rate default to 9600 if undefined ) 68 | uart0.baud_rate 115200 # Baud rate for the default hardware serial port 69 | second_usb_serial_enable false # This enables a second usb serial port (to have both pronterface 70 | # and a terminal connected) 71 | #leds_disable true # disable using leds after config loaded 72 | #play_led_disable true # disable the play led 73 | pause_button_enable true # Pause button enable 74 | #pause_button_pin 2.12 # pause button pin. default is P2.12 75 | kill_button_enable true # set to true to enable a kill button 76 | kill_button_pin 1.24! # kill button mapped to X-min, NC to ground 77 | #msd_disable false # disable the MSD (USB SDCARD) when set to true (needs special binary) 78 | #dfu_enable false # for linux developers, set to true to enable DFU 79 | 80 | # Extruder module configuration 81 | extruder.hotend.enable true # Whether to activate the extruder module at all. All configuration is ignored if false 82 | extruder.hotend.steps_per_mm 140 # Steps per mm for extruder stepper 83 | extruder.hotend.default_feed_rate 600 # Default rate ( mm/minute ) for moves where only the extruder moves 84 | extruder.hotend.acceleration 500 # Acceleration for the stepper motor, as of 0.6, arbitrary ratio 85 | extruder.hotend.max_speed 50 # mm/s 86 | 87 | extruder.hotend.step_pin 2.3 # Pin for extruder step signal 88 | extruder.hotend.dir_pin 0.22 # Pin for extruder dir signal 89 | extruder.hotend.en_pin 0.21 # Pin for extruder enable signal 90 | 91 | # extruder offset 92 | #extruder.hotend.x_offset 0 # x offset from origin in mm 93 | #extruder.hotend.y_offset 0 # y offset from origin in mm 94 | #extruder.hotend.z_offset 0 # z offset from origin in mm 95 | 96 | # firmware retract settings when using G10/G11, these are the defaults if not defined, must be defined for each extruder if not using the defaults 97 | #extruder.hotend.retract_length 3 # retract length in mm 98 | #extruder.hotend.retract_feedrate 45 # retract feedrate in mm/sec 99 | #extruder.hotend.retract_recover_length 0 # additional length for recover 100 | #extruder.hotend.retract_recover_feedrate 8 # recover feedrate in mm/sec (should be less than retract feedrate) 101 | #extruder.hotend.retract_zlift_length 0 # zlift on retract in mm, 0 disables 102 | #extruder.hotend.retract_zlift_feedrate 6000 # zlift feedrate in mm/min (Note mm/min NOT mm/sec) 103 | 104 | delta_current 1.5 # First extruder stepper motor current 105 | 106 | # Second extruder module configuration 107 | #extruder.hotend2.enable true # Whether to activate the extruder module at all. All configuration is ignored if false 108 | #extruder.hotend2.steps_per_mm 140 # Steps per mm for extruder stepper 109 | #extruder.hotend2.default_feed_rate 600 # Default rate ( mm/minute ) for moves where only the extruder moves 110 | #extruder.hotend2.acceleration 500 # Acceleration for the stepper motor, as of 0.6, arbitrary ratio 111 | #extruder.hotend2.max_speed 50 # mm/s 112 | 113 | #extruder.hotend2.step_pin 2.8 # Pin for extruder step signal 114 | #extruder.hotend2.dir_pin 2.13 # Pin for extruder dir signal 115 | #extruder.hotend2.en_pin 4.29 # Pin for extruder enable signal 116 | 117 | #extruder.hotend2.x_offset 0 # x offset from origin in mm 118 | #extruder.hotend2.y_offset 25.0 # y offset from origin in mm 119 | #extruder.hotend2.z_offset 0 # z offset from origin in mm 120 | #epsilon_current 1.5 # Second extruder stepper motor current 121 | 122 | 123 | # Laser module configuration 124 | laser_module_enable false # Whether to activate the laser module at all. All configuration is 125 | # ignored if false. 126 | #laser_module_pin 2.5 # this pin will be PWMed to control the laser. Only P2.0 - P2.5, P1.18, P1.20, P1.21, P1.23, P1.24, P1.26, P3.25, P3.26 127 | # can be used since laser requires hardware PWM 128 | #laser_module_max_power 0.8 # this is the maximum duty cycle that will be applied to the laser 129 | #laser_module_tickle_power 0.0 # this duty cycle will be used for travel moves to keep the laser 130 | # active without actually burning 131 | #laser_module_pwm_period 20 # this sets the pwm frequency as the period in microseconds 132 | 133 | # Hotend temperature control configuration 134 | temperature_control.hotend.enable true # Whether to activate this ( "hotend" ) module at all. 135 | # All configuration is ignored if false. 136 | temperature_control.hotend.thermistor_pin 0.23 # Pin for the thermistor to read 137 | temperature_control.hotend.heater_pin 2.7 # Pin that controls the heater, set to nc if a readonly thermistor is being defined 138 | temperature_control.hotend.thermistor EPCOS100K # see http://smoothieware.org/temperaturecontrol#toc5 139 | #temperature_control.hotend.beta 4066 # or set the beta value 140 | temperature_control.hotend.set_m_code 104 # 141 | temperature_control.hotend.set_and_wait_m_code 109 # 142 | temperature_control.hotend.designator T # 143 | 144 | #temperature_control.hotend.p_factor 13.7 # permanently set the PID values after an auto pid 145 | #temperature_control.hotend.i_factor 0.097 # 146 | #temperature_control.hotend.d_factor 24 # 147 | 148 | #temperature_control.hotend.max_pwm 64 # max pwm, 64 is a good value if driving a 12v resistor with 24v. 149 | 150 | # Hotend2 temperature control configuration 151 | #temperature_control.hotend2.enable true # Whether to activate this ( "hotend" ) module at all. 152 | # All configuration is ignored if false. 153 | 154 | #temperature_control.hotend2.thermistor_pin 0.25 # Pin for the thermistor to read 155 | #temperature_control.hotend2.heater_pin 1.23 # Pin that controls the heater 156 | #temperature_control.hotend2.thermistor EPCOS100K # see http://smoothieware.org/temperaturecontrol#toc5 157 | ##temperature_control.hotend2.beta 4066 # or set the beta value 158 | #temperature_control.hotend2.set_m_code 884 # 159 | #temperature_control.hotend2.set_and_wait_m_code 889 # 160 | #temperature_control.hotend2.designator T1 # 161 | 162 | #temperature_control.hotend2.p_factor 13.7 # permanently set the PID values after an auto pid 163 | #temperature_control.hotend2.i_factor 0.097 # 164 | #temperature_control.hotend2.d_factor 24 # 165 | 166 | #temperature_control.hotend2.max_pwm 64 # max pwm, 64 is a good value if driving a 12v resistor with 24v. 167 | 168 | temperature_control.bed.enable true # 169 | temperature_control.bed.thermistor_pin 0.24 # 170 | temperature_control.bed.heater_pin 2.5 # 171 | temperature_control.bed.thermistor Honeywell100K # see http://smoothieware.org/temperaturecontrol#toc5 172 | #temperature_control.bed.beta 3974 # or set the beta value 173 | 174 | temperature_control.bed.set_m_code 140 # 175 | temperature_control.bed.set_and_wait_m_code 190 # 176 | temperature_control.bed.designator B # 177 | 178 | #temperature_control.bed.bang_bang false # set to true to use bang bang control rather than PID 179 | #temperature_control.bed.hysteresis 2.0 # set to the temperature in degrees C to use as hysteresis 180 | # when using bang bang 181 | 182 | # Switch module for fan control 183 | switch.fan.enable true # 184 | switch.fan.input_on_command M106 # 185 | switch.fan.input_off_command M107 # 186 | switch.fan.output_pin 2.6 # 187 | switch.fan.output_type pwm # pwm output settable with S parameter in the input_on_comand 188 | #switch.fan.max_pwm 255 # set max pwm for the pin default is 255 189 | 190 | #switch.misc.enable true # 191 | #switch.misc.input_on_command M42 # 192 | #switch.misc.input_off_command M43 # 193 | #switch.misc.output_pin 2.4 # 194 | #switch.misc.output_type digital # just an on or off pin 195 | 196 | # automatically toggle a switch at a specified temperature. Different ones of these may be defined to monitor different temperatures and switch different swithxes 197 | # useful to turn on a fan or water pump to cool the hotend 198 | #temperatureswitch.hotend.enable true # 199 | #temperatureswitch.hotend.designator T # first character of the temperature control designator to use as the temperature sensor to monitor 200 | #temperatureswitch.hotend.switch misc # select which switch to use, matches the name of the defined switch 201 | #temperatureswitch.hotend.threshold_temp 60.0 # temperature to turn on (if rising) or off the switch 202 | #temperatureswitch.hotend.heatup_poll 15 # poll heatup at 15 sec intervals 203 | #temperatureswitch.hotend.cooldown_poll 60 # poll cooldown at 60 sec intervals 204 | 205 | # Switch module for spindle control 206 | #switch.spindle.enable false # 207 | 208 | # Endstops 209 | endstops_enable false # no endstops on polargraph 210 | #corexy_homing false # set to true if homing on a hbit or corexy 211 | alpha_min_endstop 1.24^ # add a ! to invert if endstop is NO connected to ground 212 | alpha_max_endstop 1.25^ # NOTE set to nc if this is not installed 213 | alpha_homing_direction home_to_min # or set to home_to_max and set alpha_max 214 | alpha_min 0 # this gets loaded after homing when home_to_min is set 215 | alpha_max 200 # this gets loaded after homing when home_to_max is set 216 | beta_min_endstop 1.26^ # 217 | beta_max_endstop 1.27^ # 218 | beta_homing_direction home_to_min # 219 | beta_min 0 # 220 | beta_max 200 # 221 | gamma_min_endstop 1.28^ # 222 | gamma_max_endstop 1.29^ # 223 | gamma_homing_direction home_to_min # 224 | gamma_min 0 # 225 | gamma_max 200 # 226 | 227 | # optional order in which axis will home, default is they all home at the same time, 228 | # if this is set it will force each axis to home one at a time in the specified order 229 | #homing_order XYZ # x axis followed by y then z last 230 | 231 | # optional enable limit switches, actions will stop if any enabled limit switch is triggered 232 | #alpha_limit_enable false # set to true to enable X min and max limit switches 233 | #beta_limit_enable false # set to true to enable Y min and max limit switches 234 | #gamma_limit_enable false # set to true to enable Z min and max limit switches 235 | 236 | alpha_fast_homing_rate_mm_s 50 # feedrates in mm/second 237 | beta_fast_homing_rate_mm_s 50 # " 238 | gamma_fast_homing_rate_mm_s 4 # " 239 | alpha_slow_homing_rate_mm_s 25 # " 240 | beta_slow_homing_rate_mm_s 25 # " 241 | gamma_slow_homing_rate_mm_s 2 # " 242 | 243 | alpha_homing_retract_mm 5 # distance in mm 244 | beta_homing_retract_mm 5 # " 245 | gamma_homing_retract_mm 1 # " 246 | 247 | #endstop_debounce_count 100 # uncomment if you get noise on your endstops, default is 100 248 | 249 | # optional Z probe 250 | zprobe.enable false # set to true to enable a zprobe 251 | zprobe.probe_pin 1.28!^ # pin probe is attached to if NC remove the ! 252 | zprobe.slow_feedrate 5 # mm/sec probe feed rate 253 | #zprobe.debounce_count 100 # set if noisy 254 | zprobe.fast_feedrate 100 # move feedrate mm/sec 255 | zprobe.probe_height 5 # how much above bed to start probe 256 | #gamma_min_endstop nc # normally 1.28. Change to nc to prevent conflict, 257 | 258 | # associated with zprobe the leveling strategy to use 259 | #leveling-strategy.three-point-leveling.enable true # a leveling strategy that probes three points to define a plane and keeps the Z parallel to that plane 260 | #leveling-strategy.three-point-leveling.point1 100.0,0.0 # the first probe point (x,y) optional may be defined with M557 261 | #leveling-strategy.three-point-leveling.point2 200.0,200.0 # the second probe point (x,y) 262 | #leveling-strategy.three-point-leveling.point3 0.0,200.0 # the third probe point (x,y) 263 | #leveling-strategy.three-point-leveling.home_first true # home the XY axis before probing 264 | #leveling-strategy.three-point-leveling.tolerance 0.03 # the probe tolerance in mm, anything less that this will be ignored, default is 0.03mm 265 | #leveling-strategy.three-point-leveling.probe_offsets 0,0,0 # the probe offsets from nozzle, must be x,y,z, default is no offset 266 | #leveling-strategy.three-point-leveling.save_plane false # set to true to allow the bed plane to be saved with M500 default is false 267 | 268 | # Panel 269 | panel.enable false # set to true to enable the panel code 270 | panel.lcd smoothiepanel # set type of panel 271 | panel.encoder_a_pin 3.25!^ # encoder pin 272 | panel.encoder_b_pin 3.26!^ # encoder pin 273 | 274 | # Example for reprap discount GLCD 275 | # on glcd EXP1 is to left and EXP2 is to right, pin 1 is bottom left, pin 2 is top left etc. 276 | # +5v is EXP1 pin 10, Gnd is EXP1 pin 9 277 | #panel.lcd reprap_discount_glcd # 278 | #panel.spi_channel 0 # spi channel to use ; GLCD EXP1 Pins 3,5 (MOSI, SCLK) 279 | #panel.spi_cs_pin 0.16 # spi chip select ; GLCD EXP1 Pin 4 280 | #panel.encoder_a_pin 3.25!^ # encoder pin ; GLCD EXP2 Pin 3 281 | #panel.encoder_b_pin 3.26!^ # encoder pin ; GLCD EXP2 Pin 5 282 | #panel.click_button_pin 1.30!^ # click button ; GLCD EXP1 Pin 2 283 | #panel.buzz_pin 1.31 # pin for buzzer ; GLCD EXP1 Pin 1 284 | #panel.back_button_pin 2.11!^ # back button ; GLCD EXP2 Pin 8 285 | 286 | # pins used with other panels 287 | #panel.up_button_pin 0.1! # up button if used 288 | #panel.down_button_pin 0.0! # down button if used 289 | #panel.click_button_pin 0.18! # click button if used 290 | 291 | panel.menu_offset 0 # some panels will need 1 here 292 | 293 | panel.alpha_jog_feedrate 6000 # x jogging feedrate in mm/min 294 | panel.beta_jog_feedrate 6000 # y jogging feedrate in mm/min 295 | panel.gamma_jog_feedrate 200 # z jogging feedrate in mm/min 296 | 297 | panel.hotend_temperature 185 # temp to set hotend when preheat is selected 298 | panel.bed_temperature 60 # temp to set bed when preheat is selected 299 | 300 | # Example of a custom menu entry, which will show up in the Custom entry. 301 | # NOTE _ gets converted to space in the menu and commands, | is used to separate multiple commands 302 | custom_menu.power_on.enable true # 303 | custom_menu.power_on.name Power_on # 304 | custom_menu.power_on.command M80 # 305 | 306 | custom_menu.power_off.enable true # 307 | custom_menu.power_off.name Power_off # 308 | custom_menu.power_off.command M81 # 309 | 310 | # Only needed on a smoothieboard 311 | currentcontrol_module_enable true # 312 | 313 | return_error_on_unhandled_gcode false # 314 | 315 | # network settings 316 | network.enable false # enable the ethernet network services 317 | network.webserver.enable true # enable the webserver 318 | network.telnet.enable true # enable the telnet server 319 | network.ip_address auto # use dhcp to get ip address 320 | # uncomment the 3 below to manually setup ip address 321 | #network.ip_address 192.168.3.222 # the IP address 322 | #network.ip_mask 255.255.255.0 # the ip mask 323 | #network.ip_gateway 192.168.3.1 # the gateway address 324 | #network.mac_override xx.xx.xx.xx.xx.xx # override the mac address, only do this if you have a conflict 325 | -------------------------------------------------------------------------------- /smoothiecat: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # The smoothieboard doesn't have flow control, so it is necessary 3 | # to wait for it to respond "ok" before sending another waypoint. 4 | use warnings; 5 | use strict; 6 | use Device::SerialPort; 7 | use Data::Dumper; 8 | use Time::HiRes 'usleep'; 9 | 10 | my $dev_file = shift || "/dev/ttyACM1"; 11 | #my $dev_file = "/dev/tty.usbmodem1411"; 12 | 13 | my $dev = Device::SerialPort->new($dev_file) 14 | or die "$dev_file: $!\n"; 15 | 16 | $dev->baudrate(115200); 17 | 18 | sub wait_ok 19 | { 20 | my $dev = shift; 21 | 22 | for(1..10000) 23 | { 24 | my $in = $dev->input(); 25 | return if $in =~ /^ok/msg; 26 | 27 | print "read: ", Dumper($in) if $in; 28 | usleep(10000); 29 | } 30 | 31 | die "Did not receive ok from board\n"; 32 | } 33 | 34 | # wait for the ok 35 | #wait_ok($dev); 36 | 37 | # Read all the gcode lines from the file 38 | my @gcode = <>; 39 | my $line_count = @gcode; 40 | my $line_num = 0; 41 | 42 | printf "Read %d gcode commands\n", $line_count; 43 | 44 | for (@gcode) 45 | { 46 | chomp; 47 | $line_num++; 48 | printf "%8.2f: %s\n", $line_num * 100 / $line_count, $_; 49 | $dev->write("$_\r\n"); 50 | 51 | # wait for the ok 52 | wait_ok($dev); 53 | } 54 | -------------------------------------------------------------------------------- /vecsort.c: -------------------------------------------------------------------------------- 1 | /** \file 2 | * Topologically sort vectors for faster laser cutting or plotting. 3 | */ 4 | #include 5 | #include 6 | #include 7 | 8 | typedef struct _vector vector_t; 9 | struct _vector 10 | { 11 | vector_t * next; 12 | vector_t ** prev; 13 | double x1; 14 | double y1; 15 | double x2; 16 | double y2; 17 | }; 18 | 19 | 20 | typedef struct 21 | { 22 | vector_t * vectors; 23 | } vectors_t; 24 | 25 | // Red/Green/Blue 26 | #define VECTOR_PASSES 3 27 | 28 | // close enough for floating point work 29 | static inline int fpeq(double x, double y) 30 | { 31 | const double eps = 1e-8; 32 | return fabs(x-y) < eps; 33 | } 34 | 35 | 36 | static double 37 | vector_transit_len( 38 | vector_t * v 39 | ) 40 | { 41 | double lx = 0; 42 | double ly = 0; 43 | 44 | double transit_len_sum = 0; 45 | 46 | while (v) 47 | { 48 | double t_dx = lx - v->x1; 49 | double t_dy = ly - v->y1; 50 | 51 | double transit_len = sqrt(t_dx * t_dx + t_dy * t_dy); 52 | if (transit_len != 0) 53 | transit_len_sum += transit_len; 54 | 55 | // Advance the point 56 | lx = v->x2; 57 | ly = v->y2; 58 | v = v->next; 59 | } 60 | 61 | return transit_len_sum; 62 | } 63 | 64 | 65 | static void 66 | vector_stats( 67 | vector_t * v 68 | ) 69 | { 70 | double lx = 0; 71 | double ly = 0; 72 | double cut_len_sum = 0; 73 | int cuts = 0; 74 | 75 | double transit_len_sum = 0; 76 | int transits = 0; 77 | 78 | while (v) 79 | { 80 | double t_dx = lx - v->x1; 81 | double t_dy = ly - v->y1; 82 | 83 | double transit_len = sqrt(t_dx * t_dx + t_dy * t_dy); 84 | if (transit_len != 0) 85 | { 86 | transits++; 87 | transit_len_sum += transit_len; 88 | } 89 | 90 | double c_dx = v->x1 - v->x2; 91 | double c_dy = v->y1 - v->y2; 92 | 93 | double cut_len = sqrt(c_dx*c_dx + c_dy*c_dy); 94 | if (cut_len != 0) 95 | { 96 | cuts++; 97 | cut_len_sum += cut_len; 98 | } 99 | 100 | // Advance the point 101 | lx = v->x2; 102 | ly = v->y2; 103 | v = v->next; 104 | } 105 | 106 | fprintf(stderr, "Cuts: %u len %.0f\n", cuts, cut_len_sum); 107 | fprintf(stderr, "Move: %u len %.0f\n", transits, transit_len_sum); 108 | } 109 | 110 | 111 | static void 112 | vector_create( 113 | vectors_t * const vectors, 114 | double x1, 115 | double y1, 116 | double x2, 117 | double y2 118 | ) 119 | { 120 | // Find the end of the list and, if vector optimization is 121 | // turned on, check for duplicates 122 | vector_t ** iter = &vectors->vectors; 123 | while (*iter) 124 | { 125 | vector_t * const p = *iter; 126 | 127 | if (fpeq(p->x1,x1) && fpeq(p->y1,y1) 128 | && fpeq(p->x2,x2) && fpeq(p->y2,y2)) 129 | return; 130 | 131 | if (fpeq(p->x1,x2) && fpeq(p->y1,y2) 132 | && fpeq(p->x2,x1) && fpeq(p->y2,y1)) 133 | return; 134 | 135 | if (fpeq(x1,x2) && fpeq(y1,y2)) 136 | return; 137 | 138 | iter = &p->next; 139 | } 140 | 141 | vector_t * const v = calloc(1, sizeof(*v)); 142 | if (!v) 143 | return; 144 | 145 | v->x1 = x1; 146 | v->y1 = y1; 147 | v->x2 = x2; 148 | v->y2 = y2; 149 | 150 | // Append it to the now known end of the list 151 | v->next = NULL; 152 | v->prev = iter; 153 | *iter = v; 154 | } 155 | 156 | 157 | 158 | /** 159 | * Generate a list of vectors. 160 | * 161 | * The vector format is: 162 | * P r,g,b -- Color of the vector 163 | * M x,y -- Move (start a line at x,y) 164 | * L x,y -- Line to x,y from the current position 165 | * Z -- Closing line segment to the starting position 166 | * 167 | * Multi segment vectors are split into individual vectors, which are 168 | * then passed into the topological sort routine. 169 | * 170 | * Exact duplictes will be deleted to try to avoid double hits.. 171 | */ 172 | static vectors_t * 173 | vectors_parse( 174 | FILE * const vector_file 175 | ) 176 | { 177 | vectors_t * const vectors = calloc(VECTOR_PASSES, sizeof(*vectors)); 178 | double mx = 0, my = 0; 179 | double lx = 0, ly = 0; 180 | int pass = 0; 181 | int count = 0; 182 | 183 | char buf[256]; 184 | 185 | while (fgets(buf, sizeof(buf), vector_file)) 186 | { 187 | //fprintf(stderr, "read '%s'\n", buf); 188 | const char cmd = buf[0]; 189 | double x, y; 190 | 191 | switch (cmd) 192 | { 193 | case 'P': 194 | { 195 | // note that they will be in bgr order in the file 196 | int r, g, b; 197 | sscanf(buf+1, "%d %d %d", &b, &g, &r); 198 | if (r == 0 && g != 0 && b == 0) 199 | { 200 | pass = 0; 201 | } else 202 | if (r != 0 && g == 0 && b == 0) 203 | { 204 | pass = 1; 205 | } else 206 | if (r == 0 && g == 0 && b != 0) 207 | { 208 | pass = 2; 209 | } else { 210 | fprintf(stderr, "non-red/green/blue vector? %d,%d,%d\n", r, g, b); 211 | exit(-1); 212 | } 213 | break; 214 | } 215 | case 'M': 216 | // Start a new line. 217 | // This also implicitly sets the 218 | // current laser position 219 | sscanf(buf+1, "%lf %lf", &mx, &my); 220 | lx = mx; 221 | ly = my; 222 | break; 223 | case 'L': 224 | // Add a line segment from the current 225 | // point to the new point, and update 226 | // the current point to the new point. 227 | sscanf(buf+1, "%lf %lf", &x, &y); 228 | vector_create(&vectors[pass], lx, ly, x, y); 229 | count++; 230 | lx = x; 231 | ly = y; 232 | break; 233 | case 'Z': 234 | // Closing segment from the current point 235 | // back to the starting point 236 | vector_create(&vectors[pass], lx, ly, mx, my); 237 | lx = mx; 238 | lx = my; 239 | break; 240 | case 'X': 241 | goto done; 242 | default: 243 | fprintf(stderr, "Unknown command '%c'", cmd); 244 | return NULL; 245 | } 246 | } 247 | 248 | done: 249 | fprintf(stderr, "read %u segments\n", count); 250 | /* 251 | for (int i = 0 ; i < VECTOR_PASSES ; i++) 252 | { 253 | vector_stats(vectors[i].vectors); 254 | } 255 | 256 | fprintf(stderr, "---\n"); 257 | */ 258 | 259 | return vectors; 260 | } 261 | 262 | 263 | /** Find the closest vector to a given point and remove it from the list. 264 | * 265 | * This might reverse a vector if it is closest to draw it in reverse 266 | * order. 267 | */ 268 | static vector_t * 269 | vector_find_closest( 270 | vector_t * v, 271 | const double cx, 272 | const double cy 273 | ) 274 | { 275 | double best_dist = 1e9; 276 | vector_t * best = NULL; 277 | int do_reverse = 0; 278 | 279 | while (v) 280 | { 281 | double dx1 = cx - v->x1; 282 | double dy1 = cy - v->y1; 283 | double dist1 = dx1*dx1 + dy1*dy1; 284 | 285 | if (dist1 < best_dist) 286 | { 287 | best = v; 288 | best_dist = dist1; 289 | do_reverse = 0; 290 | } 291 | 292 | double dx2 = cx - v->x2; 293 | double dy2 = cy - v->y2; 294 | double dist2 = dx2*dx2 + dy2*dy2; 295 | if (dist2 < best_dist) 296 | { 297 | best = v; 298 | best_dist = dist2; 299 | do_reverse = 1; 300 | } 301 | 302 | v = v->next; 303 | } 304 | 305 | if (!best) 306 | return NULL; 307 | 308 | // Remove it from the list 309 | if (best->prev) 310 | *best->prev = best->next; 311 | if (best->next) 312 | best->next->prev = best->prev; 313 | 314 | // If reversing is required, flip the x1/x2 and y1/y2 315 | if (do_reverse) 316 | { 317 | double x1 = best->x1; 318 | double y1 = best->y1; 319 | best->x1 = best->x2; 320 | best->y1 = best->y2; 321 | best->x2 = x1; 322 | best->y2 = y1; 323 | } 324 | 325 | best->next = NULL; 326 | best->prev = NULL; 327 | 328 | return best; 329 | } 330 | 331 | 332 | /** 333 | * Optimize the cut order to minimize transit time. 334 | * 335 | * Simplistic greedy algorithm: look for the closest vector that starts 336 | * or ends at the same point as the current point. 337 | * 338 | * This does not split vectors. 339 | */ 340 | static vector_t * 341 | vector_optimize( 342 | vector_t ** vectors, 343 | double *cx_ptr, 344 | double *cy_ptr 345 | ) 346 | { 347 | vector_t * vs = NULL; 348 | vector_t * vs_tail = NULL; 349 | double cx = *cx_ptr; 350 | double cy = *cy_ptr; 351 | 352 | while (*vectors) 353 | { 354 | vector_t * v = vector_find_closest(*vectors, cx, cy); 355 | if (!v) 356 | { 357 | fprintf(stderr, "nothing close?\n"); 358 | abort(); 359 | } 360 | 361 | if (!vs) 362 | { 363 | // Nothing on the list yet 364 | vs = vs_tail = v; 365 | } else { 366 | // Add it to the tail of the list 367 | v->next = NULL; 368 | v->prev = &vs_tail->next; 369 | vs_tail->next = v; 370 | vs_tail = v; 371 | } 372 | 373 | // Move the current point to the end of the line segment 374 | cx = v->x2; 375 | cy = v->y2; 376 | } 377 | 378 | //vector_stats(vs); 379 | *cx_ptr = cx; 380 | *cy_ptr = cy; 381 | 382 | // update the pointers 383 | *vectors = vs; 384 | if (vs) 385 | vs->prev = vectors; 386 | 387 | return vs; 388 | } 389 | 390 | 391 | /* 392 | * Attempt to remove long transits. 393 | * Find the longest transit and attempt to move that point 394 | * to a closer point. Then check to see if it reduces the transit. 395 | * returns the reduction in distance 396 | */ 397 | static double 398 | vector_refine( 399 | vector_t * const vector, 400 | double *cx_ptr, 401 | double *cy_ptr 402 | ) 403 | { 404 | const double initial_transit_len = vector_transit_len(vector); 405 | double cx = *cx_ptr; 406 | double cy = *cy_ptr; 407 | 408 | // find the longest transit 409 | vector_t * v = vector; 410 | double max_transit = 0; 411 | vector_t * transit_v = NULL; 412 | 413 | while (v) 414 | { 415 | double t_dx = cx - v->x1; 416 | double t_dy = cy - v->y1; 417 | 418 | double transit_len = sqrt(t_dx * t_dx + t_dy * t_dy); 419 | if (!fpeq(transit_len, 0) && max_transit < transit_len) 420 | { 421 | max_transit = transit_len; 422 | transit_v = v; 423 | } 424 | 425 | // Advance the point 426 | cx = v->x2; 427 | cy = v->y2; 428 | v = v->next; 429 | } 430 | 431 | if (!transit_v) 432 | { 433 | fprintf(stderr, "no longest transit?\n"); 434 | return 0; 435 | } 436 | 437 | fprintf(stderr, "Total transit: %.3f\n", initial_transit_len); 438 | fprintf(stderr, "longest transit: %.3f: %.3f,%.3f\n", 439 | max_transit, 440 | transit_v->x1, 441 | transit_v->y1 442 | ); 443 | 444 | // then find the closest *end point* prior to this transit 445 | vector_t * closest = NULL; 446 | double min_dist = 1e9; 447 | for(vector_t * v = vector ; v != transit_v ; v = v->next) 448 | { 449 | double dx = v->x2 - transit_v->x1; 450 | double dy = v->y2 - transit_v->y1; 451 | double dist = dx*dx + dy*dy; 452 | if (min_dist < dist) 453 | continue; 454 | min_dist = dist; 455 | closest = v; 456 | } 457 | 458 | if (!closest) 459 | { 460 | fprintf(stderr, "could not find a close one?\n"); 461 | return 0; 462 | } 463 | 464 | // move the longest transit destination to come after the 465 | // one closest to it, then re-sort based on that point 466 | 467 | // remove transit_v from the list 468 | if (transit_v->next) 469 | transit_v->next->prev = transit_v->prev; 470 | if (transit_v->prev) 471 | *transit_v->prev = transit_v->next; 472 | 473 | // re-insert it after the closest one 474 | transit_v->next = closest->next; 475 | transit_v->prev = &closest->next; 476 | closest->next = transit_v; 477 | if (transit_v->next) 478 | transit_v->next->prev = &transit_v->next; 479 | 480 | // now sort the ones that come after it 481 | double cx2 = transit_v->x2; 482 | double cy2 = transit_v->y2; 483 | vector_optimize(&transit_v->next, &cx2, &cy2); 484 | 485 | const double new_transit_len = vector_transit_len(vector); 486 | fprintf(stderr, "Refine transit %.3f\n", new_transit_len); 487 | 488 | *cx_ptr = cx2; 489 | *cy_ptr = cy2; 490 | 491 | return initial_transit_len - new_transit_len; 492 | } 493 | 494 | 495 | static void 496 | output_vector( 497 | FILE * const pjl_file, 498 | const vector_t * v 499 | ) 500 | { 501 | double lx = 0; 502 | double ly = 0; 503 | 504 | while (v) 505 | { 506 | if (fpeq(v->x1,lx) && fpeq(v->y1,ly)) 507 | { 508 | // This is the continuation of a line, so 509 | // just add additional points 510 | fprintf(pjl_file, "L %.3f %.3f\n", 511 | v->x2, 512 | v->y2 513 | ); 514 | } else { 515 | // Stop the laser; we need to transit 516 | // and then start the laser as we go to 517 | // the next point. Note initial ";" 518 | fprintf(pjl_file, "\nM %.3f %.3f\nL %.3f %.3f\n", 519 | v->x1, 520 | v->y1, 521 | v->x2, 522 | v->y2 523 | ); 524 | } 525 | 526 | // Changing power on the fly is not supported for now 527 | // \todo: Check v->power and adjust ZS, XR, etc 528 | 529 | // Move to the next vector, updating our current point 530 | lx = v->x2; 531 | ly = v->y2; 532 | v = v->next; 533 | } 534 | fprintf(pjl_file, "\n"); 535 | } 536 | 537 | 538 | static void 539 | generate_vectors( 540 | FILE * const vector_file, 541 | FILE * const pjl_file 542 | ) 543 | { 544 | vectors_t * const vectors = vectors_parse(vector_file); 545 | double lx = 0; 546 | double ly = 0; 547 | 548 | for (int i = 0 ; i < VECTOR_PASSES ; i++) 549 | { 550 | vectors_t * const vs = &vectors[i]; 551 | if (!vs->vectors) 552 | continue; 553 | 554 | fprintf(stderr, "Group %d\n", i); 555 | vector_stats(vs->vectors); 556 | vector_optimize( 557 | &vs->vectors, 558 | &lx, &ly 559 | ); 560 | 561 | vector_stats(vs->vectors); 562 | 563 | /* 564 | for(int i = 0 ; i < 8 ; i++) 565 | { 566 | double sx = vs->vectors->x1; 567 | double sy = vs->vectors->y1; 568 | if (vector_refine(vs->vectors, &sx, &sy) <= 0) 569 | break; 570 | lx = sx; 571 | ly = sy; 572 | } 573 | */ 574 | 575 | 576 | fprintf(pjl_file, "P %d %d %d\n", 577 | i == 0 ? 100 : 0, 578 | i == 1 ? 100 : 0, 579 | i == 2 ? 100 : 0 580 | ); 581 | output_vector(pjl_file, vs->vectors); 582 | fprintf(pjl_file, "\n\n"); 583 | } 584 | } 585 | 586 | 587 | int main(void) 588 | { 589 | generate_vectors(stdin, stdout); 590 | return 0; 591 | } 592 | --------------------------------------------------------------------------------