A collection of functions for working with points in a 2D coordinate system, along with additional utility functions.
- What's new
- How to use — install, imports, develops, publishes
- Examples
- Function reference
- Changelog
This release is 2.0.0 (not 1.8.x) on purpose: nearest now returns null for an empty list, and collision uses true circular distance. Both can require code or tuning changes, so SemVer treats this as major—users on ^1.x stay on 1.x until they upgrade consciously.
collision— Euclidean radius vs the old axis-aligned bounds; retune if you depended on the box.nearest—nullwhen no candidates; guard before using the point.collisionInArray— Same semantics ascollision; barrel import cycle removed.collision— Optional callback typed as() => void.
See CHANGELOG.md for full notes.
Use Node 18+. The repo pins Node 20 for development (.nvmrc — nvm use recommended).
npm:
npm install pointscapepnpm / Yarn:
pnpm add pointscape
# or
yarn add pointscapeThe published tarball contains only dist/ (ESM + CJS + types), README, CHANGELOG, and LICENSE—see package.json → files. Import ESM with import or CommonJS with require per your bundler; types are exposed through exports for both.
- Default import — one object with every export (larger surface; fine for scripts).
import pointscape from "pointscape";- Named imports (preferred for tree-shaking) — see Types and imports below.
Use named imports so bundlers can tree-shake unused functions:
import { distance, collision, nearest, Point } from "pointscape";
import type { Bounds, Line, PointType } from "pointscape";Functions take any { x: number; y: number }; you do not have to allocate a Point class instance. PointType matches instances of Point (the class exported from this package).
Open a PR against the default branch; CI runs npm ci, tests, and npm run build on every push/PR (see .github/workflows/ci.yml).
git clone https://github.com/Arman2409/pointscape.git
cd pointscape
nvm use # optional: picks Node from .nvmrc
npm ci
npm test
npm run build- Bump
versioninpackage.jsonand updateCHANGELOG.md. npm loginwith an account that [maintainspointscape**](https://www.npmjs.com/package/pointscape) on the public registry (https://registry.npmjs.org/`).npm publish— theprepackscript rebuildsdist/first.
Preview tarball contents locally: npm run publish:dry-run.
See also npm files publish guide — only dist/, readme, changelog, and license are published.
Most of the functions are designed for working with points in a 2D coordinate system.
import {
distance,
middle,
angle,
center,
perimeter
} from "pointscape";
const point1 = { x: 0, y: 0 };
const point2 = { x: 10, y: 10 };
// Plain { x, y } objects work for all point APIs
const distanceBetweenPoints = distance(point1, point2);
// result: 14.142135623730951
const middlePoint = middle(point1, point2);
// result: {x: 5, y: 5}
const angleBetweenPoints = angle(point1, point2);
// result: 0.7853981633974483
const point3 = { x: 0, y: 10 }, point4 = { x: 10, y: 0 };
const perimeterOfPoints = perimeter(
[point1, point2, point3, point4 ]
);
// result: 48.2842712474619The Point class can also be used for working with the points.
import { Point } from "pointscape";
const point1 = new Point(0, 0);
const point2 = new Point(1, 1);
const distance = point1.distanceTo(point2);
// result: 1.4142135623730951
const angle = point1.angleTo(point2);
// result: 0.7853981633974483
// nearestFromPoints follows the same rules as nearest(); empty input yields null.There are other utility functions as well.
import {
inRange,
chunk,
randomBoolean } from "pointscape";
// Helper functions for math
const isInTheRange = inRange(1, 0, 10);
// result: true
// Helper functions for arrays
const chunks = chunk([1, 1, 1, 1], 2);
// result: [[1, 1], [1, 1]]
// Helper functions for randomization
const randomBool = randomBoolean();
// result: true or false- distance
interface Point {
x: number
y: number
}
(point1: Point, point2: Point) => numberReturns the distance beetween two points, each point is an object with x and y properties.
- area
(points: Point[]) => numberReturns the area enclosed by the given points. Takes an array of points as argument, where each point is an object with x and y properties.
- collision
(point1: Point, point2: Point, collisionDistance: number, [callback]?: () => void) => booleanReturns true if the Euclidean distance between the two points is less than or equal to collisionDistance (treat collisionDistance as a non-negative radius for a circle around each position). Optionally invokes callback when a collision is detected.
- collisionInArray
(initialPoint: Point, points: Point[], radius: number) => Point[]Returns every point in points whose distance to initialPoint is within radius, using the same circular rule as collision.
- positionInCircle
(point: Point, radius: number, angleInRadians: number) => PointReturns the x and y coordinates for the current point in the circle, given its center point, radius, and angle.
- angle
(point1: Point, point2: Point) => numberReturns the angle formed by the connection of two points.
- middle
(point1: Point, point2: Point) => PointReturns the midpoint between two points.
- nearest
(point: Point, points: Point[]) => Point | nullReturns the nearest point to the given point from the array, or null if points is empty.
- perimeter
(points: Point[]) => numberReturns the perimeter of the figure formed by the given points.
- pointWithoutCollision(minX, maxX, minY, maxY, distance, points)
interface Bounds {
min: number
max: number
}
(xBounds: Bounds, yBounds: Bounds, distance: number, points: Point[]) => Point | stringReturns a point that doesn't collide with any of the given points within the specified distance, if such a point exists, otherwise returns error string.
- randomPoint
([xBounds]: Bounds, [yBounds]: Bounds) => PointReturns a random point within the given dimensions, if provided, otherwise in 100 units on both axes.
- randomPointInDistance
(point: Point, distance: number) => PointReturns a random point within the given distance from the specified point.
- randomPoints
([xBounds]: Bounds, [yBounds]: Bounds, quantity: number,) => Point[]Returns a specified quantity of random points within the given dimensions, if dimensions are provided, otherwise in the range of 100.
- possibleConnections
(pointsCount: number) => numberReturns the quantity of possible connections among given quantity of points.
- circleArea
(radius: number) => numberReturns the area of the circle given its radius.
- center
(points: Point[]) => PointReturns the center of given points.
- farest
(point: Point, points: Point[]) => Point | nullReturns the farthest point from the given point among the given array; null if the array is empty.
- rotate
(point: Point, points: Point[], angleInRadians: number) => Point[]Returns the points rotated around the given point.
- sort
(points: Point[], coordinate?: "x" | "y") => Point[]Mutates points in place (Array.sort) and returns the same array reference. Omit coordinate to sort primarily by x; "y" sorts by y.
- scale
(scaleFactorX: number, scaleFactorY: number, points: Point[]) => Point[]Returns the scaled points.
- inLine
interface Line {
start: Point
end: Point
}
(point: Point, line: Line) => booleanReturns boolean value indicating whether or not the given coordinates are on line defined by two other points.
- cross
(line1: Line, line2: Line) => booleanReturns boolean value indicating if two lines each defined by two points intersect.
- move
(point: Point, xStep: number, yStep: number) => PointReturns a point of with the new coordinates.
- lerp
(point1: Point, point2: Point, t: number) => PointReturns the linearly interpolated point between point1 and point2 at parameter t (0 = point1, 1 = point2, 0.5 = midpoint). Values of t outside [0, 1] extrapolate beyond the two points.
- square
(point: Point, size: number, [direction]: "left" | "right" | "down" | "up" ) => Point[]Returns an array of points representing a shape of square.Takes four parameters: starting coordinates (x and y), size of square side, and direction which should be one of the values "left", "right", "up", "down".
- rectangle(point, width, height, [direction])
(point: Point, width: number, height: number, [direction]: "left" | "right" | "down" | "up" ) => Point[]Returns vertices of a rectangle starting at point, advancing width then height along the directional path (same directional convention as square).
- triangle(point, size, [direction])
(point: Point, size: number, [direction]: "left" | "right" | "down" | "up" ) => Point[]Returns an array of points representing a shape of triangle.Takes same parameters as square function.
- pentagon(center, radius, [angle])
(centerPoint: Point, radius: number, angle?: number) => Point[]Returns vertices of a pentagon around centerPoint with radius and rotation angle (degrees, default 0).
- degreesToRadians
(degrees: number) => numberConverts degrees to radians.
- radiansToDegrees
(radians: number) => numberConverts radians to degrees.
- inRange
(number: number, min: number, max: number) => booleanReturns true if the given number is within the specified range.
- roundToPrecision
(number: number, precision: -100 | -10 | 0 | 10 | 100 | number) => numberRounds the number to the given precision.
- average
(numbers: number[]) => numberReturns the average of all numbers in an array.
- intersection
(arr1: any[], arr2: any[]) => any[]Returns the array of intersection of two arrays.
- difference
(arr1: any[], arr2: any[]) => any[]Returns the array of difference of two arrays.
- chunk
(arr: any[], perArr: number) => any[][]Returns an array splited into chunks based on elements count per chunk.
- removeDuplicates(arr)
(arr: any[]) => any[]Returns the array without duplicates.
- sample
(arr: any[], [size]: number[]) => any[]Returns a random sample from an array with optional size argument for sampling length. If not specified, it returns only one element.
- randomNumber
(min: number, max: number) => numberReturns a random number within the given range.
- randomBoolean
() => booleanReturns a random boolean value.
- uniqueId
([other ids]: string[]) => string Returns a unique ID that's different from the provided IDs, or a random ID if no other IDs are given.