mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-17 09:59:39 +00:00
Merge pull request #250 from revarbat/revarbat_dev
Fixed broken line-plane intersections. Attachment enhanced vnf_polyhedron()
This commit is contained in:
commit
9a9f169f8f
6 changed files with 140 additions and 25 deletions
|
@ -461,13 +461,16 @@ function find_anchor(anchor, geom) =
|
||||||
rpts = apply(rot(from=anchor, to=RIGHT) * move(point3d(-cp)), points),
|
rpts = apply(rot(from=anchor, to=RIGHT) * move(point3d(-cp)), points),
|
||||||
hits = [
|
hits = [
|
||||||
for (face = faces) let(
|
for (face = faces) let(
|
||||||
verts = select(rpts, face)
|
verts = select(rpts, face),
|
||||||
|
xs = subindex(verts,0),
|
||||||
|
ys = subindex(verts,1),
|
||||||
|
zs = subindex(verts,2)
|
||||||
) if (
|
) if (
|
||||||
max(subindex(verts,0)) >= -eps &&
|
max(xs) >= -eps &&
|
||||||
max(subindex(verts,1)) >= -eps &&
|
max(ys) >= -eps &&
|
||||||
max(subindex(verts,2)) >= -eps &&
|
max(zs) >= -eps &&
|
||||||
min(subindex(verts,1)) <= eps &&
|
min(ys) <= eps &&
|
||||||
min(subindex(verts,2)) <= eps
|
min(zs) <= eps
|
||||||
) let(
|
) let(
|
||||||
poly = select(points, face),
|
poly = select(points, face),
|
||||||
pt = polygon_line_intersection(poly, [cp,cp+anchor], bounded=[true,false], eps=eps)
|
pt = polygon_line_intersection(poly, [cp,cp+anchor], bounded=[true,false], eps=eps)
|
||||||
|
|
|
@ -1007,11 +1007,20 @@ function closest_point_on_plane(plane, point) =
|
||||||
// Returns [LINE, undef] if the line is on the plane.
|
// Returns [LINE, undef] if the line is on the plane.
|
||||||
// Returns undef if line is parallel to, but not on the given plane.
|
// Returns undef if line is parallel to, but not on the given plane.
|
||||||
function _general_plane_line_intersection(plane, line, eps=EPSILON) =
|
function _general_plane_line_intersection(plane, line, eps=EPSILON) =
|
||||||
let( a = plane*[each line[0],-1],
|
let(
|
||||||
b = plane*[each(line[1]-line[0]),-1] )
|
l0 = line[0], // Ray start point
|
||||||
approx(b,0,eps)
|
u = line[1] - l0, // Ray direction vector
|
||||||
? points_on_plane(line[0],plane,eps)? [line,undef]: undef
|
n = plane_normal(plane),
|
||||||
: [ line[0]+a/b*(line[1]-line[0]), a/b ];
|
p0 = n * plane[3], // A point on the plane
|
||||||
|
w = l0 - p0 // Vector from plane point to ray start
|
||||||
|
) approx(n*u, 0, eps=eps) ? (
|
||||||
|
// Line is parallel to plane.
|
||||||
|
approx(n*w, 0, eps=eps)
|
||||||
|
? [line, undef] // Line is on the plane.
|
||||||
|
: undef // Line never intersects the plane.
|
||||||
|
) : let(
|
||||||
|
t = (-n * w) / (n * u) // Distance ratio along ray
|
||||||
|
) [ l0 + u*t, t ];
|
||||||
|
|
||||||
|
|
||||||
// Function: plane_line_angle()
|
// Function: plane_line_angle()
|
||||||
|
@ -1098,8 +1107,8 @@ function polygon_line_intersection(poly, line, bounded=false, eps=EPSILON) =
|
||||||
linevec = unit(line[1] - line[0]),
|
linevec = unit(line[1] - line[0]),
|
||||||
lp1 = line[0] + (bounded[0]? 0 : -1000000) * linevec,
|
lp1 = line[0] + (bounded[0]? 0 : -1000000) * linevec,
|
||||||
lp2 = line[1] + (bounded[1]? 0 : 1000000) * linevec,
|
lp2 = line[1] + (bounded[1]? 0 : 1000000) * linevec,
|
||||||
poly2d = clockwise_polygon(project_plane(poly, p1, p2, p3)),
|
poly2d = clockwise_polygon(project_plane(poly, plane)),
|
||||||
line2d = project_plane([lp1,lp2], p1, p2, p3),
|
line2d = project_plane([lp1,lp2], plane),
|
||||||
parts = split_path_at_region_crossings(line2d, [poly2d], closed=false),
|
parts = split_path_at_region_crossings(line2d, [poly2d], closed=false),
|
||||||
inside = [for (part = parts)
|
inside = [for (part = parts)
|
||||||
if (point_in_polygon(mean(part), poly2d)>0) part
|
if (point_in_polygon(mean(part), poly2d)>0) part
|
||||||
|
@ -1107,7 +1116,7 @@ function polygon_line_intersection(poly, line, bounded=false, eps=EPSILON) =
|
||||||
)
|
)
|
||||||
!inside? undef :
|
!inside? undef :
|
||||||
let(
|
let(
|
||||||
isegs = [for (seg = inside) lift_plane(seg, p1, p2, p3) ]
|
isegs = [for (seg = inside) lift_plane(seg, plane) ]
|
||||||
)
|
)
|
||||||
isegs
|
isegs
|
||||||
)
|
)
|
||||||
|
@ -1264,7 +1273,6 @@ function find_circle_2tangents(pt1, pt2, pt3, r, d, tangents=false) =
|
||||||
x = hyp * cos(a/2),
|
x = hyp * cos(a/2),
|
||||||
tp1 = pt2 + x * v1,
|
tp1 = pt2 + x * v1,
|
||||||
tp2 = pt2 + x * v2,
|
tp2 = pt2 + x * v2,
|
||||||
// fff=echo(tp1=tp1,cp=cp,pt2=pt2),
|
|
||||||
dang1 = vector_angle(tp1-cp,pt2-cp),
|
dang1 = vector_angle(tp1-cp,pt2-cp),
|
||||||
dang2 = vector_angle(tp2-cp,pt2-cp)
|
dang2 = vector_angle(tp2-cp,pt2-cp)
|
||||||
)
|
)
|
||||||
|
|
91
scripts/gencheat.sh
Executable file
91
scripts/gencheat.sh
Executable file
|
@ -0,0 +1,91 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
|
||||||
|
function ucase
|
||||||
|
{
|
||||||
|
echo "$1" | tr '[:lower:]' '[:upper:]'
|
||||||
|
}
|
||||||
|
|
||||||
|
function lcase
|
||||||
|
{
|
||||||
|
echo "$1" | tr '[:upper:]' '[:lower:]'
|
||||||
|
}
|
||||||
|
|
||||||
|
function columnize
|
||||||
|
{
|
||||||
|
cols=4
|
||||||
|
TMPFILE=$(mktemp -t $(basename $0).XXXXXX) || exit 1
|
||||||
|
cat >>$TMPFILE
|
||||||
|
totcnt=$(wc -l $TMPFILE | awk '{print $1}')
|
||||||
|
maxrows=$((($totcnt+$cols-1)/$cols))
|
||||||
|
maxcols=$cols
|
||||||
|
if [[ $maxcols -gt $totcnt ]] ; then
|
||||||
|
maxcols=$totcnt
|
||||||
|
fi
|
||||||
|
cnt=0
|
||||||
|
hdrln1="| $(ucase $1) "
|
||||||
|
hdrln2='|:-----'
|
||||||
|
n=1
|
||||||
|
while [[ $n < $maxcols ]] ; do
|
||||||
|
hdrln1+=' | '
|
||||||
|
hdrln2+=' |:------'
|
||||||
|
n=$(($n+1))
|
||||||
|
done
|
||||||
|
hdrln1+=' |'
|
||||||
|
hdrln2+=' |'
|
||||||
|
n=0
|
||||||
|
while [[ $n < $maxrows ]] ; do
|
||||||
|
lines[$n]=""
|
||||||
|
n=$(($n+1))
|
||||||
|
done
|
||||||
|
col=0
|
||||||
|
while IFS= read -r line; do
|
||||||
|
if [[ $col != 0 ]] ; then
|
||||||
|
lines[$cnt]+=" | "
|
||||||
|
fi
|
||||||
|
lines[$cnt]+="$line"
|
||||||
|
cnt=$(($cnt+1))
|
||||||
|
if [[ $cnt = $maxrows ]] ; then
|
||||||
|
cnt=0
|
||||||
|
col=$(($col+1))
|
||||||
|
fi
|
||||||
|
done <$TMPFILE
|
||||||
|
rm -f $TMPFILE
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo $hdrln1
|
||||||
|
echo $hdrln2
|
||||||
|
n=0
|
||||||
|
while [[ $n < $maxrows ]] ; do
|
||||||
|
echo "| ${lines[$n]} |"
|
||||||
|
n=$(($n+1))
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function mkconstindex
|
||||||
|
{
|
||||||
|
sed 's/([^)]*)//g' | sed 's/[^a-zA-Z0-9_.:$]//g' | awk -F ':' '{printf "[%s](%s#%s)\n", $3, $1, $3}'
|
||||||
|
}
|
||||||
|
|
||||||
|
function mkotherindex
|
||||||
|
{
|
||||||
|
sed 's/([^)]*)//g' | sed 's/[^a-zA-Z0-9_.:$]//g' | awk -F ':' '{printf "[%s()](%s#%s)\n", $3, $1, $3}'
|
||||||
|
}
|
||||||
|
|
||||||
|
CHEAT_FILES=$(grep '^include' std.scad | sed 's/^.*<\([a-zA-Z0-9.]*\)>/\1/'|grep -v 'version.scad')
|
||||||
|
|
||||||
|
(
|
||||||
|
echo '## Belfry OpenScad Library Cheat Sheet'
|
||||||
|
echo
|
||||||
|
echo '( [Alphabetic Index](Index) )'
|
||||||
|
echo
|
||||||
|
for f in $CHEAT_FILES ; do
|
||||||
|
#echo "### $f"
|
||||||
|
(
|
||||||
|
egrep -H 'Constant: ' $f | mkconstindex
|
||||||
|
egrep -H 'Function: |Function&Module: |Module: ' $f | mkotherindex
|
||||||
|
) | columnize $f
|
||||||
|
echo
|
||||||
|
done
|
||||||
|
) > BOSL2.wiki/CheatSheet.md
|
||||||
|
|
|
@ -53,7 +53,7 @@ test_tri_functions();
|
||||||
//test__general_plane_line_intersection();
|
//test__general_plane_line_intersection();
|
||||||
//test_plane_line_angle();
|
//test_plane_line_angle();
|
||||||
//test_plane_line_intersection();
|
//test_plane_line_intersection();
|
||||||
//test_polygon_line_intersection();
|
test_polygon_line_intersection();
|
||||||
//test_plane_intersection();
|
//test_plane_intersection();
|
||||||
test_coplanar();
|
test_coplanar();
|
||||||
test_points_on_plane();
|
test_points_on_plane();
|
||||||
|
@ -542,6 +542,17 @@ module test_distance_from_plane() {
|
||||||
*test_distance_from_plane();
|
*test_distance_from_plane();
|
||||||
|
|
||||||
|
|
||||||
|
module test_polygon_line_intersection() {
|
||||||
|
poly1 = [[50,50,50], [50,-50,50], [-50,-50,50]];
|
||||||
|
assert_approx(polygon_line_intersection(poly1, [CENTER, UP]), [0,0,50]);
|
||||||
|
assert_approx(polygon_line_intersection(poly1, [CENTER, UP+RIGHT]), [50,0,50]);
|
||||||
|
assert_approx(polygon_line_intersection(poly1, [CENTER, UP+BACK+RIGHT]), [50,50,50]);
|
||||||
|
assert_approx(polygon_line_intersection(poly1, [[0,0,50], [1,0,50]]), [[[0,0,50], [50,0,50]]]);
|
||||||
|
assert_approx(polygon_line_intersection(poly1, [[0,0,0], [1,0,0]]), undef);
|
||||||
|
}
|
||||||
|
*test_polygon_line_intersection();
|
||||||
|
|
||||||
|
|
||||||
module test_coplanar() {
|
module test_coplanar() {
|
||||||
assert(coplanar([ [5,5,1],[0,0,1],[-1,-1,1] ]) == false);
|
assert(coplanar([ [5,5,1],[0,0,1],[-1,-1,1] ]) == false);
|
||||||
assert(coplanar([ [5,5,1],[0,0,0],[-1,-1,1] ]) == true);
|
assert(coplanar([ [5,5,1],[0,0,0],[-1,-1,1] ]) == true);
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
BOSL_VERSION = [2,0,410];
|
BOSL_VERSION = [2,0,415];
|
||||||
|
|
||||||
|
|
||||||
// Section: BOSL Library Version Functions
|
// Section: BOSL Library Version Functions
|
||||||
|
|
14
vnf.scad
14
vnf.scad
|
@ -341,13 +341,15 @@ function vnf_vertex_array(
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// vnf = A VNF structure, or list of VNF structures.
|
// vnf = A VNF structure, or list of VNF structures.
|
||||||
// convexity = Max number of times a line could intersect a wall of the shape.
|
// convexity = Max number of times a line could intersect a wall of the shape.
|
||||||
module vnf_polyhedron(vnf,
|
// extent = If true, calculate anchors by extents, rather than intersection. Default: true.
|
||||||
convexity=10,anchor="origin",cp,
|
// cp = Centerpoint of VNF to use for anchoring when `extent` is false. Default: `[0, 0, 0]`
|
||||||
spin=0, orient=UP, extent=false
|
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `"origin"`
|
||||||
)
|
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
|
||||||
{
|
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
|
||||||
|
module vnf_polyhedron(vnf, convexity=2, extent=true, cp=[0,0,0], anchor="origin", spin=0, orient=UP) {
|
||||||
vnf = is_vnf_list(vnf)? vnf_merge(vnf) : vnf;
|
vnf = is_vnf_list(vnf)? vnf_merge(vnf) : vnf;
|
||||||
attachable(anchor=anchor, spin=spin, orient=orient, vnf=vnf, extent=extent, cp=is_def(cp) ? cp : vnf_centroid(vnf)){
|
cp = is_def(cp) ? cp : vnf_centroid(vnf);
|
||||||
|
attachable(anchor,spin,orient, vnf=vnf, extent=extent, cp=cp) {
|
||||||
polyhedron(vnf[0], vnf[1], convexity=convexity);
|
polyhedron(vnf[0], vnf[1], convexity=convexity);
|
||||||
children();
|
children();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue