diff --git a/geometry.scad b/geometry.scad index 189d129..531a370 100644 --- a/geometry.scad +++ b/geometry.scad @@ -102,7 +102,6 @@ function distance_from_line(line, pt) = norm(d - ((d * n) * n)); - // Function: line_normal() // Usage: // line_normal([P1,P2]) @@ -186,6 +185,39 @@ function line_segment_intersection(line,segment,eps=EPSILON) = ) isect[2]<0-eps || isect[2]>1+eps ? undef : isect[0]; +// Function: line_closest_point() +// Usage: +// line_closest_point(line,pt); +// Description: +// Returns the point on the given `line` that is closest to the given point `pt`. +// Arguments: +// line = A list of two points that are on the unbounded line. +// pt = The point to find the closest point on the line to. +function line_closest_point(line,pt) = + let( + n = line_normal(line), + isect = _general_line_intersection(line,[pt,pt+n]) + ) isect[0]; + + +// Function: segment_closest_point() +// Usage: +// segment_closest_point(seg,pt); +// Description: +// Returns the point on the given line segment `seg` that is closest to the given point `pt`. +// Arguments: +// seg = A list of two points that are the endpoints of the bounded line segment. +// pt = The point to find the closest point on the segment to. +function segment_closest_point(seg,pt) = + let( + n = line_normal(seg), + isect = _general_line_intersection(seg,[pt,pt+n]) + ) + isect[1]<=0? seg[0] : + isect[1]>=1? seg[1] : + isect[0]; + + // Function: find_circle_2tangents() // Usage: // find_circle_2tangents(pt1, pt2, pt3, r|d); diff --git a/paths.scad b/paths.scad index cbe5877..9966369 100644 --- a/paths.scad +++ b/paths.scad @@ -52,6 +52,31 @@ function path_length(path,closed=false) = sum([for (i = [0:1:len(path)-2]) norm(path[i+1]-path[i])])+(closed?norm(path[len(path)-1]-path[0]):0); +// Function: path_closest_point() +// Usage: +// path_closest_point(path, pt); +// Description: +// Finds the closest path segment, and point on that segment to the given point. +// Returns `[SEGNUM, POINT]` +// Arguments: +// path = The path to find the closest point on. +// pt = the point to find the closest point to. +// Example(2D): +// path = circle(d=100,$fn=6); +// pt = [20,10]; +// closest = path_closest_point(path, pt); +// stroke(path, closed=true); +// color("blue") translate(pt) circle(d=3, $fn=12); +// color("red") translate(closest[1]) circle(d=3, $fn=12); +function path_closest_point(path, pt) = + let( + pts = [for (seg=idx(path)) segment_closest_point(select(path,seg,seg+1),pt)], + dists = [for (p=pts) norm(p-pt)], + min_seg = min_index(dists) + ) [min_seg, pts[min_seg]]; + + + // Function: path3d_spiral() // Description: // Returns a 3D spiral path.