This might be handy if you have an SVG file that you want to use as, say, a mask for a generative algorithm.
Place the SVG file in the same directory that you are running penplot from.
import { Orientation } from 'penplot'; | |
import { polylinesToSVG } from 'penplot/util/svg'; | |
import { parse } from 'extract-svg-path'; | |
import parseSvgPath from 'parse-svg-path'; | |
import svgPathContours from 'svg-path-contours'; | |
import normalizePathScale from 'normalize-path-scale'; | |
import boundPoints from 'bound-points'; | |
export const orientation = Orientation.LANDSCAPE; | |
export const dimensions = [ 22.0, 22.0 ]; | |
export default function createPlot (context, dimensions) { | |
const [ width, height ] = dimensions; | |
let lines = []; | |
return window.fetch('svg-test.svg') | |
.then(resp => resp.text()) | |
.then(text => { | |
// Update list of lines | |
lines = toPolylines(text); | |
// Return penplot options to start rendering | |
return { | |
draw, | |
print, | |
background: 'white', | |
animate: false, | |
clear: true | |
}; | |
}); | |
// render SVG into line segments for penplotter | |
function toPolylines (svgContents) { | |
// Extract <path> data from SVG contents | |
const svgPath = parse(svgContents); | |
// Turn into MoveTo, LineTo, etc SVG commands | |
const svgCommands = parseSvgPath(svgPath); | |
// Normalize all the commands and discretize curves/etc into 2D polylines | |
const curveDetail = 1; | |
const contours = svgPathContours(svgCommands, curveDetail); | |
// Now, to work with general SVGs you may want to normalize the path scale | |
// so that your print doesn't need to match the same size as your SVG | |
// Do this by getting all 2D points of the polylines | |
const points = contours.reduce((a, b) => a.concat(b), []); | |
// Then get the bounding box of all 2D points | |
const bounds = boundPoints(points); | |
// And normalize each polyline to that bounding box | |
const lines = contours.map(line => normalizePathScale(line, bounds)); | |
// Now you are in 0..1 range, you can apply translation/scale here to center it | |
const x = width / 2; | |
const y = height / 2; | |
const margin = 2; // margin from edge in centimeters | |
const scale = Math.min(width, height) / 2 - margin; | |
return lines.map(line => { | |
return line.map(point => { | |
return [ x + point[0] * scale, y + point[1] * scale ]; | |
}); | |
}); | |
} | |
function draw () { | |
lines.forEach(points => { | |
context.beginPath(); | |
points.forEach(p => context.lineTo(p[0], p[1])); | |
context.stroke(); | |
}); | |
} | |
function print () { | |
return polylinesToSVG(lines, { | |
dimensions | |
}); | |
} | |
} |