mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-01 09:49:45 +00:00
find_first_match()
This commit is contained in:
parent
fd8319e0f4
commit
475602329d
2 changed files with 95 additions and 58 deletions
25
arrays.scad
25
arrays.scad
|
@ -221,6 +221,31 @@ function in_list(val,list,idx) =
|
||||||
: val==list[s][idx];
|
: val==list[s][idx];
|
||||||
|
|
||||||
|
|
||||||
|
// Function: find_first_match()
|
||||||
|
// Topics: List Handling
|
||||||
|
// See Also: in_list()
|
||||||
|
// Usage:
|
||||||
|
// idx = find_first_match(val, list, <start=>, <eps=>);
|
||||||
|
// indices = find_first_match(val, list, all=true, <start=>, <eps=>);
|
||||||
|
// Description:
|
||||||
|
// Finds the first item in `list` that matches `val`, returning the index.
|
||||||
|
// Arguments:
|
||||||
|
// val = The value to search for.
|
||||||
|
// list = The list to search through.
|
||||||
|
// ---
|
||||||
|
// start = The index to start searching from.
|
||||||
|
// all = If true, returns a list of all matching item indices.
|
||||||
|
// eps = The maximum allowed floating point rounding error for numeric comparisons.
|
||||||
|
function find_first_match(val, list, start=0, all=false, eps=EPSILON) =
|
||||||
|
all? [for (i=[start:1:len(list)-1]) if(val==list[i] || approx(val, list[i], eps=eps)) i] :
|
||||||
|
__find_first_match(val, list, eps=eps, i=start);
|
||||||
|
|
||||||
|
function __find_first_match(val, list, eps, i=0) =
|
||||||
|
i >= len(list)? undef :
|
||||||
|
approx(val, list[i], eps=eps)? i :
|
||||||
|
__find_first_match(val, list, eps=eps, i=i+1);
|
||||||
|
|
||||||
|
|
||||||
// Function: min_index()
|
// Function: min_index()
|
||||||
// Usage:
|
// Usage:
|
||||||
// idx = min_index(vals);
|
// idx = min_index(vals);
|
||||||
|
|
128
regions.scad
128
regions.scad
|
@ -121,6 +121,76 @@ function point_in_region(point, region, eps=EPSILON, _i=0, _cnt=0) =
|
||||||
) pip==0? 0 : point_in_region(point, region, eps=eps, _i=_i+1, _cnt = _cnt + (pip>0? 1 : 0));
|
) pip==0? 0 : point_in_region(point, region, eps=eps, _i=_i+1, _cnt = _cnt + (pip>0? 1 : 0));
|
||||||
|
|
||||||
|
|
||||||
|
// Function: polygons_equal()
|
||||||
|
// Usage:
|
||||||
|
// b = polygons_equal(poly1, poly2, <eps>)
|
||||||
|
// Description:
|
||||||
|
// Returns true if the components of region1 and region2 are the same polygons
|
||||||
|
// within given epsilon tolerance.
|
||||||
|
// Arguments:
|
||||||
|
// poly1 = first polygon
|
||||||
|
// poly2 = second polygon
|
||||||
|
// eps = tolerance for comparison
|
||||||
|
// Example(NORENDER):
|
||||||
|
// polygons_equal(pentagon(r=4),
|
||||||
|
// rot(360/5, p=pentagon(r=4))); // returns true
|
||||||
|
// polygons_equal(pentagon(r=4),
|
||||||
|
// rot(90, p=pentagon(r=4))); // returns false
|
||||||
|
function polygons_equal(poly1, poly2, eps=EPSILON) =
|
||||||
|
let(
|
||||||
|
poly1 = cleanup_path(poly1),
|
||||||
|
poly2 = cleanup_path(poly2),
|
||||||
|
l1 = len(poly1),
|
||||||
|
l2 = len(poly2)
|
||||||
|
) l1 != l2 ? false :
|
||||||
|
let( maybes = find_first_match(poly1[0], poly2, eps=eps, all=true) )
|
||||||
|
maybes == []? false :
|
||||||
|
[for (i=maybes) if (__polygons_equal(poly1, poly2, eps, i)) 1] != [];
|
||||||
|
|
||||||
|
function __polygons_equal(poly1, poly2, eps, st) =
|
||||||
|
max([for(d=poly1-select(poly2,st,st-1)) d*d])<eps*eps;
|
||||||
|
|
||||||
|
|
||||||
|
// Function: poly_in_polygons()
|
||||||
|
// Topics: Polygons, Comparators
|
||||||
|
// See Also: polygons_equal(), regions_equal()
|
||||||
|
// Usage:
|
||||||
|
// bool = poly_in_polygons(poly, polys);
|
||||||
|
// Description:
|
||||||
|
// Returns true if one of the polygons in `polys` is equivalent to the polygon `poly`.
|
||||||
|
// Arguments:
|
||||||
|
// poly = The polygon to search for.
|
||||||
|
// polys = The list of polygons to look for the polygon in.
|
||||||
|
function poly_in_polygons(poly, polys) =
|
||||||
|
__poly_in_polygons(poly, polys, 0);
|
||||||
|
|
||||||
|
function __poly_in_polygons(poly, polys, i) =
|
||||||
|
i >= len(polys)? false :
|
||||||
|
polygons_equal(poly, polys[i])? true :
|
||||||
|
__poly_in_polygons(poly, polys, i+1);
|
||||||
|
|
||||||
|
|
||||||
|
// Function: regions_equal()
|
||||||
|
// Usage:
|
||||||
|
// b = regions_equal(region1, region2, <eps>)
|
||||||
|
// Description:
|
||||||
|
// Returns true if the components of region1 and region2 are the same polygons
|
||||||
|
// within given epsilon tolerance.
|
||||||
|
// Arguments:
|
||||||
|
// poly1 = first polygon
|
||||||
|
// poly2 = second polygon
|
||||||
|
// eps = tolerance for comparison
|
||||||
|
function regions_equal(region1, region2) =
|
||||||
|
assert(is_region(region1) && is_region(region2))
|
||||||
|
len(region1) != len(region2)? false :
|
||||||
|
__regions_equal(region1, region2, 0);
|
||||||
|
|
||||||
|
function __regions_equal(region1, region2, i) =
|
||||||
|
i >= len(region1)? true :
|
||||||
|
!poly_in_polygons(region1[i], region2)? false :
|
||||||
|
__regions_equal(region1, region2, i+1);
|
||||||
|
|
||||||
|
|
||||||
// Function: region_path_crossings()
|
// Function: region_path_crossings()
|
||||||
// Usage:
|
// Usage:
|
||||||
// region_path_crossings(path, region);
|
// region_path_crossings(path, region);
|
||||||
|
@ -222,64 +292,6 @@ function split_nested_region(region) =
|
||||||
) outs;
|
) outs;
|
||||||
|
|
||||||
|
|
||||||
function find_first_approx(val, list, start=0, all=false, eps=EPSILON) =
|
|
||||||
all? [for (i=[start:1:len(list)-1]) if(approx(val, list[i], eps=eps)) i] :
|
|
||||||
__find_first_approx(val, list, eps=eps, i=start);
|
|
||||||
|
|
||||||
function __find_first_approx(val, list, eps, i=0) =
|
|
||||||
i >= len(list)? undef :
|
|
||||||
approx(val, list[i], eps=eps)? i :
|
|
||||||
__find_first_approx(val, list, eps=eps, i=i+1);
|
|
||||||
|
|
||||||
|
|
||||||
// Function: polygons_equal()
|
|
||||||
// Usage:
|
|
||||||
// b = polygons_equal(poly1, poly2, <eps>)
|
|
||||||
// Description:
|
|
||||||
// Returns true if the components of region1 and region2 are the same polygons
|
|
||||||
// within given epsilon tolerance.
|
|
||||||
// Arguments:
|
|
||||||
// poly1 = first polygon
|
|
||||||
// poly2 = second polygon
|
|
||||||
// eps = tolerance for comparison
|
|
||||||
// Example(NORENDER):
|
|
||||||
// polygons_equal(pentagon(r=4),
|
|
||||||
// rot(360/5, p=pentagon(r=4))); // returns true
|
|
||||||
// polygons_equal(pentagon(r=4),
|
|
||||||
// rot(90, p=pentagon(r=4))); // returns false
|
|
||||||
function polygons_equal(poly1, poly2, eps=EPSILON) =
|
|
||||||
let( l1 = len(poly1), l2 = len(poly2))
|
|
||||||
l1 != l2 ? false :
|
|
||||||
let( maybes = find_first_approx(poly1[0], poly2, eps=eps, all=true) )
|
|
||||||
maybes == []? false :
|
|
||||||
[for (i=maybes) if (__polygons_equal(poly1, poly2, eps, i)) 1] != [];
|
|
||||||
|
|
||||||
function __polygons_equal(poly1, poly2, eps, st) =
|
|
||||||
max([for(d=poly1-select(poly2,st,st-1)) d*d])<eps*eps;
|
|
||||||
|
|
||||||
// Function: regions_equal()
|
|
||||||
// Usage:
|
|
||||||
// b = regions_equal(region1, region2, <eps>)
|
|
||||||
// Description:
|
|
||||||
// Returns true if the components of region1 and region2 are the same polygons
|
|
||||||
// within given epsilon tolerance.
|
|
||||||
// Arguments:
|
|
||||||
// poly1 = first polygon
|
|
||||||
// poly2 = second polygon
|
|
||||||
// eps = tolerance for comparison
|
|
||||||
function regions_equal(region1, region2) =
|
|
||||||
assert(is_region(region1) && is_region(region2))
|
|
||||||
len(region1)==len(region2) &&
|
|
||||||
[
|
|
||||||
for (a=region1)
|
|
||||||
if (1!=sum(
|
|
||||||
[for(b=region2)
|
|
||||||
if (polygons_equal(path3d(a), path3d(b)))
|
|
||||||
1]
|
|
||||||
)
|
|
||||||
) 1
|
|
||||||
] == [];
|
|
||||||
|
|
||||||
|
|
||||||
// Section: Region Extrusion and VNFs
|
// Section: Region Extrusion and VNFs
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue