diff --git a/modules/arrow/src/geoarrow/convert-geoarrow-to-binary-geometry.ts b/modules/arrow/src/geoarrow/convert-geoarrow-to-binary-geometry.ts index 379b26c6dc..6ddbd8fef6 100644 --- a/modules/arrow/src/geoarrow/convert-geoarrow-to-binary-geometry.ts +++ b/modules/arrow/src/geoarrow/convert-geoarrow-to-binary-geometry.ts @@ -159,23 +159,32 @@ export function getBinaryGeometriesFromArrow( function getMeanCentersFromBinaryGeometries(binaryGeometries: BinaryFeatures[]): number[][] { const globalMeanCenters: number[][] = []; binaryGeometries.forEach((binaryGeometry: BinaryFeatures) => { - const binaryGeometryType = - binaryGeometry.points && binaryGeometry.points.positions.value.length > 0 - ? 'points' - : binaryGeometry.lines && binaryGeometry.lines.positions.value.length > 0 - ? 'lines' - : binaryGeometry.polygons && binaryGeometry.polygons.positions.value.length > 0 - ? 'polygons' - : null; + let binaryGeometryType: string | null = null; + if (binaryGeometry.points && binaryGeometry.points.positions.value.length > 0) { + binaryGeometryType = 'points'; + } else if (binaryGeometry.lines && binaryGeometry.lines.positions.value.length > 0) { + binaryGeometryType = 'lines'; + } else if (binaryGeometry.polygons && binaryGeometry.polygons.positions.value.length > 0) { + binaryGeometryType = 'polygons'; + } const binaryContent = binaryGeometryType ? binaryGeometry[binaryGeometryType] : null; - if (binaryContent) { + if (binaryContent && binaryGeometryType !== null) { const featureIds = binaryContent.featureIds.value; const flatCoordinateArray = binaryContent.positions.value; const nDim = binaryContent.positions.size; - - const meanCenters = getMeanCentersFromGeometry(featureIds, flatCoordinateArray, nDim); - globalMeanCenters.concat(meanCenters); + const primitivePolygonIndices = binaryContent.primitivePolygonIndices?.value; + + const meanCenters = getMeanCentersFromGeometry( + featureIds, + flatCoordinateArray, + nDim, + binaryGeometryType, + primitivePolygonIndices + ); + meanCenters.forEach((center) => { + globalMeanCenters.push(center); + }); } }); return globalMeanCenters; @@ -191,20 +200,31 @@ function getMeanCentersFromBinaryGeometries(binaryGeometries: BinaryFeatures[]): function getMeanCentersFromGeometry( featureIds: TypedArray, flatCoordinateArray: TypedArray, - nDim: number + nDim: number, + geometryType: string, + primitivePolygonIndices?: TypedArray ) { const meanCenters: number[][] = []; const vertexCount = flatCoordinateArray.length; let vertexIndex = 0; while (vertexIndex < vertexCount) { - const featureId = featureIds[vertexIndex]; + const featureId = featureIds[vertexIndex / nDim]; const center = [0, 0]; let vertexCountInFeature = 0; - while (vertexIndex < vertexCount && featureIds[vertexIndex] === featureId) { - center[0] += flatCoordinateArray[vertexIndex]; - center[1] += flatCoordinateArray[vertexIndex + 1]; - vertexIndex += nDim; - vertexCountInFeature++; + while (vertexIndex < vertexCount && featureIds[vertexIndex / nDim] === featureId) { + if ( + geometryType === 'polygons' && + primitivePolygonIndices && + primitivePolygonIndices.indexOf(vertexIndex / nDim) >= 0 + ) { + // skip the first point since it is the same as the last point in each ring for polygons + vertexIndex += nDim; + } else { + center[0] += flatCoordinateArray[vertexIndex]; + center[1] += flatCoordinateArray[vertexIndex + 1]; + vertexIndex += nDim; + vertexCountInFeature++; + } } center[0] /= vertexCountInFeature; center[1] /= vertexCountInFeature; diff --git a/modules/arrow/test/geoarrow/convert-geoarrow-to-binary-geometry.spec.ts b/modules/arrow/test/geoarrow/convert-geoarrow-to-binary-geometry.spec.ts index 4157a71b13..088e9b35a8 100644 --- a/modules/arrow/test/geoarrow/convert-geoarrow-to-binary-geometry.spec.ts +++ b/modules/arrow/test/geoarrow/convert-geoarrow-to-binary-geometry.spec.ts @@ -45,7 +45,11 @@ const expectedPointBinaryGeometry = { } ], bounds: [1, 1, 2, 2], - featureTypes: {polygon: false, point: true, line: false} + featureTypes: {polygon: false, point: true, line: false}, + meanCenters: [ + [1, 1], + [2, 2] + ] }; const expectedMultiPointBinaryGeometry = { @@ -74,7 +78,11 @@ const expectedMultiPointBinaryGeometry = { } ], bounds: [1, 1, 4, 4], - featureTypes: {polygon: false, point: true, line: false} + featureTypes: {polygon: false, point: true, line: false}, + meanCenters: [ + [1.5, 1.5], + [3.5, 3.5] + ] }; const expectedLineBinaryGeometry = { @@ -103,7 +111,11 @@ const expectedLineBinaryGeometry = { } ], bounds: [0, 0, 3, 3], - featureTypes: {polygon: false, point: false, line: true} + featureTypes: {polygon: false, point: false, line: true}, + meanCenters: [ + [0.5, 0.5], + [2.5, 2.5] + ] }; const expectedMultiLineBinaryGeometry = { @@ -135,7 +147,11 @@ const expectedMultiLineBinaryGeometry = { } ], bounds: [1, 1, 8, 8], - featureTypes: {polygon: false, point: false, line: true} + featureTypes: {polygon: false, point: false, line: true}, + meanCenters: [ + [2.5, 2.5], + [6.5, 6.5] + ] }; const expectedPolygonBinaryGeometry = { @@ -173,7 +189,11 @@ const expectedPolygonBinaryGeometry = { } ], bounds: [0, 0, 11, 11], - featureTypes: {polygon: true, point: false, line: false} + featureTypes: {polygon: true, point: false, line: false}, + meanCenters: [ + [0.5, 0.5], + [10.5, 10.5] + ] }; const expectedMultiPolygonBinaryGeometry = { @@ -212,7 +232,8 @@ const expectedMultiPolygonBinaryGeometry = { } ], bounds: [0, 0, 3, 3], - featureTypes: {polygon: true, point: false, line: false} + featureTypes: {polygon: true, point: false, line: false}, + meanCenters: [[1.5, 1.5]] }; test('ArrowUtils#getBinaryGeometriesFromArrow', (t) => { @@ -256,7 +277,8 @@ async function testGetBinaryGeometriesFromArrow( t.notEqual(encoding, undefined, 'encoding is not undefined'); if (geoColumn && encoding) { - const binaryData = getBinaryGeometriesFromArrow(geoColumn, encoding); + const options = {meanCenter: true}; + const binaryData = getBinaryGeometriesFromArrow(geoColumn, encoding, options); t.deepEqual(binaryData, expectedBinaryGeometries, 'binary geometries are correct'); }