Merge pull request #488 from adrianVmariano/master

endpoint fixes
This commit is contained in:
Revar Desmera 2021-04-02 18:57:08 -07:00 committed by GitHub
commit 0cfd2a2be8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 89 additions and 29 deletions

View file

@ -413,16 +413,17 @@ function bezier_curvature(curve, u) =
// Topics: Bezier Segments
// See Also: bezier_curvature(), bezier_tangent(), bezier_derivative(), bezier_points()
// Description:
// Takes a list of bezier curve control points and generates n points along the bezier path.
// Points start at the first control point and are sampled every `1/n`th
// of the way along the bezier parameter, ending *before* the final control point by default.
// The distance between the points will *not* be equidistant. If you wish to add the
// endpoint you can set `endpoint` to true. The degree of the bezier curve is one
// less than the number of points in `curve`.
// Takes a list of bezier control points and generates n points along the bezier curve they define.
// Points start at the first control point and are sampled uniformly along the bezier parameter.
// The endpoints of the output will be *exactly* equal to the first and last bezier control points
// when endpoint is true. If endpoint is false the sampling stops one step before the final point
// of the bezier curve, but you still get n, more tightly spaced, points.
// The distance between the points will *not* be equidistant.
// The degree of the bezier curve is one less than the number of points in `curve`.
// Arguments:
// curve = The list of endpoints and control points for this bezier segment.
// n = The number of points to generate along the bezier curve.
// endpoint = if true then add the endpoint (an extra point, giving n+1 points output). Default: False
// endpoint = if false then exclude the endpoint. Default: True
// Example(2D): Quadratic (Degree 2) Bezier.
// bez = [[0,0], [30,30], [80,0]];
// move_copies(bezier_curve(bez, 8)) sphere(r=1.5, $fn=12);
@ -435,9 +436,11 @@ function bezier_curvature(curve, u) =
// bez = [[0,0], [5,15], [40,20], [60,-15], [80,0]];
// move_copies(bezier_curve(bez, 8)) sphere(r=1.5, $fn=12);
// trace_bezier(bez, N=len(bez)-1);
function bezier_curve(curve,n,endpoint) = [each bezier_points(curve, [0:1/n:(n-0.5)/n]),
if (endpoint) curve[len(curve)-1]
];
function bezier_curve(curve,n,endpoint=true) =
[
each bezier_points(curve, rangex(endpoint?n-1:n,0,1)),
if (endpoint) last(curve)
];
// Function: bezier_segment_closest_point()
// Usage:

View file

@ -1238,15 +1238,17 @@ module path_extrude(path, convexity=10, clipsize=100) {
module path_spread(path, n, spacing, sp=undef, rotate_children=true, closed=false)
{
length = path_length(path,closed);
distances = is_def(sp)? (
is_def(n) && is_def(spacing)? range(s=sp, step=spacing, n=n) :
is_def(n)? range(s=sp, e=length, n=n) :
range(s=sp, step=spacing, e=length)
) : is_def(n) && is_undef(spacing)? (
closed?
let(range=range(s=0,e=length, n=n+1)) list_head(range) :
range(s=0, e=length, n=n)
) : (
distances =
is_def(sp)? ( // Start point given
is_def(n) && is_def(spacing)? range(s=sp, step=spacing, n=n) :
is_def(n)? range(s=sp, e=length, n=n) :
range(s=sp, step=spacing, e=length)
)
: is_def(n) && is_undef(spacing)? ( // N alone given
closed ? rangex(s=0, e=length, n=n)
: range(s=0, e=length, n=n)
)
: ( // No start point and spacing is given, N maybe given
let(
n = is_def(n)? n : floor(length/spacing)+(closed?0:1),
ptlist = range(s=0,step=spacing,n=n),
@ -1600,13 +1602,17 @@ function resample_path(path, N, spacing, closed=false) =
assert(num_defined([N,spacing])==1,"Must define exactly one of N and spacing")
assert(is_bool(closed))
let(
length = path_length(path,closed),
N = is_def(N) ? N : round(length/spacing) + (closed?0:1),
spacing = length/(closed?N:N-1), // Note: worried about round-off error, so don't include
distlist = range(closed?N:N-1,step=spacing), // last point when closed=false
cuts = path_cut_points(path, distlist, closed=closed)
length = path_length(path,closed),
// In the open path case decrease N by 1 so that we don't try to get
// path_cut to return the endpoint (which might fail due to rounding)
// Add last point later
N = is_def(N) ? N-(closed?0:1) : round(length/spacing),
distlist = rangex(N,e=length),
cuts = path_cut_points(path, distlist, closed=closed)
)
concat(subindex(cuts,0),closed?[]:[last(path)]); // Then add last point here
[ each subindex(cuts,0),
if (!closed) last(path) // Then add last point here
];

View file

@ -346,7 +346,7 @@ function _bezcorner(points, parm) =
] : _smooth_bez_fill(points,parm),
N = max(3,$fn>0 ?$fn : ceil(bezier_segment_length(P)/$fs))
)
bezier_curve(P,N,endpoint=true);
bezier_curve(P,N+1,endpoint=true);
function _chamfcorner(points, parm) =
let(

View file

@ -533,7 +533,7 @@ module dashed_stroke(path, dashpat=[3,3], width=1, closed=false) {
function arc(N, r, angle, d, cp, points, width, thickness, start, wedge=false, long=false, cw=false, ccw=false, endpoint=true) =
assert(is_bool(endpoint))
!endpoint ? assert(!wedge, "endpoint cannot be false if wedge is true")
list_head(arc(N,r,angle,d,cp,points,width,thickness,start,wedge,long,cw,ccw,true)) :
list_head(arc(N+1,r,angle,d,cp,points,width,thickness,start,wedge,long,cw,ccw,true)) :
assert(is_undef(N) || is_integer(N), "Number of points must be an integer")
// First try for 2D arc specified by width and thickness
is_def(width) && is_def(thickness)? (
@ -1875,7 +1875,7 @@ function reuleaux_polygon(N=3, r, d, anchor=CENTER, spin=0) =
sa = ca + 180 + (90/N),
ea = ca + 180 - (90/N),
cp = polar_to_xy(r, ca)
) each arc(N=ssegs, r=slen, cp=cp, angle=[sa,ea], endpoint=false)
) each arc(N=ssegs-1, r=slen, cp=cp, angle=[sa,ea], endpoint=false)
],
anchors = [
for (i = [0:1:N-1]) let(

View file

@ -830,6 +830,15 @@ module test_lcm() {
test_lcm();
module test_complex(){
assert_equal( complex(ident(4)), c_ident(4));
assert_equal( complex(3), [3,0]);
assert_equal( complex([1,2]), [[1,0],[2,0]]);
assert_equal( complex([[1,2],[3,4]]), [[ [1,0],[2,0] ], [ [3,0],[4,0]]]);
}
test_complex();
module test_c_mul() {
assert_equal(c_mul([4,5],[9,-4]), [56,29]);
assert_equal(c_mul([-7,2],[24,3]), [-174, 27]);

42
tests/test_rounding.scad Normal file
View file

@ -0,0 +1,42 @@
include <../std.scad>
include <../rounding.scad>
module test_round_corners() {
test1 = turtle(["move", 10, "move", 10, "left", 30, "move", 17, "left", 155, "move", 10, "right", 90, "move", 10,"left", 90, "move", 30]);
test2 = turtle(["move", 20, "left", 30, "move", 17, "left", 155, "move", 10, "right", 90, "move", 10,"left", 90, "move", 30]);
assert_approx(round_corners(test2, cut=.5, $fn=8,closed=true),
[[-0.606288551887,1.51404651037],[0.280235443937,0.414087063263],[1.63092692777,0],[16.2021229436,0],[19.8705904774,0.482962913145],[23.2890580113,1.89893852818],[34.1829092195,8.18850645576],[34.2505074296,8.28809878531],[34.2143124553,8.40289457772],[34.1018154298,8.44570309758],[25.9629982589,7.73364886061],[25.0818786883,8.01146479408],[24.6552785953,8.83095594797],[23.994133744,16.387876178],[23.5675336511,17.2073673319],[22.6864140805,17.4851832654],[-5.00680751277,15.0623403194],[-5.5709968443,14.7138107731],[-5.62744081644,14.0530562616]]);
assert_approx(round_corners(test2, cut=.5, $fn=8,closed=false),
[[0,0],[16.2021229436,0],[19.8705904774,0.482962913145],[23.2890580113,1.89893852818],[34.1829092195,8.18850645576],[34.2505074296,8.28809878531],[34.2143124553,8.40289457772],[34.1018154298,8.44570309758],[25.9629982589,7.73364886061],[25.0818786883,8.01146479408],[24.6552785953,8.83095594797],[23.994133744,16.387876178],[23.5675336511,17.2073673319],[22.6864140805,17.4851832654],[-5.99691348681,14.975717271]]);
assert_approx(round_corners(test2, radius=[9,1.5,1.5,3], $fn=8,closed=false),[[0,0],[17.5884572681,0],[19.917828674,0.306667563398],[22.0884572681,1.20577136594],[28.8628496345,5.11696862225],[29.5970120924,6.19860893897],[29.2039100968,7.44536918473],[27.9821160204,7.91029877507],[26.2547769306,7.75917618664],[25.1598619019,8.1044015691],[24.6297512693,9.12273461966],[24.1503946842,14.6018054592],[23.090173419,16.6384715603],[20.9003433617,17.3289223252],[-5.99691348681,14.975717271]]);
assert_approx(round_corners(test2, radius=[0,9,1.5,1.5,3,0], $fn=8,closed=false),[[0,0],[17.5884572681,0],[19.917828674,0.306667563398],[22.0884572681,1.20577136594],[28.8628496345,5.11696862225],[29.5970120924,6.19860893897],[29.2039100968,7.44536918473],[27.9821160204,7.91029877507],[26.2547769306,7.75917618664],[25.1598619019,8.1044015691],[24.6297512693,9.12273461966],[24.1503946842,14.6018054592],[23.090173419,16.6384715603],[20.9003433617,17.3289223252],[-5.99691348681,14.975717271]]);
assert_approx(round_corners(test2, radius=[4,9,1.5,1.5,3,5], $fn=8,closed=true), [[-1.00632035384,2.51302092923],[0.46513599873,0.687303493898],[2.70701955022,0],[17.5884572681,0],[19.917828674,0.306667563398],[22.0884572681,1.20577136594],[28.8628496345,5.11696862225],[29.5970120924,6.19860893897],[29.2039100968,7.44536918473],[27.9821160204,7.91029877507],[26.2547769306,7.75917618664],[25.1598619019,8.1044015691],[24.6297512693,9.12273461966],[24.1503946842,14.6018054592],[23.090173419,16.6384715603],[20.9003433617,17.3289223252],[0.712818162855,15.5627427257],[-3.11056954856,13.2008342139],[-3.49307800348,8.72304539674]]);
assert_approx(round_corners(test1, radius=[4,0,9,1.5,1.5,3,5], $fn=8, closed=true),[[-1.00632035384,2.51302092923],[0.46513599873,0.687303493898],[2.70701955022,0],[10,0],[17.5884572681,0],[19.917828674,0.306667563398],[22.0884572681,1.20577136594],[28.8628496345,5.11696862225],[29.5970120924,6.19860893897],[29.2039100968,7.44536918473],[27.9821160204,7.91029877507],[26.2547769306,7.75917618664],[25.1598619019,8.1044015691],[24.6297512693,9.12273461966],[24.1503946842,14.6018054592],[23.090173419,16.6384715603],[20.9003433617,17.3289223252],[0.712818162855,15.5627427257],[-3.11056954856,13.2008342139],[-3.49307800348,8.72304539674]]);
assert_approx(round_corners(test1, joint=3, $fn=8, closed=true),[[-1.11523430308,2.78500492805],[0.515477620423,0.76169028093],[3,0],[7,0],[13,0],[17,0],[19.8977774789,0.381499642545],[22.5980762114,1.5],[32.124355653,7],[32.4498754498,7.47958777023],[32.2755782213,8.03238795439],[31.7338477701,8.23853277176],[27.7490689777,7.88990980077],[25.5592389204,8.58036056568],[24.4990176552,10.6170266668],[24.1503946842,14.6018054592],[23.090173419,16.6384715603],[20.9003433617,17.3289223252],[-3.00832939254,15.2371844993],[-4.71130594915,14.1851659419],[-4.88167918373,12.190712343]]);
assert_approx(round_corners(test1, joint=3, $fn=8, method="chamfer", closed=true), [[-1.11523430308,2.78500492805],[3,0],[7,0],[13,0],[17,0],[22.5980762114,1.5],[32.124355653,7],[31.7338477701,8.23853277176],[27.7490689777,7.88990980077],[24.4990176552,10.6170266668],[24.1503946842,14.6018054592],[20.9003433617,17.3289223252],[-3.00832939254,15.2371844993],[-4.88167918373,12.190712343]]);
assert_approx(round_corners(test1, joint=3, $fn=4, method="smooth", closed=true),[[-1.11523430308,2.78500492805],[-0.506080589514,1.46865494252],[0.353393568173,0.522188424009],[1.55153656203,0.0761524785012],[3,0],[7,0],[8.5,0],[10,0],[11.5,0],[13,0],[17,0],[18.4890098964,0.041015625],[19.9246392896,0.28125],[21.2880480021,0.791015625],[22.5980762114,1.5],[32.124355653,7],[33.2706335159,7.70183488048],[33.674933057,8.1697248947],[33.0753795745,8.32110126636],[31.7338477701,8.23853277176],[27.7490689777,7.88990980077],[26.3293465324,7.8480447775],[25.2718192958,8.2378271955],[24.7043208711,9.21160321051],[24.4990176552,10.6170266668],[24.1503946842,14.6018054592],[23.9450914683,16.0072289155],[23.3775930436,16.9810049305],[22.320065807,17.3707873485],[20.9003433617,17.3289223252],[-3.00832939254,15.2371844993],[-4.39040765537,15.0374479012],[-5.22744753731,14.5025539523],[-5.32708255097,13.514211823],[-4.88167918373,12.190712343]]);
assert_approx(round_corners(test1, joint=3, $fn=4, method="smooth", k=.1, closed=true), [[-1.11523430308,2.78500492805],[-0.374134800869,0.998685360916],[0.164916998481,0.243687931204],[1.06619720521,0.0239336361004],[3,0],[7,0],[8.95,0],[10,0],[11.05,0],[13,0],[17,0],[18.9465459674,0.012890625],[19.9648316685,0.13125],[20.9058726414,0.537890625],[22.5980762114,1.5],[32.124355653,7],[33.7650948284,7.95986239101],[34.2335990876,8.34587161753],[33.6284170693,8.39334886112],[31.7338477701,8.23853277176],[27.7490689777,7.88990980077],[25.829925477,7.74788623096],[24.9991076092,7.91282206324],[24.6924075141,8.70237713407],[24.4990176552,10.6170266668],[24.1503946842,14.6018054592],[23.9570048253,16.5164549919],[23.6503047302,17.3060100627],[22.8194868624,17.470945895],[20.9003433617,17.3289223252],[-3.00832939254,15.2371844993],[-4.91564186446,15.0455441488],[-5.63782937704,14.7549077223],[-5.57131429138,13.9792788941],[-4.88167918373,12.190712343]]);
assert_approx(round_corners(test1, joint=[3,0,3,5,2,2,4], $fn=4, method="smooth", k=[.8,0,.7,.5,0,.4,1], closed=true),[[-1.11523430308,2.78500492805],[-0.605039930997,1.82113212873],[0.494750995442,0.731063793612],[1.91554107964,0.115316610302],[3,0],[10,0],[17,0],[18.2602418609,0.055078125],[19.9045431002,0.35625],[21.4791356824,0.917578125],[22.5980762114,1.5],[30.3923048454,6],[32.3027679503,7.1697248008],[32.9766005188,7.94954149117],[31.9773447146,8.20183544393],[29.7414583739,8.06422128626],[26.7528742796,7.80275405802],[25.3902084366,7.69137858706],[24.8741147528,7.76386137763],[24.713114411,8.25952793415],[24.5861733979,9.62083196871],[24.0632389414,15.5980001573],[23.9283556903,16.6198201409],[23.5934897955,17.2383006602],[22.9262565325,17.4606811745],[21.8965380598,17.4160780679],[-2.01213469444,15.324340242],[-2.97951536307,15.0445310318],[-4.28698915458,13.9242432294],[-4.69675267167,12.2519315552],[-4.50993441604,11.262377367]]);
assert_approx(round_corners(test2, cut=.6, $fn=4, method="smooth", k=[.8,.7,.5,0,.4,1], closed=true), [[-0.758025389489,1.89296943206],[-0.411245984888,1.23782454268],[0.336282532724,0.496904475915],[1.30199436026,0.0783807655462],[2.03910170463,0],[15.1195326672,0],[17.1697224117,0.0896023299387],[19.8447085729,0.579555495773],[22.4062911263,1.49273668813],[24.2266086926,2.44023366641],[33.3031485364,7.68057638855],[33.9293399672,8.06397643682],[34.1502016939,8.3195765203],[33.8226761739,8.40227076906],[33.0898209499,8.35716505304],[31.5228787369,8.220075373],[26.897837498,7.84205448929],[25.1461574492,8.08806923839],[24.5997041686,9.77041731835],[24.1688520829,14.390836426],[24.116478533,14.9894688406],[23.9403981733,16.3233811597],[23.5032548901,17.1307628876],[22.6322299704,17.4210646163],[21.2880067431,17.3628384763],[-4.80585474409,15.0799214086],[-5.0950068559,14.9962858485],[-5.48581351579,14.6614294736],[-5.6082926909,14.161572005],[-5.55245232227,13.8657921816]]);
assert_approx(round_corners([[0,0],[10,0],[10,10]], cut=1, method="chamfer",closed=false), [[0,0],[8.58578643763,0],[10,1.41421356237],[10,10]]);
}
test_round_corners();
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap

View file

@ -40,7 +40,7 @@ test_turtle();
module test_arc() {
assert_approx(arc(N=8, d=100, angle=135, cp=[10,10]), [[60,10],[57.1941665154,26.5139530978],[49.0915741234,41.1744900929],[36.6016038258,52.3362099614],[21.1260466978,58.7463956091],[4.40177619483,59.6856104947],[-11.6941869559,55.0484433951],[-25.3553390593,45.3553390593]]);
assert_approx(arc(N=8, d=100, angle=135, cp=[10,10],endpoint=false), [[60,10],[57.1941665154,26.5139530978],[49.0915741234,41.1744900929],[36.6016038258,52.3362099614],[21.1260466978,58.7463956091],[4.40177619483,59.6856104947],[-11.6941869559,55.0484433951]]);
assert_approx(arc(N=8, d=100, angle=135, cp=[10,10],endpoint=false), [[60,10],[57.8470167866,24.5142338627],[51.5734806151,37.778511651],[41.7196642082,48.6505226681],[29.1341716183,56.1939766256],[14.9008570165,59.7592363336],[0.245483899194,59.0392640202],[-13.5698368413,54.0960632174]]);
assert_approx(arc(N=8, d=100, angle=[45,225], cp=[10,10]), [[45.3553390593,45.3553390593],[26.5139530978,57.1941665154],[4.40177619483,59.6856104947],[-16.6016038258,52.3362099614],[-32.3362099614,36.6016038258],[-39.6856104947,15.5982238052],[-37.1941665154,-6.51395309776],[-25.3553390593,-25.3553390593]]);
assert_approx(arc(N=8, d=100, start=45, angle=135, cp=[10,10]), [[45.3553390593,45.3553390593],[31.6941869559,55.0484433951],[15.5982238052,59.6856104947],[-1.12604669782,58.7463956091],[-16.6016038258,52.3362099614],[-29.0915741234,41.1744900929],[-37.1941665154,26.5139530978],[-40,10]]);
assert_approx(arc(N=8, d=100, start=45, angle=-90, cp=[10,10]), [[45.3553390593,45.3553390593],[52.3362099614,36.6016038258],[57.1941665154,26.5139530978],[59.6856104947,15.5982238052],[59.6856104947,4.40177619483],[57.1941665154,-6.51395309776],[52.3362099614,-16.6016038258],[45.3553390593,-25.3553390593]]);