diff --git a/drawing.scad b/drawing.scad index 15b12687..e850c9c0 100644 --- a/drawing.scad +++ b/drawing.scad @@ -360,7 +360,7 @@ module stroke( translate(path[0]) { $fn = segs(width[0]/2); if (is_undef(endcap_angle1)) { - rotate_extrude(convexity=convexity) { + rotate_extrude(convexity=convexity,angle=360) { right_half(planar=true) { polygon(endcap_shape1); } diff --git a/geometry.scad b/geometry.scad index 0307f02a..e9352f03 100644 --- a/geometry.scad +++ b/geometry.scad @@ -1784,27 +1784,28 @@ function point_in_polygon(point, poly, nonzero=false, eps=_EPSILON) = // Topics: Geometry, Polygons, Lines, Intersection // See Also: polygon_area(), centroid(), polygon_normal(), point_in_polygon(), polygon_line_intersection() // Usage: -// pt = polygon_line_intersection(poly, line, [bounded], [nonzero], [eps]); +// pt_or_segments = polygon_line_intersection(poly, line, [bounded], [nonzero], [eps]); // Description: -// Takes a possibly bounded line, and a 2D or 3D planar polygon, and finds their intersection. Note the polygon is -// treated as its boundary and interior, so the intersection may include both points and line segments. -// If the line does not intersect the polygon then returns `undef`. -// In 3D if the line is not on the plane of the polygon but intersects it then you get a single intersection point. -// Otherwise the polygon and line are in the same plane, or when your input is 2D, you get a list of segments and -// single point lists. Use `is_vector` to distinguish these two cases. +// Takes a possibly bounded line, and a 2D or 3D planar polygon, and finds their intersection. The polygon is +// treated as its boundary and interior, so the intersection may include both points and line segments. +// Returns: +// * If the line does not intersect the polygon: `undef`. +// * In 3D if the line is not coplanar with the polygon but intersects it: the intersection point as a 3-vector, `[x,y,z]`. +// * In the 2D case or the 3D case when the line is coplanar with the polygon: list of segments or degenerate single point "segments". // . -// In the 2D case, a common result is a list containing a single segment, which lists the two intersection points -// with the boundary of the polygon. -// When single points are in the intersection (the line just touches a polygon corner) they appear on the segment -// list as lists of a single point -// (like single point segments) so a single point intersection in 2D has the form `[[[x,y,z]]]` as compared -// to a single point intersection in 3D, which has the form `[x,y,z]`. You can identify whether an entry in the -// segment list is a true segment by checking its length, which is 2 for a segment and 1 for a point. +// In 3D, you can distinguish output cases using {{is_vector()}}. When run on the output it returns `true` when the output is a single +// intersection point from a non-coplanar line. +// . +// In the 2D or coplanar case, the result is a **list** of segments, so the common case of a single segment will be a +// singleton list of the form `[[p1,p2]]`. A single point appears on the segment list as a degenerate segment or the form `[p]`, +// so this means in 3D a single point will appears as `[[[x,y,z]]]` in the coplanar case. This makes it possible to distinguish +// the coplanar and non-coplanar cases. An intersection featuring two segments and a point could look like `[[p1,p2], [q], [r1,r2]]`. +// To determine if an entry in the segment list is a true segment, check its length, which is 2 for a segment and 1 for a point. // Arguments: // poly = The 3D planar polygon to find the intersection with. // line = A list of two distinct 3D points on the line. // bounded = If false, the line is considered unbounded. If true, it is treated as a bounded line segment. If given as `[true, false]` or `[false, true]`, the boundedness of the points are specified individually, allowing the line to be treated as a half-bounded ray. Default: false (unbounded) -// nonzero = set to true to use the nonzero rule for determining it points are in a polygon. See point_in_polygon. Default: false. +// nonzero = set to true to use the nonzero rule for determining it points are in a polygon. See {{point_in_polygon()}}. Default: false. // eps = Tolerance in geometric comparisons. Default: 1e-9 // Example(3D): The line intersects the 3d hexagon in a single point. // hex = zrot(140,p=rot([-45,40,20],p=path3d(hexagon(r=15)))); diff --git a/rounding.scad b/rounding.scad index 8e371b75..ebd4e849 100644 --- a/rounding.scad +++ b/rounding.scad @@ -5045,9 +5045,37 @@ module prism_connector(profile, desc1, anchor1, desc2, anchor2, shift1, shift2, // joint = 3; // rounded_prism(rect(12), rect(8), h=15, joint_sides=joint,atype="prismoid") // attach_prism(circle(r=3,$fn=128),RIGHT+FWD, length=4, fillet=2, edge_joint=joint, $fn=32); - - - +// Example(3D,Big): Complicated example where we use attach_prism() to create attachments and then connect a bezier sweep to those attachments using descriptions. The blue line segments show the bezier control points. Note that we use {{bezier_sweep()}} rather than {{path_sweep()}} to ensure that the ends of the sweep mate properly, and setting `last_normal` ensures that the points on the attached prisms line up with the sweep. +// sq = subdivide_path(circle(r=3,$fn=7),maxlen=.5); +// vspace=20; +// bezlen=40; +// cylr=20; +// cylh=65; +// straightlen=5; +// smoothcurve=true; // true for C2 joint +// k=0.6; +// cyl(r=cylr,h=cylh, rounding=2, circum=true, $fn=256) +// let(cylinder=parent()) +// attach_prism(sq,FWD,length=straightlen,shift=-vspace,fillet=2,spin=90) +// let(front=parent()) +// restore(cylinder) +// attach_prism(sq, RIGHT, length=straightlen, shift=vspace, fillet=2,spin=90) +// let(right=parent()) +// restore(cylinder) +// let(avg_dir = desc_dir(front,anchor="end") + desc_dir(right,anchor="end"), +// path=[ +// desc_point(front,anchor="end"), +// if (smoothcurve) desc_point(front,anchor="end")+bezlen*(1-k)*desc_dir(front,anchor="end"), +// desc_point(front,anchor="end")+bezlen*desc_dir(front,anchor="end"), +// down(vspace/2,desc_point(cylinder,CTR)+ (cylr+straightlen+bezlen)*avg_dir), +// desc_point(right,anchor="end")+bezlen*desc_dir(right,anchor="end"), +// if (smoothcurve) desc_point(right,anchor="end")+bezlen*(1-k)*desc_dir(right,anchor="end"), +// desc_point(right,anchor="end")] +// ) +// { +// bezier_sweep(zrot(90,sq), path, 40, last_normal=UP); +// color("lightblue")stroke(path); +// } module attach_prism(profile, anchor, fillet=0, rounding=0, inside=false, l, length, h, height, endpoint, T=IDENT, shift=0, overlap=1,