UNPKG

@jscad/modeling

Version:

Constructive Solid Geometry (CSG) Library for JSCAD

82 lines (72 loc) 2.91 kB
const geom2 = require('../geometries/geom2') /** * Construct a polygon in two dimensional space from a list of points, or a list of points and paths. * * NOTE: The ordering of points is important, and must define a counter clockwise rotation of points. * * @param {Object} options - options for construction * @param {Array} options.points - points of the polygon : either flat or nested array of 2D points * @param {Array} [options.paths] - paths of the polygon : either flat or nested array of point indexes * @param {String} [options.orientation='counterclockwise'] - orientation of points * @returns {geom2} new 2D geometry * @alias module:modeling/primitives.polygon * * @example * let roof = [[10,11], [0,11], [5,20]] * let wall = [[0,0], [10,0], [10,10], [0,10]] * * let poly = polygon({ points: roof }) * or * let poly = polygon({ points: [roof, wall] }) * or * let poly = polygon({ points: roof, paths: [0, 1, 2] }) * or * let poly = polygon({ points: [roof, wall], paths: [[0, 1, 2], [3, 4, 5, 6]] }) */ const polygon = (options) => { const defaults = { points: [], paths: [], orientation: 'counterclockwise' } const { points, paths, orientation } = Object.assign({}, defaults, options) if (!(Array.isArray(points) && Array.isArray(paths))) throw new Error('points and paths must be arrays') let listofpolys = points if (Array.isArray(points[0])) { if (!Array.isArray(points[0][0])) { // points is an array of something... convert to list listofpolys = [points] } } listofpolys.forEach((list, i) => { if (!Array.isArray(list)) throw new Error('list of points ' + i + ' must be an array') if (list.length < 3) throw new Error('list of points ' + i + ' must contain three or more points') list.forEach((point, j) => { if (!Array.isArray(point)) throw new Error('list of points ' + i + ', point ' + j + ' must be an array') if (point.length < 2) throw new Error('list of points ' + i + ', point ' + j + ' must contain by X and Y values') }) }) let listofpaths = paths if (paths.length === 0) { // create a list of paths based on the points let count = 0 listofpaths = listofpolys.map((list) => list.map((point) => count++)) } // flatten the listofpoints for indexed access const allpoints = [] listofpolys.forEach((list) => list.forEach((point) => allpoints.push(point))) // convert the list of paths into a list of sides, and accumulate let sides = [] listofpaths.forEach((path) => { const setofpoints = path.map((index) => allpoints[index]) const geometry = geom2.fromPoints(setofpoints) sides = sides.concat(geom2.toSides(geometry)) }) // convert the list of sides into a geometry let geometry = geom2.create(sides) if (orientation === 'clockwise') { geometry = geom2.reverse(geometry) } return geometry } module.exports = polygon