@@ -309,6 +309,97 @@ const geomtypes = [
309309 GeometryCollection,
310310]
311311
312+ Base. @kwdef struct IsApprox
313+ atol:: Float64 = 0.0
314+ rtol:: Float64 = sqrt (eps (Float64))
315+ end
316+
317+ function Base.:(== )(geo1:: AbstractGeometry , geo2:: AbstractGeometry ):: Bool
318+ compare (== , geo1, geo2)
319+ end
320+ function Base. isequal (geo1:: AbstractGeometry , geo2:: AbstractGeometry ):: Bool
321+ compare (isequal, geo1, geo2)
322+ end
323+ function Base. isapprox (geo1:: AbstractGeometry , geo2:: AbstractGeometry ; kw... ):: Bool
324+ compare (IsApprox (;kw... ), geo1, geo2)
325+ end
326+ function (cmp:: IsApprox )(geo1:: AbstractGeometry , geo2:: AbstractGeometry ):: Bool
327+ compare (cmp, geo1, geo2)
328+ end
329+ function compare (≅ , geo1:: AbstractGeometry , geo2:: AbstractGeometry ):: Bool
330+ (typeof (geo1) === typeof (geo2)) || return false
331+ ng1 = ngeom (geo1)
332+ ng2 = ngeom (geo2)
333+ ng1 == ng2 || return false
334+ for i in 1 : ng1
335+ (getgeom (geo1, i) ≅ getgeom (geo2, i)) || return false
336+ end
337+ return true
338+ end
339+ function compare (≅ , pt1:: Point , pt2:: Point ):: Bool
340+ is3d = GeoInterface. is3d (pt1)
341+ is3d === GeoInterface. is3d (pt2) || return false
342+ GeoInterface. getcoord (pt1,1 ) ≅ GeoInterface. getcoord (pt2,1 ) || return false
343+ GeoInterface. getcoord (pt1,2 ) ≅ GeoInterface. getcoord (pt2,2 ) || return false
344+ if is3d
345+ GeoInterface. getcoord (pt1,3 ) ≅ GeoInterface. getcoord (pt2,3 ) || return false
346+ end
347+ return true
348+ end
349+
350+ function _norm (x,y,z)
351+ return sqrt (x^ 2 + y^ 2 + z^ 2 )
352+ end
353+
354+ function compare (cmp:: IsApprox , pt1:: Point , pt2:: Point ):: Bool
355+ is3d = GeoInterface. is3d (pt1)
356+ is3d === GeoInterface. is3d (pt2) || return false
357+ x1 = GeoInterface. getcoord (pt1,1 )
358+ x2 = GeoInterface. getcoord (pt2,1 )
359+ y1 = GeoInterface. getcoord (pt1,2 )
360+ y2 = GeoInterface. getcoord (pt2,2 )
361+ if is3d
362+ z1 = GeoInterface. getcoord (pt1,3 )
363+ z2 = GeoInterface. getcoord (pt2,3 )
364+ else
365+ z1 = 0.0
366+ z2 = 0.0
367+ end
368+ lhs = _norm (x1 - x2, y1 - y2, z1 - z2)
369+ rhs = cmp. atol + cmp. rtol * max (_norm (x1,y1,z2), _norm (x2,y2,z2))
370+ return lhs <= rhs
371+ end
372+
373+ typesalt (:: Type{GeometryCollection} ) = 0xd1fd7c6403c36e5b
374+ typesalt (:: Type{PreparedGeometry} ) = 0xbc1a26fe2f5b7537
375+ typesalt (:: Type{LineString} ) = 0x712352fe219fca15
376+ typesalt (:: Type{LinearRing} ) = 0xac7644fd36955ef1
377+ typesalt (:: Type{MultiLineString} ) = 0x85aff0a53a2f2a32
378+ typesalt (:: Type{MultiPoint} ) = 0x6213e67dbfd3b570
379+ typesalt (:: Type{MultiPolygon} ) = 0xff2f957b4cdb5832
380+ typesalt (:: Type{Point} ) = 0x4b5c101d3843160e
381+ typesalt (:: Type{Polygon} ) = 0xa5c895d62ef56723
382+
383+ function Base. hash (geo:: AbstractGeometry , h:: UInt ):: UInt
384+ salt = typesalt (typeof (geo))
385+ h = hash (salt, h)
386+ for i in 1 : ngeom (geo)
387+ g = getgeom (geo,i)
388+ h = hash (g, h)
389+ end
390+ return h
391+ end
392+
393+ function Base. hash (pt:: Point , h:: UInt ):: UInt
394+ h = hash (getcoord (pt,1 ), h)
395+ h = hash (getcoord (pt,2 ), h)
396+ if GeoInterface. is3d (pt)
397+ h = hash (getcoord (pt,3 ), h)
398+ end
399+ h = hash (getcoord (pt,2 ), h)
400+ return h
401+ end
402+
312403# teach ccall how to get the pointer to pass to libgeos
313404# this way the Julia compiler will track the lifetimes for us
314405Base. unsafe_convert (:: Type{Ptr{Cvoid}} , x:: AbstractGeometry ) = x. ptr
0 commit comments