Experimenting with coordinate systems
This commit is contained in:
29
fcad/align.scad
Normal file
29
fcad/align.scad
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
function fAlign(modelA, coordNameA, modelB, coordNameB) = (
|
||||||
|
let(coordA = fModelCoord(modelA, coordNameA),
|
||||||
|
coordB = fModelCoord(modelB, coordNameB),
|
||||||
|
translation = fCoordTranslation(coordA) - fCoordTranslation(coordB),
|
||||||
|
rotation = fCoordRotation(coordA) - fCoordRotation(coordB),
|
||||||
|
scale = fCoordScale(coordA) - fCoordScale(coordB))
|
||||||
|
fUnion(
|
||||||
|
modelA,
|
||||||
|
fTranslate(
|
||||||
|
fRotate(modelB, coordNameB, rotation),
|
||||||
|
translation
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
function fAttach(modelA, coordNameA, modelB, coordNameB) = (
|
||||||
|
let(coordA = fModelCoord(modelA, coordNameA),
|
||||||
|
coordB = fModelCoord(modelB, coordNameB),
|
||||||
|
translation = fCoordTranslation(coordA) - fCoordTranslation(coordB),
|
||||||
|
rotation = fCoordRotation(coordA) - (-1 * fCoordRotation(coordB)),
|
||||||
|
scale = fCoordScale(coordA) - fCoordScale(coordB))
|
||||||
|
fUnion(
|
||||||
|
modelA,
|
||||||
|
fTranslate(
|
||||||
|
fRotate(modelB, coordNameB, rotation),
|
||||||
|
translation
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
@@ -35,3 +35,11 @@ function fCoordRotation(coord) = (
|
|||||||
function fCoordScale(coord) = (
|
function fCoordScale(coord) = (
|
||||||
fMapLookup(fKeyScale, coord)
|
fMapLookup(fKeyScale, coord)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
function fCoordInverse(coord) = (
|
||||||
|
fCoord(
|
||||||
|
translation=[0, 0, 0] - fCoordTranslation(coord),
|
||||||
|
rotation=[180, 180, 180] + fCoordRotation(coord),
|
||||||
|
scale=1 / fCoordScale(coord)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|||||||
@@ -13,8 +13,14 @@ function fCube(dims) = (
|
|||||||
[1, 3, 7, 5], // +z
|
[1, 3, 7, 5], // +z
|
||||||
],
|
],
|
||||||
coords=[
|
coords=[
|
||||||
[ "/x+,/y+,-z+", fCoord(translation=[x / 2, y / 2, 0]) ],
|
[ "-x-,/y-,/z-", fCoord(translation=[ 0, y / 2, z / 2], rotation=[ 0, -90, 0]) ],
|
||||||
[ "/x+,/y+,+z+", fCoord(translation=[x / 2, y / 2, z]) ],
|
[ "+x+,/y+,/z+", fCoord(translation=[ x, y / 2, z / 2], rotation=[ 0, 90, 0]) ],
|
||||||
|
|
||||||
|
[ "/x-,-y-,/z-", fCoord(translation=[x / 2, 0, z / 2], rotation=[-90, 0, 0]) ],
|
||||||
|
[ "/x+,+y+,/z+", fCoord(translation=[x / 2, y, z / 2], rotation=[ 90, 0, 0]) ],
|
||||||
|
|
||||||
|
[ "/x-,/y-,-z-", fCoord(translation=[x / 2, y / 2, 0], rotation=[180, 0, 180]) ],
|
||||||
|
[ "/x+,/y+,+z+", fCoord(translation=[x / 2, y / 2, z], rotation=[ 0, 0, 0]) ],
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ function fCylinder(h, r, r1=undef, r2=undef, sides=36) = (
|
|||||||
// sides
|
// sides
|
||||||
[for (side = side_range)
|
[for (side = side_range)
|
||||||
[for (vertex = [2, 3, 1, 0]) (side * 2 + vertex) % (sides * 2)]]
|
[for (vertex = [2, 3, 1, 0]) (side * 2 + vertex) % (sides * 2)]]
|
||||||
)
|
),
|
||||||
|
coords=[
|
||||||
|
[ "start", fCoord() ],
|
||||||
|
]
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,25 +1,3 @@
|
|||||||
module fDraw(model) {
|
module fDraw(model) {
|
||||||
polyhedron(points=fModelPoints(model), faces=fModelFaces(model));
|
polyhedron(points=fModelPoints(model), faces=fModelFaces(model));
|
||||||
}
|
}
|
||||||
|
|
||||||
module fDrawN(model, scales) {
|
|
||||||
fDraw(model);
|
|
||||||
points = fModelPoints(model);
|
|
||||||
model_max = fMaxPoint(model);
|
|
||||||
translation =
|
|
||||||
[for (axis = [0 : 2])
|
|
||||||
scales[axis] * model_max[axis]];
|
|
||||||
translate(translation) children();
|
|
||||||
}
|
|
||||||
|
|
||||||
module fDrawX(model) {
|
|
||||||
fDrawN(model, [1, 0, 0]) children();
|
|
||||||
}
|
|
||||||
|
|
||||||
module fDrawY(model) {
|
|
||||||
fDrawN(model, [0, 1, 0]) children();
|
|
||||||
}
|
|
||||||
|
|
||||||
module fDrawZ(model) {
|
|
||||||
fDrawN(model, [0, 0, 1]) children();
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
|
include <align.scad>;
|
||||||
include <coord.scad>;
|
include <coord.scad>;
|
||||||
include <cube.scad>;
|
include <cube.scad>;
|
||||||
include <cylinder.scad>;
|
include <cylinder.scad>;
|
||||||
include <draw.scad>;
|
include <draw.scad>;
|
||||||
include <math.scad>;
|
include <math.scad>;
|
||||||
include <model.scad>;
|
include <model.scad>;
|
||||||
include <model_util.scad>;
|
include <rotate.scad>;
|
||||||
include <sphere.scad>;
|
include <sphere.scad>;
|
||||||
include <translate.scad>;
|
include <translate.scad>;
|
||||||
include <types.scad>;
|
include <types.scad>;
|
||||||
|
include <union.scad>;
|
||||||
|
|||||||
@@ -6,4 +6,3 @@ function fCartesianProduct(vecs) = (
|
|||||||
for (val2 = fCartesianProduct(fVectorSlice(vecs, start=1)))
|
for (val2 = fCartesianProduct(fVectorSlice(vecs, start=1)))
|
||||||
concat(val1, val2)]
|
concat(val1, val2)]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,13 @@
|
|||||||
/// fKeyFaces "faces" fModelFaces(): [ [ pointIdx, ... ], ... ]
|
/// fKeyFaces "faces" fModelFaces(): [ [ pointIdx, ... ], ... ]
|
||||||
/// fKeyCoords "coords" fModelCoords(): [ [ name, coord ], ... ]
|
/// fKeyCoords "coords" fModelCoords(): [ [ name, coord ], ... ]
|
||||||
|
|
||||||
|
/// OpenSCAD uses right-handed coordinates. We name directions on these axes:
|
||||||
|
/// X: left (-), right (+)
|
||||||
|
/// Y: back (-), front (+)
|
||||||
|
/// Z: bottom (-), top (+)
|
||||||
|
/// Coordinate systems that attach to surfaces should generally have the Z axis
|
||||||
|
/// normal to the surface.
|
||||||
|
///
|
||||||
/// Standard model coords names:
|
/// Standard model coords names:
|
||||||
///
|
///
|
||||||
/// [-/+] edge ("/" is midpoint)
|
/// [-/+] edge ("/" is midpoint)
|
||||||
@@ -39,15 +46,15 @@ function fModelFaces(model) = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
fCoordAliases = [
|
fCoordAliases = [
|
||||||
[ "bottom", "/x+,/y+,-z-" ],
|
[ "left", "-x-,/y-,/z-" ],
|
||||||
|
[ "right", "+x+,/y+,/z+" ],
|
||||||
|
|
||||||
|
[ "back", "/x-,-y-,/z-" ],
|
||||||
|
[ "front", "/x+,+y+,/z+" ],
|
||||||
|
|
||||||
|
[ "bottom", "/x-,/y-,-z-" ],
|
||||||
[ "top", "/x+,/y+,+z+" ],
|
[ "top", "/x+,/y+,+z+" ],
|
||||||
|
|
||||||
[ "back", "-x-,/y+,/z+" ],
|
|
||||||
[ "front", "+x+,/y+,/z+" ],
|
|
||||||
|
|
||||||
[ "left", "/x+,-y-,/z+" ],
|
|
||||||
[ "right", "/x+,+y+,/z+" ],
|
|
||||||
|
|
||||||
[ "center", "/x+,/y+,/z+" ],
|
[ "center", "/x+,/y+,/z+" ],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
function fMinPoint(model) = (
|
|
||||||
[for (axis = [0 : 2])
|
|
||||||
min([for (point = fModelPoints(model)) point[axis]])]
|
|
||||||
);
|
|
||||||
|
|
||||||
function fMaxPoint(model) = (
|
|
||||||
[for (axis = [0 : 2])
|
|
||||||
max([for (point = fModelPoints(model)) point[axis]])]
|
|
||||||
);
|
|
||||||
|
|
||||||
function fCenterPoint(model) = (
|
|
||||||
let(model_min = fMinPoint(model),
|
|
||||||
model_max = fMaxPoint(model),
|
|
||||||
model_size =
|
|
||||||
[for (axis = [0 : 2])
|
|
||||||
model_max[axis] - model_min[axis]])
|
|
||||||
[for (axis = [0 : 2])
|
|
||||||
model_min[axis] + (model_size[axis] / 2)]
|
|
||||||
);
|
|
||||||
45
fcad/rotate.scad
Normal file
45
fcad/rotate.scad
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
function fRotate(model, coordName, rotation) = (
|
||||||
|
// Shift the coordinate frame to the origin, rotate, then restore
|
||||||
|
let(coord = fModelCoord(model, coordName),
|
||||||
|
inverseCoord = fCoordInverse(coord),
|
||||||
|
zeroed = fTranslate(model, fCoordTranslation(inverseCoord)),
|
||||||
|
xMatrix = fRotationMatrixX(rotation[0]),
|
||||||
|
yMatrix = fRotationMatrixY(rotation[1]),
|
||||||
|
zMatrix = fRotationMatrixZ(rotation[2]))
|
||||||
|
fTranslate(
|
||||||
|
fModel(
|
||||||
|
points=
|
||||||
|
[for (point = fModelPoints(zeroed))
|
||||||
|
([point] * xMatrix * yMatrix * zMatrix)[0]],
|
||||||
|
faces=fModelFaces(model),
|
||||||
|
coords=fModelCoords(model)
|
||||||
|
),
|
||||||
|
fCoordTranslation(coord)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// These matrices are transposed because we apply them with post-multiplication
|
||||||
|
// to work around OpenSCAD bugs.
|
||||||
|
function fRotationMatrixX(theta) = (
|
||||||
|
[
|
||||||
|
[ 1, 0, 0 ],
|
||||||
|
[ 0, cos(theta), sin(theta) ],
|
||||||
|
[ 0, -sin(theta), cos(theta) ],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
function fRotationMatrixY(theta) = (
|
||||||
|
[
|
||||||
|
[ cos(theta), 0, -sin(theta) ],
|
||||||
|
[ 0, 1, 0 ],
|
||||||
|
[ sin(theta), 0, cos(theta) ],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
function fRotationMatrixZ(theta) = (
|
||||||
|
[
|
||||||
|
[ cos(theta), sin(theta), 0 ],
|
||||||
|
[ -sin(theta), cos(theta), 0 ],
|
||||||
|
[ 0, 0, 1 ],
|
||||||
|
]
|
||||||
|
);
|
||||||
@@ -2,49 +2,8 @@ function fTranslate(model, translation) = (
|
|||||||
fModel(
|
fModel(
|
||||||
points=
|
points=
|
||||||
[for (point = fModelPoints(model))
|
[for (point = fModelPoints(model))
|
||||||
[for (axis = [0 : 2])
|
point + translation],
|
||||||
point[axis] + translation[axis]]
|
faces=fModelFaces(model),
|
||||||
],
|
coords=fModelCoords(model)
|
||||||
faces=fModelFaces(model)
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
function fZeroN(model, scales) = (
|
|
||||||
let(model_min = fMinPoint(model),
|
|
||||||
translation =
|
|
||||||
[for (axis = [0 : 2])
|
|
||||||
scales[axis] * model_min[axis]])
|
|
||||||
fTranslate(model, translation)
|
|
||||||
);
|
|
||||||
|
|
||||||
function fZeroX(model) = (
|
|
||||||
fZeroN(model, [-1, 0, 0])
|
|
||||||
);
|
|
||||||
|
|
||||||
function fZeroY(model) = (
|
|
||||||
fZeroN(model, [0, -1, 0])
|
|
||||||
);
|
|
||||||
|
|
||||||
function fZeroZ(model) = (
|
|
||||||
fZeroN(model, [0, 0, -1])
|
|
||||||
);
|
|
||||||
|
|
||||||
function fCenterN(model, scales) = (
|
|
||||||
let(model_center = fCenterPoint(model),
|
|
||||||
translation =
|
|
||||||
[for (axis = [0 : 2])
|
|
||||||
scales[axis] * model_center[axis]])
|
|
||||||
fTranslate(model, translation)
|
|
||||||
);
|
|
||||||
|
|
||||||
function fCenterX(model) = (
|
|
||||||
fCenterN(model, [-1, 0, 0])
|
|
||||||
);
|
|
||||||
|
|
||||||
function fCenterY(model) = (
|
|
||||||
fCenterN(model, [0, -1, 0])
|
|
||||||
);
|
|
||||||
|
|
||||||
function fCenterZ(model) = (
|
|
||||||
fCenterN(model, [0, 0, -1])
|
|
||||||
);
|
|
||||||
|
|||||||
10
fcad/union.scad
Normal file
10
fcad/union.scad
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
function fUnion(modelA, modelB) = (
|
||||||
|
let(numPointsA = len(fModelPoints(modelA)))
|
||||||
|
fModel(
|
||||||
|
points=concat(fModelPoints(modelA), fModelPoints(modelB)),
|
||||||
|
faces=concat(fModelFaces(modelA),
|
||||||
|
[for (face = fModelFaces(modelB))
|
||||||
|
[for (point = face) point + numPointsA]])
|
||||||
|
)
|
||||||
|
// TODO: how should we handle coords here?
|
||||||
|
);
|
||||||
22
test.scad
22
test.scad
@@ -1,5 +1,21 @@
|
|||||||
use <fcad/fcad.scad>;
|
use <fcad/fcad.scad>;
|
||||||
|
|
||||||
fDrawX(fCylinder(10, r1=5, r2=2))
|
module testAxes(translation=[0, 0, 0], rotation=[0, 0, 0]) {
|
||||||
fDrawX(fSphere(10))
|
color("red") fDraw(fTranslate(fRotate(fRotate(fCylinder(h=100, r=1), "start", [0, 90, 0]), "start", rotation), translation));
|
||||||
fDrawX(fCube(10));
|
color("green") fDraw(fTranslate(fRotate(fRotate(fCylinder(h=100, r=1), "start", [-90, 0, 0]), "start", rotation), translation));
|
||||||
|
color("blue") fDraw(fTranslate(fRotate(fRotate(fCylinder(h=100, r=1), "start", [0, 0, 0]), "start", rotation), translation));
|
||||||
|
}
|
||||||
|
|
||||||
|
testAxes(translation=[0, 0, 200], rotation=[0, 0, 0]);
|
||||||
|
testAxes(translation=[200, 0, 0], rotation=[0, 180, ]);
|
||||||
|
testAxes(translation=[0, 0, -200], rotation=[180, 0, 0]);
|
||||||
|
testAxes(translation=[-200, 0, 0], rotation=[0, -90, 0]);
|
||||||
|
testAxes(translation=[0, 200, 0], rotation=[-90, 0, 0]);
|
||||||
|
testAxes(translation=[0, -200, 0], rotation=[90, 0, 0]);
|
||||||
|
|
||||||
|
|
||||||
|
//result = fAttach(fCube(10), "top", fCube(5), "bottom5");
|
||||||
|
//result = fRotate(fCube(5), "front", [0, 360, 360]);
|
||||||
|
|
||||||
|
//echo(result);
|
||||||
|
//#fDraw(result);
|
||||||
Reference in New Issue
Block a user