From a6a130056a5c6efd7a78d5d0881ae1e2d8106a7c Mon Sep 17 00:00:00 2001 From: cormullion Date: Wed, 1 Jun 2022 11:33:21 +0100 Subject: [PATCH] docs and tests for release 3.3 --- CHANGELOG.md | 5 +- docs/src/assets/figures/pro-text-example.png | Bin 8195 -> 6627 bytes .../src/assets/figures/pro-text-placement.png | Bin 9723 -> 11501 bytes docs/src/assets/figures/texttrack.svg | 1065 +++++++++++++++++ docs/src/example/examples.md | 70 +- docs/src/howto/polygons.md | 10 + docs/src/howto/text.md | 164 +-- docs/src/index.md | 2 +- test/polymorph-test.jl | 32 + test/runtests.jl | 1 + 10 files changed, 1189 insertions(+), 160 deletions(-) create mode 100644 docs/src/assets/figures/texttrack.svg create mode 100644 test/polymorph-test.jl diff --git a/CHANGELOG.md b/CHANGELOG.md index c62a13fd..03aece22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## [v3.3.0] - forthcoming +## [v3.3.0] - 2022-06-01 11:28:44 ### Added @@ -8,9 +8,10 @@ - `textfit()` algorithm revisited; it's quicker, at least.... - `polymorph()` keywords changed -- `polymorph()` can now morph between open polygons +- `polymorph()` can now also morph between open polygons - minimum Julia version is now 1.6 - there are still bugs/edgecases in `polyhull()` which I can't find/fix +- docs now built on Linux (for LaTeX purposes) ### Removed diff --git a/docs/src/assets/figures/pro-text-example.png b/docs/src/assets/figures/pro-text-example.png index 407b5d873935dc4c6e701d4cf6ed870ab5ebac88..9aac33119b5f829a310177022053beb1abdf5730 100644 GIT binary patch literal 6627 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 z zlGV!BzklbVqJZF!2ncYit3S%g(KZh_#70q(_~uDdb$wP50zeeq$tifs>8q@A@?U(7 z18DObNEmddE!`GKMOFe5*9;Mx-Z=zsiomg1-I{`{(B4?0Nl3jrZ1p5 zqxTti7#U;LZzi*M6%|1dU1f6TqoaH~zjST9p%3li96VF7F)&6SIGH9U}VOgg<>LHFbS`wVW8dC!0m~m3y3@Ab1weE2q=n>dDzPL5`4(*nnslK>o z__K01#N3bJS4Sq}X-S;k=#{XyurXZ$smU;LbXAb%%ti ze)Iy^Pj(0c-V^nb{c%rE@1e5t&Pa^2NJs=JYltm$=4V1?`%GyGKki_v0eTB4H9+mc zCr1#jD-X=ds|&+h6z>+&xLoyJBDbyvoVdCP;BO^HS zW+TnEaC#<@IwWO^r!kW%AN~WSB+uQS_8*g)C zYb`kytDH;x?86dH+q5Yk>DLwi@ZV61ECCA%Y0Z|>uSJnEN_^$~Z)Byo8nA^u zbbH>K5K(I9H3XU~hqg}_$}d(Ku{*nhjm5=Ze@%o<$}rLY=M)JC(xp#-)mTv*7;MqeB^7FQG=h?old1WPU;Irn z;Wye*YUdfS>LSWkOExu<8tsi#Mpr-P%s;NxhKZ^M|1+f$B^(FBNfYC;D~;N2?7iTa zOPhXvek#YCF8n(|E_W+EF?w(HLgK`Iy(7K?x%uvTZ2;HIOaZ3PPR{rR7|7&%3xUQa zPIgXni@)#e19O>xo6|+WH+#Xs0d&{|4v3x}7MKtOn+J?+D9|GeG|PZNL{=6+|4g_j z-y?kz60*(o^=)Plby{(ZiFvFwTcxGzL)kXA@4bd68{rMkHMS^P>(+p@thAE(N>hlt z`^D(@H4#f?z^3opp8P2?&5`Kh>Q#` zYo31`queY!a%(FTY;hk3m5{pF$WijC`DhN+YGYTvBSM{uABIk^Fo8RnzhegXwCcbB zp})o%m(L#n*uJ+DZS<-;Oj_R0BslU=5-y9{-uA;pM_9qm&Uo`*g4yyzsGj2T;_7Mu z5*uu8T;s0_o69%xVWN4K6XXH6Umt|*FR+J@QE@<`A5Ve#>W#<4+}e za7xN>+s6v-dEIQ0rrcN*s;4^lqsZ4!58eU->5Y%iFcUPtpfKHItDcoD)M6}{k9hWY zOWbw=$x1-R9Qpuy&aRF0-=0WBxF6Qnlx$A_{8^}~I2KAxDhEQCbKjE_7)`qZG|{8$ z%h}V-x*s=8Szk&@%lq>f#|jr42<3800B#Yq$wb4?!uo}Xm?$7H;NWri_A?ho)s_e3 zLR0XMd1=`T1}^&x*B4=-VeEy4BFc)>Gz$$-C}6t6W&MNN-UXv+%%?KaVi+X&o^f{9 z8b1TLrRwG;>5U%fe$PU#;`SZWJlIrOdAYCXdl|KtfB;(LH>#grZ2LX=kv~oPnSewJ z(wBPsgX4CqM~VM6G~*r&g|!{>IzKm!iQ(_*)6>=6bodYpGn{-T;d!}*~%kYD%^?QZ}#)rqOf39Ah zqKmBKDJnu*Z`P0KBqfTMuzebuyk`LbvA(O+u@;oYYS%#LJn}<7Sb-1^@6-4aBM6xE z8if4sFJ=m0F#S%P@ZVJUEh+y0zx96;jZ69X`?0?zl&7Bn(Zf?$(N?Ymzx(`u0I0ME AEdT%j diff --git a/docs/src/assets/figures/pro-text-placement.png b/docs/src/assets/figures/pro-text-placement.png index d66a7b1b000e2b5687d0278220532ce04a12a68c..5e9aa13ad4ce6d1a041e99189199a5363a828e6f 100644 GIT binary patch literal 11501 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 literal 9723 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 TzXv?c1(B0deqAYH^8SASe-t4g diff --git a/docs/src/assets/figures/texttrack.svg b/docs/src/assets/figures/texttrack.svg new file mode 100644 index 00000000..67f0400e --- /dev/null +++ b/docs/src/assets/figures/texttrack.svg @@ -0,0 +1,1065 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/src/example/examples.md b/docs/src/example/examples.md index 2152a187..fce1e7b3 100644 --- a/docs/src/example/examples.md +++ b/docs/src/example/examples.md @@ -43,7 +43,7 @@ graphics without you having to provide the usual set-up and finish instructions: ```julia -# using Luxor +using Luxor @png begin fontsize(50) @@ -54,26 +54,36 @@ finish instructions: ![background](../assets/figures/hello-world-macro.png) -```julia -@svg begin +```@example +using Luxor + +@drawsvg begin + background("black") sethue("red") - randpoint = Point(rand(-200:200), rand(-200:200)) - circle(randpoint, 2, :fill) - sethue("black") + randpoint = Point(rand(-300:300), rand(-300:300)) + circle(randpoint, 5, :fill) + sethue("white") foreach(f -> arrow(f, between(f, randpoint, .1), arrowheadlength=6), - first.(collect(Table(fill(20, 15), fill(20, 15))))) + first.(collect(Table(fill(30, 20), fill(30, 20))))) end ``` -![background](../assets/figures/circle-dots.png) The `@draw` and `drawsvg` macros are useful if you work in Juno/VS Code IDEs or a notebook environment such as Jupyter or Pluto and don't need to always save your work in files. They create a PNG or SVG format drawing in memory, rather -than saved in a file. It's displayed in the plot pane or in -an adjacent cell. +than saved in a file. + +In this document, which was generated by Documenter.jl, the result +of executing the code is included and displayed as a +graphic. + +For Juno and VS Code, the graphic is usually displayed in +the plot pane. In Pluto, it appears above the cell. ```julia +using Luxor + @draw begin setopacity(0.85) steps = 20 @@ -137,10 +147,10 @@ Here's a version of the Sierpinski recursive triangle, clipped to a circle. ![Sierpinski](../assets/figures/sierpinski.png) ```julia -# using Luxor, Colors -# Drawing() -# background("white") -# origin() +using Luxor, Colors +Drawing() +background("white") +origin() function triangle(points, degree) sethue(cols[degree]) @@ -170,8 +180,8 @@ depth = 8 # 12 is ok, 20 is right out (on my computer, at least) cols = distinguishable_colors(depth) # from Colors.jl draw(depth) -# finish() -# preview() +finish() +preview() ``` The Point type is an immutable composite type containing `x` and `y` fields that specify a 2D point. @@ -181,7 +191,7 @@ The Point type is an immutable composite type containing `x` and `y` fields that [`tickline()`](@ref) is useful for generating spaced points along a line: ```@example -using Luxor # hide +using Luxor @drawsvg begin background("black") fontsize(12) @@ -196,7 +206,7 @@ end 800 150 The [`arrow`](@ref) functions let you add decoration to the arrow shafts, so it's possible to use this function to create more complicated spacings. Here's how a curved number line could be made: ```@example -using Luxor # hide +using Luxor @drawsvg begin background("antiquewhite") _counter() = (a = -1; () -> a += 1) @@ -268,10 +278,10 @@ If you have the right fonts installed, you can easily draw simple ``\LaTeX`` equ ```@example # drawing with 800×300 canvas -using Luxor # hide +using Luxor using MathTeXEngine -d = Drawing(800, 300, :svg) # hide -origin() # hide +d = Drawing(800, 300, :svg) +origin() background("khaki") f(t) = Point(4cos(t) + 2cos(5t), 4sin(t) + 2sin(5t)) setline(15) @@ -283,8 +293,8 @@ fontsize(35) end sethue("grey5") text(L"f(t) = [4\cos(t) + 2\cos(5t), 4\sin(t) + 2\sin(5t)]", halign=:center) -finish() # hide -d # hide +finish() +d ``` ## Triangulations @@ -294,12 +304,12 @@ random points can be used to derive a set of Voronoi cells. ```@example # Inspired by @TheCedarPrince! -using Luxor, Colors, Random # hide -Random.seed!(42) # hide +using Luxor, Colors, Random +Random.seed!(42) -d = @drawsvg begin # hide -background("black") # hide -setlinejoin("bevel") # hide +d = @drawsvg begin +background("black") +setlinejoin("bevel") verts = randompointarray(BoundingBox(), 40) triangles = polytriangulate(verts) # create Delaunay @@ -340,6 +350,6 @@ for v in verts strokepath() end end -end 800 500 # hide -d # hide +end 800 500 +d ``` diff --git a/docs/src/howto/polygons.md b/docs/src/howto/polygons.md index 59602bca..1d3efca1 100644 --- a/docs/src/howto/polygons.md +++ b/docs/src/howto/polygons.md @@ -1227,6 +1227,16 @@ nothing # hide ![polysampling 2](../assets/figures/polysample2.png) +!!! note + + In Luxor, you'll meet `close` and `closed` options. + `close` is an instruction to path-drawing functions, + that says "join the most recent point to the first + point". Whereas, `closed` is an indication that the + polygons or paths should be treated as being closed + rather than open, ie whether that last segment joining + the end point to the first is used for calculations. + ### Polygon side lengths `polydistances` returns an array of the accumulated side lengths of a polygon. diff --git a/docs/src/howto/text.md b/docs/src/howto/text.md index e9dd7908..ab0c34b5 100644 --- a/docs/src/howto/text.md +++ b/docs/src/howto/text.md @@ -16,17 +16,10 @@ Use: - `fontface(fontname)` to specify the fontname - `fontsize(fontsize)` to specify the fontsize -```@example -using Luxor # hide -Drawing(600, 100, "../assets/figures/toy-text-example.png") # hide -origin() # hide -background("azure") # hide -sethue("black") # hide +```julia fontsize(16) fontface("Georgia-Bold") text("Georgia: a serif typeface designed in 1993 by Matthew Carter.", halign=:center) -finish() # hide -nothing # hide ``` ![text placement](../assets/figures/toy-text-example.png) @@ -42,16 +35,9 @@ Use: - `setfont(fontname, fontsize)` to specify the fontname and size - `settext(text, [position])` to place the text at a position, and optionally specify horizontal and vertical alignment, rotation (in degrees counterclockwise!), and the presence of any pseudo-Pango-flavored markup. -```@example -using Luxor # hide -Drawing(600, 100, "../assets/figures/pro-text-example.png") # hide -origin() # hide -background("azure") # hide -sethue("black") # hide +```julia setfont("Georgia Bold", 16) settext("Georgia: a serif typeface designed in 1993 by Matthew Carter.", halign="center") -finish() # hide -nothing # hide ``` ![text placement](../assets/figures/pro-text-example.png) @@ -68,11 +54,7 @@ To select a font in the Pro text API, use [`setfont`](@ref) and supply both the Use [`text`](@ref) to place text. -```@example -using Luxor # hide -Drawing(400, 150, "../assets/figures/text-placement.png") # hide -origin() # hide -background("white") # hide +```julia fontsize(80) # hide sethue("black") # hide pt1 = Point(-100, 0) @@ -87,23 +69,15 @@ text("5", pt2, halign=:center, valign = :top) text("6", pt3, halign=:right, valign = :top) sethue("red") map(p -> circle(p, 4, :fill), [pt1, pt2, pt3]) -finish() # hide -nothing # hide ``` ![text placement](../assets/figures/text-placement.png) -```@example -using Luxor # hide -Drawing(400, 300, "../assets/figures/text-rotation.png") # hide -origin() # hide -background("white") # hide +```julia sethue("black") # hide fontsize(10) fontface("Georgia") [text(string(θ), Point(40cos(θ), 40sin(θ)), angle=θ) for θ in 0:π/12:47π/24] -finish() # hide -nothing # hide ``` ![text rotation](../assets/figures/text-rotation.png) @@ -141,15 +115,16 @@ to parse the `LaTeXString`. You should load MathTeXEngine.jl !!! note - MathTeXEngine.jl is a package that renders + MathTeXEngine.jl is a package that renders many `LaTeXString`s without requiring a ``\LaTeX`` compiler. The package uses the fonts _Computer Modern_ and _New Computer Modern_. They're included with the MathTeXEngine package, and you can find them in your `julia` folder in `packages/MathTeXEngine/.../assets/fonts`. You should - make sure these have been installed before running - Luxor and writing ``\LaTeX`` strings. + make sure these have been copied to your system's + font directories before running Luxor and writing + ``\LaTeX`` strings. ```@example using Luxor @@ -179,6 +154,15 @@ nothing # hide ![textbox](../assets/figures/latexexample.svg) +!!! note + + The string macros in the + [LaTeXStrings.jl](https://github.com/stevengj/LaTeXStrings.jl) + package allow you to enter LaTeX equations + without having to escape backslashes and dollar signs + (and they'll add the dollar signs for you if you omit + them). + ## Notes on fonts Fonts are loaded when you first start using Luxor/Cairo in a Julia session. This partly explains why starting a Luxor/Cairo session can take a few seconds. @@ -223,10 +207,7 @@ For PNG files, the appearance of fonts when output is controlled to some extent `textoutlines(string, position)` converts the text into graphic path(s), places them starting at `position`, and applies the `action`. -```@example -using Luxor # hide -Drawing(400, 400, "../assets/figures/textoutlines.png") # hide -origin() # hide +```julia fontface("Times-Roman") fontsize(500) setline(4) @@ -235,8 +216,6 @@ textoutlines("&", O, :path, valign=:middle, halign=:center) fillpreserve() sethue("black") strokepath() -finish() # hide -nothing # hide ``` ![text outlines](../assets/figures/textoutlines.png) @@ -262,12 +241,7 @@ The `textextents(str)` function returns the dimensions of the string `str`, give The [`label`](@ref) function places text relative to a specific point, and you can use compass points or angles to indicate where it should be. So `:N` (for North) places a text label directly above the point, as does `3π/2`. -```@example -using Luxor # hide -Drawing(400, 350, "../assets/figures/labels.png") # hide -origin() # hide -background("white") # hide -sethue("black") +```julia fontsize(15) octagon = ngon(O, 100, 8, 0, vertices=true) @@ -277,9 +251,6 @@ for i in 1:8 circle(octagon[i], 5, :fill) label(string(compass[i]), compass[i], octagon[i], leader=true, leaderoffsets=[0.2, 0.9], offset=50) end - -finish() # hide -nothing # hide ``` ![labels](../assets/figures/labels.png) @@ -288,12 +259,7 @@ nothing # hide Use `textcurve(str)` to draw a string `str` on a circular arc or spiral. -```@example -using Luxor # hide -Drawing(800, 800, "../assets/figures/text-spiral.png") # hide - -origin() # hide -background("ivory") # hide +```julia sethue("royalblue4") # hide fontsize(7) fontface("Menlo") @@ -307,20 +273,13 @@ textcurve("this spiral contains every word in julia names(Base): " * textstring, fontsize(35) fontface("Avenir-Black") textcentered("julia names(Base)", 0, 0) -finish() # hide - -nothing # hide ``` ![text on a curve or spiral](../assets/figures/text-spiral.png) For shorter strings, [`textcurvecentered`](@ref) tries to place the text on a circular arc by its center point. -```@example -using Luxor # hide -Drawing(400, 250, "../assets/figures/text-centered.png") # hide -origin() # hide -background("white") # hide +```julia fontface("Arial-Black") fontsize(24) # hide sethue("black") # hide @@ -337,8 +296,6 @@ textcurvecentered("hello world", π/2, 100, O; letter_spacing = 0, baselineshift = 10 ) -finish() # hide -nothing # hide ``` ![text centered on curve](../assets/figures/text-centered.png) @@ -386,15 +343,6 @@ You can use newly-created text paths as a clipping region - here the text paths ![text clipping](../assets/figures/text-path-clipping.png) ```julia -using Luxor - -currentwidth = 1250 # pts -currentheight = 800 # pts -Drawing(currentwidth, currentheight, "/tmp/text-path-clipping.png") - -origin() -background("darkslategray3") - fontsize(600) # big fontsize to use for clipping fontface("Agenda-Black") str = "julia" # string to be clipped @@ -412,36 +360,26 @@ fontface("Monaco") fontsize(10) namelist = map(x->string(x), names(Base)) # get list of function names in Base. -let - x = -20 - y = -h - while y < currentheight - sethue(rand(7:10)/10, rand(7:10)/10, rand(7:10)/10) - s = namelist[rand(1:end)] - text(s, x, y) - se = textextents(s) - x += se[5] # move to the right - if x > w - x = -20 # next row - y += 10 - end +x = -20 +y = -h +while y < currentheight + sethue(rand(7:10)/10, rand(7:10)/10, rand(7:10)/10) + s = namelist[rand(1:end)] + text(s, x, y) + se = textextents(s) + x += se[5] # move to the right + if x > w + x = -20 # next row + y += 10 end end - -finish() -preview() ``` ## Text blocks, boxes, and wrapping Longer lines of text can be made to wrap inside an imaginary rectangle with [`textwrap`](@ref). Specify the required width of the rectangle, and the location of the top left corner. -```@example - -using Luxor # hide -Drawing(500, 400, "../assets/figures/text-wrapping.png") # hide -origin() # hide -background("white") # hide +```julia fontface("Georgia") fontsize(12) # hide sethue("black") # hide @@ -459,20 +397,13 @@ leo tristique, a condimentum tortor faucibus.""" setdash("dot") box(O, 200, 200, :stroke) textwrap(loremipsum, 200, O - (200/2, 200/2)) - -finish() # hide -nothing # hide ``` ![text wrapping](../assets/figures/text-wrapping.png) [`textwrap`](@ref) accepts a function that allows you to insert code that responds to the next line's linenumber, contents, position, and height. -```@example -using Luxor, Colors # hide -Drawing(500, 400, "../assets/figures/text-wrapping-1.png") # hide -origin() # hide -background("white") # hide +```julia fontface("Georgia") fontsize(12) # hide sethue("black") # hide @@ -492,9 +423,6 @@ textwrap(loremipsum, 200, O - (200/2, 200/2), sethue(Colors.HSB(rescale(lnumber, 1, 15, 0, 360), 1, 1)) text(string("line ", lnumber), pt - (50, 0)) end) - -finish() # hide -nothing # hide ``` ![text wrapped](../assets/figures/text-wrapping-1.png) @@ -503,12 +431,7 @@ The [`textbox`](@ref) function also draws text inside a box, but doesn't alter t This example counts the number of characters drawn, using a simple closure. The function returns the position of the start of what would have been the next line. -```@example -using Luxor, Colors # hide -Drawing(600, 300, "../assets/figures/textbox.png") # hide -origin() # hide -background("ivory") # hide -sethue("black") # hide +```julia fontface("Georgia") fontsize(30) @@ -539,9 +462,6 @@ finishpos = textbox(filter(!isempty, split(loremipsum, "\n")), fontsize(10) text(string(counter(0), " characters"), finishpos) - -finish() # hide -nothing # hide ``` ![textbox](../assets/figures/textbox.png) @@ -557,13 +477,7 @@ The tracking units depend on the current font size. In a 0.35mm, so a 1000 units of tracking for 12 point text produces about 4.2mm of space between each character. -```@example -using Luxor # hide -Drawing(600, 400, "../assets/figures/texttrack.svg") # hide -origin() # hide -background("white") # hide -sethue("black") # hide - +```julia function text_tracking_example() fonts = [ "Verdana", @@ -584,12 +498,10 @@ function text_tracking_example() texttrack("This is some text in $(f): it’s been tracked by -$(tracking)", nextgridpoint(grid), -tracking, fsize) end - - finish() # hide + finish() end text_tracking_example() -nothing # hide ``` ![textbox](../assets/figures/texttrack.svg) @@ -635,8 +547,6 @@ To animate the drawing of text, you can obtain and store the paths, and then bui ![text animation](../assets/figures/textanimation.gif) ```julia -using Luxor - function frame(scene, framenumber) background("black") sethue("gold") diff --git a/docs/src/index.md b/docs/src/index.md index 241efd00..bb7b21df 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -56,5 +56,5 @@ This documentation was built using [Documenter.jl](https://github.com/JuliaDocs) ```@example using Dates # hide -println("Documentation built $(Dates.now()) with Julia $(VERSION)") # hide +println("Documentation built $(Dates.now()) with Julia $(VERSION) on $(Sys.KERNEL)") # hide ``` diff --git a/test/polymorph-test.jl b/test/polymorph-test.jl new file mode 100644 index 00000000..8eb459ba --- /dev/null +++ b/test/polymorph-test.jl @@ -0,0 +1,32 @@ +using Luxor +using Test +using Random + +Random.seed!(42) + +function polymorph_test_1(fname) + Drawing(500, 500, fname) + background("grey20") + origin() + sethue("white") + + poly1 = [Point(70x, -200 + 20sin(x)) for x in -π:0.1:π] + poly2 = [Point(70x, 200 + 20sin(2x)) for x in -π:0.1:π] + + poly(poly1, :stroke) + poly(poly2, :stroke) + + # test that first points and last points remain the same x + for i in 0:0.02:1.0 + pm = polymorph(poly1, poly2, i, closed=false, samples=50) + poly.(pm, :stroke) + @test first(pm[1]).x ≈ poly1[1].x ≈ poly2[1].x + @test poly1[end].x ≈ poly2[end].x ≈ last(pm[1]).x + end + + @test finish() == true + + println("...finished test: output in $(fname)") +end + +polymorph_test_1("polymorph-test-1.png") diff --git a/test/runtests.jl b/test/runtests.jl index c69ec094..6f711162 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -48,6 +48,7 @@ function run_all_tests() include("convexandclockwise.jl") include("various-points-tests.jl") include("polyhull-test.jl") + include("polymorph-test.jl") end @testset "text" begin