var fs = require('fs'); var parser = require('./rrpl_parser'); var compressor = require('./compress'); var PI = Math.PI var cos = Math.cos var sin = Math.sin function dist(x0,y0,x1,y1){ return Math.sqrt(Math.pow(x1-x0,2)+Math.pow(y1-y0,2)) } function flat2tuple(L){ var result = [] for (var i = 0; i < L.length; i+=2){ result.push([L[i],L[i+1]]) } return result; } function sameLine(x0,y0,x1,y1,x2,y2){ var a= x0 * (y1 - y2) + x1 * (y2 - y0) + x2 * (y0 - y1) return Math.abs(a) < 0.0001; } function angleBetween(x0,y0,x1,y1,x2,y2){ var a0 = Math.atan2(y2-y1,x2-x1) var a1 = Math.atan2(y1-y0,x1-x0) return Math.abs(a0-a1) } function one2polylines(S){ var lines = parser.toLines(parser.toRects(parser.parse(S))).map(x=>flat2tuple(x)); // console.log(lines) // console.log("\n\n\n\n") var joined = lines.map(x=>false); for (var i = 0; i < lines.length; i++){ if (!joined[i]){ var redo = true; while (redo){ redo = false; for (var j = 0; j < lines.length; j++){ if (!joined[j] && i != j){ var fbi = [lines[i],lines[i].slice().reverse()] var fbj= [lines[j],lines[j].slice().reverse()] var bk = false; for (var ki = 0; ki < fbi.length; ki++){ for (var kj = 0; kj < fbj.length; kj++){ var d = dist( fbi[ki][fbi[ki].length-1][0], fbi[ki][fbi[ki].length-1][1], fbj[kj][0][0], fbj[kj][0][1]) var a = angleBetween( fbi[ki][fbi[ki].length-2][0], fbi[ki][fbi[ki].length-2][1], fbj[kj][0][0], fbj[kj][0][1], fbj[kj][1][0], fbj[kj][1][1], ) if (d < 0.01 && a < Math.PI/4){ if (a < 0.001){ lines[i] = fbi[ki].slice(0,-1).concat(fbj[kj].slice(1)); }else{ lines[i] = fbi[ki].concat(fbj[kj].slice(1)); } joined[j] = true; redo = true; bk = true; break; } } if (bk){break;} } } } } } } var lines = lines.filter((x,i)=>(!joined[i])); // console.log(lines) return lines } function tubify(args){ var args = (args != undefined) ? args : {}; var pts = (args.pts != undefined) ? args.pts : []; var wid = (args.wid != undefined) ? args.wid : (x)=>(10); var vtxlist0 = [] var vtxlist1 = [] var vtxlist = [] for (var i = 1; i < pts.length-1; i++){ var w = wid(i/pts.length) var a1 = Math.atan2(pts[i][1]-pts[i-1][1],pts[i][0]-pts[i-1][0]); var a2 = Math.atan2(pts[i][1]-pts[i+1][1],pts[i][0]-pts[i+1][0]); var a = (a1+a2)/2; if (a < a2){a+=PI} vtxlist0.push([pts[i][0]+w*cos(a),(pts[i][1]+w*sin(a))]); vtxlist1.push([pts[i][0]-w*cos(a),(pts[i][1]-w*sin(a))]); } var l = pts.length-1 var a0 = Math.atan2(pts[1][1]-pts[0][1],pts[1][0]-pts[0][0]) - Math.PI/2; var a1 = Math.atan2(pts[l][1]-pts[l-1][1],pts[l][0]-pts[l-1][0]) - Math.PI/2; var w0 = wid(0) var w1 = wid(1) vtxlist0.unshift([pts[0][0]+w0*Math.cos(a0),(pts[0][1]+w0*Math.sin(a0))]) vtxlist1.unshift([pts[0][0]-w0*Math.cos(a0),(pts[0][1]-w0*Math.sin(a0))]) vtxlist0.push([pts[l][0]+w1*Math.cos(a1),(pts[l][1]+w1*Math.sin(a1))]) vtxlist1.push([pts[l][0]-w1*Math.cos(a1),(pts[l][1]-w1*Math.sin(a1))]) return [vtxlist0,vtxlist1] } function previewPolylines(P){ var result = "<path d='"; for (var i = 0; i < P.length; i++){ for (var j = 0; j < P[i].length; j++){ if (j == 0){ result += "M " }else{ result += "L " } var x = Math.round(P[i][j][0]*1000) var y = Math.round(P[i][j][1]*1000) result += x + " " + y + " " } // result += "z " } result += "' stroke-width='10' stroke='black' fill='none'/>" return result; } function drawOutlinedPolylines(P,args){ var args = (args != undefined) ? args : {}; var strw = (args.strw != undefined) ? args.strw : 16; var csize = (args.csize != undefined) ? args.csize : 1000; var pad = (args.pad != undefined) ? args.pad : 80; var transf = function(x,y){ return [ Math.round(x * (csize-pad*2) + pad), Math.round(y * (csize-pad*2) + pad), ] } var result = "" for (var i = 0; i < P.length; i++){ result += "<path d='"; var tube = tubify({pts:P[i],wid:x=>strw/csize}) var half = tube[0].length; tube = tube[0].concat(tube[1].slice().reverse()) for (var j = 0; j < tube.length+1; j++){ if (j == 0){ result += "M " }else if (j == half || j == half*2){ result += "A "+Math.floor(strw/2)+" "+Math.floor(strw/2)+" 0 0 1 " }else{ result += "L " } var x = tube[j%tube.length][0] var y = tube[j%tube.length][1] var [x,y] = transf(x,y); result += x + " " + y + " " } result += "z' />" } return result } function main(dict, toFolder, isCompiled){ if (!isCompiled){ parser.preprocess(dict) } dict["。"] = "0-(0|((0-47-48-58-0)|(35-0-0-0-17)|(0-14-48-38-0))|0)-0"; for (var k in dict){ if (!dict[k].length){ continue; } process.stdout.write(k); var ret = "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1000 1000'>" + drawOutlinedPolylines(one2polylines(dict[k])) + "</svg>" fs.writeFile(toFolder+"/"+compressor.key2hex(k)+".svg", ret, function(err) { }); } } var file_in = (process.argv[2] != undefined) ? process.argv[2]: 'dist/min-trad-compiled.json' var file_out = (process.argv[3] != undefined) ? process.argv[3]: 'svg' var is_compiled = (process.argv[4] != undefined) ? process.argv[4]-0: 1 fs.readFile(file_in, 'utf8', function(err, contents) { main(JSON.parse(contents),file_out,is_compiled) });