mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-29 16:29:40 +00:00
more error messages for star()
improve speed and flexibility of apply() fix triangulation bug add support for single point 2d solutions in polygon_line_intersection
This commit is contained in:
parent
2ea90b7467
commit
4f8ebb2e80
4 changed files with 46 additions and 21 deletions
16
affine.scad
16
affine.scad
|
@ -142,6 +142,9 @@ function affine3d_to_2d(m) =
|
|||
// Applies the specified transformation matrix to a point, pointlist, bezier patch or VNF.
|
||||
// Both inputs can be 2D or 3D, and it is also allowed to supply 3D transformations with 2D
|
||||
// data as long as the the only action on the z coordinate is a simple scaling.
|
||||
// .
|
||||
// If you construct your own matrices you can also use a transform that acts like a projection
|
||||
// with fewer rows to produce lower dimensional output.
|
||||
// Arguments:
|
||||
// transform = The 2D or 3D transformation matrix to apply to the point/points.
|
||||
// points = The point, pointlist, bezier patch, or VNF to apply the transformation to.
|
||||
|
@ -173,14 +176,15 @@ function apply(transform,points) =
|
|||
? /* BezPatch */ [for (x=points) apply(transform,x)] :
|
||||
let(
|
||||
tdim = len(transform[0])-1,
|
||||
datadim = len(points[0])
|
||||
datadim = len(points[0]),
|
||||
outdim = min(datadim,len(transform)),
|
||||
matrix = [for(i=[0:1:tdim]) [for(j=[0:1:outdim-1]) transform[j][i]]]
|
||||
)
|
||||
tdim == 3 && datadim == 3 ? [for(p=points) point3d(transform*concat(p,[1]))] :
|
||||
tdim == 2 && datadim == 2 ? [for(p=points) point2d(transform*concat(p,[1]))] :
|
||||
tdim == 3 && datadim == 2 ?
|
||||
tdim==datadim && (datadim==3 || datadim==2) ? [for(p=points) concat(p,1)] * matrix
|
||||
: tdim == 3 && datadim == 2 ?
|
||||
assert(is_2d_transform(transform), str("Transforms is 3d but points are 2d"))
|
||||
[for(p=points) point2d(transform*concat(p,[0,1]))] :
|
||||
assert(false, str("Unsupported combination: transform with dimension ",tdim,", data of dimension ",datadim));
|
||||
[for(p=points) concat(p,[0,1])]*matrix
|
||||
: assert(false, str("Unsupported combination: transform with dimension ",tdim,", data of dimension ",datadim));
|
||||
|
||||
|
||||
// Function: rot_decode()
|
||||
|
|
|
@ -654,11 +654,24 @@ function polygon_line_intersection(poly, line, bounded=false, nonzero=false, eps
|
|||
boundedline = [line[0] + (bounded[0]? 0 : -bound) * linevec,
|
||||
line[1] + (bounded[1]? 0 : bound) * linevec],
|
||||
parts = split_path_at_region_crossings(boundedline, [poly], closed=false),
|
||||
inside = [for (part = parts)
|
||||
if (point_in_polygon(mean(part), poly,nonzero=nonzero,eps=eps)>=0) part
|
||||
inside = [
|
||||
if(point_in_polygon(parts[0][0], poly, nonzero=nonzero, eps=eps) == 0)
|
||||
[parts[0][0]], // Add starting point if it is on the polygon
|
||||
for(part = parts)
|
||||
if (point_in_polygon(mean(part), poly, nonzero=nonzero, eps=eps) >=0 )
|
||||
part
|
||||
else if(len(part)==2 && point_in_polygon(part[1], poly, nonzero=nonzero, eps=eps) == 0)
|
||||
[part[1]] // Add segment end if it is on the polygon
|
||||
]
|
||||
)
|
||||
len(inside)==0? undef : _merge_segments(inside, [inside[0]], eps)
|
||||
(
|
||||
len(inside)==0 ? undef :
|
||||
let(
|
||||
seglist = [for (entry=_merge_segments(inside, [inside[0]], eps))
|
||||
same_shape(entry,[[0,0]]) ? entry[0]:entry]
|
||||
)
|
||||
len(seglist)==1 && is_vector(seglist[0]) ? seglist[0] : seglist
|
||||
)
|
||||
: // 3d case
|
||||
let(indices = noncollinear_triple(poly))
|
||||
indices==[] ? undef : // Polygon is collinear
|
||||
|
@ -681,13 +694,14 @@ function polygon_line_intersection(poly, line, bounded=false, nonzero=false, eps
|
|||
)
|
||||
segments==undef ? undef : [for(seg=segments) lift_plane(plane,seg)];
|
||||
|
||||
|
||||
function _merge_segments(insegs,outsegs, eps, i=1) = //let(f=echo(insegs=insegs, outsegs=outsegs,lo=last(outsegs[1]), fi=insegs[i][0]))
|
||||
function _merge_segments(insegs,outsegs, eps, i=1) =
|
||||
i==len(insegs) ? outsegs :
|
||||
approx(last(outsegs)[1], insegs[i][0], eps) ? _merge_segments(insegs, [each list_head(outsegs),[last(outsegs)[0],insegs[i][1]]], eps, i+1)
|
||||
approx(last(last(outsegs)), insegs[i][0], eps)
|
||||
? _merge_segments(insegs, [each list_head(outsegs),[last(outsegs)[0],last(insegs[i])]], eps, i+1)
|
||||
: _merge_segments(insegs, [each outsegs, insegs[i]], eps, i+1);
|
||||
|
||||
|
||||
|
||||
// Function: plane_intersection()
|
||||
// Usage:
|
||||
// line = plane_intersection(plane1, plane2)
|
||||
|
@ -1443,10 +1457,10 @@ function point_in_polygon(point, poly, nonzero=false, eps=EPSILON) =
|
|||
) 2*(len(cross)%2)-1;
|
||||
|
||||
|
||||
// Function: polygon_triangulation(poly, [ind], [eps])
|
||||
// Function: polygon_triangulate(poly, [ind], [eps])
|
||||
// Usage:
|
||||
// triangles = polygon_triangulation(poly)
|
||||
// triangles = polygon_triangulation(poly, ind)
|
||||
// triangles = polygon_triangulate(poly)
|
||||
// triangles = polygon_triangulate(poly, ind)
|
||||
// Description:
|
||||
// Given a simple polygon in 2D or 3D, triangulates it and returns a list
|
||||
// of triples indexing into the polygon vertices. When the optional argument `ind` is
|
||||
|
@ -1467,7 +1481,7 @@ function point_in_polygon(point, poly, nonzero=false, eps=EPSILON) =
|
|||
// eps = A maximum tolerance in geometrical tests. Default: EPSILON
|
||||
// Example:
|
||||
// poly = star(id=10, od=15,n=11);
|
||||
// tris = polygon_triangulation(poly);
|
||||
// tris = polygon_triangulate(poly);
|
||||
// polygon(poly);
|
||||
// up(1)
|
||||
// color("blue");
|
||||
|
@ -1477,11 +1491,11 @@ function point_in_polygon(point, poly, nonzero=false, eps=EPSILON) =
|
|||
// include<BOSL2/polyhedra.scad>
|
||||
// vnf = regular_polyhedron_info(name="dodecahedron",side=5,info="vnf");
|
||||
// %vnf_polyhedron(vnf);
|
||||
// vnf_tri = [vnf[0], [for(face=vnf[1]) each polygon_triangulation(vnf[0], face) ] ];
|
||||
// vnf_tri = [vnf[0], [for(face=vnf[1]) each polygon_triangulate(vnf[0], face) ] ];
|
||||
// color("blue")
|
||||
// vnf_wireframe(vnf_tri, d=.15);
|
||||
|
||||
function polygon_triangulation(poly, ind, eps=EPSILON) =
|
||||
function polygon_triangulate(poly, ind, eps=EPSILON) =
|
||||
assert(is_path(poly), "Polygon `poly` should be a list of 2d or 3d points")
|
||||
assert(is_undef(ind)
|
||||
|| (is_vector(ind) && min(ind)>=0 && max(ind)<len(poly) ),
|
||||
|
|
|
@ -1563,7 +1563,9 @@ function star(n, r, ir, d, or, od, id, step, realign=false, align_tip, align_pit
|
|||
)
|
||||
assert(is_def(n), "Must specify number of points, n")
|
||||
assert(count==1, "Must specify exactly one of ir, id, step")
|
||||
assert(stepOK, str("Parameter 'step' must be between 2 and ",floor(n/2-1/2)," for ",n," point star"))
|
||||
assert(stepOK, n==4 ? "Parameter 'step' not allowed for 4 point stars"
|
||||
: n==5 || n==6 ? str("Parameter 'step' must be 2 for ",n," point stars")
|
||||
: str("Parameter 'step' must be between 2 and ",floor(n/2-1/2)," for ",n," point stars"))
|
||||
let(
|
||||
mat = !is_undef(_mat) ? _mat :
|
||||
( realign? rot(-180/n, planar=true) : affine2d_identity() ) * (
|
||||
|
|
7
vnf.scad
7
vnf.scad
|
@ -211,7 +211,7 @@ function vnf_triangulate(vnf) =
|
|||
let(
|
||||
vnf = is_vnf_list(vnf)? vnf_merge(vnf) : vnf,
|
||||
verts = vnf[0],
|
||||
faces = [for (face=vnf[1]) polygon_triangulation(verts, face)]
|
||||
faces = [for (face=vnf[1]) each polygon_triangulate(verts, face)]
|
||||
) [verts, faces];
|
||||
|
||||
|
||||
|
@ -546,6 +546,11 @@ function vnf_volume(vnf) =
|
|||
])/6;
|
||||
|
||||
|
||||
function vnf_area(vnf) =
|
||||
let(verts=vnf[0])
|
||||
sum([for(face=vnf[1]) polygon_area(select(verts,face))]);
|
||||
|
||||
|
||||
// Function: vnf_centroid()
|
||||
// Usage:
|
||||
// vol = vnf_centroid(vnf);
|
||||
|
|
Loading…
Reference in a new issue