mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-29 00:09:41 +00:00
Fix path_normals to handle 2d and better error message.
Improve error message for bogus endcaps to stroke() and running unit() on a zero vector
This commit is contained in:
parent
029cbb8997
commit
1627c3409d
3 changed files with 26 additions and 15 deletions
36
paths.scad
36
paths.scad
|
@ -351,22 +351,32 @@ function path_tangents(path, closed=false, uniform=true) =
|
|||
// norms = path_normals(path, <tangents>, <closed>);
|
||||
// Description:
|
||||
// Compute the normal vector to the input path. This vector is perpendicular to the
|
||||
// path tangent and lies in the plane of the curve. When there are collinear points,
|
||||
// the curve does not define a unique plane and the normal is not uniquely defined.
|
||||
// path tangent and lies in the plane of the curve. For 3d paths we define the plane of the curve
|
||||
// at path point i to be the plane defined by point i and its two neighbors. At the endpoints of open paths
|
||||
// we use the three end points. The computed normal is the one lying in this plane and pointing to the
|
||||
// right of the direction of the path. If points are collinear then the path does not define a unique plane
|
||||
// and hence the (right pointing) normal is not uniquely defined. In this case the function issues an error.
|
||||
// For 2d paths the plane is always defined so the normal fails to exist only
|
||||
// when the derivative is zero (in the case of repeated points).
|
||||
function path_normals(path, tangents, closed=false) =
|
||||
assert(is_path(path))
|
||||
assert(is_path(path,[2,3]))
|
||||
assert(is_bool(closed))
|
||||
let( tangents = default(tangents, path_tangents(path,closed)) )
|
||||
assert(is_path(tangents))
|
||||
let(
|
||||
tangents = default(tangents, path_tangents(path,closed)),
|
||||
dim=len(path[0])
|
||||
)
|
||||
assert(is_path(tangents) && len(tangents[0])==dim,"Dimensions of path and tangents must match")
|
||||
[
|
||||
for(i=idx(path)) let(
|
||||
pts = i==0? (closed? select(path,-1,1) : select(path,0,2)) :
|
||||
i==len(path)-1? (closed? select(path,i-1,i+1) : select(path,i-2,i)) :
|
||||
select(path,i-1,i+1)
|
||||
) unit(cross(
|
||||
cross(pts[1]-pts[0], pts[2]-pts[0]),
|
||||
tangents[i]
|
||||
))
|
||||
for(i=idx(path))
|
||||
let(
|
||||
pts = i==0 ? (closed? select(path,-1,1) : select(path,0,2))
|
||||
: i==len(path)-1 ? (closed? select(path,i-1,i+1) : select(path,i-2,i))
|
||||
: select(path,i-1,i+1)
|
||||
)
|
||||
dim == 2 ? [tangents[i].y,-tangents[i].x]
|
||||
: let(v=cross(cross(pts[1]-pts[0], pts[2]-pts[0]),tangents[i]))
|
||||
assert(norm(v)>EPSILON, "3D path contains collinear points")
|
||||
v
|
||||
];
|
||||
|
||||
|
||||
|
|
|
@ -108,7 +108,8 @@ module stroke(
|
|||
cap=="tail"? [[0,0], [w/2,l2], [w/2,l2-l], [0,-l], [-w/2,l2-l], [-w/2,l2]] :
|
||||
cap=="tail2"? [[w/2,0], [w/2,-l], [0,-l-l2], [-w/2,-l], [-w/2,0]] :
|
||||
is_path(cap)? cap :
|
||||
[]
|
||||
is_undef(cap)? [] :
|
||||
assert(false, str("Invalid endcap: ",cap))
|
||||
) * linewidth;
|
||||
|
||||
assert(is_bool(closed));
|
||||
|
|
|
@ -128,7 +128,7 @@ function vceil(v) =
|
|||
// unit([0,0,0]); // Asserts an error.
|
||||
function unit(v, error=[[["ASSERT"]]]) =
|
||||
assert(is_vector(v), str("Expected a vector. Got: ",v))
|
||||
norm(v)<EPSILON? (error==[[["ASSERT"]]]? assert(norm(v)>=EPSILON) : error) :
|
||||
norm(v)<EPSILON? (error==[[["ASSERT"]]]? assert(norm(v)>=EPSILON,"Tried to normalize a zero vector") : error) :
|
||||
v/norm(v);
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue