Skip to content

Commit 350152f

Browse files
authored
Don't clone on pointers. (#198)
1 parent d8e9986 commit 350152f

File tree

1 file changed

+110
-39
lines changed

1 file changed

+110
-39
lines changed

src/geos_types.jl

Lines changed: 110 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,16 @@ end
2929
mutable struct Point <: AbstractGeometry
3030
ptr::GEOSGeom
3131
context::GEOSContext
32+
function Point(obj::Point, context::GEOSContext = get_global_context())
33+
point = new(cloneGeom(obj, context), context)
34+
finalizer(destroyGeom, point)
35+
point
36+
end
3237
# create a point from a pointer - only makese sense if it is a pointer to a point, otherwise error
33-
function Point(obj::Union{Point,GEOSGeom}, context::GEOSContext = get_global_context())
38+
function Point(obj::GEOSGeom, context::GEOSContext = get_global_context())
3439
id = LibGEOS.geomTypeId(obj, context)
3540
point = if id == GEOS_POINT
36-
point = new(cloneGeom(obj, context), context)
41+
point = new(obj, context)
3742
else
3843
open_issue_if_conversion_makes_sense(Point, id)
3944
end
@@ -52,15 +57,25 @@ end
5257
mutable struct MultiPoint <: AbstractMultiGeometry
5358
ptr::GEOSGeom
5459
context::GEOSContext
60+
function MultiPoint(obj::Point, context::GEOSContext = get_global_context())
61+
multipoint = new(
62+
createCollection(GEOS_MULTIPOINT, [cloneGeom(obj, context)], context),
63+
context,
64+
)
65+
finalizer(destroyGeom, multipoint)
66+
multipoint
67+
end
68+
function MultiPoint(obj::MultiPoint, context::GEOSContext = get_global_context())
69+
multipoint = new(cloneGeom(obj, context), context)
70+
finalizer(destroyGeom, multipoint)
71+
multipoint
72+
end
5573
# create a multipoint from a pointer - only makes sense if it is a pointer to a multipoint
5674
# or to a point, otherwise error
57-
function MultiPoint(
58-
obj::Union{Point,MultiPoint,GEOSGeom},
59-
context::GEOSContext = get_global_context(),
60-
)
75+
function MultiPoint(obj::GEOSGeom, context::GEOSContext = get_global_context())
6176
id = LibGEOS.geomTypeId(obj, context)
6277
multipoint = if id == GEOS_MULTIPOINT
63-
new(cloneGeom(obj, context), context)
78+
new(obj, context)
6479
elseif id == GEOS_POINT
6580
new(createCollection(GEOS_MULTIPOINT, [cloneGeom(obj, context)], context), context)
6681
else
@@ -83,20 +98,25 @@ mutable struct MultiPoint <: AbstractMultiGeometry
8398
)
8499
# create a multipoint from a list of points
85100
MultiPoint(points::Vector{LibGEOS.Point}, context::GEOSContext = get_context(points)) =
86-
MultiPoint(createCollection(GEOS_MULTIPOINT, points, context), context)
101+
MultiPoint(
102+
createCollection(GEOS_MULTIPOINT, cloneGeom.(points, Ref(context)), context),
103+
context,
104+
)
87105
end
88106

89107
mutable struct LineString <: AbstractGeometry
90108
ptr::GEOSGeom
91109
context::GEOSContext
110+
function LineString(obj::LineString, context::GEOSContext = get_global_context())
111+
line = new(cloneGeom(obj, context), context)
112+
finalizer(destroyGeom, line)
113+
line
114+
end
92115
# create a linestring from a linestring pointer, otherwise error
93-
function LineString(
94-
obj::Union{LineString,GEOSGeom},
95-
context::GEOSContext = get_global_context(),
96-
)
116+
function LineString(obj::GEOSGeom, context::GEOSContext = get_global_context())
97117
id = LibGEOS.geomTypeId(obj, context)
98118
line = if id == GEOS_LINESTRING
99-
new(cloneGeom(obj, context), context)
119+
new(obj, context)
100120
else
101121
open_issue_if_conversion_makes_sense(LineString, id)
102122
end
@@ -122,14 +142,27 @@ end
122142
mutable struct MultiLineString <: AbstractMultiGeometry
123143
ptr::GEOSGeom
124144
context::GEOSContext
125-
# create a multiline string from a multilinestring or a linestring pointer, else error
126145
function MultiLineString(
127-
obj::Union{LineString,MultiLineString,GEOSGeom},
146+
obj::MultiLineString,
128147
context::GEOSContext = get_global_context(),
129148
)
149+
multiline = new(cloneGeom(obj, context), context)
150+
finalizer(destroyGeom, multiline)
151+
multiline
152+
end
153+
function MultiLineString(obj::LineString, context::GEOSContext = get_global_context())
154+
multiline = new(
155+
createCollection(GEOS_MULTILINESTRING, [cloneGeom(obj, context)], context),
156+
context,
157+
)
158+
finalizer(destroyGeom, multiline)
159+
multiline
160+
end
161+
# create a multiline string from a multilinestring or a linestring pointer, else error
162+
function MultiLineString(obj::GEOSGeom, context::GEOSContext = get_global_context())
130163
id = LibGEOS.geomTypeId(obj, context)
131164
multiline = if id == GEOS_MULTILINESTRING
132-
new(cloneGeom(obj, context), context)
165+
new(obj, context)
133166
elseif id == GEOS_LINESTRING
134167
new(
135168
createCollection(GEOS_MULTILINESTRING, [cloneGeom(obj, context)], context),
@@ -159,7 +192,7 @@ mutable struct MultiLineString <: AbstractMultiGeometry
159192
) = MultiLineString(
160193
createCollection(
161194
GEOS_MULTILINESTRING,
162-
GEOSGeom[ls.ptr for ls in multiline],
195+
GEOSGeom[cloneGeom(ls, context) for ls in multiline],
163196
context,
164197
),
165198
context,
@@ -169,14 +202,16 @@ end
169202
mutable struct LinearRing <: AbstractGeometry
170203
ptr::GEOSGeom
171204
context::GEOSContext
205+
function LinearRing(obj::LinearRing, context::GEOSContext = get_global_context())
206+
ring = new(cloneGeom(obj, context), context)
207+
finalizer(destroyGeom, ring)
208+
ring
209+
end
172210
# create a linear ring from a linear ring pointer, otherwise error
173-
function LinearRing(
174-
obj::Union{LinearRing,GEOSGeom},
175-
context::GEOSContext = get_global_context(),
176-
)
211+
function LinearRing(obj::GEOSGeom, context::GEOSContext = get_global_context())
177212
id = LibGEOS.geomTypeId(obj, context)
178213
ring = if id == GEOS_LINEARRING
179-
new(cloneGeom(obj, context), context)
214+
new(obj, context)
180215
else
181216
open_issue_if_conversion_makes_sense(LinearRing, id)
182217
end
@@ -198,16 +233,23 @@ end
198233
mutable struct Polygon <: AbstractGeometry
199234
ptr::GEOSGeom
200235
context::GEOSContext
236+
function Polygon(obj::Polygon, context::GEOSContext = get_global_context())
237+
polygon = new(cloneGeom(obj, context), context)
238+
finalizer(destroyGeom, polygon)
239+
polygon
240+
end
241+
function Polygon(obj::LinearRing, context::GEOSContext = get_global_context())
242+
polygon = new(createPolygon(cloneGeom(obj, context), context), context)
243+
finalizer(destroyGeom, polygon)
244+
polygon
245+
end
201246
# create polygon using GEOSGeom pointer - only makes sense if pointer points to a polygon or a linear ring to start with.
202-
function Polygon(
203-
obj::Union{Polygon,LinearRing,GEOSGeom},
204-
context::GEOSContext = get_global_context(),
205-
)
247+
function Polygon(obj::GEOSGeom, context::GEOSContext = get_global_context())
206248
id = LibGEOS.geomTypeId(obj, context)
207249
polygon = if id == GEOS_POLYGON
208-
new(cloneGeom(obj, context), context)
250+
new(obj, context)
209251
elseif id == GEOS_LINEARRING
210-
new(cloneGeom(createPolygon(obj, context), context), context)
252+
new(createPolygon(obj, context), context)
211253
else
212254
open_issue_if_conversion_makes_sense(Polygon, id)
213255
end
@@ -231,20 +273,37 @@ mutable struct Polygon <: AbstractGeometry
231273
exterior::LinearRing,
232274
holes::Vector{LinearRing},
233275
context::GEOSContext = get_context(exterior),
234-
) = Polygon(createPolygon(exterior, holes, context), context)
276+
) = Polygon(
277+
createPolygon(
278+
cloneGeom(exterior, context),
279+
cloneGeom.(holes, Ref(context)),
280+
context,
281+
),
282+
context,
283+
)
235284
end
236285

237286
mutable struct MultiPolygon <: AbstractMultiGeometry
238287
ptr::GEOSGeom
239288
context::GEOSContext
289+
function MultiPolygon(obj::MultiPolygon, context::GEOSContext = get_global_context())
290+
multipolygon = new(cloneGeom(obj, context), context)
291+
finalizer(destroyGeom, multipolygon)
292+
multipolygon
293+
end
294+
function MultiPolygon(obj::Polygon, context::GEOSContext = get_global_context())
295+
multipolygon = new(
296+
createCollection(GEOS_MULTIPOLYGON, [cloneGeom(obj, context)], context),
297+
context,
298+
)
299+
finalizer(destroyGeom, multipolygon)
300+
multipolygon
301+
end
240302
# create multipolygon using a multipolygon or polygon pointer, else error
241-
function MultiPolygon(
242-
obj::Union{Polygon,MultiPolygon,GEOSGeom},
243-
context::GEOSContext = get_global_context(),
244-
)
303+
function MultiPolygon(obj::GEOSGeom, context::GEOSContext = get_global_context())
245304
id = LibGEOS.geomTypeId(obj, context)
246305
multipolygon = if id == GEOS_MULTIPOLYGON
247-
new(cloneGeom(obj, context), context)
306+
new(obj, context)
248307
elseif id == GEOS_POLYGON
249308
new(
250309
createCollection(GEOS_MULTIPOLYGON, [cloneGeom(obj, context)], context),
@@ -259,7 +318,14 @@ mutable struct MultiPolygon <: AbstractMultiGeometry
259318

260319
# create multipolygon from list of Polygon objects
261320
MultiPolygon(polygons::Vector{Polygon}, context::GEOSContext = get_context(polygons)) =
262-
MultiPolygon(createCollection(GEOS_MULTIPOLYGON, polygons, context), context)
321+
MultiPolygon(
322+
createCollection(
323+
GEOS_MULTIPOLYGON,
324+
cloneGeom.(polygons, Ref(context)),
325+
context,
326+
),
327+
context,
328+
)
263329

264330
# create multipolygon using list of polygon coordinates - note that each polygon can have holes as explained above in Polygon comments
265331
MultiPolygon(
@@ -284,14 +350,19 @@ end
284350
mutable struct GeometryCollection <: AbstractMultiGeometry
285351
ptr::GEOSGeom
286352
context::GEOSContext
287-
# create a geometric collection from a pointer to a geometric collection, else error
288353
function GeometryCollection(
289-
obj::Union{GeometryCollection,GEOSGeom},
354+
obj::GeometryCollection,
290355
context::GEOSContext = get_global_context(),
291356
)
357+
geometrycollection = new(cloneGeom(obj, context), context)
358+
finalizer(destroyGeom, geometrycollection)
359+
geometrycollection
360+
end
361+
# create a geometric collection from a pointer to a geometric collection, else error
362+
function GeometryCollection(obj::GEOSGeom, context::GEOSContext = get_global_context())
292363
id = LibGEOS.geomTypeId(obj, context)
293364
geometrycollection = if id == GEOS_GEOMETRYCOLLECTION
294-
new(cloneGeom(obj, context), context)
365+
new(obj, context)
295366
else
296367
open_issue_if_conversion_makes_sense(GeometryCollection, id)
297368
end
@@ -312,7 +383,7 @@ mutable struct GeometryCollection <: AbstractMultiGeometry
312383
) = GeometryCollection(
313384
createCollection(
314385
GEOS_GEOMETRYCOLLECTION,
315-
GEOSGeom[geom.ptr for geom in collection],
386+
GEOSGeom[cloneGeom(geom, context) for geom in collection],
316387
context,
317388
),
318389
context,

0 commit comments

Comments
 (0)