From 835db1717e9ab45b8e21f0621557d5275bcc4115 Mon Sep 17 00:00:00 2001 From: Justin Lin Date: Thu, 4 Mar 2021 08:33:00 +0800 Subject: [PATCH] lines_intersection support 3D --- README.md | 4 ++-- docs/lib3x-lines_intersection.md | 8 ++++++-- src/__comm__/__line_intersection.scad | 21 +++++++++++++++++++-- src/_impl/_bijection_offset_impl.scad | 4 ++-- src/_impl/_trim_shape_impl.scad | 2 +- src/lines_intersection.scad | 5 ++--- 6 files changed, 32 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index cbdc0158..2ca086a1 100644 --- a/README.md +++ b/README.md @@ -76,8 +76,7 @@ These examples incubate dotSCAD and dotSCAD refactors these examples. See [examp ### 2D Function - [bijection_offset](https://openhome.cc/eGossip/OpenSCAD/lib3x-bijection_offset.html) - [contours](https://openhome.cc/eGossip/OpenSCAD/lib3x-contours.html) -- [in_shape](https://openhome.cc/eGossip/OpenSCAD/lib3x-in_shape.html) -- [lines_intersection](https://openhome.cc/eGossip/OpenSCAD/lib3x-lines_intersection.html) +- [in_shape](https://openhome.cc/eGossip/OpenSCAD/lib3x-in_shape.html) - [trim_shape](https://openhome.cc/eGossip/OpenSCAD/lib3x-trim_shape.html) ### 2D/3D Function @@ -86,6 +85,7 @@ These examples incubate dotSCAD and dotSCAD refactors these examples. See [examp - [bezier_smooth](https://openhome.cc/eGossip/OpenSCAD/lib3x-bezier_smooth.html) - [cross_sections](https://openhome.cc/eGossip/OpenSCAD/lib3x-cross_sections.html) - [in_polyline](https://openhome.cc/eGossip/OpenSCAD/lib3x-in_polyline.html) +- [lines_intersection](https://openhome.cc/eGossip/OpenSCAD/lib3x-lines_intersection.html) - [paths2sections](https://openhome.cc/eGossip/OpenSCAD/lib3x-paths2sections.html) - [path_scaling_sections](https://openhome.cc/eGossip/OpenSCAD/lib3x-path_scaling_sections.html) - [midpt_smooth](https://openhome.cc/eGossip/OpenSCAD/lib3x-midpt_smooth.html) diff --git a/docs/lib3x-lines_intersection.md b/docs/lib3x-lines_intersection.md index f71d59e7..8307ab77 100644 --- a/docs/lib3x-lines_intersection.md +++ b/docs/lib3x-lines_intersection.md @@ -6,8 +6,8 @@ Find the intersection of two line segments. Return `[]` if lines don't intersect ## Parameters -- `line1` : Two points of 2D line1. -- `line2` : Two points of 2D line2. +- `line1` : Two points of 2D or 3D line1. +- `line2` : Two points of 2D or 3D line2. - `ext` : Default to `false`, which doesn't extend a line to an intersection with another line. - `epsilon` : An upper bound on the relative error due to rounding in floating point arithmetic. Default to 0.0001. @@ -21,3 +21,7 @@ Find the intersection of two line segments. Return `[]` if lines don't intersect assert(lines_intersection(line1, line2) == [0, 2.5]); assert(lines_intersection(line1, line3, ext = true) == [0, 10]); + + line4 = [[0, 0, 0], [10, 10, 10]]; + line5 = [[10, 0, 0], [0, 10, 10]]; + assert(lines_intersection(line4, line5) == [5, 5, 5]); \ No newline at end of file diff --git a/src/__comm__/__line_intersection.scad b/src/__comm__/__line_intersection.scad index 68222d8d..66bf2d22 100644 --- a/src/__comm__/__line_intersection.scad +++ b/src/__comm__/__line_intersection.scad @@ -1,4 +1,4 @@ -function __line_intersection(line_pts1, line_pts2, epsilon = 0.0001) = +function __line_intersection2(line_pts1, line_pts2, epsilon = 0.0001) = let( a1 = line_pts1[0], a2 = line_pts1[1], @@ -10,4 +10,21 @@ function __line_intersection(line_pts1, line_pts2, epsilon = 0.0001) = c = cross(a, b) ) abs(c) < epsilon ? [] : // they are parallel or conincident edges - a1 + a * cross(s, b) / c; \ No newline at end of file + a1 + a * cross(s, b) / c; + +function __line_intersection3(line_pts1, line_pts2, epsilon = 0.0001) = + let( + a1 = line_pts1[0], + a2 = line_pts1[1], + b1 = line_pts2[0], + b2 = line_pts2[1], + a = a2 - a1, + b = b2 - b1, + s = b1 - a1, + n1 = cross(a, b), + norm_n1 = norm(n1) + ) + cross(a, s) * (b2 - a1) != 0 || // they aren't coplanar + norm_n1 < epsilon ? [] : // they are parallel or conincident edges + let(n2 = cross(s, b)) + a1 + a * (norm(n2) / norm_n1 * (n1 * n2 >= 0 ? 1 : -1)); \ No newline at end of file diff --git a/src/_impl/_bijection_offset_impl.scad b/src/_impl/_bijection_offset_impl.scad index 333703dc..e59ce4c1 100644 --- a/src/_impl/_bijection_offset_impl.scad +++ b/src/_impl/_bijection_offset_impl.scad @@ -38,7 +38,7 @@ function _bijection_offset_impl(pts, d, epsilon) = offset_es = _bijection__bijection_offset_edges(es, d), leng = len(offset_es), leng_minus_one = leng - 1, - last_p = __line_intersection(offset_es[leng_minus_one], offset_es[0], epsilon) + last_p = __line_intersection2(offset_es[leng_minus_one], offset_es[0], epsilon) ) concat( last_p != [] && last_p == last_p ? [last_p] : [], @@ -47,7 +47,7 @@ function _bijection_offset_impl(pts, d, epsilon) = let( this_edge = offset_es[i], next_edge = offset_es[i + 1], - p = __line_intersection(this_edge, next_edge, epsilon) + p = __line_intersection2(this_edge, next_edge, epsilon) ) // p == p to avoid [nan, nan], because [nan, nan] != [nan, nan] if(p != [] && p == p) p diff --git a/src/_impl/_trim_shape_impl.scad b/src/_impl/_trim_shape_impl.scad index 48a86de0..d04bf1cb 100644 --- a/src/_impl/_trim_shape_impl.scad +++ b/src/_impl/_trim_shape_impl.scad @@ -4,7 +4,7 @@ use <../__comm__/__lines_from.scad>; function _trim_shape_any_intersection_sub(lines, line, lines_leng, i, epsilon) = let( - p = __line_intersection(lines[i], line, epsilon) + p = __line_intersection2(lines[i], line, epsilon) ) (p != [] && __in_line(line, p, epsilon) && __in_line(lines[i], p, epsilon)) ? [i, p] : _trim_shape_any_intersection(lines, line, lines_leng, i + 1, epsilon); diff --git a/src/lines_intersection.scad b/src/lines_intersection.scad index d28021a7..7b42c57b 100644 --- a/src/lines_intersection.scad +++ b/src/lines_intersection.scad @@ -12,8 +12,7 @@ use <__comm__/__line_intersection.scad>; use <__comm__/__in_line.scad>; function lines_intersection(line1, line2, ext = false, epsilon = 0.0001) = - let( - pt = __line_intersection(line1, line2, epsilon) - ) + let(pt = len(line1[0]) == 2 ? __line_intersection2(line1, line2, epsilon) : + __line_intersection3(line1, line2, epsilon)) ext ? pt : pt != [] && __in_line(line1, pt, epsilon) && __in_line(line2, pt, epsilon) ? pt : []; \ No newline at end of file