Skip to content

Commit fb9a3d7

Browse files
authored
Switch to re-entrant methods (#46)
* switch to re-entrant methods we switch from GEOSconnection (with a `status::Symbol`) to GEOScontext (with a `ptr::GEOSContextHandle_t`), since the former is deprecated for the latter. This change only applies to everything after GEOS v3.5.0. There will be a global-level `_context` object that is passed to every method to maintain the same behavior for now. We might want to also provide methods that allows users to pass in their own context, and fallback on the global _context object otherwise. * expose `context::GEOScontext` as an optional argument to all methods * switch to WK*Reader and WK*Writer style methods - introduced `WKTReader`, `WKBReader`, `WKTWriter` and `WKBWriter` types - we should be promoting the Julian (wrapper) geometry types through `readgeom` and `writegeom`, rather than encouraging the C-pointers in `_readgeom` and `_writegeom` - the corresponding changes are `parseWKT` -> `readgeom`, `geomFromWKT` -> `_readgeom`, and `geomToWKT` -> `_writegeom` - moved the `GEOMTYPE` dict into `src/geos_operations.jl` since `src/geos_functions.jl` is meant more for a direct 1-1 mapping with the corresponding C functions * bugfix * remove module readers and writers in favor of ones local to methods * update docs * add deprecated functions for a smoother transition * GEOScontext -> GEOSContext * test readgeom instead of _readgeom * bugfix
1 parent f3ad74e commit fb9a3d7

15 files changed

+1531
-5985
lines changed

README.md

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,42 +9,37 @@ LibGEOS is a LGPL-licensed package for manipulation and analysis of planar geome
99
Among other things, it allows you to parse [Well-known Text (WKT)](https://en.wikipedia.org/wiki/Well-known_text)
1010

1111
```julia
12-
p1 = parseWKT("POLYGON((0 0,1 0,1 1,0 0))")
13-
p2 = parseWKT("POLYGON((0 0,1 0,1 1,0 1,0 0))")
14-
p3 = parseWKT("POLYGON((2 0,3 0,3 1,2 1,2 0))")
12+
p1 = readgeom("POLYGON((0 0,1 0,1 1,0 0))")
13+
p2 = readgeom("POLYGON((0 0,1 0,1 1,0 1,0 0))")
14+
p3 = readgeom("POLYGON((2 0,3 0,3 1,2 1,2 0))")
1515
```
1616
![Example 1](examples/example1.png)
1717

1818
Add a buffer around them
1919
```julia
20-
g1 = buffer(p1,0.5)
21-
g2 = buffer(p2,0.5)
22-
g3 = buffer(p3,0.5)
20+
g1 = buffer(p1, 0.5)
21+
g2 = buffer(p2, 0.5)
22+
g3 = buffer(p3, 0.5)
2323
```
2424
![Example 2](examples/example2.png)
2525

2626
and take the union of different geometries
2727
```julia
28-
polygon = union(buffer(p1,0.5),buffer(p3,0.5))
28+
polygon = LibGEOS.union(g1, g3)
2929
```
3030
![Example 3](examples/example3.png)
3131

3232
GEOS functionality is extensive, so coverage is incomplete, but the basic functionality for working with geospatial data is already available. I'm learning as I go along, so documentation is lacking, but if you're interested, you can have a look at the examples in the `examples/` folder, or the tests in `test/test_geo_interface.jl` and `test/test_geos_operations.jl`.
3333

34-
Installation (on Linux and OS X)
34+
Installation
3535
------------
36-
1. First, install a copy of GEOS, and point the `LD_LIBRARY_PATH` (Linux) or `DYLD_LIBRARY_PATH` (OS X) variable to the GEOS library by adding, e.g.,
37-
```bash
38-
export DYLD_LIBRARY_PATH="/usr/local/Cellar/geos/3.4.2/lib:$DYLD_LIBRARY_PATH"
39-
```
40-
to your start-up file (e.g. ``.bash_profile``).
41-
42-
2. At the Julia prompt, run
36+
1. At the Julia prompt, run
4337
```julia
4438
julia> Pkg.add("LibGEOS")
4539
```
40+
This will install both the Julia package and GEOS shared libraries together. To just reinstall the GEOS shared libraries, run `Pkg.build("LibGEOS")`.
4641

47-
3. Test that `LibGEOS` works by runnning
42+
2. Test that `LibGEOS` works by runnning
4843
```julia
4944
julia> Pkg.test("LibGEOS")
5045
```

examples/example1.png

-22.2 KB
Loading

examples/example2.png

-11.2 KB
Loading

examples/example3.png

-13.2 KB
Loading

examples/readme_examples.ipynb

Lines changed: 910 additions & 5465 deletions
Large diffs are not rendered by default.

src/LibGEOS.jl

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ module LibGEOS
1313
import Base: contains
1414

1515
export Point, MultiPoint, LineString, MultiLineString, LinearRing, Polygon, MultiPolygon, GeometryCollection,
16-
parseWKT, geomFromWKT, geomToWKT,
16+
parseWKT, geomFromWKT, geomToWKT, readgeom, writegeom,
1717
project, projectNormalized, interpolate, interpolateNormalized,
1818
buffer, envelope, intersection, convexhull, difference, symmetricDifference,
1919
boundary, union, unaryUnion, pointOnSurface, centroid, node,
@@ -40,35 +40,85 @@ module LibGEOS
4040
end
4141
end
4242

43-
mutable struct GEOSconnection
44-
status::Symbol
43+
mutable struct GEOSContext
44+
ptr::GEOSContextHandle_t
4545

46-
function GEOSconnection()
47-
connection = new(:Initialized)
48-
initializeGEOS(
49-
C_NULL,
46+
function GEOSContext()
47+
context = new(GEOS_init_r())
48+
GEOSContext_setNoticeHandler_r(context.ptr, C_NULL)
49+
GEOSContext_setErrorHandler_r(context.ptr,
5050
cfunction(geosjl_errorhandler,Ptr{Void},(Ptr{UInt8},Ptr{Void}))
5151
)
52-
finalizer(connection, finalizeGEOS)
53-
connection
52+
finalizer(context, context -> (GEOS_finish_r(context.ptr); context.ptr = C_NULL))
53+
context
5454
end
5555
end
5656

57-
initializeGEOS(notice_f, error_f) = initGEOS(notice_f, error_f)
58-
function finalizeGEOS(connection::GEOSconnection)
59-
connection.status = :Finished
60-
finishGEOS()
57+
mutable struct WKTReader
58+
ptr::Ptr{GEOSWKTReader}
59+
60+
function WKTReader(context::GEOSContext)
61+
reader = new(GEOSWKTReader_create_r(context.ptr))
62+
finalizer(reader, function(reader)
63+
GEOSWKTReader_destroy_r(context.ptr, reader.ptr)
64+
reader.ptr = C_NULL
65+
end)
66+
reader
67+
end
68+
end
69+
70+
mutable struct WKTWriter
71+
ptr::Ptr{GEOSWKTWriter}
72+
73+
function WKTWriter(context::GEOSContext; trim::Bool=true, outputdim::Int=3, roundingprecision::Int=-1)
74+
writer = new(GEOSWKTWriter_create_r(context.ptr))
75+
finalizer(writer, function(writer)
76+
GEOSWKTWriter_destroy_r(context.ptr, writer.ptr)
77+
GEOSWKTWriter_setTrim_r(context.ptr, writer.ptr, UInt8(trim))
78+
GEOSWKTWriter_setOutputDimension_r(context.ptr, writer.ptr, outputdim)
79+
GEOSWKTWriter_setRoundingPrecision_r(context.ptr, writer.ptr, roundingprecision)
80+
writer.ptr = C_NULL
81+
end)
82+
writer
83+
end
84+
end
85+
86+
mutable struct WKBReader
87+
ptr::Ptr{GEOSWKBReader}
88+
89+
function WKBReader(context::GEOSContext)
90+
reader = new(GEOSWKBReader_create_r(context.ptr))
91+
finalizer(reader, function(reader)
92+
GEOSWKBReader_destroy_r(context.ptr, reader.ptr)
93+
reader.ptr = C_NULL
94+
end)
95+
reader
96+
end
97+
end
98+
99+
mutable struct WKBWriter
100+
ptr::Ptr{GEOSWKBWriter}
101+
102+
function WKBWriter(context::GEOSContext)
103+
writer = new(GEOSWKBWriter_create_r(context.ptr))
104+
finalizer(writer, function(writer)
105+
GEOSWKBWriter_destroy_r(context.ptr, writer.ptr)
106+
writer.ptr = C_NULL
107+
end)
108+
writer
109+
end
61110
end
62111

63112
function __init__()
64113
# Always check your dependencies from `deps.jl`
65114
check_deps()
66115

67-
global const _connection = GEOSconnection()
116+
global const _context = GEOSContext()
68117
end
69118

70119
include("geos_functions.jl")
71120
include("geos_types.jl")
72121
include("geos_operations.jl")
73122
include("geo_interface.jl")
123+
include("deprecated.jl")
74124
end

src/deprecated.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
@Base.deprecate parseWKT(geom::String) readgeom(geom)
2+
@Base.deprecate geomFromWKT(geom::String) _readgeom(geom)
3+
@Base.deprecate geomToWKT(geom::Ptr{GEOSGeometry}) writegeom(geom)

src/geos_c.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,14 @@ function finishGEOS_r(handle::GEOSContextHandle_t)
5454
ccall((:finishGEOS_r,libgeos),Void,(GEOSContextHandle_t,),handle)
5555
end
5656

57+
function GEOS_init_r()
58+
ccall((:GEOS_init_r,libgeos),GEOSContextHandle_t,())
59+
end
60+
61+
function GEOS_finish_r(handle::GEOSContextHandle_t)
62+
ccall((:GEOS_finish_r,libgeos),Void,(GEOSContextHandle_t,),handle)
63+
end
64+
5765
function GEOSContext_setNoticeHandler_r(extHandle::GEOSContextHandle_t,nf::GEOSMessageHandler)
5866
ccall((:GEOSContext_setNoticeHandler_r,libgeos),GEOSMessageHandler,(GEOSContextHandle_t,GEOSMessageHandler),extHandle,nf)
5967
end

0 commit comments

Comments
 (0)