Experimenting with coordinate systems

This commit is contained in:
Ian Gulliver
2016-12-25 23:19:30 -08:00
parent bc2fdc1f67
commit 786214cd00
13 changed files with 143 additions and 100 deletions

29
fcad/align.scad Normal file
View 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
)
)
);

View File

@@ -35,3 +35,11 @@ function fCoordRotation(coord) = (
function fCoordScale(coord) = (
fMapLookup(fKeyScale, coord)
);
function fCoordInverse(coord) = (
fCoord(
translation=[0, 0, 0] - fCoordTranslation(coord),
rotation=[180, 180, 180] + fCoordRotation(coord),
scale=1 / fCoordScale(coord)
)
);

View File

@@ -13,8 +13,14 @@ function fCube(dims) = (
[1, 3, 7, 5], // +z
],
coords=[
[ "/x+,/y+,-z+", fCoord(translation=[x / 2, y / 2, 0]) ],
[ "/x+,/y+,+z+", fCoord(translation=[x / 2, y / 2, z]) ],
[ "-x-,/y-,/z-", fCoord(translation=[ 0, y / 2, z / 2], rotation=[ 0, -90, 0]) ],
[ "+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]) ],
]
)
);

View File

@@ -19,6 +19,9 @@ function fCylinder(h, r, r1=undef, r2=undef, sides=36) = (
// sides
[for (side = side_range)
[for (vertex = [2, 3, 1, 0]) (side * 2 + vertex) % (sides * 2)]]
)
),
coords=[
[ "start", fCoord() ],
]
)
);

View File

@@ -1,25 +1,3 @@
module fDraw(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();
}

View File

@@ -1,10 +1,12 @@
include <align.scad>;
include <coord.scad>;
include <cube.scad>;
include <cylinder.scad>;
include <draw.scad>;
include <math.scad>;
include <model.scad>;
include <model_util.scad>;
include <rotate.scad>;
include <sphere.scad>;
include <translate.scad>;
include <types.scad>;
include <union.scad>;

View File

@@ -6,4 +6,3 @@ function fCartesianProduct(vecs) = (
for (val2 = fCartesianProduct(fVectorSlice(vecs, start=1)))
concat(val1, val2)]
);

View File

@@ -4,6 +4,13 @@
/// fKeyFaces "faces" fModelFaces(): [ [ pointIdx, ... ], ... ]
/// 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:
///
/// [-/+] edge ("/" is midpoint)
@@ -39,15 +46,15 @@ function fModelFaces(model) = (
);
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+" ],
[ "back", "-x-,/y+,/z+" ],
[ "front", "+x+,/y+,/z+" ],
[ "left", "/x+,-y-,/z+" ],
[ "right", "/x+,+y+,/z+" ],
[ "center", "/x+,/y+,/z+" ],
];

View File

@@ -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
View 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 ],
]
);

View File

@@ -2,49 +2,8 @@ function fTranslate(model, translation) = (
fModel(
points=
[for (point = fModelPoints(model))
[for (axis = [0 : 2])
point[axis] + translation[axis]]
],
faces=fModelFaces(model)
point + translation],
faces=fModelFaces(model),
coords=fModelCoords(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
View 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?
);

View File

@@ -1,5 +1,21 @@
use <fcad/fcad.scad>;
fDrawX(fCylinder(10, r1=5, r2=2))
fDrawX(fSphere(10))
fDrawX(fCube(10));
module testAxes(translation=[0, 0, 0], rotation=[0, 0, 0]) {
color("red") fDraw(fTranslate(fRotate(fRotate(fCylinder(h=100, r=1), "start", [0, 90, 0]), "start", rotation), translation));
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);