Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A few updates #10

Merged
merged 10 commits into from
Feb 2, 2015
Merged
34 changes: 32 additions & 2 deletions src/Clipper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,14 @@ function Path(ct::Integer=0)
@cxx ClipperLib::Path(ct)
end

function Path(pts::Vector{(Int, Int)}, ct::Integer=0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ct isn't needed here, because Path(::Int) preallocates and this is push!ing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the ct argument.

p = Path(ct)
for point in pts
push!(p, IntPoint(point...))
end
p
end


@doc """
This structure is fundamental to the Clipper Library. It's a list or array of
Expand Down Expand Up @@ -534,6 +542,10 @@ function Base.length(c::__ClipperPolyTree)
@cxx c->Total()
end

function child_count(c::__ClipperPolyTree)
@cxx c->ChildCount()
end

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs tests.

Apparently the PolyTree is just an array of PolyNodes: https://github.com/Voxel8/Clipper.jl/blob/6a3cce9ea409d7b4977024e3bbee1830955cb205/src/clipper_cpp.jl#L138

It would be convenient if we could define getindex too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wrote a test for child_count.

I am struggling with implementing getindex. Here is what I tried:

@inline function Base.getindex(p::__ClipperPolyTree, i::Integer)
    icxx"$p[$i-1];"
end

I get the following error when I try to call getindex

ERROR: LoadError: MethodError: `getindex` has no method matching getindex(::Cxx.CppValue{Cxx.CppBaseType{symbol("ClipperLib::PolyTree")},(false,false,false)}, ::Int64)
Closest candidates are:
  getindex(::(Any...,), ::Int64)
  getindex(::(Any...,), ::Real)
  getindex{T}(::FloatRange{T}, ::Integer)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PolyTree is a subclass of PolyNode, so I don't think getindex makes sense. See definition here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed getindex from this PR. If we later decide we want it we can add it back in in another PR.

@doc """
The returned Polynode will be the first child if any, otherwise the next
sibling, otherwise the next sibling of the Parent etc.
Expand Down Expand Up @@ -701,7 +713,7 @@ parameter is the amount to which the supplied paths will be offset - negative
delta values to shrink polygons and positive delta to expand them.

This method can be called multiple times, offsetting the same paths by different
amounts (ie using different deltas).
amounts (ie using different deltas)
""" ->
function execute!(c::__ClipperClipperOffset, sol::__ClipperPaths, delta)
@cxx c->Execute(sol, delta)
Expand Down Expand Up @@ -926,6 +938,10 @@ end
@cxx a->push_back(b)
end

@inline function Base.push!(a::__ClipperPath, b::(Int, Int))
push!(a, IntPoint(b...))
end

@inline function Base.push!(a::__ClipperPaths,
b::__ClipperPath)
@cxx a->push_back(b)
Expand Down Expand Up @@ -979,6 +995,14 @@ end
length(p)
end

function ==(a::__ClipperPath, b::__ClipperPath)
length(a) != length(b) && return false
for i = 1:length(a)
a[i] != b[i] && return false
end
return true
end

function Base.show(io::IO, v::__ClipperIntPoint)
print(io, string("(", x(v),",", y(v),")"))
end
Expand All @@ -991,15 +1015,21 @@ function Base.show(io::IO, p::__ClipperPath)
if isempty(p)
return
end
print("Path([")
for i = 1:length(p)-1
print(io, string("(", x(p[i]), ",", y(p[i]), "), "))
end
print(io, string("(", x(p[end]), ",", y(p[end]), ")"))
print("])")
end

function Base.show(io::IO, p::__ClipperPaths)
for i = 1:length(p)
len = length(p)
for i = 1:len
show(io, p[i])
if i < len
print(io, "; ")
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that you made show(::Path) output code that can construct it. Can you do the same for Paths?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a show method that works, but I am having trouble writing a constructor for Paths() that takes an array of Path() objects. It appears I can't specify an array of a type alias, @sjkelly does that sound correct?

end
end

Expand Down
58 changes: 58 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@ push!(a, b)
push!(a, b)
println(a)

#test path constructor
p1 = Path()
push!(p1, IntPoint(0, 0))
push!(p1, IntPoint(0, 10))
push!(p1, IntPoint(10, 10))
p2 = Path([(0,0), (0,10), (10,10)])
@test p1 == p2

#test push shortcut
p = Path()
push!(p, (0, 0))
@test p == Path([(0,0)])

# test setindex
p = Path(2)
p[1] = IntPoint(1,1)
Expand Down Expand Up @@ -239,6 +252,51 @@ f = first(sol)
@show next(f)
@show parent(f)

# path equality
println("Testing path equality")
p1 = Path()
push!(p1, IntPoint(0,0))
push!(p1, IntPoint(10,0))
push!(p1, IntPoint(10,10))
p2 = Path()
push!(p2, IntPoint(0,0))
push!(p2, IntPoint(10,0))
push!(p2, IntPoint(10,10))
@test p1 == p2

# offsetting a polygon with holes.
println("Testing offset of a polygon with holes...")
perimeter = Path()
push!(perimeter, IntPoint(-10,-10))
push!(perimeter, IntPoint(60,-10))
push!(perimeter, IntPoint(60,60))
push!(perimeter, IntPoint(-10,60))

hole = Path()
push!(hole, IntPoint(4,4))
push!(hole, IntPoint(4,8))
push!(hole, IntPoint(8,8))
push!(hole, IntPoint(8,4))

hole2 = Path()
push!(hole2, IntPoint(12,4))
push!(hole2, IntPoint(12,8))
push!(hole2, IntPoint(16,8))
push!(hole2, IntPoint(16,4))

o = Offset()
paths = Paths()
push!(paths, perimeter)
push!(paths, hole)
push!(paths, hole2)
add!(o, paths, jtMiter, etClosedPolygon)

outpaths = Paths()
execute!(o, outpaths, -2)
@test length(outpaths) == 2
@show outpaths[1]
@show outpaths

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra prints should be removed. For testing, silent == all good.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a lot of these. We can keep everything silent by making an IOBuffer and checking string equality:

julia> p = Path(5)
(0,0), (0,0), (0,0), (0,0), (0,0)

julia> a = IOBuffer()
IOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=0, maxsize=Inf, ptr=1, mark=-1)

julia> show(a, p)

julia> ASCIIString(a.data)
"(0,0), (0,0), (0,0), (0,0), (0,0)"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've implemented the tests using an IOBuffer


p = Path()
push!(p, IntPoint(0,0))
push!(p, IntPoint(10,0))
Expand Down