For the Clojure version, please visit: thi.ng/geom-clj
{{pkg.description}}
This project is a partially ported from the Clojure version of the same name. All polymorphic operations built on @thi.ng/defmulti.
The following 2D/3D shape primitives are provided. All these types are implemented as
basic data container classes with additional eponymous factory functions (e.g.
Circle
(class) => circle()
(function)), which are encouraged to be used
instead of calling class constructors directly. For many shapes there're
multiple ways to create them, please also check
linked sources and/or docs.
Important
Support for 3D shapes is WIP and currently limited to the various operations provided by this package, but does not yet find any usage outside (e.g. for visualization). Sill, even the ops supported so far can be useful for many use cases...
Shape/Form | Description | Hiccup support |
---|---|---|
AABB | 3D Axis-aligned bounding box | ✅(1) |
Arc | 2D elliptic arc | ✅ |
BPatch | 2D cubic bezier patch (4x4 points) | ✅ |
Circle | 2D circle | ✅ |
ComplexPolygon | 2D polygon w/ holes | ✅ |
Cubic | 2D cubic bezier | ✅ |
Cubic3 | 3D cubic bezier | ✅(1) |
Ellipse | 2D ellipse | ✅ |
Extra | Custom embedded hiccup/SVG data | ✅ |
Group | group of 2D shapes | ✅ |
Group3 | group of 3D shapes | ✅(1) |
Line | 2D line segment | ✅ |
Line3 | 3D line segment | ✅(1) |
Path | 2D path (w/ optional holes/sub-paths) | ✅ |
Path3 | 3D path (w/ optional holes/sub-paths) | ✅(1),(2) |
Plane | 3D plane | ✅(1) |
Points | 2D point cloud | ✅ |
Points3 | 3D point cloud | ✅(1) |
Polygon | 2D simple polygon (no holes) | ✅ |
Polygon3 | 3D simple polygon (no holes) | ✅ |
Polyline | 2D polyline | ✅ |
Polyline3 | 3D polyline | ✅(1) |
Quad | 2D quad (4-gon) | ✅ |
Quad3 | 2D quad (4-gon) | ✅(1) |
Quadratic | 2D quadratic bezier | ✅ |
Quadratic3 | 3D quadratic bezier | ✅(1) |
Ray | 2D ray | ✅ |
Ray3 | 3D ray | ✅(1) |
Rectangle | 2D rectangle | ✅ |
Sphere | 3D sphere | ✅(1) |
Text | Basic stub for text labels | ✅(3) |
Triangle | 2D triangle | ✅ |
Triangle3 | 3D triangle | ✅(1) |
- (1) valid hiccup format, but currently still missing external tool/library support
- (2) only lines, cubic & quadratic curve segments supported
- (3) merely treated as a point in space (e.g. used for placing text labels), no geometry of text itself
Note
Sidebar with background information for advanced usage only. Most users can safely ignore this.
With very few exceptions these all are implementing the IToHiccup
interface and so
can be easily converted (via
hiccup) to a
variety of other formats, incl. conversion to SVG.
By design, for more flexibility and for performance reasons, the hiccup flavor
used by this package is not compatible with that used by
thi.ng/hiccup-svg,
though the latter provides a
convertTree()
function for that purpose. This is only needed for some cases of dynamic
in-browser SVG DOM creation...
Instead, the hiccup format used here for interim interop is compatible with that used by the thi.ng/hiccup-canvas package (see its readme for details) and avoids extraneous stringification of geometry data and attrib values. A brief example to illustrate some differences:
import { circle, asSvg } from "@thi.ng/geom";
import { convertTree } from "@thi.ng/hiccup-svg";
// a circle with RGBA color attrib
const a = circle([100, 200], 300, { fill: [1, 0.5, 0, 1] });
// invocation of the IToHiccup interface (all shapes support it)
console.log(a.toHiccup());
// [ "circle", { fill: [ 1, 0, 0, 1 ] }, [ 100, 200 ], 300 ]
// convert shape into to a SVG compatible hiccup format
// (i.e. stringify attributes, convert colors etc.)
console.log(convertTree(a));
// [ "circle", { fill: "#ff8000", cx: "100", cy: "200", r: "300" } ]
// asSvg() automatically uses convertTree() when serializing shape(s) to SVG
console.log(asSvg(a));
// <circle fill="#ff8000" cx="100" cy="200" r="300"/>
For 2D shape types only, SVG conversion is included via the
asSvg()
and
svgDoc()
functions.
The following operations are provided (many also applicable to shape groups directly and/or perform automatic resampling/conversion if needed).
Operation | Description |
---|---|
applyTransforms() |
applies any spatial transformation attributes |
arcLength() |
compute arc length / perimeter of shape boundary |
area() |
signed/unsigned surface area |
asCubic() |
convert shape boundary to cubic bezier segments |
asPath() |
convert shape to path |
asPolygon() |
convert shape to polygon(s) |
asPolyline() |
convert shape to polyline(s) |
asSector() |
convert arc to sector (path) |
asSvg() |
serialize shape/group/hierarchy to SVG |
bounds() |
compute bounding box |
center() |
center shape around origin or point |
centroid() |
compute shape centroid |
classifyPoint() |
classify point in relation to shape boundary (in/out) |
clipConvex() |
clip shape against convex boundary |
closestPoint() |
compute closest point on shape boundary |
convexHull() |
compute convex hull (2d only) |
convolve() |
kernel based vertex convolution/filtering |
edges() |
extract edges |
edgesFromTessellation() |
extract unique edges from tessellation results |
fitIntoBounds2() |
rescale/reposition a 2D shape into a destination boundary |
fitIntoBounds3() |
rescale/reposition a 3D shape into a destination boundary |
fitAllIntoBounds2() |
rescale/reposition multiple 2D shapes into a boundary |
flip() |
reverse order (vertices or direction) |
graphFromTessellation() |
create graph from tessellation results |
intersects() |
pairwise shape intersection (various types) |
mapPoint() |
transform world space point into local shape UV space |
offset() |
shape/path offsetting |
pointAt() |
compute point on shape boundary at parametric position |
pointInside() |
check if point is inside shape |
proximity() |
distance from point to shape boundary |
resample() |
resample/convert shape |
rotate() |
rotate shape (2D only) |
rotateAroundAxis() |
rotate shape (3D only) |
rotateX() |
rotate shape (3D only) |
rotateY() |
rotate shape (3D only) |
rotateZ() |
rotate shape (3D only) |
scale() |
scale shape (uniformly/non-uniformly) |
scaleWithCenter() |
scale shape with pivot point |
scatter() |
create random points inside a shape boundary |
simplify() |
simplify shape/boundary (Douglas-Peucker) |
splitArcLength() |
split shapes & groups based on max. arc length |
splitAt() |
split shape/boundary at parametric position |
splitNearPoint() |
split shape/boundary near world position |
subdivCurve() |
recursively apply curve subdivision kernel |
tangentAt() |
compute tangent at parametric position |
tessellate() |
(recursively) tessellate shape |
transformVertices() |
apply custom function to each vertex |
transform() |
apply transformation matrix |
translate() |
translate shape |
union() |
compute shape union |
unmapPoint() |
transform local shape UV point into world space |
vertices() |
extract/sample vertices from shape boundary |
volume() |
compute shape volume (3D only) |
warpPoint() |
transfer single point between the local spaces defined by 2 shapes |
warpPoints() |
transfer points between the local spaces defined by 2 shapes |
warpPointsBPatch() |
transfer points to the local spaces of a bezier patch |
withAttribs() |
shallow copy of given shape with new attribs assigned |
In addition to the above listed direct shape type functions, the following additional shape creation helpers are provided:
- aabbFromMinMax()
- aabbFromMinMaxWithMargin()
- aabbFromCentroid()
- aabbWithCentroidAndMargin()
- intersectionAABB()
- inscribedAABB()
- rectFromMinMax()
- rectFromMinMaxWithMargin()
- rectWithCentroid()
- rectWithCentroidAndMargin()
- intersectionRect()
- inscribedSquare()
- inscribedSquareHex()
Some of the shape operations require configuration with specific algorithms and/or constants. In all cases this relies on a completely extensible mechanism, but the package provides presets for common options/implementations:
To be used with subdivideCurve()
:
To be used with tessellate()
:
See thi.ng/geom-tessellate readme for diagrams/illustrations of each algorithm!
- TESSELLATE_EARCUT
- TESSELLATE_EARCUT_COMPLEX
- TESSELLATE_EDGE_SPLIT
- TESSELLATE_INSET
- TESSELLATE_QUAD_FAN
- TESSELLATE_RIM_TRIS
- TESSELLATE_TRI_FAN
- TESSELLATE_TRI_FAN_BOUNDARY
- TESSELLATE_TRI_FAN_SPLIT
Tessellation behaviors:
- basicTessellation(): default impl
- meshTessellation(): uses kD-tree to deduplicate result points
Tessellation post-processing:
- edgesFromTessellation()
- edgePointsFromTessellation()
- graphFromTessellation()
- groupFromTessellation()
To be used with convolve()
:
This package acts as a higher-level frontend for most of the following related packages (which are more low-level, lightweight and usable by themselves too):
{{repo.supportPackages}}
{{repo.relatedPackages}}
{{meta.status}}
{{meta.blogPosts}}
{{pkg.install}}
{{pkg.size}}
{{pkg.deps}}
{{repo.examples}}
{{pkg.docs}}