{"id":37035367,"url":"https://github.com/bertt/geoparquet","last_synced_at":"2026-01-14T04:11:19.463Z","repository":{"id":65061354,"uuid":"581487105","full_name":"bertt/geoparquet","owner":"bertt","description":".NET 8 Reader/Writer library for GeoParquet files.","archived":false,"fork":false,"pushed_at":"2025-11-04T20:52:23.000Z","size":20381,"stargazers_count":20,"open_issues_count":4,"forks_count":4,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-04T21:19:09.602Z","etag":null,"topics":["geoparquet"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bertt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-12-23T10:30:25.000Z","updated_at":"2025-11-04T20:31:02.000Z","dependencies_parsed_at":"2024-06-28T22:43:21.978Z","dependency_job_id":"1765bcc0-8cbf-4f52-b93f-69335e5b1b7c","html_url":"https://github.com/bertt/geoparquet","commit_stats":{"total_commits":38,"total_committers":1,"mean_commits":38.0,"dds":0.0,"last_synced_commit":"0c7b7ab893456086275ceff35b6334a44c5cd393"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/bertt/geoparquet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bertt%2Fgeoparquet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bertt%2Fgeoparquet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bertt%2Fgeoparquet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bertt%2Fgeoparquet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bertt","download_url":"https://codeload.github.com/bertt/geoparquet/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bertt%2Fgeoparquet/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28409149,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T01:52:23.358Z","status":"online","status_checked_at":"2026-01-14T02:00:06.678Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["geoparquet"],"created_at":"2026-01-14T04:11:18.939Z","updated_at":"2026-01-14T04:11:19.448Z","avatar_url":"https://github.com/bertt.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GeoParquet\n\n ![Build status](https://github.com/bertt/geoparquet/actions/workflows/build.yml/badge.svg)[![Nuget](https://img.shields.io/nuget/vpre/bertt.geoparquet)](https://www.nuget.org/packages/bertt.geoparquet)\n\n.NET 8 Reader/Writer library for GeoParquet files.\n\nhttps://geoparquet.org/\n\nSpecification: https://github.com/opengeospatial/geoparquet/blob/main/format-specs/geoparquet.md\n\nSchema: https://github.com/opengeospatial/geoparquet/blob/main/format-specs/schema.json\n\nBlog: https://bertt.wordpress.com/2022/12/20/geoparquet-geospatial-vector-data-using-apache-parquet/\n\nNuGet: https://www.nuget.org/packages/bertt.geoparquet/\n\nSample GeoParquet JSON metadata:\n\n```json\n{\n   \"version\":\"1.0.0\",\n   \"primary_column\":\"geometry\",\n   \"columns\":{\n      \"geometry\":{\n         \"encoding\":\"WKB\",\n         \"geometry_types\":[\n            \"MultiPolygon\"\n         ],\n         \"bbox\":[\n            3.358378252510583,\n            50.750367484598314,\n            7.227498450845831,\n            53.55501451790761\n         ]\n      }\n   }\n}\n```\n\n## Architecture\n\nIn this package there are functions for handling Geometadata:\n\n1] Reading\n\nFor reading GeoParquet files there is a ParquetFileReader extension method GetGeoMetadata() to obtain the Geo metadata\n\n2] Writing \n\nFor writing GeoParquet files there is GeoMetadata.GetGeoMetadata(GeoColumn geoColumn) static function to get the geo metadata dictionary. This \ndictionary can be passed to the ParquetFileWriter constructor.\n\nSee sample code below for reading/writing samples.\n\n## geoparquet-tools\n\nIn development: geoparquet-tools, a command line tool for inspecting GeoParquet files.\n\nSee releases for first version, build for Linux, Mac, Windows\n\nInstall\n\n```\n$ wget https://github.com/bertt/geoparquet/releases/download/0.1/geoparquet-tools-linux-x64.tar.gz\n$ tar -xf geoparquet-tools-linux-x64.tar.gz\n$ ./geoparquet-tools\n```\n\nOptions:\n\n```\n-i \u003cfile\u003e : inspect GeoParquet file\n-h : help\n```\n## Sample code\n\nIn these samples NetTopologySuite (https://github.com/NetTopologySuite/NetTopologySuite) is used for handling geometries, but any library that can handle \nWKB geometries can be used.\n\n\n### Reading\n\nUse extension method 'parquetReader.GetGeoMetadata()':\n\n```\nvar file = \"testfixtures/gemeenten2016_1.0.parquet\";\nvar file1 = new ParquetFileReader(file);\n\nvar geoParquet = file1.GetGeoMetadata();\nAssert.That(geoParquet.Version == \"1.0.0\");\n\nvar rowGroupReader = file1.RowGroup(0);\nvar gemName = rowGroupReader.Column(33).LogicalReader\u003cString\u003e().First();\nAssert.IsTrue(gemName == \"Appingedam\");\n\nvar geometryWkb = rowGroupReader.Column(17).LogicalReader\u003cbyte[]\u003e().First();\nvar wkbReader = new WKBReader();\nvar multiPolygon = (MultiPolygon)wkbReader.Read(geometryWkb);\nAssert.That(multiPolygon.Coordinates.Count() == 165);\nvar firstCoordinate = multiPolygon.Coordinates.First();\nAssert.That(firstCoordinate.CoordinateValue.X == 6.8319922331647964);\nAssert.That(firstCoordinate.CoordinateValue.Y == 53.327288101088072);\n```\n\nSample reading GeoParquet file with GeoArrow encoding:\n\n```\nvar geomColumnId = GetColumnId(rowGroupReader, \"xy\");\nAssert.That(geoParquet.Columns.First().Value.Encoding == \"geoarrow.multipolygon\");\n\nif (geomColumnId != null)\n{\n    var geometryArrow = rowGroupReader.Column((int)geomColumnId).LogicalReader\u003cDouble?[][][][]\u003e().First();\n    Assert.That(geometryArrow.Length == 1);\n    Assert.That(geometryArrow[0].Length == 1);\n    Assert.That(geometryArrow[0][0].Length == 165); //165 vertices\n    Assert.That(geometryArrow[0][0][0].Length == 2); //2 points\n    Assert.That(geometryArrow[0][0][0][0] == 6.8319922331647964); // longitude first vertice\n    Assert.That(geometryArrow[0][0][0][1] == 53.327288101088072); // latitude first vertice\n}\n\n```\n\n### Writing \n\nUse GeoMetadata.GetGeoMetadata to construct the ParquetFileWriter, store the geometries as WKB.\n\nResult Parquet file can be visualized in QGIS:\n\n![image](https://user-images.githubusercontent.com/538812/210020220-b89da098-0877-45bd-87f2-8285941bf697.png)\n\n```\nvar columns = new Column[]\n{\n    new Column\u003cstring\u003e(\"city\"),\n    new Column\u003cbyte[]\u003e(\"geometry\")\n};\n\nvar bbox = new double[] {  3.3583782525105832,\n            50.750367484598314,\n            7.2274984508458306,\n            53.555014517907608};\n\nvar geoColumn = new GeoColumn();\ngeoColumn.Bbox = bbox;\ngeoColumn.Encoding = \"WKB\";\ngeoColumn.Geometry_types.Add(\"Point\");\nvar geometadata = GeoMetadata.GetGeoMetadata(geoColumn);\n\nvar parquetFileWriter = new ParquetFileWriter(@\"writing_sample.parquet\", columns, keyValueMetadata: geometadata);\nvar rowGroup = parquetFileWriter.AppendRowGroup();\n\nvar nameWriter = rowGroup.NextColumn().LogicalWriter\u003cString\u003e();\nnameWriter.WriteBatch(new string[] { \"London\", \"Derby\" });\n        \nvar geom0 = new Point(5, 51);\nvar geom1 = new Point(5.5, 51);\n\nvar wkbWriter = new WKBWriter();\nvar wkbBytes = new byte[][] { wkbWriter.Write(geom0), wkbWriter.Write(geom1) };\n\nvar geometryWriter = rowGroup.NextColumn().LogicalWriter\u003cbyte[]\u003e();\ngeometryWriter.WriteBatch(wkbBytes);\nparquetFileWriter.Close();\n  ```\n\n### Writing geometries with native encoding\n\nSee unit tests.\n\nSuppported encodings:\n\n- Point - MultiPoint \n\n- Line\n\n- Polygon\n\n## Dependencies\n\n- ParquetSharp 21 https://github.com/G-Research/ParquetSharp\n\n# Roadmap\n\n- Add support for multiple geometry columns;\n\n- add writing Apache Arrow encoding for geometries;\n\n- add support for crs;\n\n- add (spatial) filters.\n\n## History\n\n2023-11-26: version 1.0.1 - target .net 6 and 8\n\n2023-11-16: version 1.0 - using schema v1.0.0, ParquetSharp to 13 - to .NET 8\n\n2023-07-13: version 0.5 - using schema v1.0.0-beta.1, ParquetSharp to 12.0.1\n\n2023-01-01: version 0.4 - using ParquetSharp 10.0.1-beta1 instead of Parquet.Net 4\n\n2022-12-30: version 0.3.1 - make geometry column name optional in SetGeoMetadata\n\n2022-12-30: version 0.3 - add extension method to write geo metadata\n\n2022-12-27: version 0.2 - add extension method to read geo metadata\n\n2022-12-23: version 0.1 - implementing reader\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbertt%2Fgeoparquet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbertt%2Fgeoparquet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbertt%2Fgeoparquet/lists"}