Created
November 4, 2017 23:02
-
-
Save josephg/b8de10fba45a53ffd37a145fe81cf79b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Layers is a list (layers[0] is the bottom). Each layer is: | |
// clip: polygon[] for clipping layers below | |
// content: path[] of stuff to actually draw. | |
const polyToPslg = require('poly-to-pslg') | |
const pathsToPslg = require('paths-to-pslg') | |
const pslgToPaths = require('pslg-to-paths') | |
const pathtrimPslg = require('pathtrim-pslg') | |
const boxIntersect = require('box-intersect') | |
const pslgUnion = (a, b) => { | |
const offset = a.points.length | |
const points = a.points.concat(b.points) | |
const edges = a.edges.concat(b.edges.map(([a,b]) => ([a+offset, b+offset]))) | |
return {points, edges} | |
} | |
const bbForPath = path => { | |
if (path.length === 0) return [0,0,0,0] | |
let l= Infinity, r = -Infinity, t = Infinity, b = -Infinity | |
for (let i = 0; i < path.length; i++) { | |
const [x, y] = path[i] | |
if (x < l) l = x | |
if (x > r) r = x | |
if (y < t) t = y | |
if (y > b) b = y | |
} | |
return [l, t, r, b] | |
} | |
function flatten(layers) { | |
if (layers.length == 0) return [] | |
//if (layers.length == 1) return layers[0].content | |
// I'm going to go from the bottom to the top, aggregating the content and clipping region | |
// from each layer. Note that each layer is not clipped by its own clipping plane. | |
// The clipping plane from the bottom layer is unused. | |
let contentPslg = {points:[], edges:[]} //pathsToPslg(layers[0].content) | |
let pathsOutside = [] | |
let pathsBBs = [] | |
let clipBBs = [] | |
for (let i = 0; i < layers.length; i++) { | |
const l = layers[i] | |
// Clip the aggregate content | |
if (l.clip) { | |
const clipBBs = l.clip.map(poly => bbForPath(poly)) | |
const moveIdx = [] | |
boxIntersect(pathsBBs, clipBBs, (pi, ci) => { | |
moveIdx.push(pi) | |
}) | |
moveIdx.sort((a, b) => a-b) | |
let last = -1 | |
const newGeom = [] | |
let off = 0 | |
for (let i = 0; i < moveIdx.length; i++) { | |
const pi = moveIdx[i] | |
if (pi === last) continue | |
last = pi | |
newGeom.push(pathsOutside[pi-off]) | |
pathsOutside.splice(pi-off, 1) | |
pathsBBs.splice(pi-off, 1) | |
off++ | |
} | |
//console.log('newGeom len', newGeom.length) | |
contentPslg = pslgUnion(contentPslg, pathsToPslg(newGeom)) | |
const {points, edges} = polyToPslg(l.clip) | |
contentPslg = pathtrimPslg(contentPslg.points, contentPslg.edges, points, edges, false) | |
} | |
// And add the new content. | |
if (l.content) { | |
const off = pathsOutside.length | |
pathsOutside.push.apply(pathsOutside, l.content) | |
for (let i = off; i < pathsOutside.length; i++) pathsBBs.push(bbForPath(pathsOutside[i])) | |
} | |
} | |
return pslgToPaths(contentPslg.points, contentPslg.edges).concat(pathsOutside) | |
} | |
module.exports = flatten | |
/* | |
{ | |
const tri = [ | |
[0.5, 0.25], | |
[0.25, 0.5], | |
[0.75, 0.75] | |
] | |
const sq = [ | |
[0.25, 0.25], | |
[0.25, 0.6], | |
[0.6, 0.6], | |
[0.6, 0.25] | |
] | |
const vert = [] | |
for (let x = 0; x <= 1; x += 0.1) { | |
vert.push([[x, 0], [x, 1]]) | |
} | |
const horiz = [] | |
for (let y = 0; y <= 1; y += 0.1) { | |
horiz.push([[0, y], [1, y]]) | |
} | |
console.log(flatten([ | |
{content: vert}, | |
{clip: [tri]} | |
])) | |
} | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment