Skip to content

Commit

Permalink
Merge pull request #300 from hyrodium/fix/revert_arithmetic_and_broad…
Browse files Browse the repository at this point in the history
…casting

Update around broadcasting
  • Loading branch information
cormullion authored Apr 15, 2024
2 parents f0c6897 + 2c5edb2 commit fa064b8
Show file tree
Hide file tree
Showing 15 changed files with 55 additions and 92 deletions.
5 changes: 2 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@

Some 'invalid' `Point` methods have been removed:

- broadcasting `between.(pt1, pt2, range)` now needs `Ref`; `between.(Ref(pt1), Ref(pt2), range)` (or use the new for 4.0 method `between(pt1, pt2, range)`)

- `Point(x, y) .+ n` is no longer valid. Use `Point(x, y) .+ Point(m, n)`.
- Broadcasting on xy-elements like `Point(x, y) .+ n` are no longer valid. Use `Point(x, y) + Point(n, n)`.
- `Point`-`Real` arithmetic operations such as `Point(x, y) + n` are also no longer valid.

LaTeX support is still under development.
See https://github.com/JuliaGraphics/Cairo.jl/pull/357.
Expand Down
6 changes: 3 additions & 3 deletions docs/src/howto/polygons.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ for (pos, n) in tiles
circle(Point(0, 0), 4, action=:fill)
label.([string(i) for i in 1:n], slope.(Ref(O), plist), plist, offset=5)
label.([string(i) for i in 1:n], slope.(O, plist), plist, offset=5)
end
end
Expand Down Expand Up @@ -614,7 +614,7 @@ background("white") # hide
setline(2) # hide
setlinejoin("round") # hide
spine = between(O - (200, 0), O + (200, 0), 0:0.025:1)
spine = between.(O - (200, 0), O + (200, 0), 0:0.025:1)
sethue("red")
prettypoly(spine, action = :stroke)
Expand Down Expand Up @@ -960,7 +960,7 @@ origin() # hide
setline(0.5)
@layer begin
rule.(Ref(O), (0, (π / 2)))
rule.(O, (0, (π / 2)))
end
P = O
Expand Down
8 changes: 4 additions & 4 deletions src/BoundingBox.jl
Original file line number Diff line number Diff line change
Expand Up @@ -155,15 +155,15 @@ end
# basics
# adding a number to a box makes the box larger all round
+(z::Number, bb1::BoundingBox) =
BoundingBox(bb1.corner1 .- z, bb1.corner2 .+ z)
BoundingBox(bb1.corner1 - Point(z,z), bb1.corner2 + Point(z,z))
+(bb1::BoundingBox, z::Number) =
BoundingBox(bb1.corner1 .- z, bb1.corner2 .+ z)
BoundingBox(bb1.corner1 - Point(z,z), bb1.corner2 + Point(z,z))

# subtracting a number makes the box smaller all round
-(z::Number, bb1::BoundingBox) =
BoundingBox(bb1.corner1 .+ z, bb1.corner2 .- z)
BoundingBox(bb1.corner1 + Point(z,z), bb1.corner2 - Point(z,z))
-(bb1::BoundingBox, z::Number) =
BoundingBox(bb1.corner1 .+ z, bb1.corner2 .- z)
BoundingBox(bb1.corner1 + Point(z,z), bb1.corner2 - Point(z,z))

function (*)(bb::BoundingBox, s::Real)
c = midpoint(bb...)
Expand Down
8 changes: 4 additions & 4 deletions src/arrows.jl
Original file line number Diff line number Diff line change
Expand Up @@ -719,13 +719,13 @@ function tickline(startpos, finishpos;
# 1 major/minor division means 3 ticks (beginning, middle, end)

if log == true
majorticklocations = between.(Ref(O), Ref(newfinishpos), log10.(range(1, 10, length=(major+2))))
majorticklocations = between.(O, newfinishpos, log10.(range(1, 10, length=(major+2))))
n_minorticks = ((major + 1) * (minor + 1)) + 1
minorticklocations = between.(Ref(O), Ref(newfinishpos), log10.(range(1, 10, length=n_minorticks)))
minorticklocations = between.(O, newfinishpos, log10.(range(1, 10, length=n_minorticks)))
else
majorticklocations = between.(Ref(O), Ref(newfinishpos), range(0, 1, length=(major+2)))
majorticklocations = between.(O, newfinishpos, range(0, 1, length=(major+2)))
n_minorticks = ((major + 1) * (minor + 1)) + 1
minorticklocations = between.(Ref(O), Ref(newfinishpos), range(0, 1, length=n_minorticks))
minorticklocations = between.(O, newfinishpos, range(0, 1, length=n_minorticks))
end
if vertices == true
else
Expand Down
4 changes: 2 additions & 2 deletions src/bars.jl
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ function barchart(values;
maxbarrange = maxvalue + abs(maxvalue)
basepoint = boundingbox - (0, margin)
hpositions = between.(
Ref(boxbottomleft(basepoint)),
Ref(boxbottomright(basepoint)),
boxbottomleft(basepoint),
boxbottomright(basepoint),
# skip first and last, then take every other one, which is at halfway
range(0.0, stop=1.0, length=2length(values) + 1))[2:2:end-1]
@layer begin
Expand Down
4 changes: 2 additions & 2 deletions src/bezierpath.jl
Original file line number Diff line number Diff line change
Expand Up @@ -663,9 +663,9 @@ function brush(pt1, pt2, width = 10;
for j in 1:strokes
shiftedline = [O + (0, 0), O + (0, n)]
if tidystart
shiftedline .+= Ref(Point(rand((-width/2):(width/2)), 0))
shiftedline .+= Point(rand((-width/2):(width/2)), 0)
else
shiftedline .+= Ref(Point(rand((-width/2):(width/2)), rand((-width/2):(width/2))))
shiftedline .+= Point(rand((-width/2):(width/2)), rand((-width/2):(width/2)))
end
pbp = bezierstroke(shiftedline[1],
shiftedline[2],
Expand Down
40 changes: 2 additions & 38 deletions src/point.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,27 +38,9 @@ Base.zero(::Point) = O
Point((x, y)::Tuple{Real,Real}) = Point(x, y)

# for broadcasting
Base.size(::Point) = (2,)
# Base.size(::Point) = (2,)
Base.getindex(p::Point, i) = (p.x, p.y)[i]
Broadcast.broadcastable(x::Point) = x
Broadcast.BroadcastStyle(::Type{Point}) = Broadcast.Style{Point}()
Broadcast.BroadcastStyle(::Broadcast.AbstractArrayStyle{0}, s::Broadcast.Style{Point}) = s
Broadcast.BroadcastStyle(s::Broadcast.AbstractArrayStyle, ::Broadcast.Style{Point}) = s
Broadcast.BroadcastStyle(s::Broadcast.Style{Point}, ::Broadcast.Style{Tuple}) = s
Broadcast.instantiate(bc::Broadcast.Broadcasted{Broadcast.Style{Point}, Nothing}) = bc
function Broadcast.instantiate(bc::Broadcast.Broadcasted{Broadcast.Style{Point}})
Broadcast.check_broadcast_axes(bc.axes, bc.args...)
return bc
end
_point2tuple(p::Point) = (p.x,p.y)
_point2tuple(x) = x
_tuple2point(x::Tuple{Real, Real}) = Point(x)
_tuple2point(x::Tuple{Bool, Bool}) = x
@inline function Base.copy(bc_p::Broadcast.Broadcasted{Broadcast.Style{Point}})
args = _point2tuple.(bc_p.args)
bc_t = Broadcast.Broadcasted(bc_p.f, args, bc_p.axes)
return _tuple2point(copy(bc_t))
end
Broadcast.broadcastable(x::Point) = Ref(x)

# for iteration
Base.eltype(::Type{Point}) = Float64
Expand Down Expand Up @@ -236,24 +218,6 @@ function between(couple::NTuple{2,Point}, x)
return p1 + (x * (p2 - p1))
end

"""
between(p1::Point, p2::Point, r:range)
between(p1::Point, p2::Point, a:array)
Return an array of Points between point `p1` and point `p2` for
every `x` in range `r` or array `a`.
If `x` is 0.0, that point will be at `p1`; if `x` is 1.0, that point will be at `p2`.
When `x` is 0.5, that point is the midpoint between `p1` and `p2`.
"""
function Luxor.between(pt1::Point, pt2::Point, r::AbstractRange)
[between(pt1, pt2, e) for e in r]
end

function Luxor.between(pt1::Point, pt2::Point, a::AbstractArray)
[between(pt1, pt2, e) for e in a]
end

"""
perpendicular(p1::Point, p2::Point, p3::Point)
Expand Down
4 changes: 2 additions & 2 deletions src/polygons.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1256,7 +1256,7 @@ Move (permanently) a polygon from `frompoint` to `topoint`.
"""
function polymove!(pgon, frompoint::Point, topoint::Point)
d = topoint - frompoint
return pgon .+= Ref(d)
return pgon .+= d
end

"""
Expand All @@ -1266,7 +1266,7 @@ end
Scale (permanently) a polygon by `s`, relative to `center`.
"""
function polyscale!(pgon, s; center::Point = O)
return pgon .= between.(Ref(center), pgon, s)
return pgon .= between.(center, pgon, s)
end

"""
Expand Down
2 changes: 1 addition & 1 deletion src/randompoints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -153,5 +153,5 @@ bounding box `d` units apart.
function randompointarray(bbox::BoundingBox, d; kwargs...)
bw = boxwidth(bbox)
bh = boxheight(bbox)
return randompointarray(bw, bh, d; kwargs...) .- Ref(Point(bw/2, bh/2))
return randompointarray(bw, bh, d; kwargs...) .- Point(bw/2, bh/2)
end
4 changes: 2 additions & 2 deletions test/color-blend-test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ function color_blend_test(fname)
blendrad = blend(O, 1, O, 25, RGBA(0, 1, 1, 0.5), RGBA(0, 1, 0, 0.0))
blendlin = blend(O, Point(O.x + tiles.tilewidth/2, O.y), "orange", "magenta")
setblend(blendlin)
text("linear", O.+5)
text("linear", O + Point(5,5))
setblend(blendrad)
text("radial", O.-5)
text("radial", O - Point(5,5))
grestore()
end

Expand Down
2 changes: 1 addition & 1 deletion test/dispatcher.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ function drawthings(fname)
circle(O,100,:fillpreserve)
sethue("red")
circle(O,200,:stroke)
circle(O.+200,100,:strokepreserve)
circle(O+Point(200,200),100,:strokepreserve)
sethue("red")
fillpath()
origin()
Expand Down
2 changes: 1 addition & 1 deletion test/julia-logo-draw.jl
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ function boxes_and_rectangles(pt::Point)
for i = 1:20
randomhue()
poly(
box(pt .+ i, 10i, 10i, vertices = true),
box(pt + Point(i,i), 10i, 10i, vertices = true),
:stroke,
close = true,
)
Expand Down
7 changes: 3 additions & 4 deletions test/matrix-tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ end



function matrix_tests(fname)
@testset "matrix tests" begin
fname = "matrix-tests.pdf"
# matrix tests

# translate(dx, dy) = transform([1, 0, 0, 1, dx, dy]) shift by
Expand Down Expand Up @@ -195,12 +196,10 @@ function matrix_tests(fname)
text("hello world")

setmatrix(original_matrix)
text("0/0", O .+ 15)
text("0/0", O + Point(15, 15))

@test finish() == true
println("...finished test: output in $(fname)")
end

matrix_tests("matrix-tests.pdf")

pointmatrix("matrix-point-tests.png")
47 changes: 24 additions & 23 deletions test/point-arithmetic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ using Luxor, Test
using Random
Random.seed!(42)

function general_tests()
@testset "General tests" begin
pt1 = Point(rand() * 4, rand() * 4)

# number - Point (#270)
@test 10 .- Point(1, 1) == Point(10 - 1, 10 - 1) == Point(9, 9) == -Point(1, 1) .+ 10
@test Point(1, 1) .- 10 == Point(1 - 10, 1 - 10) == Point(1, 1) .+ -10 == -10 .+ Point(1, 1)
@test Point(10, 10) .- Point(1, 1) == Point(10 - 1, 10 - 1) == Point(9, 9) == -Point(1, 1) .+ Point(10, 10)
@test Point(1, 1) .- Point(10, 10) == Point(1 - 10, 1 - 10) == Point(1, 1) .+ Point(-10, -10) == -Point(10, 10) .+ Point(1, 1)

# arithmetic with tuples
@test pt1 + (5, 8) == Point(pt1.x + 5, pt1.y + 8)
Expand Down Expand Up @@ -38,8 +38,8 @@ function general_tests()
@test isinside(pt1 ./ 4, box(O, 10, 10, vertices=true))

# is point not in every corner of box
@test all(Ref(Point(1, 1)) .< box(O, 10, 10, vertices=true)) == false
@test any(Ref(Point(0, 0)) .< [Point(1, 1), Point(1, 2), Point(2, 3)]) == true
@test all(Point(1, 1) .< box(O, 10, 10, vertices=true)) == false
@test any(Point(0, 0) .< [Point(1, 1), Point(1, 2), Point(2, 3)]) == true
# is point outside every corner of box
@test all(Ref(Point(10, 10)) .> box(O, 10, 10, vertices=true)) == true

Expand Down Expand Up @@ -85,12 +85,13 @@ function general_tests()
pt4 = Point(6, 6)
@test intersectionlines(pt1, pt2, pt3, pt4)[1] == false

@test pt1 .* pt2 == Luxor.Point(25.0, 30.0)
@test pt1 .^ 2 == Luxor.Point(25.0, 25.0)
@test pt1 .^ 3 == Luxor.Point(125.0,125.0)
# Now `pt .^ 2` etc. are now allowed.
@test Point(Tuple(pt1) .* Tuple(pt2)) == Point(25.0, 30.0)
@test Point(Tuple(pt1) .^ 2) == Point(25.0, 25.0)
@test Point(Tuple(pt1) .^ 3) == Point(125.0,125.0)

@test all(pt1 .^ 1.5 < pt1 .^ 1.6)
@test all(pt1 .^ 1.6 > pt1 .^ 1.5)
@test all(Point(Tuple(pt1) .^ 1.5) < Point(Tuple(pt1) .^ 1.6))
@test all(Point(Tuple(pt1) .^ 1.6) > Point(Tuple(pt1) .^ 1.5))

# test between interpolation
@test isequal(midpoint(pt1, pt3), between(pt1, pt3, 0.5))
Expand Down Expand Up @@ -133,7 +134,10 @@ function general_tests()
@test_throws ErrorException pointinverse(cpt, cpt, rad)
end

function point_arithmetic_test(fname, npoints=20)
@testset "point_arithmetic_test" begin
fname = "point-arithmetic.pdf"
npoints = 100

Drawing(1200, 1200, fname)
background("white")
sethue("thistle")
Expand All @@ -146,12 +150,12 @@ function point_arithmetic_test(fname, npoints=20)
randompoints = randompointarray(Point(-600, -600), Point(600, 600), npoints)

# +
pl1 = map(pt -> pt .+ 2, randompoints)
pl1a = map(pt -> 2 .+ pt, randompoints)
pl1 = map(pt -> pt + Point(2,2), randompoints)
pl1a = map(pt -> Point(2,2) + pt, randompoints)

# -
pl2 = map(pt -> pt .- 2, randompoints)
pl2a = map(pt -> 2 .- pt, randompoints)
pl2 = map(pt -> pt - Point(2,2), randompoints)
pl2a = map(pt -> Point(2,2) - pt, randompoints)

# *
pl3 = map(pt -> pt * rand(), randompoints)
Expand All @@ -170,7 +174,7 @@ function point_arithmetic_test(fname, npoints=20)
pl6a = [1.03, 0.97, -1.05] .* randompoints[1:3]

# ^
pl7 = map(pt -> .^(pt/2, 2), randompoints)
pl7 = map(pt -> Point(.^(Tuple(pt/2), 2)), randompoints)

# ^ FAILS
# pl8 = map(pt -> ^(pt, 1.2), randompoints)
Expand All @@ -191,7 +195,7 @@ function point_arithmetic_test(fname, npoints=20)
if f(randompoints[i], randompoints[i+1])
circle(randompoints[i], 18, :fill)
circle(randompoints[i+1], 7, :fill)
text(string("$f"), randompoints[i] .- 12)
text(string("$f"), randompoints[i] - Point(12, 12))
end
end
end
Expand All @@ -202,15 +206,15 @@ function point_arithmetic_test(fname, npoints=20)
for i in 1:length(randompoints)-1
if f.(randompoints[1:npoints], randompoints[npoints:-1:1]) != true
ellipse(randompoints[i], 19, 32, :fill)
text(string("v6"), randompoints[i] .- 6)
text(string("v6"), randompoints[i] - Point(6, 6))
end
end
end

sethue("purple")
for i in 1:length(randompoints)-1
v = cmp(randompoints[i], randompoints[i+1])
text(string(round(v, digits=1)), randompoints[i] .+ 15)
text(string(round(v, digits=1)), randompoints[i] + Point(15, 15))
end

sethue("cyan")
Expand All @@ -231,13 +235,10 @@ function point_arithmetic_test(fname, npoints=20)
if any(randompoints .!= randompoints)
error("elementwise comparison failed")
else
text("the points really do compare elementwise", O .+ 15)
text("the points really do compare elementwise", O + Point(15, 15))
end

@test finish() == true

println("...finished test: output in $(fname)")
end

general_tests()
point_arithmetic_test("point-arithmetic.pdf", 100)
4 changes: 2 additions & 2 deletions test/various-points-tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ function rotate_points_test(fname)
circle.(pts, 10, :stroke)

# rotate each point by 2π
pts1 = rotatepoint.(pts, Ref(O), 2π)
pts1 = rotatepoint.(pts, O, 2π)

sethue("blue")
circle.(pts1, 20, :stroke)
Expand All @@ -21,7 +21,7 @@ function rotate_points_test(fname)
end

# now rotate each point by π
pts2 = rotatepoint.(pts, Ref(O), π)
pts2 = rotatepoint.(pts, O, π)
sethue("green")
circle.(pts2, 30, :stroke)

Expand Down

0 comments on commit fa064b8

Please sign in to comment.