From c8c5803e787ba5a125373dcce85aaea83cf1491b Mon Sep 17 00:00:00 2001 From: Johannes Wolf Date: Thu, 21 Nov 2024 02:18:05 +0100 Subject: [PATCH] sample: Add "int" option to sampling domain --- src/plot/sample.typ | 13 ++++++++++--- tests/plot/sample/ref/1.png | Bin 0 -> 7462 bytes tests/plot/sample/test.typ | 26 ++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 tests/plot/sample/ref/1.png create mode 100644 tests/plot/sample/test.typ diff --git a/src/plot/sample.typ b/src/plot/sample.typ index 3ad881d..502b0c1 100644 --- a/src/plot/sample.typ +++ b/src/plot/sample.typ @@ -8,18 +8,24 @@ /// - fn (function): Function to sample of the form `(x) => y` or `(t) => (x, y)`, where /// `x` or `t` are `float` values within the domain specified by `domain`. /// - domain (domain): Domain of `fn` used as bounding interval for the sampling points. -/// - samples (int): Number of samples in domain. +/// - samples (int,str): Number of samples in domain or "INT" to use $"diam"("domain")$ +/// number of samples (passed as int). /// - sample-at (array): List of x values the function gets sampled at in addition /// to the `samples` number of samples. Values outsides the /// specified domain are legal. /// -> array: Array of (x, y) tuples #let sample-fn(fn, domain, samples, sample-at: ()) = { - assert(samples + sample-at.len() >= 2, - message: "You must at least sample 2 values") assert(type(domain) == array and domain.len() == 2, message: "Domain must be a tuple") let (lo, hi) = domain + if samples in ("int", "INT") { + samples = hi - lo + 1 + fn = n => { fn(int(n)) } + } + + assert(samples + sample-at.len() >= 2, + message: "You must at least sample 2 values") let y0 = (fn)(lo) let is-vector = type(y0) == array @@ -29,6 +35,7 @@ y0 = (y0, ) } + let pts = sample-at + range(0, samples).map(t => lo + t / (samples - 1) * (hi - lo)) pts = pts.sorted() diff --git a/tests/plot/sample/ref/1.png b/tests/plot/sample/ref/1.png new file mode 100644 index 0000000000000000000000000000000000000000..debb9ded312ac33b1d1c9bc06c06032d804f26da GIT binary patch literal 7462 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

xbxM}WaxWrFWs=Uxdg=3@eR2k)O=M8 z`0;Ki_I*IzpVj(sjy3-nMY7qXmvnv30eTd zUNGa)!mGOPa23~Vm6^`NpYQR}k5|{M%wmiGj$bmI16I4&jf=w~hP&To3*U%Np;=9Q zdrH_~mSrmPR;4H{VlHKHeQ&~hyL`LR4H@MUp6V(qA2`r|81vB{INTjiWsSI^`9;46 zqwv3rK`%3*CAr_DnM*kiCrmS$;^h2nw%b@)b%si}J;3m1{Tm-ezMOh)@=$W_k@p|8Oz;l3~5Fl)dl3o!&9VU`{IEJw^`t zBYqRMa7ajv;C%!X1R_v_lA$2r;0PQWNkjul2AT(x2ykee_<-9R8ymB{eLE;H@KMjk zMrHS$hnE)vCAlQcJlOQ>`1ttDj8jO+UQf?8C=}}Ljh&x&v9ui9-w%aAB#2}LYV-H+ z-+!H$m>3&#tF=kc%SZe0^YM8@Ahr$;qsOI1MR#;(BuYRW4?DiUc)=OnE+81EB<)WRp&65xu4y_5yTre#s_}bAwGY<#S2vEDnC0a$*K=$ z*UD-l5_NSu^>TM$_{z^4xo0BQ6Ju19s`-KZt|OmkBf76@rTzQr<&-o$V*2%{|&jrR>{XO3e$MZ+E?&lOg#6<MA;vZwjK)76WhQJQt>}Fh5riNB=2<@~SHEpp>|)uESwrQr!kvKLW)?Ka_yh#* zp_GOX(Snn|xTHu(KQMIqs!X5QmW584Glsj#w-Ho!AjcawFv_*Wj@_^;=-qB&yB(hK z%Ukq_cYou{$-~YcewWi=6g7|#ge?&xg}EOLyva{Sui|TT&mRNN=ni}&{v4ADFp57$ z^k3@dF|W~p@E-+#+V?2_X-lG$jKKJX5giO63H}qH008<6!(H)j82@Vj_khuV#qb(< zyZ@v8FO11D0Q5fslI(wB{IdUrK~itMef##Sg1goVMk9MIn(x5`*E4xyD^2C)t11H> z(uU7;KG$ZnR?D_)dFyMJqUyutRXY9b*mYmr)nwsb=`81~zRD3p#v20XqSPF8nzH5! z=KK=S3A3a`Sx6O5F;{-4d3j^f?zDUZ2f|63yH13*$@(LGOaP+;gDii)&b+U;LnuwF zBR8(!!(=~pQ58s9N*?X@9pQdNs(!=RYEY_bZ#4mS_JX1?whRBe>a{R-mB|*nizsZc zWVd2Q!Y3g0Mp~b%d6T+Fmfv$ON%qd(&R&e~be2tLh}Etc_L+zKLh+_swm%sZV<;*t>d?0P3DwJ!98p?Ok6AEgbQX=P}zti>n~D;!@qLIWH?- z#CClXF6!BWDP%BGN5?*Q5ALM1!%XdOo^3hciSYf6j38oP zi}<|PI*y1K70H)Q>2TT`8oDz)Jr+u_c4PXX0_s|!{>O`Mv8~Y(NpnrmVQHIko;f+S?-<@qfxH7q}N)@$*ZFQr<8##nf9(yww^OYsmMObY-j}^_v zTv_*f082qLjwkK-;X)jcob` zkb)g|06v~1ydfW;=z0jCA13*#dk&(BiiRdD9Y=MGcqik#Cw$DR@VW0YpKG%|Oc)ty7hSqV0oMqJEYA3PP zM6EBg=o_yz8KL0i@$L0#dP6D`T%M99P+NoJI7{DTXm#CDz9OmSCMbHK`8WE=1cWtg z&P(HaaE`LvwMG^~^%ng5qe>QrrR6n`a>C(D9zy26)9TP-zy#n z@o7D>N^=UMJ)Ie?chUOXP%W#;0c@YID^Yzvicr%YVdnpJA>Y$&q-rks`1XdEcma?G zouQ80P!`H*plGB^3*dA44|L{1)nIU+>(+q2{n+YGM~5~<6M1f!lamu@)qec=(be4z zshvDHfT`v1gTc1e)>XXoU_nn0k0Jyj!rQydT>N&)H$#yW<3jp}9{_zkzWPuA!=j5o zAntJY_xDpv@$vCRL`2BR$pJm0zrVkq-_YZYF<~9E7Kcmhbeg^G?d|>j#uw9+N2;5e zJk@&?b<7Ee zRD=SwC$Sw-|ASvtT{Wm|4}Wj}XKzUw^n-ND%JI(OUKu`qb}Ive%${EOy31Fc^2Xq! zH}ozlRLbRBHWk3J` literal 0 HcmV?d00001 diff --git a/tests/plot/sample/test.typ b/tests/plot/sample/test.typ new file mode 100644 index 0000000..d3e794c --- /dev/null +++ b/tests/plot/sample/test.typ @@ -0,0 +1,26 @@ +#set page(width: auto, height: auto) +#import "/src/cetz.typ": * +#import "/src/lib.typ": * +#import "/tests/helper.typ": * + +#let f(n) = { + assert(type(n) == int) + range(1, n+1).map(n => calc.pow(1/3, n)).sum(default: 0) +} + +// Sample integer values +#test-case({ + plot.plot(size: (3, 3), x-tick-step: none, y-tick-step: none, + { + plot.add(domain: (0, 7), samples: "INT", f, mark: "x") + }) +}) + +// Take samples at specific points +#test-case({ + plot.plot(size: (3, 3), x-tick-step: none, y-tick-step: none, + { + plot.add(domain: (0, 1), samples: 2, x => x, mark: "x", + sample-at: (.1, .2, .3)) + }) +})