CSG: constructive solid geometry library
CSG is a constructive solid geometry library with support
for ray casting. CSG allows you to define a complex solid as a
composition of primitives. It also provides functions to perform ray
casting (find an intersection of a ray and the defined solid) or test
whether a point belongs to the solid (for Monte Carlo volume
calculation).
-- "Data.CSG" uses 'Vec3' to represent vectors and points:
>>> let p1 = fromXYZ (5, -6.5, -5)
>>> toXYZ (origin :: Point)
(0.0,0.0,0.0)
-- Define some solids:
>>> let s = sphere origin 5.0
>>> let b = cuboid (fromXYZ (-1, -1, -1)) (fromXYZ (1, 1, 1))
-- Test if a point is inside the solid:
>>> origin `inside` (s `intersect` b)
True
>>> origin `inside` (s `subtract` b)
False
-- Find the distance to the next intersection of a ray with a solid, along with the
-- surface normal:
>>> let axis = fromXYZ (1, 2, 10)
>>> let solid = cylinder origin axis 2.0 `intersect` sphere origin 3.5
>>> let ray = Ray (p1, origin <-> p1)
>>> ray `cast` solid
Just (HitPoint 0.7422558525331708 (Just (CVec3 0.7155468474912454 (-0.6952955216188516) 6.750441957464598e-2)))
-- Load a solid definition from a file:
>>> import Data.CSG.Parser
>>> Right solid2 <- parseGeometryFile "examples/reentry.geo"
>>> ray `cast` solid2
Just (HitPoint 10.877824491509912 (Just (CVec3 (-0.5690708596937849) 0.7397921176019203 0.3589790793088691)))
Please consult the Hackage page for csg
for full documentation.
By default csg
is built using CVec3
from simple-vec3 to
represent vectors and points, which according to benchmarks shows
better performance with Unboxed and Storable vectors. Build csg
with
triples
flag to use (Double, Double, Double)
instead which may be
a more convenient programmatic interface that needs no
fromXYZ
/toXYZ
.
See alternatives too.
csg-raycaster
The package also includes csg-raycaster
executable, which is a
simple interactive GUI for the ray casting algorithm.
csg-raycaster
takes a geometry defintion file as input. See
cube.geo
:
solid box = orthobrick (-150, -150, -150; 150, 150, 150);
solid rounded = sphere (0, 0, 0; 200);
solid roundedbox = rounded and box;
solid cylinder1 = cylinder (-160, 0, 0; 160, 0, 0; 100);
solid cylinder2 = cylinder (0, -160, 0; 0, 160, 0; 100);
solid cylinder3 = cylinder (0, 0, -160; 0, 0, 160; 100);
solid cross = cylinder1 or cylinder2 or cylinder3;
solid cutout = not cross;
solid top = roundedbox and cutout;
tlo top;
Please consult the Hackage page for Data.CSG.Parser for
full format specification.
csg-raycaster
may be run as
csg-raycaster cube.geo
Run as csg-raycaster --help
to see all options.
When run without a file argument, csg-raycaster
will try to display
an arbitrary CSG solid.
In the GUI window the following controls are supported:
Input |
Function |
Left mouse button + drag |
Rotate |
Right mouse button + drag |
Pan |
Mouse wheel up |
Zoom in |
Mouse wheel down |
Zoom out |
r |
Reset zoom level and camera position |
Alternatives
csg library performs no surface interpolation when doing ray casting.
Instead, we only solve ray-surface intersection equation numerically.
The library was written with Repa/vector compatibility and performance
in mind.
There're other Haskell libraries for CSG:
-
GlomeTrace:
-
Has more ray tracing-specific features, such as light sources,
different textures and materials.
-
Unlike csg
, has no tests or benchmarks.
-
In csg
solids use the same type as opposed to different types
with an existential box in GlomeTrace
.
-
implicit:
-
Offers a much richer operation set.
-
Uses function representation for CSG solids.
-
If implicit
had ray-casting support in early 2012 then I
probably wouldn't write csg
.
-
mecha: