diff --git a/.github/workflows/pypi.yaml b/.github/workflows/pypi.yaml index 24d1fbcef..aa8d68d0a 100644 --- a/.github/workflows/pypi.yaml +++ b/.github/workflows/pypi.yaml @@ -50,7 +50,7 @@ jobs: python -m twine check dist/* - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@v1.10.1 + uses: pypa/gh-action-pypi-publish@v1.10.2 with: skip-existing: true verbose: true diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..5ed565f50 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,148 @@ +# Code of Conduct + +## Our Pledge + +We, as members, contributors, creators, stewards, and maintainers, i.e. all the +participants, of UXarray pledge to make participation in our software, system +or hardware project and community a safe, healthy, open, productive, welcoming, +diverse, inclusive, and harassment-free experience for everyone, regardless of +age, body size, visible or invisible disability, ethnicity, sex characteristics, +gender identity and expression, level of experience, education, socio-economic +status, nationality, personal appearance, race, caste, color, religion, or +sexual identity and orientation, as well as any other characteristic protected +under applicable US federal or state law. + +All participants are required to abide by this Code of Conduct. + +## Our Standards + +Examples of behaviors that contribute to a positive environment for our community +include: + +- Demonstrating empathy and kindness toward other people +- Being considerate and respectful of and collaborative with differing opinions, + viewpoints, and experiences +- Acknowledging the contributions of others +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +- Focusing on what is best not just for us as individuals, but for the overall + community +- Respecting the rules and policies of the project and venue + +Examples of unacceptable behavior include, but are not limited to: + +- Public or private harassment, intimidation, or discrimination in any form +- Physical, verbal, or written abuse by anyone to anyone, including repeated + use of pronouns other than those requested +- The use of sexualized language or imagery, and sexual attention or advances + of any kind +- Personal attacks directed at other guests, members, participants, etc. +- Publishing others’ private information, such as a physical or electronic + address, without explicit permission +- Alarming, intimidating, threatening, or hostile comments or conduct +- Threatening or stalking anyone, including a participant +- Trolling, insulting or derogatory comments, and personal or political attacks +- Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies to all community spaces managed by UXarray whether +they be physical, online or face-to-face, and also applies when an individual is +officially representing the community in public spaces. This includes but is not +limited to project code, code repository, associated web pages, documentation, +mailing lists, project websites and wiki pages, issue tracker, meetings, telecons, +events, use of official email or social media accounts, and any other forums +created by the project team which the community uses for communication. In +addition, violations of this Code of Conduct outside these spaces may affect a +person's ability to participate within them. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the the `@UXARRAY/uxarray-dev` GitHub handle as the community leaders +in this group can view and manage the reported content, and hence are responsible +for enforcement. + +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant Code of Conduct, +version 2.1][homepage], [version 2.1][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/README.md b/README.md index 78cffa66c..52a85e080 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,5 @@ - - - - Shows a black logo in light color mode and a white one in dark color mode. - +
+ ----------------- diff --git a/benchmarks/asv.conf.json b/benchmarks/asv.conf.json index b108ec396..31a43921d 100644 --- a/benchmarks/asv.conf.json +++ b/benchmarks/asv.conf.json @@ -94,7 +94,7 @@ "setuptools_scm": [""], "xarray": [""], "netcdf4": [""], - "pip+git+https://github.com/philipc2/pyfma.git": [""] + "pip+pyfma": [""] }, diff --git a/benchmarks/face_bounds.py b/benchmarks/face_bounds.py index db3106fcb..b249e7b99 100644 --- a/benchmarks/face_bounds.py +++ b/benchmarks/face_bounds.py @@ -28,13 +28,3 @@ def time_face_bounds(self, grid_path): def peakmem_face_bounds(self, grid_path): """Peak memory usage obtain ``Grid.face_bounds.""" face_bounds = self.uxgrid.bounds - -class Bounds: - def setup(self): - self.uxgrid = ux.open_grid(r"C:\Users\chmie\PycharmProjects\ncar-uxarray\uxarray-hongyu\benchmarks\oQU480.grid.nc") - - def teardown(self): - del self.uxgrid - - def time_bounds(self): - self.uxgrid.bounds diff --git a/benchmarks/mpas_ocean.py b/benchmarks/mpas_ocean.py index b4d50da4b..f10fa6918 100644 --- a/benchmarks/mpas_ocean.py +++ b/benchmarks/mpas_ocean.py @@ -140,7 +140,20 @@ def time_nearest_neighbor_remapping(self): def time_inverse_distance_weighted_remapping(self): self.uxds_480["bottomDepth"].remap.inverse_distance_weighted(self.uxds_120.uxgrid) - class HoleEdgeIndices(DatasetBenchmark): def time_construct_hole_edge_indices(self, resolution): ux.grid.geometry._construct_hole_edge_indices(self.uxds.uxgrid.edge_face_connectivity) + +class CheckNorm: + param_names = ['resolution'] + params = ['480km', '120km'] + + def setup(self, resolution): + self.uxgrid = ux.open_grid(file_path_dict[resolution][0]) + + def teardown(self, resolution): + del self.uxgrid + + def time_check_norm(self, resolution): + from uxarray.grid.validation import _check_normalization + _check_normalization(self.uxgrid) diff --git a/ci/asv.yml b/ci/asv.yml index f807b3df6..a748ac96e 100644 --- a/ci/asv.yml +++ b/ci/asv.yml @@ -24,6 +24,7 @@ dependencies: - scipy - shapely - spatialpandas + - geopandas - xarray - asv - pip: diff --git a/ci/docs.yml b/ci/docs.yml index c6d7ec9cf..7fd333cc9 100644 --- a/ci/docs.yml +++ b/ci/docs.yml @@ -33,6 +33,7 @@ dependencies: - pandas - geocat-datafiles - spatialpandas + - geopandas - pip: - antimeridian - git+https://github.com/philipc2/pyfma.git # fix until https://github.com/nschloe/pyfma/pull/17 is merged diff --git a/ci/environment.yml b/ci/environment.yml index 6ef0b278c..ab49f1cdf 100644 --- a/ci/environment.yml +++ b/ci/environment.yml @@ -28,6 +28,7 @@ dependencies: - scipy - shapely - spatialpandas + - geopandas - xarray - asv - pip: diff --git a/ci/install-upstream.sh b/ci/install-upstream.sh index b0eee2b0b..790f08f4d 100644 --- a/ci/install-upstream.sh +++ b/ci/install-upstream.sh @@ -33,6 +33,7 @@ python -m pip install \ pandas \ scikit-learn \ scipy \ + geopandas \ xarray # install rest from source diff --git a/docs/internal_api/index.rst b/docs/internal_api/index.rst index 6dd40b2c0..122a1d96e 100644 --- a/docs/internal_api/index.rst +++ b/docs/internal_api/index.rst @@ -286,12 +286,17 @@ SCRIP io._scrip._encode_scrip -Shapefile +GeoPandas --------- .. autosummary:: :toctree: generated/ - io._shapefile._read_shpfile + io._geopandas._read_geodataframe + io._geopandas._read_geopandas + io._geopandas._encode_geopandas + io._geopandas._standardize_geopandas + io._geopandas._is_geopandas + io._geopandas._validate_minimum_geopandas Vertices -------- diff --git a/pyproject.toml b/pyproject.toml index 9c04be544..47e0d95d0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,6 +42,7 @@ dependencies = [ "scipy", "shapely", "spatialpandas", + "geopandas", "xarray", ] # minimal dependencies end diff --git a/test/meshfiles/geojson/README.md b/test/meshfiles/geojson/README.md new file mode 100644 index 000000000..dae56d52b --- /dev/null +++ b/test/meshfiles/geojson/README.md @@ -0,0 +1,15 @@ +GeoJSON is a format for encoding a variety of geographic data structures, including points, lines, and polygons. + +This repository contains "sample_chicago_buildings" GeoJSON file featuring a selection of buildings in Chicago. The file includes: + + Number of polygons: 10 + Polygon 1: 26 sides + Polygon 2: 36 sides + Polygon 3: 29 sides + Polygon 4: 10 sides + Polygon 5: 30 sides + Polygon 6: 8 sides + Polygon 7: 7 sides + Polygon 8: 9 sides + Polygon 9: 7 sides + Polygon 10: 19 sides diff --git a/test/meshfiles/geojson/sample_chicago_buildings.geojson b/test/meshfiles/geojson/sample_chicago_buildings.geojson new file mode 100644 index 000000000..14c1c0c5a --- /dev/null +++ b/test/meshfiles/geojson/sample_chicago_buildings.geojson @@ -0,0 +1,17 @@ +{ +"type": "FeatureCollection", +"name": "sample_chicago_buildings", +"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } }, +"features": [ +{ "type": "Feature", "properties": { "element_type": "way", "osmid": 64393495, "amenity": null, "addr:housenumber": "190", "addr:street": "South La Salle Street", "addr:city": "Chicago", "addr:postcode": "60603", "addr:state": "IL", "layer": null, "parking": null, "name": "190 South Lasalle", "nodes": [ 792361008, 10956188506, 10956188527, 10956188517, 792361009, 10956188515, 10956188525, 10956188535, 10956376205, 10956188536, 10956188529, 10956188514, 792361010, 10956188512, 10956188531, 10956188511, 792361011, 10956188532, 10956188509, 10956188519, 10956188505, 10956182602, 10956376206, 10956188518, 10956188524, 10956188508, 792361008 ], "addr:street:name": "La Salle", "addr:street:prefix": "South", "addr:street:type": "Street", "building": "office", "building:use": "office", "chicago:building_id": "358320", "wikidata": "Q1886439", "wikipedia": "en:U.S. Bank Building (Chicago)", "building:levels": null, "comment": null, "height": null, "name:en": null, "alt_name": null, "old_name": null, "building:colour": null, "government": null, "name:etymology:wikidata": null, "name:etymology:wikipedia": null, "office": null, "roof:material": null, "roof:shape": null, "start_date": null, "website": null, "wheelchair": null, "ref:nrhp": null, "brand": null, "brand:wikidata": null, "building:material": null, "short_name": null, "tourism": null, "construction": null, "addr:housename": null, "operator": null, "townhall:type": null, "ele": null, "gnis:county_name": null, "gnis:feature_id": null, "gnis:import_uuid": null, "gnis:reviewed": null, "source": null, "phone": null, "access": null, "fee": null, "roof:colour": null, "building:flats": null, "building:name": null, "denomination": null, "religion": null, "university_of_chicago:building_id": null, "university_of_chicago:business_unit_name": null, "note": null, "opening_hours": null, "contact:phone": null, "branch": null, "official_name": null, "ref": null, "heritage": null, "religion:wikidata": null, "religion:wikipedia": null, "cuisine": null, "not:brand:wikidata": null, "air_conditioning": null, "email": null, "fax": null, "fixme": null, "internet_access": null, "internet_access:fee": null, "rooms": null, "smoking": null, "architect": null, "wikimedia_commons": null, "bench": null, "bin": null, "lit": null, "shelter_type": null, "alt_name_1": null, "ways": null, "operator:wikidata": null, "operator:wikipedia": null, "type": null }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -87.6329252, 41.8800066 ], [ -87.6327917, 41.8800073 ], [ -87.6327006, 41.8800078 ], [ -87.6326038, 41.8800083 ], [ -87.6324803, 41.8800089 ], [ -87.6324787, 41.8799589 ], [ -87.6324764, 41.8798892 ], [ -87.6324741, 41.8798157 ], [ -87.6324723, 41.8797588 ], [ -87.6324704, 41.8797019 ], [ -87.632468, 41.8796286 ], [ -87.6324656, 41.8795556 ], [ -87.632464, 41.879505 ], [ -87.6325944, 41.8795029 ], [ -87.6326843, 41.8795015 ], [ -87.6327812, 41.8794999 ], [ -87.6329114, 41.8794979 ], [ -87.6329116, 41.8795065 ], [ -87.6329128, 41.8795512 ], [ -87.6329697, 41.8795511 ], [ -87.6329715, 41.8796303 ], [ -87.6329764, 41.8798459 ], [ -87.6329482, 41.8798463 ], [ -87.6329208, 41.8798466 ], [ -87.6329219, 41.8798841 ], [ -87.6329238, 41.8799544 ], [ -87.6329252, 41.8800066 ] ] ] } }, +{ "type": "Feature", "properties": { "element_type": "way", "osmid": 64398410, "amenity": null, "addr:housenumber": "227", "addr:street": "West Monroe Street", "addr:city": null, "addr:postcode": "60606", "addr:state": null, "layer": null, "parking": null, "name": "Franklin Center North Tower", "nodes": [ 792393936, 10945665623, 10945665622, 10945665627, 10945665620, 10945665613, 10945665619, 10945665617, 10945665615, 10945665616, 10945665618, 10945665614, 10945665612, 792393940, 10945665609, 10945665610, 10945665633, 10945665611, 10945665608, 10945665693, 10945665607, 6431694242, 10945665691, 10945665690, 10945665692, 792393944, 6431694243, 1579011824, 792393948, 10945665640, 6431694244, 992938565, 992938579, 10945665632, 992938582, 992938585, 792393936 ], "addr:street:name": "Monroe", "addr:street:prefix": "West", "addr:street:type": "Street", "building": "commercial", "building:use": null, "chicago:building_id": "357973", "wikidata": null, "wikipedia": "en:AT&T Corporate Center", "building:levels": "60", "comment": "270 m tall without arch element at top which is 307", "height": "306.9", "name:en": "Franklin Center North Tower", "alt_name": null, "old_name": null, "building:colour": null, "government": null, "name:etymology:wikidata": null, "name:etymology:wikipedia": null, "office": null, "roof:material": null, "roof:shape": null, "start_date": null, "website": null, "wheelchair": null, "ref:nrhp": null, "brand": null, "brand:wikidata": null, "building:material": null, "short_name": null, "tourism": null, "construction": null, "addr:housename": null, "operator": null, "townhall:type": null, "ele": null, "gnis:county_name": null, "gnis:feature_id": null, "gnis:import_uuid": null, "gnis:reviewed": null, "source": null, "phone": null, "access": null, "fee": null, "roof:colour": null, "building:flats": null, "building:name": null, "denomination": null, "religion": null, "university_of_chicago:building_id": null, "university_of_chicago:business_unit_name": null, "note": null, "opening_hours": null, "contact:phone": null, "branch": null, "official_name": null, "ref": null, "heritage": null, "religion:wikidata": null, "religion:wikipedia": null, "cuisine": null, "not:brand:wikidata": null, "air_conditioning": null, "email": null, "fax": null, "fixme": null, "internet_access": null, "internet_access:fee": null, "rooms": null, "smoking": null, "architect": null, "wikimedia_commons": null, "bench": null, "bin": null, "lit": null, "shelter_type": null, "alt_name_1": null, "ways": null, "operator:wikidata": null, "operator:wikipedia": null, "type": null }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -87.6343336, 41.8805678 ], [ -87.6343734, 41.8805672 ], [ -87.6344274, 41.8805663 ], [ -87.6345106, 41.880565 ], [ -87.6345362, 41.8805646 ], [ -87.6346406, 41.880563 ], [ -87.6346653, 41.8805626 ], [ -87.63469, 41.8805621 ], [ -87.6347393, 41.8805612 ], [ -87.6347887, 41.8805603 ], [ -87.6348133, 41.8805599 ], [ -87.634838, 41.8805594 ], [ -87.6350541, 41.8805558 ], [ -87.635139, 41.8805544 ], [ -87.6351365, 41.8803841 ], [ -87.6351239, 41.8803841 ], [ -87.6351235, 41.880359 ], [ -87.6351231, 41.880349 ], [ -87.635136, 41.8803485 ], [ -87.6351356, 41.8803213 ], [ -87.6351335, 41.8801736 ], [ -87.6351156, 41.8801747 ], [ -87.6351129, 41.880122 ], [ -87.6351121, 41.8800878 ], [ -87.6351113, 41.8800554 ], [ -87.6351072, 41.8800099 ], [ -87.634609, 41.8800177 ], [ -87.6344072, 41.8800194 ], [ -87.6343265, 41.88002 ], [ -87.6343309, 41.8801572 ], [ -87.634332, 41.8801868 ], [ -87.6343328, 41.8803518 ], [ -87.634348, 41.8803522 ], [ -87.6343481, 41.8803758 ], [ -87.6343481, 41.8803993 ], [ -87.6343314, 41.8804001 ], [ -87.6343336, 41.8805678 ] ] ] } }, +{ "type": "Feature", "properties": { "element_type": "way", "osmid": 64888258, "amenity": null, "addr:housenumber": "135", "addr:street": "South La Salle Street", "addr:city": "Chicago", "addr:postcode": "60603", "addr:state": "IL", "layer": null, "parking": null, "name": "Bank of America Building", "nodes": [ 795322075, 6432905302, 10956393870, 1631359643, 10956393869, 10956393868, 6432903656, 1629958763, 1629958756, 795322076, 10956393867, 6432903675, 10956393866, 10956393865, 10956393864, 10956393863, 6432903679, 10956393862, 795322077, 10956393845, 10956393855, 10956393844, 795322078, 6432903668, 10956393874, 10956393873, 10956393872, 10956393871, 6432905305, 795322075 ], "addr:street:name": "La Salle", "addr:street:prefix": "South", "addr:street:type": "Street", "building": "office", "building:use": "office", "chicago:building_id": "358297", "wikidata": "Q3756447", "wikipedia": "en:Field Building (Chicago)", "building:levels": null, "comment": null, "height": null, "name:en": null, "alt_name": "LaSalle National Bank Building", "old_name": "Field Building", "building:colour": null, "government": null, "name:etymology:wikidata": null, "name:etymology:wikipedia": null, "office": null, "roof:material": null, "roof:shape": null, "start_date": null, "website": null, "wheelchair": null, "ref:nrhp": null, "brand": null, "brand:wikidata": null, "building:material": null, "short_name": null, "tourism": null, "construction": null, "addr:housename": null, "operator": null, "townhall:type": null, "ele": null, "gnis:county_name": null, "gnis:feature_id": null, "gnis:import_uuid": null, "gnis:reviewed": null, "source": null, "phone": null, "access": null, "fee": null, "roof:colour": null, "building:flats": null, "building:name": null, "denomination": null, "religion": null, "university_of_chicago:building_id": null, "university_of_chicago:business_unit_name": null, "note": null, "opening_hours": null, "contact:phone": null, "branch": null, "official_name": null, "ref": null, "heritage": null, "religion:wikidata": null, "religion:wikipedia": null, "cuisine": null, "not:brand:wikidata": null, "air_conditioning": null, "email": null, "fax": null, "fixme": null, "internet_access": null, "internet_access:fee": null, "rooms": null, "smoking": null, "architect": null, "wikimedia_commons": null, "bench": null, "bin": null, "lit": null, "shelter_type": null, "alt_name_1": null, "ways": null, "operator:wikidata": null, "operator:wikipedia": null, "type": null }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -87.6321492, 41.8795042 ], [ -87.6317371, 41.8795098 ], [ -87.6316123, 41.8795113 ], [ -87.6315592, 41.879512 ], [ -87.631507, 41.8795127 ], [ -87.631399, 41.879514 ], [ -87.631381, 41.8795143 ], [ -87.631208, 41.8795172 ], [ -87.6310351, 41.8795201 ], [ -87.6309724, 41.8795198 ], [ -87.6309744, 41.8796111 ], [ -87.6309764, 41.8797023 ], [ -87.6309772, 41.8797487 ], [ -87.6309775, 41.8797692 ], [ -87.6309778, 41.8797877 ], [ -87.6309782, 41.8798077 ], [ -87.6309799, 41.8798526 ], [ -87.6309822, 41.8800052 ], [ -87.6309827, 41.8800355 ], [ -87.6311699, 41.8800327 ], [ -87.6315507, 41.8800248 ], [ -87.6319709, 41.8800203 ], [ -87.6321625, 41.8800174 ], [ -87.632161, 41.879835 ], [ -87.6321593, 41.8797925 ], [ -87.6321585, 41.8797725 ], [ -87.6321576, 41.8797534 ], [ -87.6321567, 41.8797325 ], [ -87.6321544, 41.879677 ], [ -87.6321492, 41.8795042 ] ] ] } }, +{ "type": "Feature", "properties": { "element_type": "way", "osmid": 64888389, "amenity": null, "addr:housenumber": "50", "addr:street": "West Washington Street", "addr:city": "Chicago", "addr:postcode": "60602", "addr:state": "IL", "layer": null, "parking": null, "name": "Richard J. Daley Center", "nodes": [ 795323250, 2391049825, 9576621373, 2391049370, 795323251, 2391049371, 795323252, 2391041923, 795323253, 2391049826, 795323250 ], "addr:street:name": "Washington", "addr:street:prefix": "West", "addr:street:type": "Street", "building": "public", "building:use": "office", "chicago:building_id": "354504", "wikidata": "Q1766475", "wikipedia": "en:Richard J. Daley Center", "building:levels": "32", "comment": null, "height": "197.5", "name:en": null, "alt_name": null, "old_name": "Chicago Civic Center", "building:colour": "#493e3b", "government": "administrative", "name:etymology:wikidata": "Q295267", "name:etymology:wikipedia": "en:Richard J. Daley", "office": "government", "roof:material": "concrete", "roof:shape": "flat", "start_date": "1965", "website": "https://thedaleycenter.com/", "wheelchair": "yes", "ref:nrhp": null, "brand": null, "brand:wikidata": null, "building:material": null, "short_name": null, "tourism": null, "construction": null, "addr:housename": null, "operator": null, "townhall:type": null, "ele": null, "gnis:county_name": null, "gnis:feature_id": null, "gnis:import_uuid": null, "gnis:reviewed": null, "source": null, "phone": null, "access": null, "fee": null, "roof:colour": null, "building:flats": null, "building:name": null, "denomination": null, "religion": null, "university_of_chicago:building_id": null, "university_of_chicago:business_unit_name": null, "note": null, "opening_hours": null, "contact:phone": null, "branch": null, "official_name": null, "ref": null, "heritage": null, "religion:wikidata": null, "religion:wikipedia": null, "cuisine": null, "not:brand:wikidata": null, "air_conditioning": null, "email": null, "fax": null, "fixme": null, "internet_access": null, "internet_access:fee": null, "rooms": null, "smoking": null, "architect": null, "wikimedia_commons": null, "bench": null, "bin": null, "lit": null, "shelter_type": null, "alt_name_1": null, "ways": null, "operator:wikidata": null, "operator:wikipedia": null, "type": null }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -87.630693, 41.8842887 ], [ -87.6305128, 41.884292 ], [ -87.6302078, 41.8842957 ], [ -87.6298181, 41.8843005 ], [ -87.6297296, 41.884302 ], [ -87.6297228, 41.8840803 ], [ -87.6297189, 41.8838986 ], [ -87.63025, 41.8838922 ], [ -87.6306793, 41.8838892 ], [ -87.6306849, 41.8840835 ], [ -87.630693, 41.8842887 ] ] ] } }, +{ "type": "Feature", "properties": { "element_type": "way", "osmid": 64888429, "amenity": null, "addr:housenumber": "70", "addr:street": "West Madison Street", "addr:city": "Chicago", "addr:postcode": "60602", "addr:state": "IL", "layer": null, "parking": null, "name": "Three First National Plaza", "nodes": [ 8722717277, 8722717276, 8722717275, 8722717274, 8722717273, 8722717272, 8722717271, 8722717270, 8722717269, 8722717268, 8722717267, 8722717266, 8722717265, 8722717264, 8722717263, 8722717262, 8722717260, 8728746826, 8722717283, 8722717259, 10925917309, 795323398, 10957839518, 8722717286, 795323400, 8722717285, 6431773564, 10922954295, 10922954294, 6431773554, 8722717277 ], "addr:street:name": "Madison", "addr:street:prefix": "West", "addr:street:type": "Street", "building": "office", "building:use": "office", "chicago:building_id": "356148", "wikidata": "Q1787391", "wikipedia": "en:Three First National Plaza", "building:levels": "57", "comment": null, "height": "234", "name:en": null, "alt_name": null, "old_name": null, "building:colour": null, "government": null, "name:etymology:wikidata": null, "name:etymology:wikipedia": null, "office": null, "roof:material": null, "roof:shape": null, "start_date": null, "website": null, "wheelchair": null, "ref:nrhp": null, "brand": null, "brand:wikidata": null, "building:material": null, "short_name": null, "tourism": null, "construction": null, "addr:housename": null, "operator": null, "townhall:type": null, "ele": null, "gnis:county_name": null, "gnis:feature_id": null, "gnis:import_uuid": null, "gnis:reviewed": null, "source": null, "phone": null, "access": null, "fee": null, "roof:colour": null, "building:flats": null, "building:name": null, "denomination": null, "religion": null, "university_of_chicago:building_id": null, "university_of_chicago:business_unit_name": null, "note": null, "opening_hours": null, "contact:phone": null, "branch": null, "official_name": null, "ref": null, "heritage": null, "religion:wikidata": null, "religion:wikipedia": null, "cuisine": null, "not:brand:wikidata": null, "air_conditioning": null, "email": null, "fax": null, "fixme": null, "internet_access": null, "internet_access:fee": null, "rooms": null, "smoking": null, "architect": null, "wikimedia_commons": null, "bench": null, "bin": null, "lit": null, "shelter_type": null, "alt_name_1": null, "ways": null, "operator:wikidata": null, "operator:wikipedia": null, "type": null }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -87.6300234, 41.8823194 ], [ -87.6300104, 41.88231 ], [ -87.6300097, 41.8822869 ], [ -87.6299968, 41.8822791 ], [ -87.6299706, 41.8822791 ], [ -87.6299508, 41.8822618 ], [ -87.6299572, 41.8822439 ], [ -87.6299452, 41.8822337 ], [ -87.6299121, 41.8822341 ], [ -87.6298982, 41.8822264 ], [ -87.6298969, 41.8822003 ], [ -87.6298883, 41.8821937 ], [ -87.6298564, 41.8821938 ], [ -87.6298452, 41.8821868 ], [ -87.6298426, 41.8821638 ], [ -87.6298255, 41.8821551 ], [ -87.6298009, 41.8821549 ], [ -87.6297882, 41.8821417 ], [ -87.6297889, 41.882122 ], [ -87.6297737, 41.8821095 ], [ -87.6296582, 41.8821098 ], [ -87.6295686, 41.8821101 ], [ -87.6295698, 41.8822581 ], [ -87.6295702, 41.8823052 ], [ -87.6298643, 41.8822993 ], [ -87.6298721, 41.8825615 ], [ -87.6301227, 41.8825582 ], [ -87.6301149, 41.8823711 ], [ -87.6301411, 41.8823484 ], [ -87.6301391, 41.8823213 ], [ -87.6300234, 41.8823194 ] ] ] } }, +{ "type": "Feature", "properties": { "element_type": "way", "osmid": 64888440, "amenity": null, "addr:housenumber": "1", "addr:street": "North La Salle Street", "addr:city": "Chicago", "addr:postcode": "60602", "addr:state": "IL", "layer": null, "parking": null, "name": "One North LaSalle", "nodes": [ 795323452, 10925521067, 10925898099, 10925898102, 10925521068, 795323455, 10925898095, 10925898098, 795323452 ], "addr:street:name": "La Salle", "addr:street:prefix": "North", "addr:street:type": "Street", "building": "office", "building:use": null, "chicago:building_id": "814554", "wikidata": "Q2565075", "wikipedia": "en:One North LaSalle", "building:levels": "48", "comment": null, "height": "161", "name:en": null, "alt_name": "One LaSalle Street Building", "old_name": null, "building:colour": null, "government": null, "name:etymology:wikidata": null, "name:etymology:wikipedia": null, "office": null, "roof:material": null, "roof:shape": null, "start_date": null, "website": null, "wheelchair": null, "ref:nrhp": "99001378", "brand": null, "brand:wikidata": null, "building:material": null, "short_name": null, "tourism": null, "construction": null, "addr:housename": null, "operator": null, "townhall:type": null, "ele": null, "gnis:county_name": null, "gnis:feature_id": null, "gnis:import_uuid": null, "gnis:reviewed": null, "source": null, "phone": null, "access": null, "fee": null, "roof:colour": null, "building:flats": null, "building:name": null, "denomination": null, "religion": null, "university_of_chicago:building_id": null, "university_of_chicago:business_unit_name": null, "note": null, "opening_hours": null, "contact:phone": null, "branch": null, "official_name": null, "ref": null, "heritage": null, "religion:wikidata": null, "religion:wikipedia": null, "cuisine": null, "not:brand:wikidata": null, "air_conditioning": null, "email": null, "fax": null, "fixme": null, "internet_access": null, "internet_access:fee": null, "rooms": null, "smoking": null, "architect": null, "wikimedia_commons": null, "bench": null, "bin": null, "lit": null, "shelter_type": null, "alt_name_1": null, "ways": null, "operator:wikidata": null, "operator:wikipedia": null, "type": null }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -87.6322113, 41.8820773 ], [ -87.6318343, 41.8820816 ], [ -87.6318394, 41.8822383 ], [ -87.6318447, 41.8824002 ], [ -87.63185, 41.8825619 ], [ -87.632219, 41.8825578 ], [ -87.6322167, 41.8824153 ], [ -87.6322135, 41.882214 ], [ -87.6322113, 41.8820773 ] ] ] } }, +{ "type": "Feature", "properties": { "element_type": "way", "osmid": 64888442, "amenity": null, "addr:housenumber": "2", "addr:street": "North La Salle Street", "addr:city": "Chicago", "addr:postcode": "60602", "addr:state": "IL", "layer": null, "parking": null, "name": null, "nodes": [ 795323473, 795323474, 795323475, 10922694240, 10922694253, 795323476, 10925526289, 795323473 ], "addr:street:name": "La Salle", "addr:street:prefix": "North", "addr:street:type": "Street", "building": "office", "building:use": null, "chicago:building_id": "356153", "wikidata": null, "wikipedia": null, "building:levels": "26", "comment": null, "height": "96", "name:en": null, "alt_name": null, "old_name": null, "building:colour": null, "government": null, "name:etymology:wikidata": null, "name:etymology:wikipedia": null, "office": null, "roof:material": null, "roof:shape": null, "start_date": null, "website": null, "wheelchair": null, "ref:nrhp": null, "brand": null, "brand:wikidata": null, "building:material": null, "short_name": null, "tourism": null, "construction": null, "addr:housename": null, "operator": null, "townhall:type": null, "ele": null, "gnis:county_name": null, "gnis:feature_id": null, "gnis:import_uuid": null, "gnis:reviewed": null, "source": null, "phone": null, "access": null, "fee": null, "roof:colour": null, "building:flats": null, "building:name": null, "denomination": null, "religion": null, "university_of_chicago:building_id": null, "university_of_chicago:business_unit_name": null, "note": null, "opening_hours": null, "contact:phone": null, "branch": null, "official_name": null, "ref": null, "heritage": null, "religion:wikidata": null, "religion:wikipedia": null, "cuisine": null, "not:brand:wikidata": null, "air_conditioning": null, "email": null, "fax": null, "fixme": null, "internet_access": null, "internet_access:fee": null, "rooms": null, "smoking": null, "architect": null, "wikimedia_commons": null, "bench": null, "bin": null, "lit": null, "shelter_type": null, "alt_name_1": null, "ways": null, "operator:wikidata": null, "operator:wikipedia": null, "type": null }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -87.6330914, 41.8820676 ], [ -87.6325133, 41.8820793 ], [ -87.6325223, 41.8825607 ], [ -87.6326134, 41.8825596 ], [ -87.6329198, 41.8825546 ], [ -87.6331057, 41.8825517 ], [ -87.6330934, 41.882164 ], [ -87.6330914, 41.8820676 ] ] ] } }, +{ "type": "Feature", "properties": { "element_type": "way", "osmid": 64889199, "amenity": null, "addr:housenumber": "225", "addr:street": "West Washington Street", "addr:city": "Chicago", "addr:postcode": "60606", "addr:state": "IL", "layer": null, "parking": null, "name": "Marmon Building", "nodes": [ 795327569, 795327570, 1388390362, 1388390361, 795327571, 795327572, 1388390391, 10925526154, 1388390392, 795327569 ], "addr:street:name": "Washington", "addr:street:prefix": "West", "addr:street:type": "Street", "building": "office", "building:use": null, "chicago:building_id": "355610", "wikidata": null, "wikipedia": null, "building:levels": "28", "comment": null, "height": "120", "name:en": null, "alt_name": null, "old_name": null, "building:colour": null, "government": null, "name:etymology:wikidata": null, "name:etymology:wikipedia": null, "office": null, "roof:material": null, "roof:shape": null, "start_date": null, "website": null, "wheelchair": null, "ref:nrhp": null, "brand": null, "brand:wikidata": null, "building:material": null, "short_name": null, "tourism": null, "construction": null, "addr:housename": null, "operator": null, "townhall:type": null, "ele": null, "gnis:county_name": null, "gnis:feature_id": null, "gnis:import_uuid": null, "gnis:reviewed": null, "source": null, "phone": null, "access": null, "fee": null, "roof:colour": null, "building:flats": null, "building:name": null, "denomination": null, "religion": null, "university_of_chicago:building_id": null, "university_of_chicago:business_unit_name": null, "note": null, "opening_hours": null, "contact:phone": null, "branch": null, "official_name": null, "ref": null, "heritage": null, "religion:wikidata": null, "religion:wikipedia": null, "cuisine": null, "not:brand:wikidata": null, "air_conditioning": null, "email": null, "fax": null, "fixme": null, "internet_access": null, "internet_access:fee": null, "rooms": null, "smoking": null, "architect": null, "wikimedia_commons": null, "bench": null, "bin": null, "lit": null, "shelter_type": null, "alt_name_1": null, "ways": null, "operator:wikidata": null, "operator:wikipedia": null, "type": null }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -87.6348035, 41.8830751 ], [ -87.634795, 41.8826486 ], [ -87.6348415, 41.882609 ], [ -87.6351535, 41.8826042 ], [ -87.6351989, 41.882641 ], [ -87.6351986, 41.883054 ], [ -87.6351473, 41.8830993 ], [ -87.6350014, 41.883101 ], [ -87.6348501, 41.8831026 ], [ -87.6348035, 41.8830751 ] ] ] } }, +{ "type": "Feature", "properties": { "element_type": "way", "osmid": 64889208, "amenity": null, "addr:housenumber": "1", "addr:street": "North Franklin Street", "addr:city": null, "addr:postcode": null, "addr:state": null, "layer": null, "parking": null, "name": "PNC Centre", "nodes": [ 795327600, 10925526128, 795327601, 795327602, 10922694170, 795327603, 10925526156, 795327600 ], "addr:street:name": "Franklin", "addr:street:prefix": "North", "addr:street:type": "Street", "building": "commercial", "building:use": "office", "chicago:building_id": "356208", "wikidata": null, "wikipedia": null, "building:levels": "36", "comment": null, "height": "150", "name:en": null, "alt_name": null, "old_name": null, "building:colour": null, "government": null, "name:etymology:wikidata": null, "name:etymology:wikipedia": null, "office": null, "roof:material": null, "roof:shape": null, "start_date": null, "website": null, "wheelchair": null, "ref:nrhp": null, "brand": null, "brand:wikidata": null, "building:material": null, "short_name": null, "tourism": null, "construction": null, "addr:housename": null, "operator": null, "townhall:type": null, "ele": null, "gnis:county_name": null, "gnis:feature_id": null, "gnis:import_uuid": null, "gnis:reviewed": null, "source": null, "phone": null, "access": null, "fee": null, "roof:colour": null, "building:flats": null, "building:name": null, "denomination": null, "religion": null, "university_of_chicago:building_id": null, "university_of_chicago:business_unit_name": null, "note": null, "opening_hours": null, "contact:phone": null, "branch": null, "official_name": null, "ref": null, "heritage": null, "religion:wikidata": null, "religion:wikipedia": null, "cuisine": null, "not:brand:wikidata": null, "air_conditioning": null, "email": null, "fax": null, "fixme": null, "internet_access": null, "internet_access:fee": null, "rooms": null, "smoking": null, "architect": null, "wikimedia_commons": null, "bench": null, "bin": null, "lit": null, "shelter_type": null, "alt_name_1": null, "ways": null, "operator:wikidata": null, "operator:wikipedia": null, "type": null }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -87.6351793, 41.88206 ], [ -87.6351481, 41.8820603 ], [ -87.6347543, 41.8820642 ], [ -87.6347751, 41.8825531 ], [ -87.6348922, 41.8825527 ], [ -87.6351874, 41.8825481 ], [ -87.6351833, 41.8823041 ], [ -87.6351793, 41.88206 ] ] ] } }, +{ "type": "Feature", "properties": { "element_type": "way", "osmid": 74451017, "amenity": null, "addr:housenumber": "172", "addr:street": "West Adams Street", "addr:city": "Chicago", "addr:postcode": "60603", "addr:state": "IL", "layer": null, "parking": null, "name": "W Chicago City Center", "nodes": [ 879927560, 879927564, 10956182601, 10956182602, 10956188505, 10956188519, 10956188533, 879927576, 10956376227, 10956376226, 879927579, 879931077, 10956038240, 10956038237, 10956038243, 10956038246, 10956038247, 10956038250, 10956182600, 879927560 ], "addr:street:name": "Adams", "addr:street:prefix": "West", "addr:street:type": "Street", "building": "hotel", "building:use": null, "chicago:building_id": "814688", "wikidata": null, "wikipedia": null, "building:levels": null, "comment": null, "height": null, "name:en": null, "alt_name": null, "old_name": "Midland Hotel", "building:colour": null, "government": null, "name:etymology:wikidata": null, "name:etymology:wikipedia": null, "office": null, "roof:material": null, "roof:shape": null, "start_date": null, "website": null, "wheelchair": null, "ref:nrhp": null, "brand": "W Hotels", "brand:wikidata": "Q7958488", "building:material": "brick", "short_name": "W", "tourism": "hotel", "construction": null, "addr:housename": null, "operator": null, "townhall:type": null, "ele": null, "gnis:county_name": null, "gnis:feature_id": null, "gnis:import_uuid": null, "gnis:reviewed": null, "source": null, "phone": null, "access": null, "fee": null, "roof:colour": null, "building:flats": null, "building:name": null, "denomination": null, "religion": null, "university_of_chicago:building_id": null, "university_of_chicago:business_unit_name": null, "note": null, "opening_hours": null, "contact:phone": null, "branch": null, "official_name": null, "ref": null, "heritage": null, "religion:wikidata": null, "religion:wikipedia": null, "cuisine": null, "not:brand:wikidata": null, "air_conditioning": null, "email": null, "fax": null, "fixme": null, "internet_access": null, "internet_access:fee": null, "rooms": null, "smoking": null, "architect": null, "wikimedia_commons": null, "bench": null, "bin": null, "lit": null, "shelter_type": null, "alt_name_1": null, "ways": null, "operator:wikidata": null, "operator:wikipedia": null, "type": null }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -87.6333193, 41.8800146 ], [ -87.6329803, 41.8800174 ], [ -87.6329793, 41.8799745 ], [ -87.6329764, 41.8798459 ], [ -87.6329715, 41.8796303 ], [ -87.6329697, 41.8795511 ], [ -87.6329686, 41.8795058 ], [ -87.632969, 41.8794919 ], [ -87.6331358, 41.8794902 ], [ -87.6332685, 41.8794889 ], [ -87.6333, 41.8794886 ], [ -87.6333041, 41.8795997 ], [ -87.6333056, 41.8796418 ], [ -87.633308, 41.879707 ], [ -87.633309, 41.8797313 ], [ -87.6333095, 41.8797502 ], [ -87.633314, 41.8798706 ], [ -87.6333147, 41.8798895 ], [ -87.6333177, 41.8799702 ], [ -87.6333193, 41.8800146 ] ] ] } } +] +} diff --git a/test/meshfiles/shp/5poly/5poly.cpg b/test/meshfiles/shp/5poly/5poly.cpg new file mode 100644 index 000000000..57decb481 --- /dev/null +++ b/test/meshfiles/shp/5poly/5poly.cpg @@ -0,0 +1 @@ +ISO-8859-1 diff --git a/test/meshfiles/shp/5poly/5poly.dbf b/test/meshfiles/shp/5poly/5poly.dbf new file mode 100644 index 000000000..6746e87c7 Binary files /dev/null and b/test/meshfiles/shp/5poly/5poly.dbf differ diff --git a/test/meshfiles/shp/5poly/5poly.shp b/test/meshfiles/shp/5poly/5poly.shp new file mode 100644 index 000000000..63f986b13 Binary files /dev/null and b/test/meshfiles/shp/5poly/5poly.shp differ diff --git a/test/meshfiles/shp/5poly/5poly.shx b/test/meshfiles/shp/5poly/5poly.shx new file mode 100644 index 000000000..e0b92ef2c Binary files /dev/null and b/test/meshfiles/shp/5poly/5poly.shx differ diff --git a/test/meshfiles/shp/README.md b/test/meshfiles/shp/README.md new file mode 100644 index 000000000..1d66ed55f --- /dev/null +++ b/test/meshfiles/shp/README.md @@ -0,0 +1,15 @@ +### There are 3 sub folders each containing different shapefile examples + +1. **5poly** : A very simple file containing only 5 polygons with different number of sides +2. **cb_2018_us_national_20m**: Real word shapefile containing the 2018 Census Bureau US map at 20m resolution +3. **multipoly**: Test file containing multipolygons. + +### Files Included in the Shapefile Dataset + +1. **.shp** - **Shape Format**: Contains the geometric data (polygons) for the features in the dataset. The first 100 bytes contain metadata about the file. + +2. **.shx** - **Shape Index Format**: Contains the index data for the .shp file, allowing for quick access to the geometric data. + +3. **.dbf** - **Attribute Format**: Contains attribute data for the features in the .shp file. This is a dBase file that stores information in a tabular format, where each row corresponds to a feature in the .shp file. + +4. **.cpg** - **Code Page Format**: Contains character encoding information for the .dbf file, ensuring that text data is correctly interpreted. Eg. ISO-8859-1 diff --git a/test/meshfiles/shp/cb_2018_us_nation_20m/cb_2018_us_nation_20m.cpg b/test/meshfiles/shp/cb_2018_us_nation_20m/cb_2018_us_nation_20m.cpg new file mode 100644 index 000000000..7edc66b06 --- /dev/null +++ b/test/meshfiles/shp/cb_2018_us_nation_20m/cb_2018_us_nation_20m.cpg @@ -0,0 +1 @@ +UTF-8 diff --git a/test/meshfiles/shp/cb_2018_us_nation_20m/cb_2018_us_nation_20m.dbf b/test/meshfiles/shp/cb_2018_us_nation_20m/cb_2018_us_nation_20m.dbf new file mode 100644 index 000000000..b4edf2752 Binary files /dev/null and b/test/meshfiles/shp/cb_2018_us_nation_20m/cb_2018_us_nation_20m.dbf differ diff --git a/test/meshfiles/shp/cb_2018_us_nation_20m/cb_2018_us_nation_20m.prj b/test/meshfiles/shp/cb_2018_us_nation_20m/cb_2018_us_nation_20m.prj new file mode 100644 index 000000000..b5af06c7f --- /dev/null +++ b/test/meshfiles/shp/cb_2018_us_nation_20m/cb_2018_us_nation_20m.prj @@ -0,0 +1 @@ +GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]] diff --git a/test/meshfiles/shp/cb_2018_us_nation_20m/cb_2018_us_nation_20m.shp b/test/meshfiles/shp/cb_2018_us_nation_20m/cb_2018_us_nation_20m.shp new file mode 100644 index 000000000..4604b1532 Binary files /dev/null and b/test/meshfiles/shp/cb_2018_us_nation_20m/cb_2018_us_nation_20m.shp differ diff --git a/test/meshfiles/shp/cb_2018_us_nation_20m/cb_2018_us_nation_20m.shp.ea.iso.xml b/test/meshfiles/shp/cb_2018_us_nation_20m/cb_2018_us_nation_20m.shp.ea.iso.xml new file mode 100755 index 000000000..468a4d922 --- /dev/null +++ b/test/meshfiles/shp/cb_2018_us_nation_20m/cb_2018_us_nation_20m.shp.ea.iso.xml @@ -0,0 +1,119 @@ + + + + Feature Catalog for the 2018 United States 1:20,000,000 Cartographic Boundary File + + + The United States at a scale of 1:20,000,000 + + + cb_2018_nation_20m + + + 2019-05 + + + eng + + + utf8 + + + + + + + cb_2018_us_nation_20m.shp + + + Current Nation (national) + + + false + + + + + + AFFGEOID + + + American FactFinder summary level code + geovariant code + '00US' + + + + + + + American FactFinder geographic identifier + + + + + + + + + + GEOID + + + Nation identifier + + + + + + + US + + + United States + + + + + + + + + + NAME + + + Nation name + + + + + + + United States + + + Nation + + + + + + + + + diff --git a/test/meshfiles/shp/cb_2018_us_nation_20m/cb_2018_us_nation_20m.shp.iso.xml b/test/meshfiles/shp/cb_2018_us_nation_20m/cb_2018_us_nation_20m.shp.iso.xml new file mode 100755 index 000000000..5e201739d --- /dev/null +++ b/test/meshfiles/shp/cb_2018_us_nation_20m/cb_2018_us_nation_20m.shp.iso.xml @@ -0,0 +1,531 @@ + + + + cb_2018_us_nation_20m.shp.iso.xml + + + eng + + + UTF-8 + + + +dataset + + + + + 2019-05 + + + ISO 19115 Geographic Information - Metadata + + + 2009-02-15 + + + https://www2.census.gov/geo/tiger/GENZ2018/shp/cb_2018_us_nation_20m.zip + + + + + + + + + complex + + + 1 + + + + + + + + + + + + + INCITS (formerly FIPS) codes + + + + + + + + + + + + + 2018 Cartographic Boundary File, United States, 1:20,000,000 + + + + + + 2019-05 + + + publication + + + + + + + + + + + + The 2018 cartographic boundary shapefiles are simplified representations of selected geographic areas from the U.S. Census Bureau's Master Address File / Topologically Integrated Geographic Encoding and Referencing (MAF/TIGER) Database (MTDB). These boundary files are specifically designed for small-scale thematic mapping. When possible, generalization is performed with the intent to maintain the hierarchical relationships among geographies and to maintain the alignment of geographies within a file set for a given year. Geographic areas may not align with the same areas from another year. Some geographies are available as nation-based files while others are available only as state-based files. + +This file depicts the shape of the United States clipped back to a generalized coastline. This nation layer covers the extent of the fifty states, the District of Columbia, Puerto Rico, and each of the Island Areas (American Samoa, the Commonwealth of the Northern Mariana Islands, Guam, and the U.S. Virgin Islands) when scale appropriate. + + + These files were specifically created to support small-scale thematic mapping. To improve the appearance of shapes at small scales, areas are represented with fewer vertices than detailed TIGER/Line Shapefiles. Cartographic boundary files take up less disk space than their ungeneralized counterparts. Cartographic boundary files take less time to render on screen than TIGER/Line Shapefiles. You can join this file with table data downloaded from American FactFinder by using the AFFGEOID field in the cartographic boundary file. If detailed boundaries are required, please use the TIGER/Line Shapefiles instead of the generalized cartographic boundary files. + + + + completed + + + + + + + + notPlanned + + + + + + + + Boundaries + + + theme + + + + + ISO 19115 Topic Categories + + + + + + + + + + 2018 + + + SHP + + + Cartographic Boundary + + + Generalized + + + United States + + + theme + + + + + None + + + + + + + + + + United States + + + US + + + place + + + + + ISO 3166 Codes for the representation of names of countries and their subdivisions + + + + + + + + + + otherRestrictions + + + + + + Access Constraints: None + + + Use Constraints:The intended display scale for this file is 1:20,000,000. This file should not be displayed at scales larger than 1:20,000,000. + +These products are free to use in a product or publication, however acknowledgement must be given to the U.S. Census Bureau as the source. The boundary information is for visual display at appropriate small scales only. Cartographic boundary files should not be used for geographic analysis including area or perimeter calculation. Files should not be used for geocoding addresses. Files should not be used for determining precise geographic area relationships. + + + + + + + vector + + + + + + + 20000000 + + + + + + + eng + + + + + + boundaries + + + The cartographic boundary files contain geographic data only and do not include display mapping software or statistical data. For information on how to use cartographic boundary file data with specific software package users shall contact the company that produced the software. + + + + + + + -179.174265 + + + 179.773922 + + + 17.913769 + + + 71.352561 + + + + + + + + publication date + 2019-05 + 2019-05 + + + + + + + + + + + + + true + + + + + Feature Catalog for the 2018 1:20,000,000 Cartographic Boundary File + + + + + + + + + + + https://meta.geo.census.gov/data/existing/decennial/GEO/CPMB/boundary/2018cb/nation_20m/2018_nation_20m.ea.iso.xml + + + + + + + + + + + SHP + + + + PK-ZIP, version 1.93A or higher + + + + + + + HTML + + + + + + + + + + + The online cartographic boundary files may be downloaded without charge. + + + To obtain more information about ordering Cartographic Boundary Files visit https://www.census.gov/geo/www/tiger. + + + + + + + + + + + https://www2.census.gov/geo/tiger/GENZ2018/shp/cb_2018_us_nation_20m.zip + + + Shapefile Zip File + + + + + + + + + + + https://www.census.gov/geo/maps-data/data/tiger-cart-boundary.html + + + Cartographic Boundary Shapefiles + + + Simplified representations of selected geographic areas from the Census Bureau's MAF/TIGER geographic database + + + + + + + + + + + + + dataset + + + + + + + Horizontal Positional Accuracy + + + + + + Data are not accurate. Data are generalized representations of geographic boundaries at 1:20,000,000. + + + + + + meters + + + + + Missing + + + + + + + + + The cartographic boundary files are generalized representations of extracts taken from the MAF/TIGER Database. Generalized boundary files are clipped to a simplified version of the U.S. outline. As a result, some off-shore areas may be excluded from the generalized files. Some small geographic areas, holes, or discontiguous parts of areas may not be included in generalized files if they are not visible at the target scale. + + + + + + + + The cartographic boundary files are generalized representations of extracts taken from the MAF/TIGER Database. Generalized boundary files are clipped to a simplified version of the U.S. outline. As a result, some off-shore areas may be excluded from the generalized files. Some small geographic areas, holes, or discontiguous parts of areas may not be included in generalized files if they are not visible at the target scale. + + + + + + + + The Census Bureau performed automated tests to ensure logical consistency of the source database. Segments making up the outer and inner boundaries of a polygon tie end-to-end to completely enclose the area. All polygons were tested for closure. The Census Bureau uses its internally developed geographic update system to enhance and modify spatial and attribute data in the Census MAF/TIGER database. Standard geographic codes, such as INCITS (formerly FIPS) codes for states, counties, municipalities, county subdivisions, places, American Indian/Alaska Native/Native Hawaiian areas, and congressional districts are used when encoding spatial entities. The Census Bureau performed spatial data tests for logical consistency of the codes during the compilation of the original Census MAF/TIGER database files. Feature attribute information has been examined but has not been fully tested for consistency. + +For the cartographic boundary files, the Point and Vector Object Count for the G-polygon SDTS Point and Vector Object Type reflects the number of records in the file's data table. For multi-polygon features, only one attribute record exists for each multi-polygon rather than one attribute record per individual G-polygon component of the multi-polygon feature. Cartographic Boundary File multi-polygons are an exception to the G-polygon object type classification. Therefore, when multi-polygons exist in a file, the object count will be less than the actual number of G-polygons. + + + + + + + + + + Spatial data were extracted from the MAF/TIGER database and processed through a U.S. Census Bureau batch generalization system. + + + 2019-05-01T00:00:00 + + + + + Geo-spatial Relational Database + + + + + Census MAF/TIGER database + + + MAF/TIGER + + + + + + U.S. Department of Commerce, U.S. Census Bureau, Geography Division, Geographic Customer Services Branch + + + originator + + + + + + Source Contribution: All spatial and feature data + + + + + + + + + + 201706 + 201805 + + + + + + + + + + + + + + + + + + + notPlanned + + + + This was transformed from the Census Metadata Import Format + + + + + diff --git a/test/meshfiles/shp/cb_2018_us_nation_20m/cb_2018_us_nation_20m.shx b/test/meshfiles/shp/cb_2018_us_nation_20m/cb_2018_us_nation_20m.shx new file mode 100644 index 000000000..7dbcdaa4a Binary files /dev/null and b/test/meshfiles/shp/cb_2018_us_nation_20m/cb_2018_us_nation_20m.shx differ diff --git a/test/meshfiles/shp/grid_fire.shp b/test/meshfiles/shp/grid_fire.shp deleted file mode 100644 index 90f0db26d..000000000 --- a/test/meshfiles/shp/grid_fire.shp +++ /dev/null @@ -1,1431 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MAUP/grid_fire.shp at 7a537aecafeac76953a4429d43ad92b67da249d8 · traemalcolm/MAUP · GitHub - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Skip to content - - - - - - - - - - -
- -
- - - - - - -
- - - -
- - - - - - - - - - -
-
-
- - - - - - - - - - - - - -
-
- - - - - - - - -
- - - - Permalink - -
- -
-
- - - 7a537aecaf - - - - -
-
-
- Switch branches/tags - -
- - - -
- -
- -
- - -
- -
- - - - - - - - - - - - - - - - -
- - -
-
-
-
- -
- -
- - - - Go to file - - -
- - - - - - - - - -
-
-
- - - - -
- -
-
-
 
-
- -
-
 
- Cannot retrieve contributors at this time -
-
- - - - - - - - - -
- -
- - -
- - 235 KB -
- -
- - - - -
- - - - - -
-
- -
- -
-
- - - -
- -
- View raw -
-
- -
- - - - -
- - -
- - -
-
- - -
- - - -
-
- -
-
- -
- - - - - - - - - - - - - - - - - - - - diff --git a/test/meshfiles/shp/multipoly/multipoly.cpg b/test/meshfiles/shp/multipoly/multipoly.cpg new file mode 100644 index 000000000..57decb481 --- /dev/null +++ b/test/meshfiles/shp/multipoly/multipoly.cpg @@ -0,0 +1 @@ +ISO-8859-1 diff --git a/test/meshfiles/shp/multipoly/multipoly.dbf b/test/meshfiles/shp/multipoly/multipoly.dbf new file mode 100644 index 000000000..24fa8a9d3 Binary files /dev/null and b/test/meshfiles/shp/multipoly/multipoly.dbf differ diff --git a/test/meshfiles/shp/multipoly/multipoly.shp b/test/meshfiles/shp/multipoly/multipoly.shp new file mode 100644 index 000000000..095e5e032 Binary files /dev/null and b/test/meshfiles/shp/multipoly/multipoly.shp differ diff --git a/test/meshfiles/shp/multipoly/multipoly.shx b/test/meshfiles/shp/multipoly/multipoly.shx new file mode 100644 index 000000000..4d26d5647 Binary files /dev/null and b/test/meshfiles/shp/multipoly/multipoly.shx differ diff --git a/test/test_geopandas.py b/test/test_geopandas.py new file mode 100644 index 000000000..3c7e441e7 --- /dev/null +++ b/test/test_geopandas.py @@ -0,0 +1,57 @@ +import os +import numpy as np + +from unittest import TestCase +from pathlib import Path + +import uxarray as ux +import matplotlib.pyplot as plt + +current_path = Path(os.path.dirname(os.path.realpath(__file__))) + + +class TestGeopandas(TestCase): + + shp_filename = current_path / "meshfiles" / "shp" / "cb_2018_us_nation_20m" / "cb_2018_us_nation_20m.shp" + shp_filename_5poly = current_path / "meshfiles" / "shp" / "5poly/5poly.shp" + shp_filename_multi = current_path / "meshfiles" / "shp" / "multipoly/multipoly.shp" + geojson_filename = current_path / "meshfiles"/ "geojson"/ "sample_chicago_buildings.geojson" + + def test_read_shpfile(self): + """Read a shapefile.""" + + uxgrid = ux.Grid.from_file(self.shp_filename) + assert (uxgrid.validate()) + + def test_read_shpfile_multi(self): + """Read a shapefile, that consists of multipolygons.""" + + uxgrid = ux.Grid.from_file(self.shp_filename_multi) + assert (uxgrid.validate()) + + def test_read_shpfile_5poly(self): + """Read a shapefile, that consists of 5 polygons of different + shapes.""" + + uxgrid = ux.Grid.from_file(self.shp_filename_5poly) + assert (uxgrid.validate()) + + def test_read_geojson(self): + """Read a geojson file with a few of Chicago buildings. + + Number of polygons: 10 + Polygon 1: 26 sides + Polygon 2: 36 sides + Polygon 3: 29 sides + Polygon 4: 10 sides + Polygon 5: 30 sides + Polygon 6: 8 sides + Polygon 7: 7 sides + Polygon 8: 9 sides + Polygon 9: 7 sides + Polygon 10: 19 sides + """ + + uxgrid = ux.Grid.from_file(self.geojson_filename) + assert (uxgrid.n_face == 10) + assert (uxgrid.n_max_face_nodes == 36) diff --git a/test/test_grid.py b/test/test_grid.py index 6b80aa87a..a31223ffe 100644 --- a/test/test_grid.py +++ b/test/test_grid.py @@ -281,7 +281,6 @@ def test_read_scrip(self): # Test read from scrip and from ugrid for grid class grid_CSne8 = ux.open_grid(gridfile_CSne8) # tests from scrip - pass class TestOperators(TestCase): @@ -926,7 +925,6 @@ def test_from_dataset(self): xrds = xr.open_dataset(self.gridfile_scrip) uxgrid = ux.Grid.from_dataset(xrds) - pass def test_from_face_vertices(self): single_face_latlon = [(0.0, 90.0), (-180, 0.0), (0.0, -90)] @@ -961,7 +959,35 @@ def test_populate_bounds_GCA_mix(self): face_bounds = bounds_xarray.values nt.assert_allclose(grid.bounds.values, expected_bounds, atol=ERROR_TOLERANCE) - def test_opti_bounds(self): - import uxarray - uxgrid = ux.open_grid(gridfile_CSne8) - bounds = uxgrid.bounds + def test_populate_bounds_MPAS(self): + uxgrid = ux.open_grid(self.gridfile_mpas) + bounds_xarray = uxgrid.bounds + + +class TestNormalizeExistingCoordinates(TestCase): + gridfile_mpas = current_path / "meshfiles" / "mpas" / "QU" / "mesh.QU.1920km.151026.nc" + gridfile_CSne30 = current_path / "meshfiles" / "ugrid" / "outCSne30" / "outCSne30.ug" + + def test_non_norm_initial(self): + """Check the normalization of coordinates that were initially parsed as + non-normalized.""" + from uxarray.grid.validation import _check_normalization + uxgrid = ux.open_grid(self.gridfile_mpas) + + # Make the coordinates not normalized + uxgrid.node_x.data = 5 * uxgrid.node_x.data + uxgrid.node_y.data = 5 * uxgrid.node_y.data + uxgrid.node_z.data = 5 * uxgrid.node_z.data + assert not _check_normalization(uxgrid) + + uxgrid.normalize_cartesian_coordinates() + + assert _check_normalization(uxgrid) + + def test_norm_initial(self): + """Coordinates should be normalized for grids that we construct + them.""" + from uxarray.grid.validation import _check_normalization + uxgrid = ux.open_grid(self.gridfile_CSne30) + + assert _check_normalization(uxgrid) diff --git a/uxarray/constants.py b/uxarray/constants.py index d55e25b49..e821de4d6 100644 --- a/uxarray/constants.py +++ b/uxarray/constants.py @@ -22,3 +22,5 @@ ENABLE_FMA = False GRID_DIMS = ["n_node", "n_edge", "n_face"] + +WGS84_CRS = "EPSG:4326" diff --git a/uxarray/grid/grid.py b/uxarray/grid/grid.py index b1ff3e43c..64d6ee653 100644 --- a/uxarray/grid/grid.py +++ b/uxarray/grid/grid.py @@ -12,10 +12,10 @@ Union, ) - # reader and writer imports from uxarray.io._exodus import _read_exodus, _encode_exodus from uxarray.io._mpas import _read_mpas +from uxarray.io._geopandas import _read_geodataframe from uxarray.io._ugrid import ( _read_ugrid, _encode_ugrid, @@ -38,6 +38,7 @@ _set_desired_longitude_range, _populate_node_latlon, _populate_node_xyz, + _normalize_xyz, ) from uxarray.grid.connectivity import ( _populate_edge_node_connectivity, @@ -72,6 +73,7 @@ _check_connectivity, _check_duplicate_nodes, _check_area, + _check_normalization, ) from xarray.core.utils import UncachedAccessor @@ -158,6 +160,7 @@ def __init__( # initialize attributes self._antimeridian_face_indices = None + self._ds.assign_attrs({"source_grid_spec": self.source_grid_spec}) # initialize cached data structures and flags (visualization) self._gdf = None @@ -175,6 +178,9 @@ def __init__( self._ball_tree = None self._kd_tree = None + # flag to track if coordinates are normalized + self._normalized = None + # set desired longitude range to [-180, 180] _set_desired_longitude_range(self._ds) @@ -221,7 +227,9 @@ def from_dataset( elif source_grid_spec == "ICON": grid_ds, source_dims_dict = _read_icon(dataset, use_dual=use_dual) elif source_grid_spec == "Shapefile": - raise ValueError("Shapefiles not yet supported") + raise ValueError( + "Use ux.Grid.from_geodataframe(>> import uxarray as ux + >>> grid = ux.Grid.from_file("path/to/file.shp") + + Note + ---- + All formats supported by `geopandas.read_file` can be used. + See more at: https://geopandas.org/en/stable/docs/reference/api/geopandas.read_file.html#geopandas-read-file + """ + + # determine grid/mesh specification + if backend == "geopandas": + if str(filename).endswith(".shp"): + source_grid_spec = "Shapefile" + elif str(filename).endswith(".geojson"): + source_grid_spec = "GeoJSON" + else: + source_grid_spec = "OtherGeoFormat" + + grid_ds, source_dims_dict = _read_geodataframe(filename) + + elif backend == "xarray": + grid_ds, source_dims_dict = cls.from_dataset(filename) + + else: + raise ValueError("Backend not supported") + + return cls(grid_ds, source_grid_spec, source_dims_dict) + @classmethod def from_topology( cls, @@ -1420,6 +1475,38 @@ def compute_face_areas( return self._face_areas, self._face_jacobian + def normalize_cartesian_coordinates(self): + """Normalizes Cartesian coordinates.""" + + if _check_normalization(self): + # check if coordinates are already normalized + return + + if "node_x" in self._ds: + # normalize node coordinates + node_x, node_y, node_z = _normalize_xyz( + self.node_x.values, self.node_y.values, self.node_z.values + ) + self.node_x.data = node_x + self.node_y.data = node_y + self.node_z.data = node_z + if "edge_x" in self._ds: + # normalize edge coordinates + edge_x, edge_y, edge_z = _normalize_xyz( + self.edge_x.values, self.edge_y.values, self.edge_z.values + ) + self.edge_x.data = edge_x + self.edge_y.data = edge_y + self.edge_z.data = edge_z + if "face_x" in self._ds: + # normalize face coordinates + face_x, face_y, face_z = _normalize_xyz( + self.face_x.values, self.face_y.values, self.face_z.values + ) + self.face_x.data = face_x + self.face_y.data = face_y + self.face_z.data = face_z + def to_xarray(self, grid_format: Optional[str] = "ugrid"): """Returns a xarray Dataset representation in a specific grid format from the Grid object. diff --git a/uxarray/grid/intersections.py b/uxarray/grid/intersections.py index 81829a68a..21daab6dd 100644 --- a/uxarray/grid/intersections.py +++ b/uxarray/grid/intersections.py @@ -21,7 +21,7 @@ def gca_gca_intersection(gca1_cart, gca2_cart, fma_disabled=True): Cartesian coordinates of the first GCA. gca2_cart : [n, 3] np.ndarray where n is the number of intersection points Cartesian coordinates of the second GCA. - fma_disabled : bool, optional (default=False) + fma_disabled : bool, optional (default=True) If True, the FMA operation is disabled. And a naive `np.cross` is used instead. Returns @@ -116,7 +116,7 @@ def gca_gca_intersection(gca1_cart, gca2_cart, fma_disabled=True): def gca_constLat_intersection( - gca_cart, constZ, fma_disabled=False, verbose=False, is_directed=False + gca_cart, constZ, fma_disabled=True, verbose=False, is_directed=False ): """Calculate the intersection point(s) of a Great Circle Arc (GCA) and a constant latitude line in a Cartesian coordinate system. @@ -130,7 +130,7 @@ def gca_constLat_intersection( gca_cart : [2, 3] np.ndarray Cartesian coordinates of the two end points GCA. constZ : float The constant latitude represented in cartesian of the latitude line. - fma_disabled : bool, optional (default=False) + fma_disabled : bool, optional (default=True) If True, the FMA operation is disabled. And a naive `np.cross` is used instead. verbose : bool, optional (default=False) If True, the function prints out the intermediate results. diff --git a/uxarray/grid/validation.py b/uxarray/grid/validation.py index 4f74249a5..b42b8cbb3 100644 --- a/uxarray/grid/validation.py +++ b/uxarray/grid/validation.py @@ -1,12 +1,11 @@ import numpy as np from warnings import warn - from uxarray.constants import ERROR_TOLERANCE # validation helper functions -def _check_connectivity(self): +def _check_connectivity(grid): """Check if all nodes are referenced by at least one element. If not, the mesh may have hanging nodes and may not a valid UGRID @@ -15,28 +14,28 @@ def _check_connectivity(self): # Check if all nodes are referenced by at least one element # get unique nodes in connectivity - nodes_in_conn = np.unique(self.face_node_connectivity.values.flatten()) + nodes_in_conn = np.unique(grid.face_node_connectivity.values.flatten()) # remove negative indices/fill values from the list nodes_in_conn = nodes_in_conn[nodes_in_conn >= 0] # check if the size of unique nodes in connectivity is equal to the number of nodes - if nodes_in_conn.size == self.n_node: + if nodes_in_conn.size == grid.n_node: print("-All nodes are referenced by at least one element.") return True else: warn( "Some nodes may not be referenced by any element. {0} and {1}".format( - nodes_in_conn.size, self.n_node + nodes_in_conn.size, grid.n_node ), RuntimeWarning, ) return False -def _check_duplicate_nodes(self): +def _check_duplicate_nodes(grid): """Check if there are duplicate nodes in the mesh.""" - coords1 = np.column_stack((np.vstack(self.node_lon), np.vstack(self.node_lat))) + coords1 = np.column_stack((np.vstack(grid.node_lon), np.vstack(grid.node_lat))) unique_nodes, indices = np.unique(coords1, axis=0, return_index=True) duplicate_indices = np.setdiff1d(np.arange(len(coords1)), indices) @@ -53,9 +52,9 @@ def _check_duplicate_nodes(self): return True -def _check_area(self): +def _check_area(grid): """Check if each face area is greater than our constant ERROR_TOLERANCE.""" - areas = self.face_areas + areas = grid.face_areas # Check if area of any face is close to zero if np.any(np.isclose(areas, 0, atol=ERROR_TOLERANCE)): warn( @@ -66,3 +65,47 @@ def _check_area(self): else: print("-No face area is close to zero.") return True + + +def _check_normalization(grid): + """Checks whether all the cartesiain coordinates are normalized.""" + + if grid._normalized is True: + # grid is already normalized, no need to run extra checks + return grid._normalized + + if "node_x" in grid._ds: + if not ( + np.isclose( + (grid.node_x**2 + grid.node_y**2 + grid.node_z**2), + 1.0, + atol=ERROR_TOLERANCE, + ) + ).all(): + grid._normalized = False + return False + if "edge_x" in grid._ds: + if not ( + np.isclose( + (grid.node_x**2 + grid.node_y**2 + grid.node_z**2), + 1.0, + atol=ERROR_TOLERANCE, + ) + ).all(): + grid._normalized = False + return False + if "face_x" in grid._ds: + if not ( + np.isclose( + (grid.node_x**2 + grid.node_y**2 + grid.node_z**2), + 1.0, + atol=ERROR_TOLERANCE, + ) + ).all(): + grid._normalized = False + return False + + # set the grid as normalized + grid._normalized = True + + return True diff --git a/uxarray/io/_geopandas.py b/uxarray/io/_geopandas.py new file mode 100644 index 000000000..4852a6d29 --- /dev/null +++ b/uxarray/io/_geopandas.py @@ -0,0 +1,242 @@ +import geopandas as gpd +import xarray as xr +import numpy as np +from uxarray.conventions import ugrid +from uxarray.constants import INT_DTYPE, INT_FILL_VALUE, WGS84_CRS + + +def _read_geodataframe(filepath, driver=None, **kwargs): + """Read geospatial data, using geopandas. + + Parameters + ---------- + filepath : str + Filepath to geospatial data. + driver : str, optional + Driver to use, by default None, in which case geopandas will try to infer the driver from the file extension. + **kwargs + Keyword arguments to pass to geopandas.read_file(). + + Returns + ------- + xr.Dataset + ugrid aware xarray.Dataset. + """ + grid_ds = xr.Dataset() + + gdf, max_coord_size = _gpd_read(filepath, driver=driver, **kwargs) + + node_lon, node_lat, connectivity = _extract_geometry_info(gdf, max_coord_size) + + grid_ds["node_lon"] = xr.DataArray( + data=node_lon, dims=ugrid.NODE_DIM, attrs=ugrid.NODE_LON_ATTRS + ) + grid_ds["node_lat"] = xr.DataArray( + data=node_lat, dims=ugrid.NODE_DIM, attrs=ugrid.NODE_LAT_ATTRS + ) + grid_ds["face_node_connectivity"] = xr.DataArray( + data=connectivity, + dims=ugrid.FACE_NODE_CONNECTIVITY_DIMS, + attrs=ugrid.FACE_NODE_CONNECTIVITY_ATTRS, + ) + + return grid_ds, None + + +def _gpd_read(filepath, driver=None, **kwargs): + """Read a geospatial data using geopandas. + + Parameters + ---------- + filepath : str + Filepath to geospatial data. + driver : str, optional + Driver to use, by default None, in which case geopandas will try to infer the driver from the file extension. + **kwargs + Keyword arguments to pass to geopandas.read_file(). + + Returns + ------- + gpd.GeoDataFrame + GeoDataFrame with geometries. + int + Maximum number of nodes in a polygon/multipolygon. + """ + try: + gdf = gpd.read_file(filepath, driver=driver, **kwargs) + gdf = _set_crs(gdf) + except Exception as e: + print(f"An error occurred while reading the geospatial data: {e}") + + max_polygon_nodes = gdf["geometry"].apply(_get_num_nodes).max() + + return gdf, max_polygon_nodes + + +def _set_crs(gdf): + """Set CRS for GeoDataFrame if not already set. + + Parameters + ---------- + gdf : gpd.GeoDataFrame + GeoDataFrame to set CRS for. + + Returns + ------- + gpd.GeoDataFrame + GeoDataFrame with CRS set. + """ + if gdf.crs is None: + gdf = gdf.set_crs(WGS84_CRS) + print("Original CRS: None\nAssigned CRS:", gdf.crs) + + if gdf.crs != WGS84_CRS: + gdf = gdf.to_crs(WGS84_CRS) + print("Transformed CRS:", gdf.crs) + + return gdf + + +def _extract_geometry_info(gdf, max_coord_size): + """Extract node and connectivity information from GeoDataFrame. + + Parameters + ---------- + gdf : gpd.GeoDataFrame + GeoDataFrame with geometries. + max_coord_size : int + Maximum number of nodes in a polygon/multipolygon. + + Returns + ------- + np.ndarray + Array of longitudes. + np.ndarray + Array of latitudes. + np.ndarray + Connectivity array. + """ + node_lon_list = [] + node_lat_list = [] + connectivity = np.empty((0, max_coord_size - 1), dtype=INT_DTYPE) + + node_index = 0 + + for _, row in gdf.iterrows(): + geometry = row["geometry"] + if geometry.geom_type == "Polygon": + node_lat, node_lon, connectivity, node_index = _read_polygon( + geometry, node_lat_list, node_lon_list, connectivity, node_index + ) + elif geometry.geom_type == "MultiPolygon": + node_lat, node_lon, connectivity, node_index = _read_multipolygon( + geometry, node_lat_list, node_lon_list, connectivity, node_index + ) + else: + print(f"Unsupported geometry type: {geometry.geom_type}") + + # Convert lists to numpy arrays at the end + node_lon = np.array(node_lon_list) + node_lat = np.array(node_lat_list) + + return node_lon, node_lat, connectivity + + +def _get_num_nodes(geom): + """Get number of nodes in a polygon/multipolygon. + + Parameters + ---------- + geom : gpd.GeoSeries + GeoPandas geometry object. + + Returns + ------- + int + Maximum number of nodes in a polygon or multipolygon. + """ + if geom.geom_type == "Polygon": + return len(geom.exterior.coords) + elif geom.geom_type == "MultiPolygon": + return max(len(polygon.exterior.coords) for polygon in geom.geoms) + else: + return 0 # Not a polygon or multipolygon + + +def _read_multipolygon(geometry, node_lat, node_lon, connectivity, node_index): + """Read a multipolygon. + + Parameters + ---------- + geometry : gpd.GeoSeries + GeoPandas geometry object. + node_lat : list + List of latitudes. + node_lon : list + List of longitudes. + connectivity : np.ndarray + Connectivity array. + node_index : int + Index of the current node. + + Returns + ------- + np.ndarray + Updated array of latitudes. + np.ndarray + Updated array of longitudes. + np.ndarray + Updated connectivity array. + int + Updated node index. + """ + for polygon in geometry.geoms: + node_lon, node_lat, connectivity, node_index = _read_polygon( + polygon, node_lat, node_lon, connectivity, node_index + ) + return np.array(node_lat), np.array(node_lon), connectivity, node_index + + +def _read_polygon(polygon, node_lat, node_lon, connectivity, node_index): + """Read a polygon and append its coordinates. + + Parameters + ---------- + polygon : gpd.GeoSeries + GeoPandas geometry object. + node_lat : list + List of latitudes. + node_lon : list + List of longitudes. + connectivity : np.ndarray + Connectivity array. + node_index : int + Index of the current node. + + Returns + ------- + np.ndarray + Updated array of latitudes. + np.ndarray + Updated array of longitudes. + np.ndarray + Updated connectivity array. + int + Updated node index. + """ + # Append polygon coordinates to node lists + node_lon.extend(polygon.exterior.coords.xy[0][:-1]) + node_lat.extend(polygon.exterior.coords.xy[1][:-1]) + + coord_size_polygon = len(polygon.exterior.coords.xy[0][:-1]) + max_coord_size = connectivity.shape[1] + + new_row = np.array(range(node_index, node_index + coord_size_polygon)) + padding_length = max_coord_size - len(new_row) + padding_array = np.full(padding_length, INT_FILL_VALUE) + new_row = np.concatenate((new_row, padding_array)) + + connectivity = np.vstack((connectivity, new_row)) + node_index += coord_size_polygon + + return node_lat, node_lon, connectivity, node_index diff --git a/uxarray/io/_shapefile.py b/uxarray/io/_shapefile.py deleted file mode 100644 index d841072ce..000000000 --- a/uxarray/io/_shapefile.py +++ /dev/null @@ -1,10 +0,0 @@ -def _read_shpfile(filepath): - """Read shape file. - - Not implemented. - """ - raise RuntimeError( - "Function not implemented yet. FYI, attempted to read SHAPE file: " - + str(filepath) - ) - # TODO: create ds