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

@mvarble/frames.js

v1.1.0

Published

A set of tools for working with coordinate systems in the plane.

Downloads

11

Readme

frames.js

A set of tools for working with coordinate systems in the plane.

Download

npm install @mvarble/frames.js

The Mathematics

One can simply encode affine coordinate systems in the plane by 3x3 frame matrices. This way, calculations like rigid body transformations and coordinate transforms can be streamlined into simple matrix multiplication calculations. The purpose of this module is to wrap all such calculations into a simple API.

The Code

Because we would sometimes like a frame relative to another, it is very natural to store our frames in a tree structure. To this end, a frame is nothing but a JSON object which has worldMatrix and children fields. Because frames are created primarily for rendering to the HTML canvas, one should be able to easily search through all the frames within a given context and access any sort of metadata each frame has. It is then decided that the objects will behave like unist trees. Consider the example below.

const boxFrame = {
  type: 'box',
  worldMatrix: [[10, 0, 420], [0, -10, 69], [0, 0, 1]],
};

const planeFrame = {
  type: 'frame',
  worldMatrix: [[10, 0, 400], [0, -10, 400], [0, 0, 1]],
  children: [boxFrame],
};

Since our frames are encoded with simple JSON objects, the magic of the module is in the functions which parse/generate frames. For transforming frames, we have an API for updating the frame's world matrix explicitly, providing affine transformations, or simply saying which basic (translate/rotate/scale) operation we want. Each such transformation has two froms; one which is a pure function which simply returns a new frame and an impure one that simply manipulates the frame.worldMatrix attribute. Below, transformation will be identified with its (pure/impure) function names.

We can also perform coordinate calculations which allow one to get the coordinates of a location/vector in a particular frame's coordinate system, subject to having those from another frame's coordinate system. These functions are always pure, as there aren't many examples in which one would want otherwise.

API

Since this is a small package, one can look at the source code here. Otherwise, for the most part, there are only several functions which are very useful.

Transformations

If one would like to return a translated/rotated/scaled version of a frame, it is as simple as using the following functions.

translatedFrame/translateFrame

newFrame = translatedFrame(frame, disp [, relativeFrame])

This will return a frame which corresponds to translating frame by [disp[0], disp[1]] in the coordinate system of relativeFrame. The relativeFrame will be frame if not provided. The following shows the red frame being translated at a constant velocity of [3, 4] units/second with respect to different coordinate systems. The first is translatedFrame(redFrame, [t*3, t*4]) while the second is translatedFrame(redFrame, [t*3, t*4], greenFrame) with respect to time t.

translated self translated relative

rotatedFrame/rotateFrame

newFrame = rotatedFrame(frame, theta, [, relativeFrame])

This will return a frame which corresponds to rotating frame by theta in the coordinate system of relativeFrame. Note. relativeFrame should have an orthogonal basis with both vectors having the same length in order for this to make sense. The relativeFrame will be frame if not provided. The following shows the red frame being rotated at a angular velocity of 2pi radians/second with respect to different coordinate systems. The first is rotatedFrame(redFrame, 2 * Math.PI * t) while the second is rotatedFrame(redFrame, 2 * Math.PI * t, greenFrame) with respect to time t.

rotated self rotated relative

scaledFrame/scaleFrame

newFrame = scaledFrame(frame, scales, [, relativeFrame])

This will return a frame which corresponds to scaling frame by [scales[0], scales[1]] in the coordinate system of relativeFrame. The relativeFrame will be frame if not provided. The following shows the red frame being scaled with respect to different coordinate systems. The first is scaledFrame(redFrame, [0.9 * (1 - t), 0.9 * (1 - t)]) while the second is scaledFrame(redFrame, [0.9 * (1 - t), 0.9 * (1 - t)], greenFrame) with respect to time t.

scaled self scaled relative

Locations/Vectors in Different Frames

A location is considered to be a point in the plane. A vector is considered to be a displacement in the plane. The key distinction is that the coordinates of a vector in any frame should be independent of the frame's position in the plane.

locFrameTrans

sameLoc = locFrameTrans(loc, frame1, frame2)

This will return a pair [a, b] corresponding to the frame2-coordinates of the location with frame1-coordinates [loc[0], loc[1]].

locsFrameTrans

sameLocs = locsFrameTrans(locs, frame1, frame2)

This will simply run locs.map(loc => locFrameTrans(loc, frame1, frame2)). I am not savy enough with javascript to bootstrap this into a single function.

vecFrameTrans

sameVec = vecFrameTrans(vec, frame1, frame2)

This will return a pair [a, b] corresponding to the frame2-coordinates of the vector with frame1-coordinates [vec[0], vec[1]]. This is different from locFrameTrans, as we consider vectors independent of the origin of the frame.

vecsFrameTrans

sameVecs = vecsFrameTrans(vecs, frame1, frame2)

This will simply run vecs.map(vec => vecFrameTrans(vec, frame1, frame2)). I am not savy enough with javascript to bootstrap this into a single function.

Examples

  • viewport.js: an example of how one can use this module for more interactive apps.