Skip to content

Commit

Permalink
✔️ append polygonize variants tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sanak committed May 18, 2024
1 parent 052541a commit f0a1b49
Showing 1 changed file with 168 additions and 0 deletions.
168 changes: 168 additions & 0 deletions test/tests/GEOSPolygonize.spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ function wktToGeom (wkt) {

// Create a helper function to convert a GEOS geometry to a WKT string
function geomToWkt (geomPtr) {
geos.GEOSNormalize(geomPtr)
const writer = geos.GEOSWKTWriter_create()
geos.GEOSWKTWriter_setRoundingPrecision(writer, 0)
const wktPtr = geos.GEOSWKTWriter_write(writer, geomPtr)
Expand Down Expand Up @@ -77,3 +78,170 @@ test('GEOSPolygonize', function (t) {
// End the test case
t.end()
})

// https://github.com/libgeos/geos/blob/3.12.0/tests/unit/capi/GEOSPolygonizeTest.cpp
test('GEOSPolygonize_getCutEdges - 1', function (t) {
const wkts = [
'LINESTRING(1 3, 3 3, 3 1, 1 1, 1 3)',
'LINESTRING(1 3, 3 3, 3 1, 1 1, 1 3)'
]

const geoms = wkts.map(wktToGeom)
const geomPtrs = new Int32Array(geoms)
const geomVecPtr = geos.Module._malloc(geomPtrs.length * geomPtrs.BYTES_PER_ELEMENT)
geos.Module.HEAP32.set(geomPtrs, geomVecPtr >> 2)

const gPtr = geos.GEOSPolygonizer_getCutEdges(geomVecPtr, geoms.length)

t.ok(gPtr !== 0)
t.equal(geos.GEOSGetNumGeometries(gPtr), 2)

freeGeom(gPtr)
geoms.forEach(freeGeom)

t.end()
})

test('GEOSPolygonize_getCutEdges - 2', function (t) {
// Example from JTS Developer's Guide, Chapter 6 - Polygonization
const wkts = [
'LINESTRING(0 0, 10 10)', // isolated edge
'LINESTRING(185 221, 100 100)', // dangling edge
'LINESTRING(185 221, 88 275, 180 316)',
'LINESTRING(185 221, 292 281, 180 316)',
'LINESTRING(189 98, 83 187, 185 221)',
'LINESTRING(189 98, 325 168, 185 221)'
]

const geoms = wkts.map(wktToGeom)
const geomPtrs = new Int32Array(geoms)
const geomVecPtr = geos.Module._malloc(geomPtrs.length * geomPtrs.BYTES_PER_ELEMENT)
geos.Module.HEAP32.set(geomPtrs, geomVecPtr >> 2)

const gPtr = geos.GEOSPolygonizer_getCutEdges(geomVecPtr, geoms.length)

t.ok(gPtr !== 0)
t.equal(geos.GEOSGetNumGeometries(gPtr), 0)

freeGeom(gPtr)
geoms.forEach(freeGeom)

t.end()
})

test('GEOSPolygonize_valid - 3', function (t) {
// Example from JTS Developer's Guide, Chapter 6 - Polygonization
const wkts = [
'LINESTRING (100 100, 100 300, 300 300, 300 100, 100 100)',
'LINESTRING (150 150, 150 250, 250 250, 250 150, 150 150)'
]

const geoms = wkts.map(wktToGeom)
const geomPtrs = new Int32Array(geoms)
const geomVecPtr = geos.Module._malloc(geomPtrs.length * geomPtrs.BYTES_PER_ELEMENT)
geos.Module.HEAP32.set(geomPtrs, geomVecPtr >> 2)

// GEOSPolygonize gives us a collection of two polygons
let gPtr = geos.GEOSPolygonize(geomVecPtr, geoms.length)
t.ok(gPtr !== 0)
t.equal(geos.GEOSGetNumGeometries(gPtr), 2)
t.equal(geos.GEOSGeomTypeId(gPtr), 7) // GEOS_GEOMETRYCOLLECTION
freeGeom(gPtr)

// GEOSPolygonize_valid gives us a single polygon with a hole
gPtr = geos.GEOSPolygonize_valid(geomVecPtr, geoms.length)
t.ok(gPtr !== 0)
t.equal(geos.GEOSGetNumGeometries(gPtr), 1)
t.equal(geos.GEOSGeomTypeId(gPtr), 3) // GEOS_POLYGON
freeGeom(gPtr)
geoms.forEach(freeGeom)

t.end()
})

test('GEOSPolygonize_valid - 4', function (t) {
const wkts = [
'LINESTRING (0 0, 1 1)'
]

const geoms = wkts.map(wktToGeom)
const geomPtrs = new Int32Array(geoms)
const geomVecPtr = geos.Module._malloc(geomPtrs.length * geomPtrs.BYTES_PER_ELEMENT)
geos.Module.HEAP32.set(geomPtrs, geomVecPtr >> 2)

const gPtr = geos.GEOSPolygonize_valid(geomVecPtr, geoms.length)

t.ok(gPtr !== 0)
t.equal(geos.GEOSGetNumGeometries(gPtr), 0)
t.equal(geos.GEOSGeomTypeId(gPtr), 7) // GEOS_GEOMETRYCOLLECTION

freeGeom(gPtr)
geoms.forEach(freeGeom)

t.end()
})

test('GEOSPolygonize_valid - 5', function (t) {
const wkts = [
'LINESTRING (0 0, 1 0, 1 1, 0 1, 0 0)',
'LINESTRING (1 1, 2 1, 2 2, 1 2, 1 1)'
]

const geoms = wkts.map(wktToGeom)
const geomPtrs = new Int32Array(geoms)
const geomVecPtr = geos.Module._malloc(geomPtrs.length * geomPtrs.BYTES_PER_ELEMENT)
geos.Module.HEAP32.set(geomPtrs, geomVecPtr >> 2)

const gPtr = geos.GEOSPolygonize_valid(geomVecPtr, geoms.length)

t.ok(gPtr !== 0)
t.equal(geos.GEOSGetNumGeometries(gPtr), 2)
t.equal(geos.GEOSGeomTypeId(gPtr), 6) // GEOS_MULTIPOLYGON

freeGeom(gPtr)
geoms.forEach(freeGeom)

t.end()
})

test('GEOSPolygonize_full - 6', function (t) {
const geom1Ptr = wktToGeom('MULTILINESTRING ((0 0, 1 0, 1 1, 0 1, 0 0), (0 0, 0.5 0.5), (1 1, 2 2, 1 2, 2 1, 1 1))')
const cutsPtr = geos.Module._malloc(4)
geos.Module.setValue(cutsPtr, 0, 'i32')
const danglesPtr = geos.Module._malloc(4)
geos.Module.setValue(danglesPtr, 0, 'i32')
const invalidRingsPtr = geos.Module._malloc(4)
geos.Module.setValue(invalidRingsPtr, 0, 'i32')

const result = geos.GEOSPolygonize_full(geom1Ptr, cutsPtr, danglesPtr, invalidRingsPtr)
const cuts = geos.Module.getValue(cutsPtr, 'i32')
const dangles = geos.Module.getValue(danglesPtr, 'i32')
const invalidRings = geos.Module.getValue(invalidRingsPtr, 'i32')
geos.Module._free(cutsPtr)
geos.Module._free(danglesPtr)
geos.Module._free(invalidRingsPtr)

const expected = wktToGeom('GEOMETRYCOLLECTION(POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0)))')
const expectedCuts = wktToGeom('GEOMETRYCOLLECTION EMPTY')
const expectedDangles = wktToGeom('GEOMETRYCOLLECTION(LINESTRING (0 0, 0.5 0.5))')
const expectedInvalidRings = wktToGeom('GEOMETRYCOLLECTION(LINESTRING (1 1, 2 2, 1 2, 2 1, 1 1))')

t.equal(geomToWkt(result), geomToWkt(expected))
t.equal(geomToWkt(cuts), geomToWkt(expectedCuts))
t.equal(geomToWkt(dangles), geomToWkt(expectedDangles))
t.equal(geomToWkt(invalidRings), geomToWkt(expectedInvalidRings))

freeGeom(geom1Ptr)
freeGeom(result)
freeGeom(expected)

freeGeom(cuts)
freeGeom(dangles)
freeGeom(invalidRings)

freeGeom(expectedCuts)
freeGeom(expectedDangles)
freeGeom(expectedInvalidRings)

t.end()
})

0 comments on commit f0a1b49

Please sign in to comment.