-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
OEP7: Mixed Dimension Geometry Support
OpenSCAD currently operates on two types of geometry: 2D solids and 3D solids.
There are other kinds of geometry that would be useful to support, which can be represented with a pair of dimensions:
mD-in-nD where m is the dimensionality of the geometry itself, n is the dimension of space which it is embedded in.
Additionally: m <= n
which implies that lower dimension shapes can be embedded in higher dimensional space.
As a quick example, probably the most discussed aspect of this is 2D-in-3D geometry or "oriented 2d shapes" as mentioned in OEP1: Generalized-extrusion-module (also see PR #2796).
These could be created by applying 3D transformations to 2D geometry. (e.g. translating away from z0 plane: translate([0,0,z]) some2DGeometry();
)
Geometry Dimensions | Description | Usage examples and notes |
---|---|---|
0D-in-2D | 2D Point set | Mainly useful for 2D hull() , possibly minkowski()
|
0D-in-3D | 3D Point set | Mainly useful for 3D hull() , possibly minkowski()
|
1D-in-2D | Lines and paths in 2D space | For building up 2D shapes, can be offset() to create stroked lines as in SVG |
1D-in-3D | Lines and paths in 3D space | For generalized extruding/lofting along a path |
2D-in-2D | 2D Solid | "Plain old" 2D Solid Geometry, already supported |
2D-in-3D | Planar 2D Geometry in 3D Space | Can be used as the "slices" in a loft operation |
2D*-in-3D | Non-planar, non-closed 3D surface | Maybe useful for creating and stitching NURBS/Bezier patches if support for those is ever added. This type and the one above would be the only case where a dimension pair is not enough to fully describe the difference between types. Not yet sure the best way to represent that. |
3D-in-3D | 3D Solid | "Plain old" 3D Solid Geometry, already supported |
Since OpenSCAD is still meant to model solid geometries (2D-in-2D and 3D-in-3D), only those should remain valid as top-level, exportable shapes. Other geometry types would be valid only as intermediates for generating valid solids.
However, for user convenience we may want to allow at least Preview of some or all of the proposed mixed-dimension geometries.
Currently, 2D-in-3D already does preview in this way, but that is mostly a coincidental quirk of how the OpenCSG 2D implementation works. Also, when such transformed 2D shapes get Rendered, they end up being projected down to the XY plane.
The base Geometry
class declares virtual unsigned int getDimension() const
It currently returns 2
or 3
, but would be better changed to return an enum
representing the above dimension pairs.
Some types of operations could be applicable over combinations of multiple geometry dimension types.
-
The usual affine transformations:
translate(...)
,rotate(...)
,scale(...)
,resize(...)
,mirror(...)
,multmatrix(...)
could all be applicable to combinations of various geometry dimension types. -
hull()
is only concerned with the constituent vertices of its input geometry, so any mD-in-nD type, or any combination of types could be considered valid inputs of hull. -
minkowski()
could also potentially sum over any combination of geometry dimensions. For example:minkowski() { square(100, center=true); sphere(d=10); } // would be expected to generate the same geometry as: hull() for(p=[[-50,-50],[50,-50],[-50,50],[50,50]]) translate(p) sphere(d=10);
-
projection()
could be considered applicable to any combination of mD-in-3D inputs, resulting in mD-in-2D output
For any combination of mixed dimension geometries, the result inputs of mD-in-nD and pD-in-qD should be max(m,p)
D-in-max(n,q)
D
If geometries in 2D space are mixed with those in 3D space then z=0
can be implied.
Suggested primitive module signatures:
point2(x,y);
point2([x,y]);
points2([ [x0,y0], [x1,y1], ... ]);
point3(x,y,z);
point3([x,y,z]);
points3([ [x0,y0,z0], [x1,y1,z1], ... ]);
Alternatively the space-dimension of point2
,point3
, and points2
,points3
could be implied from the provided arguments,
so the primitives could be merged/overloaded as point(...)
and points(...)
.
-
hull()
is probably the most practical use case for point sets, as a convenience (see #3632 ).
For 0D-in-3D, this would avoid the need to manually define polyhedron faces with correct winding, as long as the desired shape is convex.
For 0D-in-2D similarly would allow hull with no regard to the order of points being input. -
union()
,difference()
, andintersection()
over point sets can be trivially implemented as the typical operations from the algebra of sets. -
minkowski()
of any geometry with a set of points would be a sort of alternate/shorthand equivalent of translating the shape to each point:points_vector = [ ... ]; // for 2D or 3D points minkowski() { points(points_vector); some_shape(); // for 2D or 3D shape } // would be same as union() { for(p = points_vector) translate(p) some_shape(); // for 2D or 3D shape }
-
color(...)
maybe applicable if points are made visualizable. -
linear_extrude(...)
could transform points into vertical lines (or diagonal lines withscale
argument, helical paths withtwist
argument) -
rotate_extrude(...)
could transform points into closed circular paths, or partial arc paths withangle
parameter -
offset(r)
could transform 2D points into 2D-in-2D circles, or 3D points into 2D-in-3D circles. -
offset(delta, chamfer)
could transform 2D points into 2D-in-2D squares, or 3D points into 2D-in-3D squares (octagons with chamfer=true?). -
projection(cut=false)
could be used to convert 3D points to 2D, discarding z-component -
projection(cut=true)
could be used to filter down points to just those withz = 0
AKA paths in 2D.
One of the main ideas for this would be to support circular, elliptical, and bezier curves as primitives, in a way that would e.g. allow an SVG import, then export without any loss of information/scalability.
The viewport Preview/Render could still make use of $fs
, $fa
for visualizing, but the curves would keep their metadata without being converted to "polylines" for export formats which support such curves.
This could also be applied text()
fonts usage of bezier curves, providing the possibility of text and SVG being convertible to native OpenSCAD CSG format.
New primitives should be analogous to SVG Path Data commands
path() {
move_to([x,y]);
// TODO fill in parameter details for module signatures
line_to(...)
arc_to(...)
bezier_quadratic(...)
bezier_cubic(...)
close_path(...);
}
Paths in 3D, could overload same primitive modules as 2D paths, by simply providing z-components.
Already implemented, no particular change needed.
TO BE WRITTEN
TO BE WRITTEN
Already implemented, no particular change needed.