From efde869e63754336806f7fcf90e2149905b3efd1 Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Fri, 30 Jun 2023 16:01:19 -0400 Subject: [PATCH 1/3] Note that diff, intersect and conv_hull invoke children repeatedly --- attachments.scad | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/attachments.scad b/attachments.scad index 412c8c7..d685fb2 100644 --- a/attachments.scad +++ b/attachments.scad @@ -940,7 +940,9 @@ module tag_scope(scope){ // subtracted from it, no matter where it appears because kept objects are unioned in at the end. // If you want a child of an object tagged with a remove tag to stay in the model it may be // better to give it a tag that is not a remove tag or a keep tag. Such an object *will* be subject to -// subtractions from other remove-tagged objects. +// subtractions from other remove-tagged objects. +// . +// Note that `diff()` invokes its children three times. // . // For a step-by-step explanation of attachments, see the [Attachments Tutorial](Tutorial-Attachments). // Arguments: @@ -1196,6 +1198,8 @@ module tag_diff(tag,remove="remove", keep="keep") // unioned with the result. Attachable objects should be tagged using {{tag()}} // and non-attachable objects with {{force_tag()}}. // . +// Note that `intersect()` invokes its children three times. +// . // For a step-by-step explanation of attachments, see the [Attachments Tutorial](Tutorial-Attachments). // Arguments: // intersect = String containing space delimited set of tag names of children to intersect. Default: "intersect" @@ -1313,6 +1317,8 @@ module tag_intersect(tag,intersect="intersect",keep="keep") // not tagged with the `keep` tags are combined into a convex hull, and the children tagged with the keep tags // are unioned with the result. // . +// Note that `conv_hull()` invokes its children twice. +// . // For a step-by-step explanation of attachments, see the [Attachments Tutorial](Tutorial-Attachments). // Arguments: // keep = String containing space delimited set of tag names of children to keep out of the hull. Default: "keep" From 806e4b477d1996a3840c603bb9460139fee05f43 Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Fri, 30 Jun 2023 16:05:55 -0400 Subject: [PATCH 2/3] add rational_approx() --- math.scad | 28 ++++++++++++++++++++++++++++ tests/test_math.scad | 17 +++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/math.scad b/math.scad index 784e42e..889bab8 100644 --- a/math.scad +++ b/math.scad @@ -314,8 +314,36 @@ function lcm(a,b=[]) = assert(len(arglist)>0, "Invalid call to lcm with empty list(s)") _lcmlist(arglist); +// Function rational_approx() +// Usage: +// pq = rational_approx(x, maxq); +// Description: +// Finds the best rational approximation p/q to the number x so that q<=maxq. Returns +// the result as `[p,q]`. If the input is zero, then returns `[0,1]`. +// Example: +// pq1 = rational_approx(PI,10); // Returns: [22,7] +// pq2 = rational_approx(PI,10000); // Returns: [355, 113] +// pq3 = rational_approx(221/323,500); // Returns: [13,19] +// pq4 = rational_approx(0,50); // Returns: [0,1] +function rational_approx(x, maxq, cfrac=[], p, q) = + let( + next = floor(x), + fracpart = x-next, + cfrac = [each cfrac, next], + pq = _cfrac_to_pq(cfrac) + ) + approx(fracpart,0) ? pq + : pq[1]>maxq ? [p,q] + : rational_approx(1/fracpart,maxq,cfrac, pq[0], pq[1]); +// Converts a continued fraction given as a list with leading integer term +// into a fraction in the form p / q, returning [p,q]. +function _cfrac_to_pq(cfrac,p=0,q=1,ind) = + is_undef(ind) ? _cfrac_to_pq(cfrac,p,q,len(cfrac)-1) + : ind==0 ? [p+q*cfrac[0], q] + : _cfrac_to_pq(cfrac, q, cfrac[ind]*q+p, ind-1); + // Section: Hyperbolic Trigonometry diff --git a/tests/test_math.scad b/tests/test_math.scad index a787165..64e59ae 100644 --- a/tests/test_math.scad +++ b/tests/test_math.scad @@ -505,6 +505,23 @@ module test_lcm() { } test_lcm(); +module test_rational_approx() +{ + pq1 = rational_approx(PI,10); // Returns: [22,7] + pq2 = rational_approx(PI,10000); // Returns: [355, 113] + pq3 = rational_approx(221/323,500); // Returns: [13,19] + pq4 = rational_approx(0,50); // Returns: [0,1] + assert_equal(pq1,[22,7]); + assert_equal(pq2,[355,113]); + assert_equal(pq3,[13,19]); + assert_equal(pq4,[0,1]); + assert_equal(rational_approx(-PI,10),[-22,7]); + assert_equal(rational_approx(7,10), [7,1]); +} +test_rational_approx(); + + + module test_complex(){ From ba78c0d062ca261d18c66f542220fd6e0cd65ed0 Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Tue, 4 Jul 2023 11:27:30 -0400 Subject: [PATCH 3/3] fix triangle bug in hull_points() with fast=true --- geometry.scad | 2 ++ 1 file changed, 2 insertions(+) diff --git a/geometry.scad b/geometry.scad index aa5c067..a9f126d 100644 --- a/geometry.scad +++ b/geometry.scad @@ -2387,6 +2387,8 @@ module hull_points(points, fast=false) { attachable(){ if (len(points[0])==2) hull() polygon(points=points); + else if (len(points)==3) + polyhedron(points=points, faces=[[0,1,2]]); else { if (fast) { extra = len(points)%3;