npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@kkitahara/polytope-algebra

v1.2.8

Published

ECMAScript modules for exactly manipulating set algebra of polytopes on the basis of @kkitahara/linear-algebra.

Downloads

52

Readme

JavaScript Style Guide license version bundle size downloads per week downloads per month downloads per year downloads total

PolytopeAlgebra

ECMAScript modules for exactly manipulating set algebra of polytopes on the basis of @kkitahara/linear-algebra.

Caution

Dimensions higher than 3 were not tested so much. Although there is no known problem, please be careful if you use this code for such high dimensions.

Installation

npm install @kkitahara/polytope-algebra @kkitahara/linear-algebra @kkitahara/real-algebra

Examples

Numerical set algebra (for 2-dimensional polytopes)

import { RealAlgebra } from '@kkitahara/real-algebra'
import { LinearAlgebra } from '@kkitahara/linear-algebra'
import { PolytopeAlgebra } from '@kkitahara/polytope-algebra'
// set a reasonable tolerance for equality
let r = new RealAlgebra(1e-8)
let l = new LinearAlgebra(r)
let dim = 2
let p2d = new PolytopeAlgebra(dim, l)

Generate a new hypercube of edge length 2 * d centred at the origin.

let d = 1
let p1 = p2d.hypercube(d)

// p1
// +-----------+
// |\\\\\\\\\\\|
// |\\\\\\\\\\\|
// |\\\\\o\\\\\|
// |\\\\\\\\\\\|
// |\\\\\\\\\\\|
// +-----------+

Calculate the volume of polytopes

let vol = p2d.volume(p1)
vol.toString() // '4'

Generate a new facet.

// A facet is characterised by its normal vector (nvec),
// distance from the origin (d),
// and the direction of the normal vector (faceOutside).
let nvec = [1, 0]
d = 1
let faceOutside = true
let f = p2d.facet(nvec, d, faceOutside)

// \\\\\\\\\\\\|
// \\\\\\\\\\\\|
// \\\\\\\\\\\\|
// \\\\\\o\\\\\| f
// \\\\\\\\\\\\|
// \\\\\\\\\\\\|
// \\\\\\\\\\\\|

nvec = [1, 0]
d = 1
faceOutside = false
f = p2d.facet(nvec, d, faceOutside)

//             |\\\\\\\\\\\\
//             |\\\\\\\\\\\\
//             |\\\\\\\\\\\\
//       o   f |\\\\\\\\\\\\
//             |\\\\\\\\\\\\
//             |\\\\\\\\\\\\
//             |\\\\\\\\\\\\

// No need to normalise the normal vector,
// provided that `d` is the dot product of the normal vector and
// the position vector of a vertex on the facet.
f = p2d.facet([2, 0], 1, true)

// \\\\\\\\\|
// \\\\\\\\\|
// \\\\\\\\\|
// \\\\\\o\\| f
// \\\\\\\\\|
// \\\\\\\\\|
// \\\\\\\\\|

f = p2d.facet([2, 0], 2, true)

// \\\\\\\\\\\\|
// \\\\\\\\\\\\|
// \\\\\\\\\\\\|
// \\\\\\o\\\\\| f
// \\\\\\\\\\\\|
// \\\\\\\\\\\\|
// \\\\\\\\\\\\|

Add a facet to polytopes (in place)

p1 = p2d.hypercube(d)

// p1
// +-----------+
// |\\\\\\\\\\\|
// |\\\\\\\\\\\|
// |\\\\\o\\\\\|
// |\\\\\\\\\\\|
// |\\\\\\\\\\\|
// +-----------+

f = p2d.facet([2, -1], 1, true)

// \\\\\\\\\\\\/
// \\\\\\\\\\\/
// \\\\\\\\\\/
// \\\\\\o\\/ f
// \\\\\\\\/
// \\\\\\\/
// \\\\\\/

p1 = p2d.iaddFacet(p1, f)
p2d.volume(p1).toString() // '3'

// p1
// +-----------+
// |\\\\\\\\\\/
// |\\\\\\\\\/
// |\\\\\o\\/
// |\\\\\\\/
// |\\\\\\/
// +-----+

Copy (generate a new object)

let p2 = p2d.copy(p1)
p2d.volume(p2).toString() // '3'

// p2
// +-----------+
// |\\\\\\\\\\/
// |\\\\\\\\\/
// |\\\\\o\\/
// |\\\\\\\/
// |\\\\\\/
// +-----+

Rotation (new object is genrated, since v1.1.0)

let c4 = l.$(0, -1, 1, 0).setDim(2)
p2 = p2d.rotate(p1, c4)
p1 !== p2 // true
p2d.volume(p2).toString() // '3'

// p2
// +-__
// |\\\--_
// |\\\\\\--__
// |\\\\\o\\\\-+
// |\\\\\\\\\\\|
// |\\\\\\\\\\\|
// +-----------+

In-place rotation (new object is not genrated, since v1.1.0)

p2 = p2d.irotate(p2, c4)
p2d.volume(p2).toString() // '3'

// p2
//       +-----+
//      /\\\\\\|
//     /\\\\\\\|
//    /\\o\\\\\|
//   /\\\\\\\\\|
//  /\\\\\\\\\\|
// +-----------+

Translation (new object is generated)

p2 = p2d.translate(p1, [r.$(1, 2), 0])
p1 !== p2 // true
p2d.volume(p2).toString() // '3'

// p2
//    +-----------+
//    |\\\\\\\\\\/
//    |\\\\\\\\\/
//    |\\o\\\\\/
//    |\\\\\\\/
//    |\\\\\\/
//    +-----+

In-place translation (new object is not generated)

p1 = p2d.itranslate(p1, [r.$(1, 2), 0])
p2d.volume(p1).toString() // '3'

// p1
//    +-----------+
//    |\\\\\\\\\\/
//    |\\\\\\\\\/
//    |\\o\\\\\/
//    |\\\\\\\/
//    |\\\\\\/
//    +-----+

Scaling (new object is generated)

p2 = p2d.scale(p1, 2)
p1 !== p2 // true
p2d.volume(p2).toString() // '12'

// p2
// +-----------------------+
// |\\\\\\\\\\\\\\\\\\\\\\/
// |\\\\\\\\\\\\\\\\\\\\\/
// |\\\\\\\\\\\\\\\\\\\\/
// |\\\\\\\\\\\\\\\\\\\/
// |\\\\\\\\\\\\\\\\\\/
// |\\\\\o\\\\\\\\\\\/
// |\\\\\\\\\\\\\\\\/
// |\\\\\\\\\\\\\\\/
// |\\\\\\\\\\\\\\/
// |\\\\\\\\\\\\\/
// |\\\\\\\\\\\\/
// +-----------+

In-place scaling (new object is not generated)

p1 = p2d.iscale(p1, r.$(1, 3))
p2d.volume(p1).toString() // '1 / 3'

//      p1
//      +---+
//      |o\/
//      +-+

Multiplication (intersection, new object is generated)

p1 = p2d.hypercube(1)
p2 = p2d.itranslate(p2d.hypercube(1), [1, 1])
let p3 = p2d.mul(p1, p2)
p3 !== p1 // true
p3 !== p2 // true
p2d.volume(p3).toString() // '1'

//
//
//
// p1
// +-----------+
// |\\\\\\\\\\\|
// |\\\\\\\\\\\|
// |\\\\\o\\\\\|
// |\\\\\\\\\\\|
// |\\\\\\\\\\\|
// +-----------+

//       p2
//       +-----------+
//       |\\\\\\\\\\\|
//       |\\\\\\\\\\\|
//       |\\\\\\\\\\\|
//       |\\\\\\\\\\\|
//       |\\\\\\\\\\\|
//       o-----------+
//
//
//

//
//
//
//       p3
//       +-----+
//       |\\\\\|
//       |\\\\\|
//       o-----+
//
//
//

Subtraction (set difference, new object is generated)

p1 = p2d.hypercube(1)
p2 = p2d.itranslate(p2d.hypercube(1), [1, 1])
p3 = p2d.sub(p1, p2)
p3 !== p1 // true
p3 !== p2 // true
p2d.volume(p3).toString() // '3'

//
//
//
// p1
// +-----------+
// |\\\\\\\\\\\|
// |\\\\\\\\\\\|
// |\\\\\o\\\\\|
// |\\\\\\\\\\\|
// |\\\\\\\\\\\|
// +-----------+

//       p2
//       +-----------+
//       |\\\\\\\\\\\|
//       |\\\\\\\\\\\|
//       |\\\\\\\\\\\|
//       |\\\\\\\\\\\|
//       |\\\\\\\\\\\|
//       o-----------+
//
//
//

//
//
//
// p3
// +-----+
// |\\\\\|
// |\\\\\|
// |\\\\\o-----+
// |\\\\\\\\\\\|
// |\\\\\\\\\\\|
// +-----------+

Addition (union, new object is generated)

p1 = p2d.hypercube(1)
p2 = p2d.itranslate(p2d.hypercube(1), [1, 1])
p3 = p2d.add(p1, p2)
p3 !== p1 // true
p3 !== p2 // true
p2d.volume(p3).toString() // '7'

//
//
//
// p1
// +-----------+
// |\\\\\\\\\\\|
// |\\\\\\\\\\\|
// |\\\\\o\\\\\|
// |\\\\\\\\\\\|
// |\\\\\\\\\\\|
// +-----------+

//       p2
//       +-----------+
//       |\\\\\\\\\\\|
//       |\\\\\\\\\\\|
//       |\\\\\\\\\\\|
//       |\\\\\\\\\\\|
//       |\\\\\\\\\\\|
//       o-----------+
//
//
//

//
//       +-----------+
//       |\\\\\\\\\\\|
// p3    |\\\\\\\\\\\|
// +-----+\\\\\\\\\\\|
// |\\\\\\\\\\\\\\\\\|
// |\\\\\\\\\\\\\\\\\|
// |\\\\\o\\\\\+-----+
// |\\\\\\\\\\\|
// |\\\\\\\\\\\|
// +-----------+

JSON (stringify and parse)

let str = JSON.stringify(p3)
let p4 = JSON.parse(str, p2d.reviver)
let p5 = p2d.mul(p3, p4)
p2d.volume(p4).toString() // '7'
p2d.volume(p5).toString() // '7'

Exact set algebra for polytopes

You can work with an exact algebra if you use

import { ExactRealAlgebra as RealAlgebra } from '@kkitahara/real-algebra'
import { LinearAlgebra } from '@kkitahara/linear-algebra'
import { PolytopeAlgebra } from '@kkitahara/polytope-algebra'
let r = new RealAlgebra()
let l = new LinearAlgebra(r)
let dim = 3
let p3d = new PolytopeAlgebra(dim, l)

insted of RealAlgebra. See the documents of @kkitahara/real-algebra for more details about the exact algebra. :warning: The exact algebra can take a long time, and, in some cases, it can consume huge amount of memory.

Another implementation

Another implementation of the algebra is available:

...
...
import { AnotherPolytopeAlgebra } from '@kkitahara/polytope-algebra'
...
...
let p3d = new AnotherPolytopeAlgebra(3, l)

It internally uses the intersection operation for union and difference operations (these are much more time-consuming than intersection operation). So, in some cases, it may be more efficient than the original PolytopeAlgebra.

ESDoc documents

For more examples, see ESDoc documents:

cd node_modules/@kkitahara/polytope-algebra
npm install --only=dev
npm run doc

and open doc/index.html in your browser.

LICENSE

© 2019 Koichi Kitahara
Apache 2.0