kopia lustrzana https://github.com/onthegomap/planetiler
Migrate to eclipse formatter to support multiple IDEs (#122)
rodzic
bce75230f2
commit
cce51668f2
|
@ -1,4 +1,5 @@
|
||||||
---
|
---
|
||||||
|
|
||||||
name: Bug report
|
name: Bug report
|
||||||
about: Create a report to help improve Planetiler
|
about: Create a report to help improve Planetiler
|
||||||
title: "[BUG] "
|
title: "[BUG] "
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
---
|
---
|
||||||
|
|
||||||
name: Feature request
|
name: Feature request
|
||||||
about: Suggest an idea for Planetiler
|
about: Suggest an idea for Planetiler
|
||||||
title: "[FEATURE] "
|
title: "[FEATURE] "
|
||||||
|
|
|
@ -15,7 +15,8 @@ updates:
|
||||||
ignore:
|
ignore:
|
||||||
- dependency-name: "com.graphhopper:graphhopper-reader-osm"
|
- dependency-name: "com.graphhopper:graphhopper-reader-osm"
|
||||||
- package-ecosystem: maven
|
- package-ecosystem: maven
|
||||||
directory: "/planetiler-examples"
|
# workaround for https://github.com/dependabot/dependabot-core/issues/4425
|
||||||
|
directory: "/.github/planetiler-examples-dependabot"
|
||||||
open-pull-requests-limit: 1
|
open-pull-requests-limit: 1
|
||||||
schedule:
|
schedule:
|
||||||
interval: daily
|
interval: daily
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
This is just a workaround for https://github.com/dependabot/dependabot-core/issues/4425 so that
|
||||||
|
dependabot can update planetiler-examples/standalone.pom.xml without referring directly to a pom.xml with a
|
||||||
|
non-standard name.
|
||||||
|
-->
|
||||||
|
<project
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.onthegomap.planetiler</groupId>
|
||||||
|
<artifactId>planetiler-examples-parent-for-dependabot</artifactId>
|
||||||
|
<version>HEAD</version>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module>../../planetiler-examples/pom.xml</module>
|
||||||
|
</modules>
|
||||||
|
</project>
|
|
@ -34,10 +34,10 @@ jobs:
|
||||||
cache: 'maven'
|
cache: 'maven'
|
||||||
- name: Build with mvnw (linux/mac)
|
- name: Build with mvnw (linux/mac)
|
||||||
if: ${{ !contains(matrix.os, 'windows') }}
|
if: ${{ !contains(matrix.os, 'windows') }}
|
||||||
run: ./mvnw ${{matrix.args}} --batch-mode -no-transfer-progress package jib:buildTar --file pom.xml
|
run: ./mvnw ${{matrix.args}} --batch-mode -no-transfer-progress package verify jib:buildTar --file pom.xml
|
||||||
- name: Build with mvnw.cmd (windows)
|
- name: Build with mvnw.cmd (windows)
|
||||||
if: ${{ contains(matrix.os, 'windows') }}
|
if: ${{ contains(matrix.os, 'windows') }}
|
||||||
run: mvnw.cmd ${{matrix.args}} --batch-mode -no-transfer-progress package jib:buildTar --file pom.xml
|
run: mvnw.cmd ${{matrix.args}} --batch-mode -no-transfer-progress package verify jib:buildTar --file pom.xml
|
||||||
shell: cmd
|
shell: cmd
|
||||||
|
|
||||||
regenerate:
|
regenerate:
|
||||||
|
@ -54,7 +54,7 @@ jobs:
|
||||||
cache: 'maven'
|
cache: 'maven'
|
||||||
- run: ./scripts/regenerate-openmaptiles.sh
|
- run: ./scripts/regenerate-openmaptiles.sh
|
||||||
- run: ./mvnw -DskipTests --batch-mode -no-transfer-progress clean install -pl planetiler-basemap -am
|
- run: ./mvnw -DskipTests --batch-mode -no-transfer-progress clean install -pl planetiler-basemap -am
|
||||||
- run: ./mvnw --batch-mode -no-transfer-progress test -pl planetiler-basemap
|
- run: ./mvnw --batch-mode -no-transfer-progress verify -pl planetiler-basemap
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
name: Example project
|
name: Example project
|
||||||
|
@ -69,7 +69,7 @@ jobs:
|
||||||
java-version: 17
|
java-version: 17
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
- name: Build and test
|
- name: Build and test
|
||||||
run: mvn --batch-mode -no-transfer-progress package --file pom.xml
|
run: mvn --batch-mode -no-transfer-progress package --file standalone.pom.xml
|
||||||
working-directory: planetiler-examples
|
working-directory: planetiler-examples
|
||||||
- name: Find jar
|
- name: Find jar
|
||||||
run: mv target/*with-deps.jar ./run.jar
|
run: mv target/*with-deps.jar ./run.jar
|
||||||
|
|
|
@ -5,11 +5,19 @@ target/
|
||||||
!.mvn/wrapper/*.jar
|
!.mvn/wrapper/*.jar
|
||||||
*.log
|
*.log
|
||||||
|
|
||||||
|
# idea
|
||||||
*/.idea
|
*/.idea
|
||||||
.idea/*
|
.idea/*
|
||||||
*.iml
|
*.iml
|
||||||
!.idea/codeStyles
|
!.idea/codeStyles
|
||||||
!.idea/vcs.xml
|
!.idea/vcs.xml
|
||||||
|
!.idea/eclipseCodeFormatter.xml
|
||||||
|
|
||||||
|
# eclipse
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
bin/
|
||||||
|
|
||||||
TODO
|
TODO
|
||||||
|
|
||||||
|
|
|
@ -265,6 +265,7 @@
|
||||||
</indentOptions>
|
</indentOptions>
|
||||||
</codeStyleSettings>
|
</codeStyleSettings>
|
||||||
<codeStyleSettings language="XML">
|
<codeStyleSettings language="XML">
|
||||||
|
<option name="RIGHT_MARGIN" value="120" />
|
||||||
<indentOptions>
|
<indentOptions>
|
||||||
<option name="INDENT_SIZE" value="2" />
|
<option name="INDENT_SIZE" value="2" />
|
||||||
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||||
|
@ -594,4 +595,4 @@
|
||||||
</indentOptions>
|
</indentOptions>
|
||||||
</codeStyleSettings>
|
</codeStyleSettings>
|
||||||
</code_scheme>
|
</code_scheme>
|
||||||
</component>
|
</component>
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="EclipseCodeFormatterProjectSettings">
|
||||||
|
<option name="projectSpecificProfile">
|
||||||
|
<ProjectSpecificProfile>
|
||||||
|
<option name="formatter" value="ECLIPSE" />
|
||||||
|
<option name="importOrder" value="#;" />
|
||||||
|
<option name="pathToConfigFileJava" value="$PROJECT_DIR$/eclipse-formatter.xml" />
|
||||||
|
<option name="selectedJavaProfile" value="Planetiler" />
|
||||||
|
</ProjectSpecificProfile>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,5 @@
|
||||||
|
--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
|
||||||
|
--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED
|
||||||
|
--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
|
||||||
|
--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
|
||||||
|
--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"java.format.settings.url": "eclipse-formatter.xml",
|
||||||
|
"java.format.settings.profile": "Planetiler",
|
||||||
|
"java.completion.importOrder": [
|
||||||
|
"#",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"java.sources.organizeImports.staticStarThreshold": 5,
|
||||||
|
"java.sources.organizeImports.starThreshold": 999,
|
||||||
|
"java.saveActions.organizeImports": true
|
||||||
|
}
|
|
@ -121,3 +121,4 @@ Finally, a single-threaded writer writes encoded vector tiles to the output MBTi
|
||||||
- Create the largest prepared statement supported by SQLite (999 parameters)
|
- Create the largest prepared statement supported by SQLite (999 parameters)
|
||||||
- Iterate through finished vector tile batches until the prepared statement is full, flush to disk, then repeat
|
- Iterate through finished vector tile batches until the prepared statement is full, flush to disk, then repeat
|
||||||
- Then flush any remaining tiles at the end
|
- Then flush any remaining tiles at the end
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,14 @@
|
||||||
# Contributing to Planetiler
|
# Contributing to Planetiler
|
||||||
|
|
||||||
Pull requests are welcome! To set up your development environment:
|
Pull requests are welcome! Any pull request should:
|
||||||
|
|
||||||
|
- Include at least one unit test to verify the change in behavior
|
||||||
|
- Include an end-to-end test
|
||||||
|
in [PlanetilerTests.java](planetiler-core/src/test/java/com/onthegomap/planetiler/PlanetilerTests.java)
|
||||||
|
to verify any major new user-facing features work
|
||||||
|
- Format the change `./mvnw spotless:apply` and test with `./mvnw verify` before pushing
|
||||||
|
|
||||||
|
To set up your local development environment:
|
||||||
|
|
||||||
- Fork the repo
|
- Fork the repo
|
||||||
- Install Java 16 or later. You can download Java manually from [Adoptium](https://adoptium.net/installation.html) or
|
- Install Java 16 or later. You can download Java manually from [Adoptium](https://adoptium.net/installation.html) or
|
||||||
|
@ -15,30 +23,57 @@ Pull requests are welcome! To set up your development environment:
|
||||||
- on windows: `mvnw.cmd clean test`
|
- on windows: `mvnw.cmd clean test`
|
||||||
- or if you already have maven installed globally on your machine: `mvn clean test`
|
- or if you already have maven installed globally on your machine: `mvn clean test`
|
||||||
|
|
||||||
To edit the code:
|
GitHub Workflows will run regression tests on any pull request.
|
||||||
|
|
||||||
- [Install IntelliJ IDE](https://www.jetbrains.com/help/idea/installation-guide.html)
|
## IDE Setup
|
||||||
|
|
||||||
|
You can use any text editor as long as you format the code and test before pushing. A good IDE will make things a lot
|
||||||
|
easier though.
|
||||||
|
|
||||||
|
### IntelliJ IDEA (recommended)
|
||||||
|
|
||||||
|
- [Install IntelliJ IDEA](https://www.jetbrains.com/help/idea/installation-guide.html)
|
||||||
|
- Install
|
||||||
|
the [Adapter for Eclipse Code Formatter plugin](https://plugins.jetbrains.com/plugin/6546-adapter-for-eclipse-code-formatter)
|
||||||
- In IntelliJ, click `Open`, navigate to the the `pom.xml` file in the local copy of this repo, and `Open`
|
- In IntelliJ, click `Open`, navigate to the the `pom.xml` file in the local copy of this repo, and `Open`
|
||||||
then `Open as Project`
|
then `Open as Project`
|
||||||
- If IntelliJ asks (and you trust the code) then click `Trust Project`
|
- If IntelliJ asks (and you trust the code) then click `Trust Project`
|
||||||
- If any java source files show "Cannot resolve symbol..." errors for Planetiler classes, you might need to
|
- Under `Preferences -> Tools -> Actions on Save` (or `File -> Settings -> Tools -> Actions on Save` on Linux)
|
||||||
select: `File -> Invalidate Caches... -> Just Restart`.
|
select `Reformat code` and `Optimize imports` to automatically format code on save.
|
||||||
- If you see a "Project JDK is not defined" error, then choose `Setup SDK` and point IntelliJ at the Java 16 or later
|
|
||||||
installed on your system
|
|
||||||
- Recommended: Under `Preferences -> Tools -> Actions on Save` (or `File -> Settings -> Tools -> Actions on Save` on Linux) select `Reformat code` and `Optimize imports` to
|
|
||||||
automatically format code on save.
|
|
||||||
- To verify everything works correctly, right click on `planetiler-core/src/test/java` folder and
|
- To verify everything works correctly, right click on `planetiler-core/src/test/java` folder and
|
||||||
click `Run 'All Tests'`
|
click `Run 'All Tests'`
|
||||||
|
|
||||||
Any pull request should:
|
Troubleshooting:
|
||||||
|
|
||||||
- Include at least one unit test to verify the change in behavior
|
- If any java source files show "Cannot resolve symbol..." errors for Planetiler classes, you might need to
|
||||||
- Include an end-to-end test
|
select: `File -> Invalidate Caches... -> Just Restart`.
|
||||||
in [PlanetilerTests.java](planetiler-core/src/test/java/com/onthegomap/planetiler/PlanetilerTests.java)
|
- If you see a "Project JDK is not defined" error, then choose `Setup SDK` and point IntelliJ at the Java 16 or later
|
||||||
to verify any major new user-facing features work
|
installed on your system
|
||||||
- Use IntelliJ's auto-formatting for modified files (this should get enabled automatically)
|
|
||||||
- Be free of IntelliJ warnings for modified files
|
|
||||||
|
|
||||||
GitHub Workflows will run regression tests on any pull request.
|
### Visual Studio Code
|
||||||
|
|
||||||
TODO: Set up checkstyle and an auto-formatter to enforce standards, so you can use any IDE.
|
- Install the [Extension Pack for Java](https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-pack)
|
||||||
|
- In VSCode, click `File -> Open` and navigate to Planetiler directory
|
||||||
|
- If VSCode asks (and you trust the code) then click `Yes I trust the authors`
|
||||||
|
- To verify everything works correctly, go to the `Testing` tab and click `Run Tests`
|
||||||
|
|
||||||
|
Learn more about using VSCode with Java [here](https://code.visualstudio.com/docs/languages/java).
|
||||||
|
|
||||||
|
### Eclipse
|
||||||
|
|
||||||
|
- In [Eclipse for Java Developers](https://www.eclipse.org/downloads/packages/), click `File -> Import ...`
|
||||||
|
then `Maven -> Existing Maven Projects`, navigate to Planetiler directory, and click `Finish`
|
||||||
|
- Under `Eclipse -> Preferences...`:
|
||||||
|
- Under `Java -> Code Style -> Formatter` and choose `Import...`
|
||||||
|
choose [`eclipse-formatter.xml`](eclipse-formatter.xml) from the root of this project. Then choose `Planetiler` as
|
||||||
|
the Active profile.
|
||||||
|
- Under `Java -> Editor -> Save Actions` check `Perform selected actions on save`, `Format source code`
|
||||||
|
, `Format all lines` and `Organize imports`
|
||||||
|
- Under `Java -> Code Style -> Organize Imports` change the `number of static imports needed for .*` to 5, then remove
|
||||||
|
the groups and add 2 new groups:
|
||||||
|
- `New Static...` and `*`
|
||||||
|
- `New...` and `*`
|
||||||
|
- To verify everything works correctly, right click on `planetiler-core/src/test/java` folder and
|
||||||
|
click `Run As -> JUnit Test`
|
||||||
|
|
||||||
|
TODO: Set up checkstyle
|
||||||
|
|
|
@ -50,10 +50,11 @@ Additionally, the `planetiler-basemap` module is based on [OpenMapTiles](https:/
|
||||||
|
|
||||||
## Data
|
## Data
|
||||||
|
|
||||||
| source | license | used as default | included in repo |
|
| source | license | used as default | included in repo |
|
||||||
|----------------------------|--------------------------------------------------------------------------------------------------------------------------------------|-----------------|------------------|
|
|----------------------------|--------------------------------------------------------------------------------------------------------------------------------------|-----------------|------------------|
|
||||||
| OpenStreetMap (OSM) data | [ODBL](https://www.openstreetmap.org/copyright) | yes | yes |
|
| OpenStreetMap (OSM) data | [ODBL](https://www.openstreetmap.org/copyright) | yes | yes |
|
||||||
| Natural Earth | [public domain](https://www.naturalearthdata.com/about/terms-of-use/) | yes | yes |
|
| Natural Earth | [public domain](https://www.naturalearthdata.com/about/terms-of-use/) | yes | yes |
|
||||||
| OSM Lakelines | [MIT](https://github.com/lukasmartinelli/osm-lakelines), data from OSM [ODBL](https://www.openstreetmap.org/copyright) | yes | no |
|
| OSM Lakelines | [MIT](https://github.com/lukasmartinelli/osm-lakelines), data from OSM [ODBL](https://www.openstreetmap.org/copyright) | yes | no |
|
||||||
| OSM Water Polygons | [acknowledgement](https://osmdata.openstreetmap.de/info/license.html), data from OSM [ODBL](https://www.openstreetmap.org/copyright) | yes | yes |
|
| OSM Water Polygons | [acknowledgement](https://osmdata.openstreetmap.de/info/license.html), data from OSM [ODBL](https://www.openstreetmap.org/copyright) | yes | yes |
|
||||||
| Wikidata name translations | [CCO](https://www.wikidata.org/wiki/Wikidata:Licensing) | no | no |
|
| Wikidata name translations | [CCO](https://www.wikidata.org/wiki/Wikidata:Licensing) | no | no |
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,12 @@ First decide where to get the `planet.osm.pbf` file:
|
||||||
- Or a [Daylight Distribution](https://daylightmap.org/) snapshot from Facebook that includes extra quality/consistency
|
- Or a [Daylight Distribution](https://daylightmap.org/) snapshot from Facebook that includes extra quality/consistency
|
||||||
checks, and add-ons like ML-detected roads and buildings. Combine add-ons and re-number
|
checks, and add-ons like ML-detected roads and buildings. Combine add-ons and re-number
|
||||||
using [osmium-tool](https://osmcode.org/osmium-tool/):
|
using [osmium-tool](https://osmcode.org/osmium-tool/):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
osmium apply-changes daylight.osm.pbf admin.osc.bz2 <buildings.osc.bz2, ...> -o everything.osm.pbf
|
osmium apply-changes daylight.osm.pbf admin.osc.bz2 <buildings.osc.bz2, ...> -o everything.osm.pbf
|
||||||
osmium renumber everything.osm.pbf -o planet.osm.pbf
|
osmium renumber everything.osm.pbf -o planet.osm.pbf
|
||||||
```
|
```
|
||||||
|
|
||||||
NOTE: you need at least `admin.osc.bz2` for the `boundary` layer to show. This takes about 2.5 hours and needs as much
|
NOTE: you need at least `admin.osc.bz2` for the `boundary` layer to show. This takes about 2.5 hours and needs as much
|
||||||
RAM as the `planet.osm.pbf` size.
|
RAM as the `planet.osm.pbf` size.
|
||||||
|
|
||||||
|
|
|
@ -118,7 +118,7 @@ See the [planetiler-examples](planetiler-examples) project.
|
||||||
|
|
||||||
Some example runtimes (excluding downloading resources):
|
Some example runtimes (excluding downloading resources):
|
||||||
|
|
||||||
| Input | Profile | Machine | Time | mbtiles size | Logs |
|
| Input | Profile | Machine | Time | mbtiles size | Logs |
|
||||||
|-------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------|----------------------------------------------------------|---------------------------|--------------|--------------------------------------------------------------------------------------------------------------------------------|
|
|-------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------|----------------------------------------------------------|---------------------------|--------------|--------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| s3://osm-pds/2021/planet-211011.osm.pbf (65GB) | Basemap | DO 16cpu 128GB | 3h9m cpu:42h1m avg:13.3 | 99GB | [logs](planet-logs/v0.1.0-planet-do-16cpu-128gb.txt), [VisualVM Profile](planet-logs/v0.1.0-planet-do-16cpu-128gb.nps) |
|
| s3://osm-pds/2021/planet-211011.osm.pbf (65GB) | Basemap | DO 16cpu 128GB | 3h9m cpu:42h1m avg:13.3 | 99GB | [logs](planet-logs/v0.1.0-planet-do-16cpu-128gb.txt), [VisualVM Profile](planet-logs/v0.1.0-planet-do-16cpu-128gb.nps) |
|
||||||
| [Daylight Distribution v1.6](https://daylightmap.org/2021/09/29/daylight-v16-released.html) with ML buildings and admin boundaries (67GB) | Basemap | DO 16cpu 128GB | 3h13m cpu:43h40m avg:13.5 | 101GB | [logs](planet-logs/v0.1.0-daylight-do-16cpu-128gb.txt) |
|
| [Daylight Distribution v1.6](https://daylightmap.org/2021/09/29/daylight-v16-released.html) with ML buildings and admin boundaries (67GB) | Basemap | DO 16cpu 128GB | 3h13m cpu:43h40m avg:13.5 | 101GB | [logs](planet-logs/v0.1.0-daylight-do-16cpu-128gb.txt) |
|
||||||
|
|
|
@ -0,0 +1,480 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<profiles version="21">
|
||||||
|
<profile kind="CodeFormatterProfile" name="Planetiler" version="21">
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters"
|
||||||
|
value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration"
|
||||||
|
value="preserve_positions"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.align_with_spaces" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations"
|
||||||
|
value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="20"/>
|
||||||
|
<setting
|
||||||
|
id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_record_components" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments"
|
||||||
|
value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_logical_operator" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line" value="one_line_never"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments"
|
||||||
|
value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line" value="one_line_if_empty"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause" value="common_lines"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference"
|
||||||
|
value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line" value="one_line_if_empty"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_shift_operator" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header"
|
||||||
|
value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_parameters" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_loops" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation" value="preserve_positions"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.text_block_indentation" value="2"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_module_statements" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line" value="one_line_never"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_annotations" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines" value="2147483647"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="84"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_not_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration"
|
||||||
|
value="preserve_positions"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_arguments" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package" value="49"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header"
|
||||||
|
value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header" value="true"/>
|
||||||
|
<setting
|
||||||
|
id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.indent_tag_description" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_constructor" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_string_concatenation" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_shift_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration"
|
||||||
|
value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_shift_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration"
|
||||||
|
value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_additive_operator" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_relational_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_logical_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="preserve_positions"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration"
|
||||||
|
value="preserve_positions"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="17"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="-1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="2"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration"
|
||||||
|
value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="120"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_method_body_on_one_line" value="one_line_if_empty"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line" value="one_line_never"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line" value="one_line_if_empty"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_additive_operator" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations"
|
||||||
|
value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor"
|
||||||
|
value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_relational_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line" value="one_line_if_empty"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments"
|
||||||
|
value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter" value="48"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_relational_operator" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="2"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_additive_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type" value="49"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable" value="49"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_additive_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_shift_operator" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause" value="separate_lines_if_wrapped"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_code_block_on_one_line" value="one_line_never"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws"
|
||||||
|
value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="2"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assignment_operator" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters"
|
||||||
|
value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters"
|
||||||
|
value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line" value="one_line_never"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method" value="49"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line" value="one_line_if_empty"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration"
|
||||||
|
value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assertion_message" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting
|
||||||
|
id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_logical_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_relational_operator" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="20"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_logical_operator" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration"
|
||||||
|
value="preserve_positions"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line" value="one_line_never"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration"
|
||||||
|
value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_string_concatenation" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
|
@ -27,15 +27,15 @@ import java.util.List;
|
||||||
* <p>
|
* <p>
|
||||||
* Layer implementations extend these interfaces to subscribe to elements from different sources:
|
* Layer implementations extend these interfaces to subscribe to elements from different sources:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link LakeCenterlineProcessor}</li>
|
* <li>{@link LakeCenterlineProcessor}</li>
|
||||||
* <li>{@link NaturalEarthProcessor}</li>
|
* <li>{@link NaturalEarthProcessor}</li>
|
||||||
* <li>{@link OsmWaterPolygonProcessor}</li>
|
* <li>{@link OsmWaterPolygonProcessor}</li>
|
||||||
* <li>{@link OsmAllProcessor} to process every OSM feature</li>
|
* <li>{@link OsmAllProcessor} to process every OSM feature</li>
|
||||||
* <li>{@link OsmRelationPreprocessor} to process every OSM relation during first pass through OSM file</li>
|
* <li>{@link OsmRelationPreprocessor} to process every OSM relation during first pass through OSM file</li>
|
||||||
* <li>A {@link Tables.RowHandler} implementation in {@code Tables.java} to process input features filtered and parsed
|
* <li>A {@link Tables.RowHandler} implementation in {@code Tables.java} to process input features filtered and parsed
|
||||||
* according to the imposm3 mappings defined in the OpenMapTiles schema. Each element corresponds to a row in the
|
* according to the imposm3 mappings defined in the OpenMapTiles schema. Each element corresponds to a row in the table
|
||||||
* table that imposm3 would have generated, with generated methods for accessing the data that would have been in each
|
* that imposm3 would have generated, with generated methods for accessing the data that would have been in each
|
||||||
* column</li>
|
* column</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* Layers can also subscribe to notifications when we finished processing an input source by implementing
|
* Layers can also subscribe to notifications when we finished processing an input source by implementing
|
||||||
* {@link FinishHandler} or post-process features in that layer before rendering the output tile by implementing
|
* {@link FinishHandler} or post-process features in that layer before rendering the output tile by implementing
|
||||||
|
@ -118,9 +118,8 @@ public class BasemapProfile extends ForwardingProfile {
|
||||||
return new RowDispatch(constructor.create(), handlers);
|
return new RowDispatch(constructor.create(), handlers);
|
||||||
}).simplify().index();
|
}).simplify().index();
|
||||||
wikidataMappings = Tables.MAPPINGS
|
wikidataMappings = Tables.MAPPINGS
|
||||||
.mapResults(constructor ->
|
.mapResults(constructor -> handlerMap.getOrDefault(constructor.rowClass(), List.of()).stream()
|
||||||
handlerMap.getOrDefault(constructor.rowClass(), List.of()).stream()
|
.anyMatch(handler -> !IgnoreWikidata.class.isAssignableFrom(handler.handlerClass()))
|
||||||
.anyMatch(handler -> !IgnoreWikidata.class.isAssignableFrom(handler.handlerClass()))
|
|
||||||
).filterResults(b -> b).simplify().index();
|
).filterResults(b -> b).simplify().index();
|
||||||
|
|
||||||
// register a handler for all OSM elements that forwards to imposm3 "table row" handler methods
|
// register a handler for all OSM elements that forwards to imposm3 "table row" handler methods
|
||||||
|
@ -149,8 +148,8 @@ public class BasemapProfile extends ForwardingProfile {
|
||||||
if (elem instanceof OsmElement.Node) {
|
if (elem instanceof OsmElement.Node) {
|
||||||
return wikidataMappings.getOrElse(SimpleFeature.create(EMPTY_POINT, tags), false);
|
return wikidataMappings.getOrElse(SimpleFeature.create(EMPTY_POINT, tags), false);
|
||||||
} else if (elem instanceof OsmElement.Way) {
|
} else if (elem instanceof OsmElement.Way) {
|
||||||
return wikidataMappings.getOrElse(SimpleFeature.create(EMPTY_POLYGON, tags), false)
|
return wikidataMappings.getOrElse(SimpleFeature.create(EMPTY_POLYGON, tags), false) ||
|
||||||
|| wikidataMappings.getOrElse(SimpleFeature.create(EMPTY_LINE, tags), false);
|
wikidataMappings.getOrElse(SimpleFeature.create(EMPTY_LINE, tags), false);
|
||||||
} else if (elem instanceof OsmElement.Relation) {
|
} else if (elem instanceof OsmElement.Relation) {
|
||||||
return wikidataMappings.getOrElse(SimpleFeature.create(EMPTY_POLYGON, tags), false);
|
return wikidataMappings.getOrElse(SimpleFeature.create(EMPTY_POLYGON, tags), false);
|
||||||
} else {
|
} else {
|
||||||
|
@ -201,14 +200,13 @@ public class BasemapProfile extends ForwardingProfile {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Layers should implement this interface to subscribe to elements from <a href="https://www.naturalearthdata.com/">natural
|
* Layers should implement this interface to subscribe to elements from
|
||||||
* earth</a>.
|
* <a href="https://www.naturalearthdata.com/">natural earth</a>.
|
||||||
*/
|
*/
|
||||||
public interface NaturalEarthProcessor {
|
public interface NaturalEarthProcessor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process an element from {@code table} in the<a href="https://www.naturalearthdata.com/">natural earth
|
* Process an element from {@code table} in the<a href="https://www.naturalearthdata.com/">natural earth source</a>.
|
||||||
* source</a>.
|
|
||||||
*
|
*
|
||||||
* @see Profile#processFeature(SourceFeature, FeatureCollector)
|
* @see Profile#processFeature(SourceFeature, FeatureCollector)
|
||||||
*/
|
*/
|
||||||
|
@ -216,8 +214,8 @@ public class BasemapProfile extends ForwardingProfile {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Layers should implement this interface to subscribe to elements from <a href="https://github.com/lukasmartinelli/osm-lakelines">OSM
|
* Layers should implement this interface to subscribe to elements from
|
||||||
* lake centerlines source</a>.
|
* <a href="https://github.com/lukasmartinelli/osm-lakelines">OSM lake centerlines source</a>.
|
||||||
*/
|
*/
|
||||||
public interface LakeCenterlineProcessor {
|
public interface LakeCenterlineProcessor {
|
||||||
|
|
||||||
|
@ -231,8 +229,8 @@ public class BasemapProfile extends ForwardingProfile {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Layers should implement this interface to subscribe to elements from <a href="https://osmdata.openstreetmap.de/data/water-polygons.html">OSM
|
* Layers should implement this interface to subscribe to elements from
|
||||||
* water polygons source</a>.
|
* <a href="https://osmdata.openstreetmap.de/data/water-polygons.html">OSM water polygons source</a>.
|
||||||
*/
|
*/
|
||||||
public interface OsmWaterPolygonProcessor {
|
public interface OsmWaterPolygonProcessor {
|
||||||
|
|
||||||
|
|
|
@ -38,14 +38,14 @@ import org.yaml.snakeyaml.LoaderOptions;
|
||||||
import org.yaml.snakeyaml.Yaml;
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates code in the {@code generated} package from the OpenMapTiles schema crawled from a tag or branch in the <a
|
* Generates code in the {@code generated} package from the OpenMapTiles schema crawled from a tag or branch in the
|
||||||
* href="https://github.com/openmaptiles/openmaptiles">OpenMapTiles GitHub repo</a>.
|
* <a href="https://github.com/openmaptiles/openmaptiles">OpenMapTiles GitHub repo</a>.
|
||||||
* <p>
|
* <p>
|
||||||
* {@code OpenMapTilesSchema.java} contains the output layer definitions (i.e. attributes and allowed values) so that
|
* {@code OpenMapTilesSchema.java} contains the output layer definitions (i.e. attributes and allowed values) so that
|
||||||
* layer implementations in {@code layers} package can reference them instead of hard-coding.
|
* layer implementations in {@code layers} package can reference them instead of hard-coding.
|
||||||
* <p>
|
* <p>
|
||||||
* {@code Tables.java} contains the <a href="https://github.com/omniscale/imposm3">imposm3</a> table definitions from
|
* {@code Tables.java} contains the <a href="https://github.com/omniscale/imposm3">imposm3</a> table definitions from
|
||||||
* mapping.yaml files in the OpenMapTiles repo. Layers in the {@code layer} package can extend the {@code Handler}
|
* mapping.yaml files in the OpenMapTiles repo. Layers in the {@code layer} package can extend the {@code Handler}
|
||||||
* nested class for a table definition to "subscribe" to OSM elements that imposm3 would put in that table.
|
* nested class for a table definition to "subscribe" to OSM elements that imposm3 would put in that table.
|
||||||
* <p>
|
* <p>
|
||||||
* To run use {@code ./scripts/regenerate-openmaptiles.sh}
|
* To run use {@code ./scripts/regenerate-openmaptiles.sh}
|
||||||
|
@ -169,8 +169,7 @@ public class Generate {
|
||||||
|
|
||||||
emitLayerSchemaDefinitions(config.tileset, layers, packageName, output, tag);
|
emitLayerSchemaDefinitions(config.tileset, layers, packageName, output, tag);
|
||||||
emitTableDefinitions(tables, packageName, output, tag);
|
emitTableDefinitions(tables, packageName, output, tag);
|
||||||
LOGGER.info(
|
LOGGER.info("Done!");
|
||||||
"Done generating code in 'generated' package, now run IntelliJ 'Reformat Code' operation with 'Optimize imports' and 'Cleanup code' options selected.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Generates {@code OpenMapTilesSchema.java} */
|
/** Generates {@code OpenMapTilesSchema.java} */
|
||||||
|
@ -178,56 +177,57 @@ public class Generate {
|
||||||
Path output, String tag)
|
Path output, String tag)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
StringBuilder schemaClass = new StringBuilder();
|
StringBuilder schemaClass = new StringBuilder();
|
||||||
schemaClass.append("""
|
schemaClass.append(
|
||||||
%s
|
|
||||||
package %s;
|
|
||||||
|
|
||||||
import static com.onthegomap.planetiler.expression.Expression.*;
|
|
||||||
import com.onthegomap.planetiler.config.PlanetilerConfig;
|
|
||||||
import com.onthegomap.planetiler.stats.Stats;
|
|
||||||
import com.onthegomap.planetiler.expression.MultiExpression;
|
|
||||||
import com.onthegomap.planetiler.basemap.Layer;
|
|
||||||
import com.onthegomap.planetiler.util.Translations;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* All vector tile layer definitions, attributes, and allowed values generated from the
|
|
||||||
* <a href="https://github.com/openmaptiles/openmaptiles/blob/%s/openmaptiles.yaml">OpenMapTiles vector tile schema %s</a>.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public class OpenMapTilesSchema {
|
|
||||||
public static final String NAME = %s;
|
|
||||||
public static final String DESCRIPTION = %s;
|
|
||||||
public static final String VERSION = %s;
|
|
||||||
public static final String ATTRIBUTION = %s;
|
|
||||||
public static final List<String> LANGUAGES = List.of(%s);
|
|
||||||
|
|
||||||
/** Returns a list of expected layer implementation instances from the {@code layers} package. */
|
|
||||||
public static List<Layer> createInstances(Translations translations, PlanetilerConfig config, Stats stats) {
|
|
||||||
return List.of(
|
|
||||||
%s
|
|
||||||
);
|
|
||||||
}
|
|
||||||
"""
|
"""
|
||||||
.formatted(
|
%s
|
||||||
GENERATED_FILE_HEADER,
|
package %s;
|
||||||
packageName,
|
|
||||||
escapeJavadoc(tag),
|
import static com.onthegomap.planetiler.expression.Expression.*;
|
||||||
escapeJavadoc(tag),
|
import com.onthegomap.planetiler.config.PlanetilerConfig;
|
||||||
Format.quote(info.name),
|
import com.onthegomap.planetiler.stats.Stats;
|
||||||
Format.quote(info.description),
|
import com.onthegomap.planetiler.expression.MultiExpression;
|
||||||
Format.quote(info.version),
|
import com.onthegomap.planetiler.basemap.Layer;
|
||||||
Format.quote(info.attribution),
|
import com.onthegomap.planetiler.util.Translations;
|
||||||
info.languages.stream().map(Format::quote).collect(joining(", ")),
|
import java.util.List;
|
||||||
layers.stream()
|
import java.util.Map;
|
||||||
.map(
|
import java.util.Set;
|
||||||
l -> "new com.onthegomap.planetiler.basemap.layers.%s(translations, config, stats)"
|
|
||||||
.formatted(lowerUnderscoreToUpperCamel(l.layer.id)))
|
/**
|
||||||
.collect(joining("," + LINE_SEPARATOR))
|
* All vector tile layer definitions, attributes, and allowed values generated from the
|
||||||
.indent(6).trim()
|
* <a href="https://github.com/openmaptiles/openmaptiles/blob/%s/openmaptiles.yaml">OpenMapTiles vector tile schema %s</a>.
|
||||||
));
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public class OpenMapTilesSchema {
|
||||||
|
public static final String NAME = %s;
|
||||||
|
public static final String DESCRIPTION = %s;
|
||||||
|
public static final String VERSION = %s;
|
||||||
|
public static final String ATTRIBUTION = %s;
|
||||||
|
public static final List<String> LANGUAGES = List.of(%s);
|
||||||
|
|
||||||
|
/** Returns a list of expected layer implementation instances from the {@code layers} package. */
|
||||||
|
public static List<Layer> createInstances(Translations translations, PlanetilerConfig config, Stats stats) {
|
||||||
|
return List.of(
|
||||||
|
%s
|
||||||
|
);
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
.formatted(
|
||||||
|
GENERATED_FILE_HEADER,
|
||||||
|
packageName,
|
||||||
|
escapeJavadoc(tag),
|
||||||
|
escapeJavadoc(tag),
|
||||||
|
Format.quote(info.name),
|
||||||
|
Format.quote(info.description),
|
||||||
|
Format.quote(info.version),
|
||||||
|
Format.quote(info.attribution),
|
||||||
|
info.languages.stream().map(Format::quote).collect(joining(", ")),
|
||||||
|
layers.stream()
|
||||||
|
.map(
|
||||||
|
l -> "new com.onthegomap.planetiler.basemap.layers.%s(translations, config, stats)"
|
||||||
|
.formatted(lowerUnderscoreToUpperCamel(l.layer.id)))
|
||||||
|
.collect(joining("," + LINE_SEPARATOR))
|
||||||
|
.indent(6).trim()
|
||||||
|
));
|
||||||
for (var layer : layers) {
|
for (var layer : layers) {
|
||||||
String layerCode = generateCodeForLayer(tag, layer);
|
String layerCode = generateCodeForLayer(tag, layer);
|
||||||
schemaClass.append(layerCode);
|
schemaClass.append(layerCode);
|
||||||
|
@ -344,68 +344,70 @@ public class Generate {
|
||||||
String tag)
|
String tag)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
StringBuilder tablesClass = new StringBuilder();
|
StringBuilder tablesClass = new StringBuilder();
|
||||||
tablesClass.append("""
|
tablesClass.append(
|
||||||
%s
|
"""
|
||||||
package %s;
|
%s
|
||||||
|
package %s;
|
||||||
|
|
||||||
import static com.onthegomap.planetiler.expression.Expression.*;
|
import static com.onthegomap.planetiler.expression.Expression.*;
|
||||||
|
|
||||||
import com.onthegomap.planetiler.expression.Expression;
|
import com.onthegomap.planetiler.expression.Expression;
|
||||||
import com.onthegomap.planetiler.expression.MultiExpression;
|
import com.onthegomap.planetiler.expression.MultiExpression;
|
||||||
import com.onthegomap.planetiler.FeatureCollector;
|
import com.onthegomap.planetiler.FeatureCollector;
|
||||||
import com.onthegomap.planetiler.reader.SourceFeature;
|
import com.onthegomap.planetiler.reader.SourceFeature;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OSM element parsers generated from the <a href="https://github.com/omniscale/imposm3">imposm3</a> table definitions
|
* OSM element parsers generated from the <a href="https://github.com/omniscale/imposm3">imposm3</a> table definitions
|
||||||
* in the <a href="https://github.com/openmaptiles/openmaptiles/blob/%s/openmaptiles.yaml">OpenMapTiles vector tile schema</a>.
|
* in the <a href="https://github.com/openmaptiles/openmaptiles/blob/%s/openmaptiles.yaml">OpenMapTiles vector tile schema</a>.
|
||||||
*
|
*
|
||||||
* These filter and parse the raw OSM key/value attribute pairs on tags into records with fields that match the
|
* These filter and parse the raw OSM key/value attribute pairs on tags into records with fields that match the
|
||||||
* columns in the tables that imposm3 would generate. Layer implementations can "subscribe" to elements from each
|
* columns in the tables that imposm3 would generate. Layer implementations can "subscribe" to elements from each
|
||||||
* "table" but implementing the table's {@code Handler} interface and use the element's typed API to access
|
* "table" but implementing the table's {@code Handler} interface and use the element's typed API to access
|
||||||
* attributes.
|
* attributes.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class Tables {
|
public class Tables {
|
||||||
/** A parsed OSM element that would appear in a "row" of the imposm3 table. */
|
/** A parsed OSM element that would appear in a "row" of the imposm3 table. */
|
||||||
public interface Row {
|
public interface Row {
|
||||||
|
|
||||||
/** Returns the original OSM element. */
|
/** Returns the original OSM element. */
|
||||||
SourceFeature source();
|
SourceFeature source();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A functional interface that the constructor of a new table row can be coerced to. */
|
/** A functional interface that the constructor of a new table row can be coerced to. */
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface Constructor {
|
public interface Constructor {
|
||||||
|
|
||||||
Row create(SourceFeature source, String mappingKey);
|
Row create(SourceFeature source, String mappingKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The {@code rowClass} of an imposm3 table row and its constructor coerced to a {@link Constructor}. */
|
/** The {@code rowClass} of an imposm3 table row and its constructor coerced to a {@link Constructor}. */
|
||||||
public record RowClassAndConstructor(
|
public record RowClassAndConstructor(
|
||||||
Class<? extends Row> rowClass,
|
Class<? extends Row> rowClass,
|
||||||
Constructor create
|
Constructor create
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/** A functional interface that the typed handler method that a layer implementation can be coerced to. */
|
/** A functional interface that the typed handler method that a layer implementation can be coerced to. */
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface RowHandler<T extends Row> {
|
public interface RowHandler<T extends Row> {
|
||||||
|
|
||||||
/** Process a typed element according to the profile. */
|
/** Process a typed element according to the profile. */
|
||||||
void process(T element, FeatureCollector features);
|
void process(T element, FeatureCollector features);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The {@code handlerClass} of a layer handler and it's {@code process} method coerced to a {@link RowHandler}. */
|
/** The {@code handlerClass} of a layer handler and it's {@code process} method coerced to a {@link RowHandler}. */
|
||||||
public record RowHandlerAndClass<T extends Row>(
|
public record RowHandlerAndClass<T extends Row>(
|
||||||
Class<?> handlerClass,
|
Class<?> handlerClass,
|
||||||
RowHandler<T> handler
|
RowHandler<T> handler
|
||||||
) {}
|
) {}
|
||||||
""".formatted(GENERATED_FILE_HEADER, packageName, escapeJavadoc(tag)));
|
"""
|
||||||
|
.formatted(GENERATED_FILE_HEADER, packageName, escapeJavadoc(tag)));
|
||||||
|
|
||||||
List<String> classNames = new ArrayList<>();
|
List<String> classNames = new ArrayList<>();
|
||||||
Map<String, String> fieldNameToType = new TreeMap<>();
|
Map<String, String> fieldNameToType = new TreeMap<>();
|
||||||
|
@ -489,17 +491,19 @@ public class Generate {
|
||||||
));
|
));
|
||||||
""".formatted(
|
""".formatted(
|
||||||
classNames.stream().map(
|
classNames.stream().map(
|
||||||
className -> "MultiExpression.entry(new RowClassAndConstructor(%s.class, %s::new), %s.MAPPING)".formatted(
|
className -> "MultiExpression.entry(new RowClassAndConstructor(%s.class, %s::new), %s.MAPPING)".formatted(
|
||||||
className, className, className))
|
className, className, className))
|
||||||
.collect(joining("," + LINE_SEPARATOR)).indent(2).strip()
|
.collect(joining("," + LINE_SEPARATOR)).indent(2).strip()
|
||||||
).indent(2));
|
).indent(2));
|
||||||
|
|
||||||
String handlerCondition = classNames.stream().map(className ->
|
String handlerCondition = classNames.stream()
|
||||||
"""
|
.map(
|
||||||
if (handler instanceof %s.Handler typedHandler) {
|
className -> """
|
||||||
result.computeIfAbsent(%s.class, cls -> new ArrayList<>()).add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
|
if (handler instanceof %s.Handler typedHandler) {
|
||||||
}""".formatted(className, className)
|
result.computeIfAbsent(%s.class, cls -> new ArrayList<>()).add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
|
||||||
).collect(joining(LINE_SEPARATOR));
|
}"""
|
||||||
|
.formatted(className, className)
|
||||||
|
).collect(joining(LINE_SEPARATOR));
|
||||||
tablesClass.append("""
|
tablesClass.append("""
|
||||||
/**
|
/**
|
||||||
* Returns a map from imposm3 "table row" class to the layers that have a handler for it from a list of layer
|
* Returns a map from imposm3 "table row" class to the layers that have a handler for it from a list of layer
|
||||||
|
@ -518,15 +522,15 @@ public class Generate {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an {@link Expression} that implements the same logic as the <a href="https://imposm.org/docs/imposm3/latest/mapping.html">Imposm3
|
* Returns an {@link Expression} that implements the same logic as the
|
||||||
* Data Mapping</a> definition for a table.
|
* <a href="https://imposm.org/docs/imposm3/latest/mapping.html">Imposm3 Data Mapping</a> definition for a table.
|
||||||
*/
|
*/
|
||||||
static Expression parseImposm3MappingExpression(Imposm3Table table) {
|
static Expression parseImposm3MappingExpression(Imposm3Table table) {
|
||||||
if (table.type_mappings != null) {
|
if (table.type_mappings != null) {
|
||||||
return or(
|
return or(
|
||||||
table.type_mappings.entrySet().stream().map(entry ->
|
table.type_mappings.entrySet().stream()
|
||||||
parseImposm3MappingExpression(entry.getKey(), entry.getValue(), table.filters)
|
.map(entry -> parseImposm3MappingExpression(entry.getKey(), entry.getValue(), table.filters)
|
||||||
).toList()
|
).toList()
|
||||||
).simplify();
|
).simplify();
|
||||||
} else {
|
} else {
|
||||||
return parseImposm3MappingExpression(table.type, table.mapping, table.filters);
|
return parseImposm3MappingExpression(table.type, table.mapping, table.filters);
|
||||||
|
@ -534,8 +538,8 @@ public class Generate {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an {@link Expression} that implements the same logic as the <a href="https://imposm.org/docs/imposm3/latest/mapping.html#filters">Imposm3
|
* Returns an {@link Expression} that implements the same logic as the
|
||||||
* Data Mapping filters</a> for a table.
|
* <a href="https://imposm.org/docs/imposm3/latest/mapping.html#filters">Imposm3 Data Mapping filters</a> for a table.
|
||||||
*/
|
*/
|
||||||
static Expression parseImposm3MappingExpression(String type, JsonNode mapping, Imposm3Filters filters) {
|
static Expression parseImposm3MappingExpression(String type, JsonNode mapping, Imposm3Filters filters) {
|
||||||
return and(
|
return and(
|
||||||
|
|
Plik diff jest za duży
Load Diff
Plik diff jest za duży
Load Diff
|
@ -51,7 +51,8 @@ import com.onthegomap.planetiler.util.Translations;
|
||||||
/**
|
/**
|
||||||
* Defines the logic for generating map elements in the {@code aerodrome_label} layer from source features.
|
* Defines the logic for generating map elements in the {@code aerodrome_label} layer from source features.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is ported to Java from <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/aerodrome_label">OpenMapTiles
|
* This class is ported to Java from
|
||||||
|
* <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/aerodrome_label">OpenMapTiles
|
||||||
* aerodrome_layer sql files</a>.
|
* aerodrome_layer sql files</a>.
|
||||||
*/
|
*/
|
||||||
public class AerodromeLabel implements
|
public class AerodromeLabel implements
|
||||||
|
|
|
@ -45,8 +45,8 @@ import com.onthegomap.planetiler.util.Translations;
|
||||||
/**
|
/**
|
||||||
* Defines the logic for generating map elements in the {@code aeroway} layer from source features.
|
* Defines the logic for generating map elements in the {@code aeroway} layer from source features.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is ported to Java from <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/aeroway">OpenMapTiles
|
* This class is ported to Java from
|
||||||
* aeroway sql files</a>.
|
* <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/aeroway">OpenMapTiles aeroway sql files</a>.
|
||||||
*/
|
*/
|
||||||
public class Aeroway implements
|
public class Aeroway implements
|
||||||
OpenMapTilesSchema.Aeroway,
|
OpenMapTilesSchema.Aeroway,
|
||||||
|
@ -54,8 +54,7 @@ public class Aeroway implements
|
||||||
Tables.OsmAerowayPolygon.Handler,
|
Tables.OsmAerowayPolygon.Handler,
|
||||||
Tables.OsmAerowayPoint.Handler {
|
Tables.OsmAerowayPoint.Handler {
|
||||||
|
|
||||||
public Aeroway(Translations translations, PlanetilerConfig config, Stats stats) {
|
public Aeroway(Translations translations, PlanetilerConfig config, Stats stats) {}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void process(Tables.OsmAerowayPolygon element, FeatureCollector features) {
|
public void process(Tables.OsmAerowayPolygon element, FeatureCollector features) {
|
||||||
|
|
|
@ -86,8 +86,9 @@ import org.slf4j.LoggerFactory;
|
||||||
* Defines the logic for generating map elements for country, state, and town boundaries in the {@code boundary} layer
|
* Defines the logic for generating map elements for country, state, and town boundaries in the {@code boundary} layer
|
||||||
* from source features.
|
* from source features.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is ported to Java from <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/boundary">OpenMapTiles
|
* This class is ported to Java from
|
||||||
* boundary sql files</a>.
|
* <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/boundary">OpenMapTiles boundary sql
|
||||||
|
* files</a>.
|
||||||
*/
|
*/
|
||||||
public class Boundary implements
|
public class Boundary implements
|
||||||
OpenMapTilesSchema.Boundary,
|
OpenMapTilesSchema.Boundary,
|
||||||
|
@ -164,13 +165,13 @@ public class Boundary implements
|
||||||
BoundaryInfo info = switch (table) {
|
BoundaryInfo info = switch (table) {
|
||||||
case "ne_110m_admin_0_boundary_lines_land" -> new BoundaryInfo(2, 0, 0);
|
case "ne_110m_admin_0_boundary_lines_land" -> new BoundaryInfo(2, 0, 0);
|
||||||
case "ne_50m_admin_0_boundary_lines_land" -> new BoundaryInfo(2, 1, 3);
|
case "ne_50m_admin_0_boundary_lines_land" -> new BoundaryInfo(2, 1, 3);
|
||||||
case "ne_10m_admin_0_boundary_lines_land" -> feature.hasTag("featurecla", "Lease Limit") ? null
|
case "ne_10m_admin_0_boundary_lines_land" -> feature.hasTag("featurecla", "Lease Limit") ? null :
|
||||||
: new BoundaryInfo(2, 4, 4);
|
new BoundaryInfo(2, 4, 4);
|
||||||
case "ne_10m_admin_1_states_provinces_lines" -> {
|
case "ne_10m_admin_1_states_provinces_lines" -> {
|
||||||
Double minZoom = Parse.parseDoubleOrNull(feature.getTag("min_zoom"));
|
Double minZoom = Parse.parseDoubleOrNull(feature.getTag("min_zoom"));
|
||||||
yield minZoom != null && minZoom <= 7 ? new BoundaryInfo(4, 1, 4) :
|
yield minZoom != null && minZoom <= 7 ? new BoundaryInfo(4, 1, 4) :
|
||||||
minZoom != null && minZoom <= 7.7 ? new BoundaryInfo(4, 4, 4) :
|
minZoom != null && minZoom <= 7.7 ? new BoundaryInfo(4, 4, 4) :
|
||||||
null;
|
null;
|
||||||
}
|
}
|
||||||
default -> null;
|
default -> null;
|
||||||
};
|
};
|
||||||
|
@ -250,8 +251,8 @@ public class Boundary implements
|
||||||
int minzoom =
|
int minzoom =
|
||||||
(maritime && minAdminLevel == 2) ? 4 :
|
(maritime && minAdminLevel == 2) ? 4 :
|
||||||
minAdminLevel <= 4 ? 5 :
|
minAdminLevel <= 4 ? 5 :
|
||||||
minAdminLevel <= 6 ? 9 :
|
minAdminLevel <= 6 ? 9 :
|
||||||
minAdminLevel <= 8 ? 11 : 12;
|
minAdminLevel <= 8 ? 11 : 12;
|
||||||
if (addCountryNames && !regionIds.isEmpty()) {
|
if (addCountryNames && !regionIds.isEmpty()) {
|
||||||
// save for later
|
// save for later
|
||||||
try {
|
try {
|
||||||
|
@ -398,8 +399,7 @@ public class Boundary implements
|
||||||
try {
|
try {
|
||||||
Geometry combined = polygonizer.getGeometry().union();
|
Geometry combined = polygonizer.getGeometry().union();
|
||||||
if (combined.isEmpty()) {
|
if (combined.isEmpty()) {
|
||||||
LOGGER.warn("Unable to form closed polygon for OSM relation " + regionId
|
LOGGER.warn("Unable to form closed polygon for OSM relation " + regionId + " (likely missing edges)");
|
||||||
+ " (likely missing edges)");
|
|
||||||
} else {
|
} else {
|
||||||
countryBoundaries.put(regionId, PreparedGeometryFactory.prepare(combined));
|
countryBoundaries.put(regionId, PreparedGeometryFactory.prepare(combined));
|
||||||
}
|
}
|
||||||
|
@ -429,8 +429,7 @@ public class Boundary implements
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Minimal set of information extracted from a boundary relation to be used when processing each way in that
|
* Minimal set of information extracted from a boundary relation to be used when processing each way in that relation.
|
||||||
* relation.
|
|
||||||
*/
|
*/
|
||||||
private record BoundaryRelation(
|
private record BoundaryRelation(
|
||||||
long id,
|
long id,
|
||||||
|
@ -443,17 +442,15 @@ public class Boundary implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long estimateMemoryUsageBytes() {
|
public long estimateMemoryUsageBytes() {
|
||||||
return CLASS_HEADER_BYTES
|
return CLASS_HEADER_BYTES + MemoryEstimator.estimateSizeLong(id) + MemoryEstimator.estimateSizeInt(adminLevel) +
|
||||||
+ MemoryEstimator.estimateSizeLong(id)
|
estimateSize(disputed) + POINTER_BYTES + estimateSize(name) + POINTER_BYTES + estimateSize(claimedBy) +
|
||||||
+ MemoryEstimator.estimateSizeInt(adminLevel)
|
POINTER_BYTES + estimateSize(iso3166alpha3);
|
||||||
+ estimateSize(disputed)
|
|
||||||
+ POINTER_BYTES + estimateSize(name)
|
|
||||||
+ POINTER_BYTES + estimateSize(claimedBy)
|
|
||||||
+ POINTER_BYTES + estimateSize(iso3166alpha3);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Information to hold onto from processing a way in a boundary relation to determine the left/right region ID later. */
|
/**
|
||||||
|
* Information to hold onto from processing a way in a boundary relation to determine the left/right region ID later.
|
||||||
|
*/
|
||||||
private record CountryBoundaryComponent(
|
private record CountryBoundaryComponent(
|
||||||
int adminLevel,
|
int adminLevel,
|
||||||
boolean disputed,
|
boolean disputed,
|
||||||
|
|
|
@ -60,8 +60,9 @@ import java.util.Map;
|
||||||
/**
|
/**
|
||||||
* Defines the logic for generating map elements for buildings in the {@code building} layer from source features.
|
* Defines the logic for generating map elements for buildings in the {@code building} layer from source features.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is ported to Java from <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/building">OpenMapTiles
|
* This class is ported to Java from
|
||||||
* building sql files</a>.
|
* <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/building">OpenMapTiles building sql
|
||||||
|
* files</a>.
|
||||||
*/
|
*/
|
||||||
public class Building implements
|
public class Building implements
|
||||||
OpenMapTilesSchema.Building,
|
OpenMapTilesSchema.Building,
|
||||||
|
@ -154,10 +155,8 @@ public class Building implements
|
||||||
parseDoubleOrNull(element.buildingminLevel())
|
parseDoubleOrNull(element.buildingminLevel())
|
||||||
);
|
);
|
||||||
|
|
||||||
int renderHeight = (int) Math.ceil(height != null ? height
|
int renderHeight = (int) Math.ceil(height != null ? height : levels != null ? (levels * 3.66) : 5);
|
||||||
: levels != null ? (levels * 3.66) : 5);
|
int renderMinHeight = (int) Math.floor(minHeight != null ? minHeight : minLevels != null ? (minLevels * 3.66) : 0);
|
||||||
int renderMinHeight = (int) Math.floor(minHeight != null ? minHeight
|
|
||||||
: minLevels != null ? (minLevels * 3.66) : 0);
|
|
||||||
|
|
||||||
if (renderHeight < 3660 && renderMinHeight < 3660) {
|
if (renderHeight < 3660 && renderMinHeight < 3660) {
|
||||||
var feature = features.polygon(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
|
var feature = features.polygon(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
|
||||||
|
|
|
@ -45,15 +45,15 @@ import com.onthegomap.planetiler.util.Translations;
|
||||||
/**
|
/**
|
||||||
* Defines the logic for generating map elements in the {@code housenumber} layer from source features.
|
* Defines the logic for generating map elements in the {@code housenumber} layer from source features.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is ported to Java from <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/housenumber">OpenMapTiles
|
* This class is ported to Java from
|
||||||
* housenumber sql files</a>.
|
* <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/housenumber">OpenMapTiles housenumber sql
|
||||||
|
* files</a>.
|
||||||
*/
|
*/
|
||||||
public class Housenumber implements
|
public class Housenumber implements
|
||||||
OpenMapTilesSchema.Housenumber,
|
OpenMapTilesSchema.Housenumber,
|
||||||
Tables.OsmHousenumberPoint.Handler {
|
Tables.OsmHousenumberPoint.Handler {
|
||||||
|
|
||||||
public Housenumber(Translations translations, PlanetilerConfig config, Stats stats) {
|
public Housenumber(Translations translations, PlanetilerConfig config, Stats stats) {}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void process(Tables.OsmHousenumberPoint element, FeatureCollector features) {
|
public void process(Tables.OsmHousenumberPoint element, FeatureCollector features) {
|
||||||
|
|
|
@ -57,8 +57,9 @@ import java.util.Set;
|
||||||
* Defines the logic for generating map elements for natural land cover polygons like ice, sand, and forest in the
|
* Defines the logic for generating map elements for natural land cover polygons like ice, sand, and forest in the
|
||||||
* {@code landcover} layer from source features.
|
* {@code landcover} layer from source features.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is ported to Java from <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/landcover">OpenMapTiles
|
* This class is ported to Java from
|
||||||
* landcover sql files</a>.
|
* <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/landcover">OpenMapTiles landcover sql
|
||||||
|
* files</a>.
|
||||||
*/
|
*/
|
||||||
public class Landcover implements
|
public class Landcover implements
|
||||||
OpenMapTilesSchema.Landcover,
|
OpenMapTilesSchema.Landcover,
|
||||||
|
|
|
@ -55,8 +55,8 @@ import java.util.Set;
|
||||||
* Defines the logic for generating map elements for man-made land use polygons like cemeteries, zoos, and hospitals in
|
* Defines the logic for generating map elements for man-made land use polygons like cemeteries, zoos, and hospitals in
|
||||||
* the {@code landuse} layer from source features.
|
* the {@code landuse} layer from source features.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is ported to Java from <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/landuse">OpenMapTiles
|
* This class is ported to Java from
|
||||||
* landuse sql files</a>.
|
* <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/landuse">OpenMapTiles landuse sql files</a>.
|
||||||
*/
|
*/
|
||||||
public class Landuse implements
|
public class Landuse implements
|
||||||
OpenMapTilesSchema.Landuse,
|
OpenMapTilesSchema.Landuse,
|
||||||
|
@ -75,8 +75,7 @@ public class Landuse implements
|
||||||
FieldValues.CLASS_NEIGHBOURHOOD
|
FieldValues.CLASS_NEIGHBOURHOOD
|
||||||
);
|
);
|
||||||
|
|
||||||
public Landuse(Translations translations, PlanetilerConfig config, Stats stats) {
|
public Landuse(Translations translations, PlanetilerConfig config, Stats stats) {}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processNaturalEarth(String table, SourceFeature feature, FeatureCollector features) {
|
public void processNaturalEarth(String table, SourceFeature feature, FeatureCollector features) {
|
||||||
|
|
|
@ -65,8 +65,9 @@ import org.slf4j.LoggerFactory;
|
||||||
* Defines the logic for generating map elements for mountain peak label points in the {@code mountain_peak} layer from
|
* Defines the logic for generating map elements for mountain peak label points in the {@code mountain_peak} layer from
|
||||||
* source features.
|
* source features.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is ported to Java from <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/mountain_peak">OpenMapTiles
|
* This class is ported to Java from
|
||||||
* mountain_peak sql files</a>.
|
* <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/mountain_peak">OpenMapTiles mountain_peak
|
||||||
|
* sql files</a>.
|
||||||
*/
|
*/
|
||||||
public class MountainPeak implements
|
public class MountainPeak implements
|
||||||
BasemapProfile.NaturalEarthProcessor,
|
BasemapProfile.NaturalEarthProcessor,
|
||||||
|
|
|
@ -62,8 +62,8 @@ import java.util.Locale;
|
||||||
* Defines the logic for generating map elements for designated parks polygons and their label points in the {@code
|
* Defines the logic for generating map elements for designated parks polygons and their label points in the {@code
|
||||||
* park} layer from source features.
|
* park} layer from source features.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is ported to Java from <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/park">OpenMapTiles
|
* This class is ported to Java from
|
||||||
* park sql files</a>.
|
* <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/park">OpenMapTiles park sql files</a>.
|
||||||
*/
|
*/
|
||||||
public class Park implements
|
public class Park implements
|
||||||
OpenMapTilesSchema.Park,
|
OpenMapTilesSchema.Park,
|
||||||
|
|
|
@ -76,8 +76,8 @@ import org.locationtech.jts.geom.Point;
|
||||||
* Defines the logic for generating label points for populated places like continents, countries, cities, and towns in
|
* Defines the logic for generating label points for populated places like continents, countries, cities, and towns in
|
||||||
* the {@code place} layer from source features.
|
* the {@code place} layer from source features.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is ported to Java from <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/place">OpenMapTiles
|
* This class is ported to Java from
|
||||||
* place sql files</a>.
|
* <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/place">OpenMapTiles place sql files</a>.
|
||||||
*/
|
*/
|
||||||
public class Place implements
|
public class Place implements
|
||||||
OpenMapTilesSchema.Place,
|
OpenMapTilesSchema.Place,
|
||||||
|
@ -142,11 +142,11 @@ public class Place implements
|
||||||
// ORDER BY "rank" ASC NULLS LAST,
|
// ORDER BY "rank" ASC NULLS LAST,
|
||||||
.orderByInt(rank == null ? 15 : rank, 0, 15) // 4 bits
|
.orderByInt(rank == null ? 15 : rank, 0, 15) // 4 bits
|
||||||
// place ASC NULLS LAST,
|
// place ASC NULLS LAST,
|
||||||
.thenByInt(place == null ? 15 : place.ordinal(), 0, 15) // 4 bits
|
.thenByInt(place == null ? 15 : place.ordinal(), 0, 15) // 4 bits
|
||||||
// population DESC NULLS LAST,
|
// population DESC NULLS LAST,
|
||||||
.thenByLog(population, MAX_CITY_POPULATION, 1, 1 << (SORT_KEY_BITS - 13) - 1)
|
.thenByLog(population, MAX_CITY_POPULATION, 1, 1 << (SORT_KEY_BITS - 13) - 1)
|
||||||
// length(name) ASC
|
// length(name) ASC
|
||||||
.thenByInt(name == null ? 0 : name.length(), 0, 31) // 5 bits
|
.thenByInt(name == null ? 0 : name.length(), 0, 31) // 5 bits
|
||||||
.get();
|
.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,9 +340,9 @@ public class Place implements
|
||||||
|
|
||||||
int minzoom = rank != null && rank == 1 ? 2 :
|
int minzoom = rank != null && rank == 1 ? 2 :
|
||||||
rank != null && rank <= 8 ? Math.max(3, rank - 1) :
|
rank != null && rank <= 8 ? Math.max(3, rank - 1) :
|
||||||
placeType.ordinal() <= PlaceType.TOWN.ordinal() ? 7 :
|
placeType.ordinal() <= PlaceType.TOWN.ordinal() ? 7 :
|
||||||
placeType.ordinal() <= PlaceType.VILLAGE.ordinal() ? 8 :
|
placeType.ordinal() <= PlaceType.VILLAGE.ordinal() ? 8 :
|
||||||
placeType.ordinal() <= PlaceType.SUBURB.ordinal() ? 11 : 14;
|
placeType.ordinal() <= PlaceType.SUBURB.ordinal() ? 11 : 14;
|
||||||
|
|
||||||
var feature = features.point(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
|
var feature = features.point(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
|
||||||
.putAttrs(LanguageUtils.getNames(element.source().tags(), translations))
|
.putAttrs(LanguageUtils.getNames(element.source().tags(), translations))
|
||||||
|
@ -420,9 +420,7 @@ public class Place implements
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information extracted from a natural earth place label that will be inspected when joining with OpenStreetMap
|
* Information extracted from a natural earth place label that will be inspected when joining with OpenStreetMap data.
|
||||||
* data.
|
|
||||||
*/
|
*/
|
||||||
private record NaturalEarthPoint(String name, String wikidata, int scaleRank, Set<String> names) {}
|
private record NaturalEarthPoint(String name, String wikidata, int scaleRank, Set<String> names) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,8 +61,8 @@ import java.util.Map;
|
||||||
* Defines the logic for generating map elements for things like shops, parks, and schools in the {@code poi} layer from
|
* Defines the logic for generating map elements for things like shops, parks, and schools in the {@code poi} layer from
|
||||||
* source features.
|
* source features.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is ported to Java from <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/poi">OpenMapTiles
|
* This class is ported to Java from
|
||||||
* poi sql files</a>.
|
* <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/poi">OpenMapTiles poi sql files</a>.
|
||||||
*/
|
*/
|
||||||
public class Poi implements
|
public class Poi implements
|
||||||
OpenMapTilesSchema.Poi,
|
OpenMapTilesSchema.Poi,
|
||||||
|
@ -136,19 +136,8 @@ public class Poi implements
|
||||||
setupPoiFeature(element, features.centroidIfConvex(LAYER_NAME));
|
setupPoiFeature(element, features.centroidIfConvex(LAYER_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T extends
|
private <T extends Tables.WithSubclass & Tables.WithStation & Tables.WithFunicular & Tables.WithSport & Tables.WithInformation & Tables.WithReligion & Tables.WithMappingKey & Tables.WithName & Tables.WithIndoor & Tables.WithLayer & Tables.WithSource> void setupPoiFeature(
|
||||||
Tables.WithSubclass &
|
T element, FeatureCollector.Feature output) {
|
||||||
Tables.WithStation &
|
|
||||||
Tables.WithFunicular &
|
|
||||||
Tables.WithSport &
|
|
||||||
Tables.WithInformation &
|
|
||||||
Tables.WithReligion &
|
|
||||||
Tables.WithMappingKey &
|
|
||||||
Tables.WithName &
|
|
||||||
Tables.WithIndoor &
|
|
||||||
Tables.WithLayer &
|
|
||||||
Tables.WithSource>
|
|
||||||
void setupPoiFeature(T element, FeatureCollector.Feature output) {
|
|
||||||
String rawSubclass = element.subclass();
|
String rawSubclass = element.subclass();
|
||||||
if ("station".equals(rawSubclass) && "subway".equals(element.station())) {
|
if ("station".equals(rawSubclass) && "subway".equals(element.station())) {
|
||||||
rawSubclass = "subway";
|
rawSubclass = "subway";
|
||||||
|
|
|
@ -80,8 +80,9 @@ import org.slf4j.LoggerFactory;
|
||||||
* Defines the logic for generating map elements for roads, shipways, railroads, and paths in the {@code transportation}
|
* Defines the logic for generating map elements for roads, shipways, railroads, and paths in the {@code transportation}
|
||||||
* layer from source features.
|
* layer from source features.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is ported to Java from <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/transportation">OpenMapTiles
|
* This class is ported to Java from
|
||||||
* transportation sql files</a>.
|
* <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/transportation">OpenMapTiles transportation
|
||||||
|
* sql files</a>.
|
||||||
*/
|
*/
|
||||||
public class Transportation implements
|
public class Transportation implements
|
||||||
OpenMapTilesSchema.Transportation,
|
OpenMapTilesSchema.Transportation,
|
||||||
|
@ -214,7 +215,7 @@ public class Transportation implements
|
||||||
private static String railwayClass(String value) {
|
private static String railwayClass(String value) {
|
||||||
return value == null ? null :
|
return value == null ? null :
|
||||||
RAILWAY_RAIL_VALUES.contains(value) ? "rail" :
|
RAILWAY_RAIL_VALUES.contains(value) ? "rail" :
|
||||||
RAILWAY_TRANSIT_VALUES.contains(value) ? "transit" : null;
|
RAILWAY_TRANSIT_VALUES.contains(value) ? "transit" : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static String highwayClass(String highway, String publicTransport, String construction, String manMade) {
|
static String highwayClass(String highway, String publicTransport, String construction, String manMade) {
|
||||||
|
@ -320,8 +321,8 @@ public class Transportation implements
|
||||||
Geometry wayGeometry = element.source().worldGeometry();
|
Geometry wayGeometry = element.source().worldGeometry();
|
||||||
if (greatBritain.intersects(wayGeometry)) {
|
if (greatBritain.intersects(wayGeometry)) {
|
||||||
Transportation.RouteNetwork networkType =
|
Transportation.RouteNetwork networkType =
|
||||||
"motorway".equals(element.highway()) ? Transportation.RouteNetwork.GB_MOTORWAY
|
"motorway".equals(element.highway()) ? Transportation.RouteNetwork.GB_MOTORWAY :
|
||||||
: Transportation.RouteNetwork.GB_TRUNK;
|
Transportation.RouteNetwork.GB_TRUNK;
|
||||||
String network = "motorway".equals(element.highway()) ? "omt-gb-motorway" : "omt-gb-trunk";
|
String network = "motorway".equals(element.highway()) ? "omt-gb-motorway" : "omt-gb-trunk";
|
||||||
result.add(new RouteRelation(refMatcher.group(), network, networkType, (byte) -1,
|
result.add(new RouteRelation(refMatcher.group(), network, networkType, (byte) -1,
|
||||||
0));
|
0));
|
||||||
|
@ -434,7 +435,7 @@ public class Transportation implements
|
||||||
private boolean isPierPolygon(Tables.OsmHighwayLinestring element) {
|
private boolean isPierPolygon(Tables.OsmHighwayLinestring element) {
|
||||||
if ("pier".equals(element.manMade())) {
|
if ("pier".equals(element.manMade())) {
|
||||||
try {
|
try {
|
||||||
if (element.source().worldGeometry() instanceof LineString lineString && lineString.isClosed()) {
|
if (element.source().worldGeometry()instanceof LineString lineString && lineString.isClosed()) {
|
||||||
// ignore this because it's a polygon
|
// ignore this because it's a polygon
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,8 @@ import java.util.function.Function;
|
||||||
* Defines the logic for generating map elements for road, shipway, rail, and path names in the {@code
|
* Defines the logic for generating map elements for road, shipway, rail, and path names in the {@code
|
||||||
* transportation_name} layer from source features.
|
* transportation_name} layer from source features.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is ported to Java from <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/transportation_name">OpenMapTiles
|
* This class is ported to Java from
|
||||||
|
* <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/transportation_name">OpenMapTiles
|
||||||
* transportation_name sql files</a>.
|
* transportation_name sql files</a>.
|
||||||
*/
|
*/
|
||||||
public class TransportationName implements
|
public class TransportationName implements
|
||||||
|
@ -222,7 +223,7 @@ public class TransportationName implements
|
||||||
|
|
||||||
int minzoom = FieldValues.CLASS_TRUNK.equals(baseClass) ? 8 :
|
int minzoom = FieldValues.CLASS_TRUNK.equals(baseClass) ? 8 :
|
||||||
FieldValues.CLASS_MOTORWAY.equals(baseClass) ? 6 :
|
FieldValues.CLASS_MOTORWAY.equals(baseClass) ? 6 :
|
||||||
isLink ? 13 : 12; // fallback - get from line minzoom, but floor at 12
|
isLink ? 13 : 12; // fallback - get from line minzoom, but floor at 12
|
||||||
|
|
||||||
// inherit min zoom threshold from visible road, and ensure we never show a label on a road that's not visible yet.
|
// inherit min zoom threshold from visible road, and ensure we never show a label on a road that's not visible yet.
|
||||||
minzoom = Math.max(minzoom, transportation.getMinzoom(element, highwayClass));
|
minzoom = Math.max(minzoom, transportation.getMinzoom(element, highwayClass));
|
||||||
|
@ -235,8 +236,8 @@ public class TransportationName implements
|
||||||
.setAttr(Fields.REF, ref)
|
.setAttr(Fields.REF, ref)
|
||||||
.setAttr(Fields.REF_LENGTH, ref != null ? ref.length() : null)
|
.setAttr(Fields.REF_LENGTH, ref != null ? ref.length() : null)
|
||||||
.setAttr(Fields.NETWORK,
|
.setAttr(Fields.NETWORK,
|
||||||
(relation != null && relation.networkType() != null) ? relation.networkType().name
|
(relation != null && relation.networkType() != null) ? relation.networkType().name :
|
||||||
: !nullOrEmpty(ref) ? "road" : null)
|
!nullOrEmpty(ref) ? "road" : null)
|
||||||
.setAttr(Fields.CLASS, highwayClass)
|
.setAttr(Fields.CLASS, highwayClass)
|
||||||
.setAttr(Fields.SUBCLASS, highwaySubclass(highwayClass, null, highway))
|
.setAttr(Fields.SUBCLASS, highwaySubclass(highwayClass, null, highway))
|
||||||
.setMinPixelSize(0)
|
.setMinPixelSize(0)
|
||||||
|
@ -314,7 +315,7 @@ public class TransportationName implements
|
||||||
Function<Map<String, Object>, Double> lengthLimitCalculator =
|
Function<Map<String, Object>, Double> lengthLimitCalculator =
|
||||||
zoom >= 14 ? (p -> 0d) :
|
zoom >= 14 ? (p -> 0d) :
|
||||||
minLength > 0 ? (p -> minLength) :
|
minLength > 0 ? (p -> minLength) :
|
||||||
this::getMinLengthForName;
|
this::getMinLengthForName;
|
||||||
var result = FeatureMerge.mergeLineStrings(items, lengthLimitCalculator, tolerance, BUFFER_SIZE);
|
var result = FeatureMerge.mergeLineStrings(items, lengthLimitCalculator, tolerance, BUFFER_SIZE);
|
||||||
if (limitMerge) {
|
if (limitMerge) {
|
||||||
// remove temp keys that were just used to improve line merging
|
// remove temp keys that were just used to improve line merging
|
||||||
|
|
|
@ -49,8 +49,8 @@ import com.onthegomap.planetiler.util.Translations;
|
||||||
/**
|
/**
|
||||||
* Defines the logic for generating map elements for oceans and lakes in the {@code water} layer from source features.
|
* Defines the logic for generating map elements for oceans and lakes in the {@code water} layer from source features.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is ported to Java from <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/water">OpenMapTiles
|
* This class is ported to Java from
|
||||||
* water sql files</a>.
|
* <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/water">OpenMapTiles water sql files</a>.
|
||||||
*/
|
*/
|
||||||
public class Water implements
|
public class Water implements
|
||||||
OpenMapTilesSchema.Water,
|
OpenMapTilesSchema.Water,
|
||||||
|
|
|
@ -61,8 +61,9 @@ import org.slf4j.LoggerFactory;
|
||||||
* Defines the logic for generating map elements for ocean and lake names in the {@code water_name} layer from source
|
* Defines the logic for generating map elements for ocean and lake names in the {@code water_name} layer from source
|
||||||
* features.
|
* features.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is ported to Java from <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/water_name">OpenMapTiles
|
* This class is ported to Java from
|
||||||
* water_name sql files</a>.
|
* <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/water_name">OpenMapTiles water_name sql
|
||||||
|
* files</a>.
|
||||||
*/
|
*/
|
||||||
public class WaterName implements
|
public class WaterName implements
|
||||||
OpenMapTilesSchema.WaterName,
|
OpenMapTilesSchema.WaterName,
|
||||||
|
|
|
@ -63,8 +63,9 @@ import java.util.Map;
|
||||||
/**
|
/**
|
||||||
* Defines the logic for generating river map elements in the {@code waterway} layer from source features.
|
* Defines the logic for generating river map elements in the {@code waterway} layer from source features.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is ported to Java from <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/waterway">OpenMapTiles
|
* This class is ported to Java from
|
||||||
* waterway sql files</a>.
|
* <a href="https://github.com/openmaptiles/openmaptiles/tree/master/layers/waterway">OpenMapTiles waterway sql
|
||||||
|
* files</a>.
|
||||||
*/
|
*/
|
||||||
public class Waterway implements
|
public class Waterway implements
|
||||||
OpenMapTilesSchema.Waterway,
|
OpenMapTilesSchema.Waterway,
|
||||||
|
|
|
@ -49,7 +49,8 @@ import java.util.stream.Stream;
|
||||||
* Utilities to extract common name fields (name, name_en, name_de, name:latin, name:nonlatin, name_int) that the
|
* Utilities to extract common name fields (name, name_en, name_de, name:latin, name:nonlatin, name_int) that the
|
||||||
* OpenMapTiles schema uses across any map element with a name.
|
* OpenMapTiles schema uses across any map element with a name.
|
||||||
* <p>
|
* <p>
|
||||||
* Ported from <a href="https://github.com/openmaptiles/openmaptiles-tools/blob/master/sql/zzz_language.sql">openmaptiles-tools</a>.
|
* Ported from
|
||||||
|
* <a href="https://github.com/openmaptiles/openmaptiles-tools/blob/master/sql/zzz_language.sql">openmaptiles-tools</a>.
|
||||||
*/
|
*/
|
||||||
public class LanguageUtils {
|
public class LanguageUtils {
|
||||||
|
|
||||||
|
@ -101,12 +102,12 @@ public class LanguageUtils {
|
||||||
* element should have, derived from name, int_name, name:en, and name:de tags on the input element.
|
* element should have, derived from name, int_name, name:en, and name:de tags on the input element.
|
||||||
*
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>name is the original name value from the element</li>
|
* <li>name is the original name value from the element</li>
|
||||||
* <li>name_en is the original name:en value from the element, or name if missing</li>
|
* <li>name_en is the original name:en value from the element, or name if missing</li>
|
||||||
* <li>name_de is the original name:de value from the element, or name/ name_en if missing</li>
|
* <li>name_de is the original name:de value from the element, or name/ name_en if missing</li>
|
||||||
* <li>name:latin is the first of name, int_name, or any name: attribute that contains only latin characters</li>
|
* <li>name:latin is the first of name, int_name, or any name: attribute that contains only latin characters</li>
|
||||||
* <li>name:nonlatin is any nonlatin part of name if present</li>
|
* <li>name:nonlatin is any nonlatin part of name if present</li>
|
||||||
* <li>name_int is the first of int_name name:en name:latin name</li>
|
* <li>name_int is the first of int_name name:en name:latin name</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public static Map<String, Object> getNamesWithoutTranslations(Map<String, Object> tags) {
|
public static Map<String, Object> getNamesWithoutTranslations(Map<String, Object> tags) {
|
||||||
|
@ -126,8 +127,8 @@ public class LanguageUtils {
|
||||||
String nameDe = string(tags.get("name:de"));
|
String nameDe = string(tags.get("name:de"));
|
||||||
|
|
||||||
boolean isLatin = containsOnlyLatinCharacters(name);
|
boolean isLatin = containsOnlyLatinCharacters(name);
|
||||||
String latin = isLatin ? name
|
String latin = isLatin ? name :
|
||||||
: Stream.concat(Stream.of(nameEn, intName, nameDe), getAllNameTranslationsBesidesEnglishAndGerman(tags))
|
Stream.concat(Stream.of(nameEn, intName, nameDe), getAllNameTranslationsBesidesEnglishAndGerman(tags))
|
||||||
.filter(LanguageUtils::containsOnlyLatinCharacters)
|
.filter(LanguageUtils::containsOnlyLatinCharacters)
|
||||||
.findFirst().orElse(null);
|
.findFirst().orElse(null);
|
||||||
if (latin == null && translations != null && translations.getShouldTransliterate()) {
|
if (latin == null && translations != null && translations.getShouldTransliterate()) {
|
||||||
|
|
|
@ -61,8 +61,8 @@ public abstract class AbstractLayerTest {
|
||||||
if (vals[i - 1] > vals[i]) {
|
if (vals[i - 1] > vals[i]) {
|
||||||
fail(
|
fail(
|
||||||
Arrays.toString(vals) +
|
Arrays.toString(vals) +
|
||||||
System.lineSeparator() + "element at " + (i - 1) + " (" + vals[i - 1] + ") is greater than element at " + i
|
System.lineSeparator() + "element at " + (i - 1) + " (" + vals[i - 1] + ") is greater than element at " +
|
||||||
+ " (" + vals[i] + ")");
|
i + " (" + vals[i] + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -414,60 +414,60 @@ public class BoundaryTest extends AbstractLayerTest {
|
||||||
|
|
||||||
// shared edge
|
// shared edge
|
||||||
assertFeatures(14, List.of(), process(SimpleFeature.createFakeOsmFeature(
|
assertFeatures(14, List.of(), process(SimpleFeature.createFakeOsmFeature(
|
||||||
newLineString(0, 0, 0, 10),
|
newLineString(0, 0, 0, 10),
|
||||||
Map.of(),
|
Map.of(),
|
||||||
OSM_SOURCE,
|
OSM_SOURCE,
|
||||||
null,
|
null,
|
||||||
3,
|
3,
|
||||||
Stream.concat(
|
Stream.concat(
|
||||||
profile.preprocessOsmRelation(country1).stream(),
|
profile.preprocessOsmRelation(country1).stream(),
|
||||||
profile.preprocessOsmRelation(country2).stream()
|
profile.preprocessOsmRelation(country2).stream()
|
||||||
).map(r -> new OsmReader.RelationMember<>("", r)).toList()
|
).map(r -> new OsmReader.RelationMember<>("", r)).toList()
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
|
|
||||||
// other 2 edges of country 1
|
// other 2 edges of country 1
|
||||||
assertFeatures(14, List.of(), process(SimpleFeature.createFakeOsmFeature(
|
assertFeatures(14, List.of(), process(SimpleFeature.createFakeOsmFeature(
|
||||||
newLineString(0, 0, 5, 10),
|
newLineString(0, 0, 5, 10),
|
||||||
Map.of(),
|
Map.of(),
|
||||||
OSM_SOURCE,
|
OSM_SOURCE,
|
||||||
null,
|
null,
|
||||||
4,
|
4,
|
||||||
profile.preprocessOsmRelation(country1).stream().map(r -> new OsmReader.RelationMember<>("", r))
|
profile.preprocessOsmRelation(country1).stream().map(r -> new OsmReader.RelationMember<>("", r))
|
||||||
.toList()
|
.toList()
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
assertFeatures(14, List.of(), process(SimpleFeature.createFakeOsmFeature(
|
assertFeatures(14, List.of(), process(SimpleFeature.createFakeOsmFeature(
|
||||||
newLineString(0, 10, 5, 10),
|
newLineString(0, 10, 5, 10),
|
||||||
Map.of(),
|
Map.of(),
|
||||||
OSM_SOURCE,
|
OSM_SOURCE,
|
||||||
null,
|
null,
|
||||||
4,
|
4,
|
||||||
profile.preprocessOsmRelation(country1).stream().map(r -> new OsmReader.RelationMember<>("", r))
|
profile.preprocessOsmRelation(country1).stream().map(r -> new OsmReader.RelationMember<>("", r))
|
||||||
.toList()
|
.toList()
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
|
|
||||||
// other 2 edges of country 2
|
// other 2 edges of country 2
|
||||||
assertFeatures(14, List.of(), process(SimpleFeature.createFakeOsmFeature(
|
assertFeatures(14, List.of(), process(SimpleFeature.createFakeOsmFeature(
|
||||||
newLineString(0, 0, -5, 10),
|
newLineString(0, 0, -5, 10),
|
||||||
Map.of(),
|
Map.of(),
|
||||||
OSM_SOURCE,
|
OSM_SOURCE,
|
||||||
null,
|
null,
|
||||||
4,
|
4,
|
||||||
profile.preprocessOsmRelation(country2).stream().map(r -> new OsmReader.RelationMember<>("", r))
|
profile.preprocessOsmRelation(country2).stream().map(r -> new OsmReader.RelationMember<>("", r))
|
||||||
.toList()
|
.toList()
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
assertFeatures(14, List.of(), process(SimpleFeature.createFakeOsmFeature(
|
assertFeatures(14, List.of(), process(SimpleFeature.createFakeOsmFeature(
|
||||||
newLineString(0, 10, -5, 10),
|
newLineString(0, 10, -5, 10),
|
||||||
Map.of(),
|
Map.of(),
|
||||||
OSM_SOURCE,
|
OSM_SOURCE,
|
||||||
null,
|
null,
|
||||||
4,
|
4,
|
||||||
profile.preprocessOsmRelation(country2).stream().map(r -> new OsmReader.RelationMember<>("", r))
|
profile.preprocessOsmRelation(country2).stream().map(r -> new OsmReader.RelationMember<>("", r))
|
||||||
.toList()
|
.toList()
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
|
|
||||||
List<FeatureCollector.Feature> features = new ArrayList<>();
|
List<FeatureCollector.Feature> features = new ArrayList<>();
|
||||||
|
|
|
@ -203,7 +203,7 @@ public class LandcoverTest extends AbstractLayerTest {
|
||||||
throws GeometryException {
|
throws GeometryException {
|
||||||
assertEquals(expected,
|
assertEquals(expected,
|
||||||
profile.postProcessLayerFeatures("landcover", zoom, in).stream().map(
|
profile.postProcessLayerFeatures("landcover", zoom, in).stream().map(
|
||||||
VectorTile.Feature::attrs)
|
VectorTile.Feature::attrs)
|
||||||
.toList());
|
.toList());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,9 +44,9 @@ public class LanduseTest extends AbstractLayerTest {
|
||||||
"_minzoom", 9,
|
"_minzoom", 9,
|
||||||
"_maxzoom", 14
|
"_maxzoom", 14
|
||||||
)), process(polygonFeature(Map.of(
|
)), process(polygonFeature(Map.of(
|
||||||
"landuse", "railway",
|
"landuse", "railway",
|
||||||
"amenity", "school"
|
"amenity", "school"
|
||||||
))));
|
))));
|
||||||
assertFeatures(13, List.of(Map.of("_layer", "poi"), Map.of(
|
assertFeatures(13, List.of(Map.of("_layer", "poi"), Map.of(
|
||||||
"_layer", "landuse",
|
"_layer", "landuse",
|
||||||
"class", "school",
|
"class", "school",
|
||||||
|
@ -66,8 +66,8 @@ public class LanduseTest extends AbstractLayerTest {
|
||||||
"_layer", "landuse",
|
"_layer", "landuse",
|
||||||
"class", "cemetery"
|
"class", "cemetery"
|
||||||
)), process(polygonFeature(Map.of(
|
)), process(polygonFeature(Map.of(
|
||||||
"amenity", "grave_yard"
|
"amenity", "grave_yard"
|
||||||
))));
|
))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -24,7 +24,7 @@ public class ParkTest extends AbstractLayerTest {
|
||||||
"name", "Grand Canyon National Park",
|
"name", "Grand Canyon National Park",
|
||||||
"name_int", "Grand Canyon National Park",
|
"name_int", "Grand Canyon National Park",
|
||||||
"name:latin", "Grand Canyon National Park",
|
"name:latin", "Grand Canyon National Park",
|
||||||
// "name:es", "es name", // don't include all translations
|
// "name:es", "es name", // don't include all translations
|
||||||
"_minzoom", 5,
|
"_minzoom", 5,
|
||||||
"_maxzoom", 14
|
"_maxzoom", 14
|
||||||
)), process(polygonFeature(Map.of(
|
)), process(polygonFeature(Map.of(
|
||||||
|
|
|
@ -110,8 +110,8 @@ public class WaterTest extends AbstractLayerTest {
|
||||||
"_minzoom", 6,
|
"_minzoom", 6,
|
||||||
"_maxzoom", 14
|
"_maxzoom", 14
|
||||||
)), process(polygonFeature(Map.of(
|
)), process(polygonFeature(Map.of(
|
||||||
"leisure", "swimming_pool"
|
"leisure", "swimming_pool"
|
||||||
))));
|
))));
|
||||||
assertFeatures(14, List.of(), process(polygonFeature(Map.of(
|
assertFeatures(14, List.of(), process(polygonFeature(Map.of(
|
||||||
"natural", "bay"
|
"natural", "bay"
|
||||||
))));
|
))));
|
||||||
|
|
|
@ -17,7 +17,7 @@ import java.util.Random;
|
||||||
import org.locationtech.jts.geom.Geometry;
|
import org.locationtech.jts.geom.Geometry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performance tests for {@link MultiExpression}. Times how long a sample of elements from an OSM input file take to
|
* Performance tests for {@link MultiExpression}. Times how long a sample of elements from an OSM input file take to
|
||||||
* match.
|
* match.
|
||||||
*/
|
*/
|
||||||
public class BasemapMapping {
|
public class BasemapMapping {
|
||||||
|
|
|
@ -22,13 +22,16 @@ import org.locationtech.jts.geom.Geometry;
|
||||||
* feature.
|
* feature.
|
||||||
* <p>
|
* <p>
|
||||||
* For example to add a polygon feature for a lake and a center label point with its name:
|
* For example to add a polygon feature for a lake and a center label point with its name:
|
||||||
* <pre>{@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {@code
|
||||||
* featureCollector.polygon("water")
|
* featureCollector.polygon("water")
|
||||||
* .setAttr("class", "lake");
|
* .setAttr("class", "lake");
|
||||||
* featureCollector.centroid("water_name")
|
* featureCollector.centroid("water_name")
|
||||||
* .setAttr("class", "lake")
|
* .setAttr("class", "lake")
|
||||||
* .setAttr("name", element.getString("name"));
|
* .setAttr("name", element.getString("name"));
|
||||||
* }</pre>
|
* }
|
||||||
|
* </pre>
|
||||||
*/
|
*/
|
||||||
public class FeatureCollector implements Iterable<FeatureCollector.Feature> {
|
public class FeatureCollector implements Iterable<FeatureCollector.Feature> {
|
||||||
|
|
||||||
|
@ -265,9 +268,8 @@ public class FeatureCollector implements Iterable<FeatureCollector.Feature> {
|
||||||
* feature that appear later (higher sort key) in a layer.
|
* feature that appear later (higher sort key) in a layer.
|
||||||
*/
|
*/
|
||||||
public Feature setSortKey(int sortKey) {
|
public Feature setSortKey(int sortKey) {
|
||||||
assert sortKey >= FeatureGroup.SORT_KEY_MIN && sortKey <= FeatureGroup.SORT_KEY_MAX :
|
assert sortKey >= FeatureGroup.SORT_KEY_MIN && sortKey <= FeatureGroup.SORT_KEY_MAX : "Sort key " + sortKey +
|
||||||
"Sort key " + sortKey + " outside of allowed range [" + FeatureGroup.SORT_KEY_MIN + ", "
|
" outside of allowed range [" + FeatureGroup.SORT_KEY_MIN + ", " + FeatureGroup.SORT_KEY_MAX + "]";
|
||||||
+ FeatureGroup.SORT_KEY_MAX + "]";
|
|
||||||
this.sortKey = sortKey;
|
this.sortKey = sortKey;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -349,8 +351,8 @@ public class FeatureCollector implements Iterable<FeatureCollector.Feature> {
|
||||||
/**
|
/**
|
||||||
* Sets zoom-specific overrides to the number of pixels of detail to render outside the visible tile boundary.
|
* Sets zoom-specific overrides to the number of pixels of detail to render outside the visible tile boundary.
|
||||||
* <p>
|
* <p>
|
||||||
* If {@code buffer} is {@code null} or returns {@code null}, the buffer pixels will default to {@link
|
* If {@code buffer} is {@code null} or returns {@code null}, the buffer pixels will default to
|
||||||
* #setBufferPixels(double)}.
|
* {@link #setBufferPixels(double)}.
|
||||||
*/
|
*/
|
||||||
public Feature setBufferPixelOverrides(ZoomFunction<Number> buffer) {
|
public Feature setBufferPixelOverrides(ZoomFunction<Number> buffer) {
|
||||||
bufferPixelOverrides = buffer;
|
bufferPixelOverrides = buffer;
|
||||||
|
@ -365,8 +367,8 @@ public class FeatureCollector implements Iterable<FeatureCollector.Feature> {
|
||||||
* features to emit.
|
* features to emit.
|
||||||
*/
|
*/
|
||||||
public double getMinPixelSizeAtZoom(int zoom) {
|
public double getMinPixelSizeAtZoom(int zoom) {
|
||||||
return zoom == config.maxzoom() ? minPixelSizeAtMaxZoom
|
return zoom == config.maxzoom() ? minPixelSizeAtMaxZoom :
|
||||||
: ZoomFunction.applyAsDoubleOrElse(minPixelSize, zoom, defaultMinPixelSize);
|
ZoomFunction.applyAsDoubleOrElse(minPixelSize, zoom, defaultMinPixelSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -400,8 +402,8 @@ public class FeatureCollector implements Iterable<FeatureCollector.Feature> {
|
||||||
/**
|
/**
|
||||||
* Overrides the default minimum pixel size at and below {@code zoom} with {@code minPixelSize}.
|
* Overrides the default minimum pixel size at and below {@code zoom} with {@code minPixelSize}.
|
||||||
* <p>
|
* <p>
|
||||||
* This replaces all previous zoom overrides that were set. To use multiple zoom-level thresholds, create a {@link
|
* This replaces all previous zoom overrides that were set. To use multiple zoom-level thresholds, create a
|
||||||
* ZoomFunction} explicitly and pass it to {@link #setMinPixelSizeOverrides(ZoomFunction)}.
|
* {@link ZoomFunction} explicitly and pass it to {@link #setMinPixelSizeOverrides(ZoomFunction)}.
|
||||||
*/
|
*/
|
||||||
public Feature setMinPixelSizeBelowZoom(int zoom, double minPixelSize) {
|
public Feature setMinPixelSizeBelowZoom(int zoom, double minPixelSize) {
|
||||||
if (zoom >= config.maxzoom()) {
|
if (zoom >= config.maxzoom()) {
|
||||||
|
@ -429,7 +431,8 @@ public class FeatureCollector implements Iterable<FeatureCollector.Feature> {
|
||||||
* Sets the minimum length of line features or square root of the minimum area of polygon features to emit at all
|
* Sets the minimum length of line features or square root of the minimum area of polygon features to emit at all
|
||||||
* zoom levels, including the maximum zoom-level of the map.
|
* zoom levels, including the maximum zoom-level of the map.
|
||||||
* <p>
|
* <p>
|
||||||
* This replaces previous default values, but not overrides set with {@link #setMinPixelSizeOverrides(ZoomFunction)}.
|
* This replaces previous default values, but not overrides set with
|
||||||
|
* {@link #setMinPixelSizeOverrides(ZoomFunction)}.
|
||||||
*/
|
*/
|
||||||
public Feature setMinPixelSizeAtAllZooms(int minPixelSize) {
|
public Feature setMinPixelSizeAtAllZooms(int minPixelSize) {
|
||||||
this.minPixelSizeAtMaxZoom = minPixelSize;
|
this.minPixelSizeAtMaxZoom = minPixelSize;
|
||||||
|
@ -440,8 +443,8 @@ public class FeatureCollector implements Iterable<FeatureCollector.Feature> {
|
||||||
* Returns the simplification tolerance for lines and polygons in tile pixels at {@code zoom}.
|
* Returns the simplification tolerance for lines and polygons in tile pixels at {@code zoom}.
|
||||||
*/
|
*/
|
||||||
public double getPixelToleranceAtZoom(int zoom) {
|
public double getPixelToleranceAtZoom(int zoom) {
|
||||||
return zoom == config.maxzoom() ? pixelToleranceAtMaxZoom
|
return zoom == config.maxzoom() ? pixelToleranceAtMaxZoom :
|
||||||
: ZoomFunction.applyAsDoubleOrElse(pixelTolerance, zoom, defaultPixelTolerance);
|
ZoomFunction.applyAsDoubleOrElse(pixelTolerance, zoom, defaultPixelTolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -497,8 +500,8 @@ public class FeatureCollector implements Iterable<FeatureCollector.Feature> {
|
||||||
* Overrides the default simplification tolerance for lines and polygons in tile pixels at and below {@code zoom}
|
* Overrides the default simplification tolerance for lines and polygons in tile pixels at and below {@code zoom}
|
||||||
* with {@code minPixelSize}.
|
* with {@code minPixelSize}.
|
||||||
* <p>
|
* <p>
|
||||||
* This replaces all previous zoom overrides that were set. To use multiple zoom-level thresholds, create a {@link
|
* This replaces all previous zoom overrides that were set. To use multiple zoom-level thresholds, create a
|
||||||
* ZoomFunction} explicitly and pass it to {@link #setPixelToleranceOverrides(ZoomFunction)}
|
* {@link ZoomFunction} explicitly and pass it to {@link #setPixelToleranceOverrides(ZoomFunction)}
|
||||||
*/
|
*/
|
||||||
public Feature setPixelToleranceBelowZoom(int zoom, double tolerance) {
|
public Feature setPixelToleranceBelowZoom(int zoom, double tolerance) {
|
||||||
if (zoom == config.maxzoom()) {
|
if (zoom == config.maxzoom()) {
|
||||||
|
@ -519,9 +522,10 @@ public class FeatureCollector implements Iterable<FeatureCollector.Feature> {
|
||||||
public double getPointLabelGridPixelSizeAtZoom(int zoom) {
|
public double getPointLabelGridPixelSizeAtZoom(int zoom) {
|
||||||
double result = ZoomFunction.applyAsDoubleOrElse(labelGridPixelSize, zoom, DEFAULT_LABEL_GRID_SIZE);
|
double result = ZoomFunction.applyAsDoubleOrElse(labelGridPixelSize, zoom, DEFAULT_LABEL_GRID_SIZE);
|
||||||
// TODO is this enough? what about a grid square that ends just before the start of the tile
|
// TODO is this enough? what about a grid square that ends just before the start of the tile
|
||||||
assert result <= getBufferPixelsAtZoom(zoom) :
|
assert result <= getBufferPixelsAtZoom(
|
||||||
"to avoid inconsistent rendering of the same point between adjacent tiles, buffer pixel size should be >= label grid size but in '%s' buffer pixel size=%f was greater than label grid size=%f".formatted(
|
zoom) : "to avoid inconsistent rendering of the same point between adjacent tiles, buffer pixel size should be >= label grid size but in '%s' buffer pixel size=%f was greater than label grid size=%f"
|
||||||
getLayer(), getBufferPixelsAtZoom(zoom), result);
|
.formatted(
|
||||||
|
getLayer(), getBufferPixelsAtZoom(zoom), result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,7 +554,7 @@ public class FeatureCollector implements Iterable<FeatureCollector.Feature> {
|
||||||
* @param labelGridSize a function that returns the size of the label grid to use at each zoom level. If function is
|
* @param labelGridSize a function that returns the size of the label grid to use at each zoom level. If function is
|
||||||
* or returns null for a zoom-level, no label grid will be computed.
|
* or returns null for a zoom-level, no label grid will be computed.
|
||||||
* @see <a href="https://github.com/mapbox/postgis-vt-util/blob/master/src/LabelGrid.sql">LabelGrid postgis
|
* @see <a href="https://github.com/mapbox/postgis-vt-util/blob/master/src/LabelGrid.sql">LabelGrid postgis
|
||||||
* function</a>
|
* function</a>
|
||||||
*/
|
*/
|
||||||
public Feature setPointLabelGridPixelSize(ZoomFunction<Number> labelGridSize) {
|
public Feature setPointLabelGridPixelSize(ZoomFunction<Number> labelGridSize) {
|
||||||
this.labelGridPixelSize = labelGridSize;
|
this.labelGridPixelSize = labelGridSize;
|
||||||
|
@ -565,7 +569,7 @@ public class FeatureCollector implements Iterable<FeatureCollector.Feature> {
|
||||||
* set for label grid size. To set multiple thresholds, use the other method directly.
|
* set for label grid size. To set multiple thresholds, use the other method directly.
|
||||||
*
|
*
|
||||||
* @see <a href="https://github.com/mapbox/postgis-vt-util/blob/master/src/LabelGrid.sql">LabelGrid postgis
|
* @see <a href="https://github.com/mapbox/postgis-vt-util/blob/master/src/LabelGrid.sql">LabelGrid postgis
|
||||||
* function</a>
|
* function</a>
|
||||||
*/
|
*/
|
||||||
public Feature setPointLabelGridPixelSize(int maxzoom, double size) {
|
public Feature setPointLabelGridPixelSize(int maxzoom, double size) {
|
||||||
return setPointLabelGridPixelSize(ZoomFunction.maxZoom(maxzoom, size));
|
return setPointLabelGridPixelSize(ZoomFunction.maxZoom(maxzoom, size));
|
||||||
|
@ -579,7 +583,7 @@ public class FeatureCollector implements Iterable<FeatureCollector.Feature> {
|
||||||
* @param labelGridLimit a function that returns the size of the label grid to use at each zoom level. If function
|
* @param labelGridLimit a function that returns the size of the label grid to use at each zoom level. If function
|
||||||
* is or returns null for a zoom-level, no label grid will be computed.
|
* is or returns null for a zoom-level, no label grid will be computed.
|
||||||
* @see <a href="https://github.com/mapbox/postgis-vt-util/blob/master/src/LabelGrid.sql">LabelGrid postgis
|
* @see <a href="https://github.com/mapbox/postgis-vt-util/blob/master/src/LabelGrid.sql">LabelGrid postgis
|
||||||
* function</a>
|
* function</a>
|
||||||
*/
|
*/
|
||||||
public Feature setPointLabelGridLimit(ZoomFunction<Number> labelGridLimit) {
|
public Feature setPointLabelGridLimit(ZoomFunction<Number> labelGridLimit) {
|
||||||
this.labelGridLimit = labelGridLimit;
|
this.labelGridLimit = labelGridLimit;
|
||||||
|
@ -590,9 +594,9 @@ public class FeatureCollector implements Iterable<FeatureCollector.Feature> {
|
||||||
* Limits the density of points on an output tile at and below {@code maxzoom} by only emitting the {@code limit}
|
* Limits the density of points on an output tile at and below {@code maxzoom} by only emitting the {@code limit}
|
||||||
* features with lowest sort-key in each square of a {@code size x size} pixel grid.
|
* features with lowest sort-key in each square of a {@code size x size} pixel grid.
|
||||||
* <p>
|
* <p>
|
||||||
* This is a thin wrapper around {@link #setPointLabelGridPixelSize(ZoomFunction)} and {@link
|
* This is a thin wrapper around {@link #setPointLabelGridPixelSize(ZoomFunction)} and
|
||||||
* #setPointLabelGridLimit(ZoomFunction)}. It replaces any previous value set for label grid size or limit. To set
|
* {@link #setPointLabelGridLimit(ZoomFunction)}. It replaces any previous value set for label grid size or limit.
|
||||||
* multiple thresholds, use the other methods directly.
|
* To set multiple thresholds, use the other methods directly.
|
||||||
* <p>
|
* <p>
|
||||||
* NOTE: the label grid is computed within each tile independently of its neighbors, so to ensure consistent limits
|
* NOTE: the label grid is computed within each tile independently of its neighbors, so to ensure consistent limits
|
||||||
* and ranking of a point rendered in adjacent tiles, be sure to set the buffer pixel size to at least be larger
|
* and ranking of a point rendered in adjacent tiles, be sure to set the buffer pixel size to at least be larger
|
||||||
|
@ -602,7 +606,7 @@ public class FeatureCollector implements Iterable<FeatureCollector.Feature> {
|
||||||
* @param size the label grid size to use when computing hashes
|
* @param size the label grid size to use when computing hashes
|
||||||
* @param limit the number of lowest-sort-key points to include in each square of the grid
|
* @param limit the number of lowest-sort-key points to include in each square of the grid
|
||||||
* @see <a href="https://github.com/mapbox/postgis-vt-util/blob/master/src/LabelGrid.sql">LabelGrid postgis
|
* @see <a href="https://github.com/mapbox/postgis-vt-util/blob/master/src/LabelGrid.sql">LabelGrid postgis
|
||||||
* function</a>
|
* function</a>
|
||||||
*/
|
*/
|
||||||
public Feature setPointLabelGridSizeAndLimit(int maxzoom, double size, int limit) {
|
public Feature setPointLabelGridSizeAndLimit(int maxzoom, double size, int limit) {
|
||||||
return setPointLabelGridPixelSize(ZoomFunction.maxZoom(maxzoom, size))
|
return setPointLabelGridPixelSize(ZoomFunction.maxZoom(maxzoom, size))
|
||||||
|
@ -655,11 +659,11 @@ public class FeatureCollector implements Iterable<FeatureCollector.Feature> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the value for {@code key} attribute at or above {@code minzoom}. Below {@code minzoom} it will be ignored.
|
* Sets the value for {@code key} attribute at or above {@code minzoom}. Below {@code minzoom} it will be ignored.
|
||||||
* <p>
|
* <p>
|
||||||
* Replaces all previous value that has been for {@code key} at any zoom level. To have a value that changes at
|
* Replaces all previous value that has been for {@code key} at any zoom level. To have a value that changes at
|
||||||
* multiple zoom level thresholds, call {@link #setAttr(String, Object)} with a manually-constructed {@link
|
* multiple zoom level thresholds, call {@link #setAttr(String, Object)} with a manually-constructed
|
||||||
* ZoomFunction} value.
|
* {@link ZoomFunction} value.
|
||||||
*/
|
*/
|
||||||
public Feature setAttrWithMinzoom(String key, Object value, int minzoom) {
|
public Feature setAttrWithMinzoom(String key, Object value, int minzoom) {
|
||||||
return setAttr(key, ZoomFunction.minZoom(minzoom, value));
|
return setAttr(key, ZoomFunction.minZoom(minzoom, value));
|
||||||
|
|
|
@ -33,13 +33,13 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A collection of utilities for merging features with the same attributes in a rendered tile from {@link
|
* A collection of utilities for merging features with the same attributes in a rendered tile from
|
||||||
* Profile#postProcessLayerFeatures(String, int, List)} immediately before a tile is written to the output mbtiles
|
* {@link Profile#postProcessLayerFeatures(String, int, List)} immediately before a tile is written to the output
|
||||||
* file.
|
* mbtiles file.
|
||||||
* <p>
|
* <p>
|
||||||
* Unlike postgis-based solutions that have a full view of all features after they are loaded into the databse, the
|
* Unlike postgis-based solutions that have a full view of all features after they are loaded into the databse, the
|
||||||
* planetiler engine only sees a single input feature at a time while processing source features, then only has
|
* planetiler engine only sees a single input feature at a time while processing source features, then only has
|
||||||
* visibility into multiple features when they are grouped into a tile immediately before emitting. This ends up being
|
* visibility into multiple features when they are grouped into a tile immediately before emitting. This ends up being
|
||||||
* sufficient for most real-world use-cases but to do anything more that requires a view of multiple features
|
* sufficient for most real-world use-cases but to do anything more that requires a view of multiple features
|
||||||
* <em>not</em> within the same tile, {@link Profile} implementations must store input features manually.
|
* <em>not</em> within the same tile, {@link Profile} implementations must store input features manually.
|
||||||
*/
|
*/
|
||||||
|
@ -53,8 +53,7 @@ public class FeatureMerge {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Don't instantiate */
|
/** Don't instantiate */
|
||||||
private FeatureMerge() {
|
private FeatureMerge() {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Combines linestrings with the same set of attributes into a multilinestring where segments with touching endpoints
|
* Combines linestrings with the same set of attributes into a multilinestring where segments with touching endpoints
|
||||||
|
@ -69,7 +68,7 @@ public class FeatureMerge {
|
||||||
* @param tolerance after merging, simplify linestrings using this pixel tolerance, or -1 to skip simplification step
|
* @param tolerance after merging, simplify linestrings using this pixel tolerance, or -1 to skip simplification step
|
||||||
* @param buffer number of pixels outside the visible tile area to include detail for, or -1 to skip clipping step
|
* @param buffer number of pixels outside the visible tile area to include detail for, or -1 to skip clipping step
|
||||||
* @return a new list containing all unaltered features in their original order, then each of the merged groups
|
* @return a new list containing all unaltered features in their original order, then each of the merged groups
|
||||||
* ordered by the index of the first element in that group from the input list.
|
* ordered by the index of the first element in that group from the input list.
|
||||||
*/
|
*/
|
||||||
public static List<VectorTile.Feature> mergeLineStrings(List<VectorTile.Feature> features,
|
public static List<VectorTile.Feature> mergeLineStrings(List<VectorTile.Feature> features,
|
||||||
double minLength, double tolerance, double buffer) {
|
double minLength, double tolerance, double buffer) {
|
||||||
|
@ -78,7 +77,7 @@ public class FeatureMerge {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merges linestrings with the same attributes like {@link #mergeLineStrings(List, double, double, double)} except
|
* Merges linestrings with the same attributes like {@link #mergeLineStrings(List, double, double, double)} except
|
||||||
* with a dynamic length limit computed by {@code lengthLimitCalculator} for the attributes of each group.
|
* with a dynamic length limit computed by {@code lengthLimitCalculator} for the attributes of each group.
|
||||||
*/
|
*/
|
||||||
public static List<VectorTile.Feature> mergeLineStrings(List<VectorTile.Feature> features,
|
public static List<VectorTile.Feature> mergeLineStrings(List<VectorTile.Feature> features,
|
||||||
Function<Map<String, Object>, Double> lengthLimitCalculator, double tolerance, double buffer) {
|
Function<Map<String, Object>, Double> lengthLimitCalculator, double tolerance, double buffer) {
|
||||||
|
@ -186,7 +185,7 @@ public class FeatureMerge {
|
||||||
* @param features all features in a layer
|
* @param features all features in a layer
|
||||||
* @param minArea minimum area in square tile pixels of polygons to emit
|
* @param minArea minimum area in square tile pixels of polygons to emit
|
||||||
* @return a new list containing all unaltered features in their original order, then each of the merged groups
|
* @return a new list containing all unaltered features in their original order, then each of the merged groups
|
||||||
* ordered by the index of the first element in that group from the input list.
|
* ordered by the index of the first element in that group from the input list.
|
||||||
* @throws GeometryException if an error occurs encoding the combined geometry
|
* @throws GeometryException if an error occurs encoding the combined geometry
|
||||||
*/
|
*/
|
||||||
public static List<VectorTile.Feature> mergeOverlappingPolygons(List<VectorTile.Feature> features, double minArea)
|
public static List<VectorTile.Feature> mergeOverlappingPolygons(List<VectorTile.Feature> features, double minArea)
|
||||||
|
@ -215,7 +214,7 @@ public class FeatureMerge {
|
||||||
* @param buffer the amount (in tile pixels) to expand then contract polygons by in order to combine
|
* @param buffer the amount (in tile pixels) to expand then contract polygons by in order to combine
|
||||||
* almost-touching polygons
|
* almost-touching polygons
|
||||||
* @return a new list containing all unaltered features in their original order, then each of the merged groups
|
* @return a new list containing all unaltered features in their original order, then each of the merged groups
|
||||||
* ordered by the index of the first element in that group from the input list.
|
* ordered by the index of the first element in that group from the input list.
|
||||||
* @throws GeometryException if an error occurs encoding the combined geometry
|
* @throws GeometryException if an error occurs encoding the combined geometry
|
||||||
*/
|
*/
|
||||||
public static List<VectorTile.Feature> mergeNearbyPolygons(List<VectorTile.Feature> features, double minArea,
|
public static List<VectorTile.Feature> mergeNearbyPolygons(List<VectorTile.Feature> features, double minArea,
|
||||||
|
|
|
@ -14,13 +14,13 @@ import java.util.function.Consumer;
|
||||||
* A framework for building complex {@link Profile Profiles} that need to be broken apart into multiple handlers (i.e.
|
* A framework for building complex {@link Profile Profiles} that need to be broken apart into multiple handlers (i.e.
|
||||||
* one per layer).
|
* one per layer).
|
||||||
* <p>
|
* <p>
|
||||||
* Individual handlers added with {@link #registerHandler(Handler)} can listen on events by implementing these
|
* Individual handlers added with {@link #registerHandler(Handler)} can listen on events by implementing these handlers:
|
||||||
* handlers:
|
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link OsmRelationPreprocessor} to process every OSM relation during first pass through OSM file</li>
|
* <li>{@link OsmRelationPreprocessor} to process every OSM relation during first pass through OSM file</li>
|
||||||
* <li>{@link FeatureProcessor} to handle features from a particular source (added through {@link #registerSourceHandler(String, FeatureProcessor)})</li>
|
* <li>{@link FeatureProcessor} to handle features from a particular source (added through
|
||||||
* <li>{@link FinishHandler} to be notified whenever we finish processing each source</li>
|
* {@link #registerSourceHandler(String, FeatureProcessor)})</li>
|
||||||
* <li>{@link FeaturePostProcessor} to post-process features in a layer before rendering the output tile</li>
|
* <li>{@link FinishHandler} to be notified whenever we finish processing each source</li>
|
||||||
|
* <li>{@link FeaturePostProcessor} to post-process features in a layer before rendering the output tile</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* See {@code OpenMapTilesProfile} for a full implementation using this framework.
|
* See {@code OpenMapTilesProfile} for a full implementation using this framework.
|
||||||
*/
|
*/
|
||||||
|
@ -52,8 +52,8 @@ public abstract class ForwardingProfile implements Profile {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call {@code handler} for different events based on which interfaces {@code handler} implements: {@link
|
* Call {@code handler} for different events based on which interfaces {@code handler} implements:
|
||||||
* OsmRelationPreprocessor}, {@link FinishHandler}, or {@link FeaturePostProcessor}.
|
* {@link OsmRelationPreprocessor}, {@link FinishHandler}, or {@link FeaturePostProcessor}.
|
||||||
*/
|
*/
|
||||||
public void registerHandler(Handler handler) {
|
public void registerHandler(Handler handler) {
|
||||||
this.handlers.add(handler);
|
this.handlers.add(handler);
|
||||||
|
@ -161,8 +161,7 @@ public abstract class ForwardingProfile implements Profile {
|
||||||
public interface Handler {
|
public interface Handler {
|
||||||
|
|
||||||
/** Free any resources associated with this profile (i.e. shared data structures) */
|
/** Free any resources associated with this profile (i.e. shared data structures) */
|
||||||
default void release() {
|
default void release() {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface HandlerForLayer extends Handler {
|
public interface HandlerForLayer extends Handler {
|
||||||
|
@ -187,8 +186,7 @@ public abstract class ForwardingProfile implements Profile {
|
||||||
public interface OsmNodePreprocessor extends Handler {
|
public interface OsmNodePreprocessor extends Handler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts information from an OSM node during pass 1 of the input OSM data that the profile may need during
|
* Extracts information from an OSM node during pass 1 of the input OSM data that the profile may need during pass2.
|
||||||
* pass2.
|
|
||||||
*
|
*
|
||||||
* @see Profile#preprocessOsmNode(OsmElement.Node)
|
* @see Profile#preprocessOsmNode(OsmElement.Node)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -39,7 +39,9 @@ import org.slf4j.LoggerFactory;
|
||||||
* common use-cases.
|
* common use-cases.
|
||||||
* <p>
|
* <p>
|
||||||
* For example:
|
* For example:
|
||||||
* <pre><code>
|
*
|
||||||
|
* <pre>
|
||||||
|
* <code>
|
||||||
* public static void main(String[] args) {
|
* public static void main(String[] args) {
|
||||||
* Planetiler.create(arguments)
|
* Planetiler.create(arguments)
|
||||||
* .setProfile(new CustomProfile())
|
* .setProfile(new CustomProfile())
|
||||||
|
@ -48,7 +50,8 @@ import org.slf4j.LoggerFactory;
|
||||||
* .addOsmSource("osm", Path.of("source.osm.pbf"))
|
* .addOsmSource("osm", Path.of("source.osm.pbf"))
|
||||||
* .setOutput("mbtiles", Path.of("output.mbtiles"))
|
* .setOutput("mbtiles", Path.of("output.mbtiles"))
|
||||||
* .run();
|
* .run();
|
||||||
* }</code></pre>
|
* }</code>
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* Each call to a builder API mutates the runner instance and returns it for more chaining.
|
* Each call to a builder API mutates the runner instance and returns it for more chaining.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -140,9 +143,9 @@ public class Planetiler {
|
||||||
* @param name string to use in stats and logs to identify this stage
|
* @param name string to use in stats and logs to identify this stage
|
||||||
* @param defaultPath path to the input file to use if {@code name_path} argument is not set
|
* @param defaultPath path to the input file to use if {@code name_path} argument is not set
|
||||||
* @param defaultUrl remote URL that the file to download if {@code download=true} argument is set and {@code
|
* @param defaultUrl remote URL that the file to download if {@code download=true} argument is set and {@code
|
||||||
* name_url} argument is not set. As a shortcut, can use "geofabrik:monaco" or
|
* name_url} argument is not set. As a shortcut, can use "geofabrik:monaco" or
|
||||||
* "geofabrik:australia" shorthand to find an extract by name from <a
|
* "geofabrik:australia" shorthand to find an extract by name from
|
||||||
* href="https://download.geofabrik.de/">Geofabrik download site</a> or "aws:latest" to download
|
* <a href="https://download.geofabrik.de/">Geofabrik download site</a> or "aws:latest" to download
|
||||||
* the latest {@code planet.osm.pbf} file from <a href="https://registry.opendata.aws/osm/">AWS
|
* the latest {@code planet.osm.pbf} file from <a href="https://registry.opendata.aws/osm/">AWS
|
||||||
* Open Data Registry</a>.
|
* Open Data Registry</a>.
|
||||||
* @return this runner instance for chaining
|
* @return this runner instance for chaining
|
||||||
|
@ -180,8 +183,8 @@ public class Planetiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new ESRI shapefile source that will be processed using a projection inferred from the shapefile when {@link
|
* Adds a new ESRI shapefile source that will be processed using a projection inferred from the shapefile when
|
||||||
* #run()} is called.
|
* {@link #run()} is called.
|
||||||
* <p>
|
* <p>
|
||||||
* To override the location of the {@code shapefile} file, set {@code name_path=newpath.shp.zip} in the arguments.
|
* To override the location of the {@code shapefile} file, set {@code name_path=newpath.shp.zip} in the arguments.
|
||||||
*
|
*
|
||||||
|
@ -197,13 +200,12 @@ public class Planetiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new ESRI shapefile source that will be processed using an explicit projection when {@link #run()} is
|
* Adds a new ESRI shapefile source that will be processed using an explicit projection when {@link #run()} is called.
|
||||||
* called.
|
|
||||||
* <p>
|
* <p>
|
||||||
* To override the location of the {@code shapefile} file, set {@code name_path=newpath.shp.zip} in the arguments.
|
* To override the location of the {@code shapefile} file, set {@code name_path=newpath.shp.zip} in the arguments.
|
||||||
*
|
*
|
||||||
* @param projection the Coordinate Reference System authority code to use, parsed with {@link
|
* @param projection the Coordinate Reference System authority code to use, parsed with
|
||||||
* org.geotools.referencing.CRS#decode(String)}
|
* {@link org.geotools.referencing.CRS#decode(String)}
|
||||||
* @param name string to use in stats and logs to identify this stage
|
* @param name string to use in stats and logs to identify this stage
|
||||||
* @param defaultPath path to the input file to use if {@code name_path} key is not set through arguments. Can be a
|
* @param defaultPath path to the input file to use if {@code name_path} key is not set through arguments. Can be a
|
||||||
* {@code .shp} file with other shapefile components in the same directory, or a {@code .zip} file
|
* {@code .shp} file with other shapefile components in the same directory, or a {@code .zip} file
|
||||||
|
@ -216,8 +218,8 @@ public class Planetiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new ESRI shapefile source that will be processed with a projection inferred from the shapefile when {@link
|
* Adds a new ESRI shapefile source that will be processed with a projection inferred from the shapefile when
|
||||||
* #run()} is called.
|
* {@link #run()} is called.
|
||||||
* <p>
|
* <p>
|
||||||
* If the file does not exist and {@code download=true} argument is set, then the file will first be downloaded from
|
* If the file does not exist and {@code download=true} argument is set, then the file will first be downloaded from
|
||||||
* {@code defaultUrl}.
|
* {@code defaultUrl}.
|
||||||
|
@ -248,8 +250,8 @@ public class Planetiler {
|
||||||
* To override the location of the {@code shapefile} file, set {@code name_path=newpath.shp.zip} in the arguments and
|
* To override the location of the {@code shapefile} file, set {@code name_path=newpath.shp.zip} in the arguments and
|
||||||
* to override the download URL set {@code name_url=http://url/of/shapefile.zip}.
|
* to override the download URL set {@code name_url=http://url/of/shapefile.zip}.
|
||||||
*
|
*
|
||||||
* @param projection the Coordinate Reference System authority code to use, parsed with {@link
|
* @param projection the Coordinate Reference System authority code to use, parsed with
|
||||||
* org.geotools.referencing.CRS#decode(String)}
|
* {@link org.geotools.referencing.CRS#decode(String)}
|
||||||
* @param name string to use in stats and logs to identify this stage
|
* @param name string to use in stats and logs to identify this stage
|
||||||
* @param defaultPath path to the input file to use if {@code name_path} key is not set through arguments. Can be a
|
* @param defaultPath path to the input file to use if {@code name_path} key is not set through arguments. Can be a
|
||||||
* {@code .shp} file with other shapefile components in the same directory, or a {@code .zip} file
|
* {@code .shp} file with other shapefile components in the same directory, or a {@code .zip} file
|
||||||
|
@ -332,8 +334,8 @@ public class Planetiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates {@link #translations()} to use name translations fetched from wikidata based on the <a
|
* Updates {@link #translations()} to use name translations fetched from wikidata based on the
|
||||||
* href="https://www.wikidata.org/wiki/Wikidata:OpenStreetMap">wikidata tag</a> on OSM elements.
|
* <a href="https://www.wikidata.org/wiki/Wikidata:OpenStreetMap">wikidata tag</a> on OSM elements.
|
||||||
* <p>
|
* <p>
|
||||||
* When either {@code only_fetch_wikidata} or {@code fetch_wikidata} arguments are set to true, this downloads
|
* When either {@code only_fetch_wikidata} or {@code fetch_wikidata} arguments are set to true, this downloads
|
||||||
* translations for every OSM element that the profile cares about and stores them to {@code defaultWikidataCache} (or
|
* translations for every OSM element that the profile cares about and stores them to {@code defaultWikidataCache} (or
|
||||||
|
@ -393,8 +395,7 @@ public class Planetiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the location of the output {@code .mbtiles} file to write rendered tiles to. Fails if the file already
|
* Sets the location of the output {@code .mbtiles} file to write rendered tiles to. Fails if the file already exists.
|
||||||
* exists.
|
|
||||||
* <p>
|
* <p>
|
||||||
* To override the location of the file, set {@code argument=newpath.mbtiles} in the arguments.
|
* To override the location of the file, set {@code argument=newpath.mbtiles} in the arguments.
|
||||||
*
|
*
|
||||||
|
@ -570,9 +571,8 @@ public class Planetiler {
|
||||||
if (available < requested) {
|
if (available < requested) {
|
||||||
var format = Format.defaultInstance();
|
var format = Format.defaultInstance();
|
||||||
String warning =
|
String warning =
|
||||||
"Planetiler needs ~" + format.storage(requested) + " on " + fs + " during " + phase
|
"Planetiler needs ~" + format.storage(requested) + " on " + fs + " during " + phase +
|
||||||
+ " phase, which only has "
|
" phase, which only has " + format.storage(available) + " available";
|
||||||
+ format.storage(available) + " available";
|
|
||||||
if (config.force() || requested < available * 1.25) {
|
if (config.force() || requested < available * 1.25) {
|
||||||
LOGGER.warn(warning + ", may fail.");
|
LOGGER.warn(warning + ", may fail.");
|
||||||
} else {
|
} else {
|
||||||
|
@ -592,9 +592,9 @@ public class Planetiler {
|
||||||
|
|
||||||
if (jvmMemory < requested) {
|
if (jvmMemory < requested) {
|
||||||
String warning =
|
String warning =
|
||||||
"Planetiler needs ~" + format.storage(requested) + " memory for the JVM, but only "
|
"Planetiler needs ~" + format.storage(requested) + " memory for the JVM, but only " +
|
||||||
+ format.storage(jvmMemory) + " is available, try setting -Xmx=" + format.storage(requested).toLowerCase(
|
format.storage(jvmMemory) + " is available, try setting -Xmx=" + format.storage(requested).toLowerCase(
|
||||||
Locale.ROOT);
|
Locale.ROOT);
|
||||||
if (config.force() || requested < jvmMemory * 1.25) {
|
if (config.force() || requested < jvmMemory * 1.25) {
|
||||||
LOGGER.warn(warning + ", may fail.");
|
LOGGER.warn(warning + ", may fail.");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -14,17 +14,18 @@ import java.util.function.Consumer;
|
||||||
* <p>
|
* <p>
|
||||||
* This includes:
|
* This includes:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>How source features (OSM elements, shapefile elements, etc.) map to output features and their tags</li>
|
* <li>How source features (OSM elements, shapefile elements, etc.) map to output features and their tags</li>
|
||||||
* <li>How vector tile features in an output tile should be post-processed (see {@link FeatureMerge})</li>
|
* <li>How vector tile features in an output tile should be post-processed (see {@link FeatureMerge})</li>
|
||||||
* <li>What attributes to include in the mbtiles metadata output (see {@link Mbtiles})</li>
|
* <li>What attributes to include in the mbtiles metadata output (see {@link Mbtiles})</li>
|
||||||
* <li>Whether {@link Wikidata} class should fetch wikidata translations for an OSM element</li>
|
* <li>Whether {@link Wikidata} class should fetch wikidata translations for an OSM element</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* {@link Profile#processFeature(SourceFeature, FeatureCollector)} only handles a single element at a time. To "join"
|
* {@link Profile#processFeature(SourceFeature, FeatureCollector)} only handles a single element at a time. To "join"
|
||||||
* elements across or within sources, implementations can store data in instance fields and wait to process them until
|
* elements across or within sources, implementations can store data in instance fields and wait to process them until
|
||||||
* an element is encountered in a later source, or the {@link Profile#finish(String, FeatureCollector.Factory, Consumer)}
|
* an element is encountered in a later source, or the
|
||||||
* method is called for a source. All methods may be called concurrently by multiple threads, so implementations must be
|
* {@link Profile#finish(String, FeatureCollector.Factory, Consumer)} method is called for a source. All methods may be
|
||||||
* careful to ensure access to instance fields is thread-safe.
|
* called concurrently by multiple threads, so implementations must be careful to ensure access to instance fields is
|
||||||
|
* thread-safe.
|
||||||
* <p>
|
* <p>
|
||||||
* For complex profiles, {@link ForwardingProfile} provides a framework for splitting the logic up into several handlers
|
* For complex profiles, {@link ForwardingProfile} provides a framework for splitting the logic up into several handlers
|
||||||
* (i.e. one per layer) and forwarding each element/event to the handlers that care about it.
|
* (i.e. one per layer) and forwarding each element/event to the handlers that care about it.
|
||||||
|
@ -40,8 +41,7 @@ public interface Profile {
|
||||||
*
|
*
|
||||||
* @param node the OSM node
|
* @param node the OSM node
|
||||||
*/
|
*/
|
||||||
default void preprocessOsmNode(OsmElement.Node node) {
|
default void preprocessOsmNode(OsmElement.Node node) {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows profile to extract any information it needs from a {@link OsmElement.Way} during the first pass through OSM
|
* Allows profile to extract any information it needs from a {@link OsmElement.Way} during the first pass through OSM
|
||||||
|
@ -51,8 +51,7 @@ public interface Profile {
|
||||||
*
|
*
|
||||||
* @param way the OSM way
|
* @param way the OSM way
|
||||||
*/
|
*/
|
||||||
default void preprocessOsmWay(OsmElement.Way way) {
|
default void preprocessOsmWay(OsmElement.Way way) {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts information from <a href="https://wiki.openstreetmap.org/wiki/Relation">OSM relations</a> that will be
|
* Extracts information from <a href="https://wiki.openstreetmap.org/wiki/Relation">OSM relations</a> that will be
|
||||||
|
@ -63,8 +62,8 @@ public interface Profile {
|
||||||
* The default implementation returns {@code null} to ignore all relations
|
* The default implementation returns {@code null} to ignore all relations
|
||||||
*
|
*
|
||||||
* @param relation the OSM relation
|
* @param relation the OSM relation
|
||||||
* @return a list of relation info instances with information extracted from the relation to pass to {@link
|
* @return a list of relation info instances with information extracted from the relation to pass to
|
||||||
* #processFeature(SourceFeature, FeatureCollector)}, or {@code null} to ignore.
|
* {@link #processFeature(SourceFeature, FeatureCollector)}, or {@code null} to ignore.
|
||||||
*/
|
*/
|
||||||
default List<OsmRelationInfo> preprocessOsmRelation(OsmElement.Relation relation) {
|
default List<OsmRelationInfo> preprocessOsmRelation(OsmElement.Relation relation) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -74,7 +73,7 @@ public interface Profile {
|
||||||
* Generates output features for any input feature that should appear in the map.
|
* Generates output features for any input feature that should appear in the map.
|
||||||
* <p>
|
* <p>
|
||||||
* Multiple threads may invoke this method concurrently for a single data source so implementations should ensure
|
* Multiple threads may invoke this method concurrently for a single data source so implementations should ensure
|
||||||
* thread-safe access to any shared data structures. Separate data sources are processed sequentially.
|
* thread-safe access to any shared data structures. Separate data sources are processed sequentially.
|
||||||
* <p>
|
* <p>
|
||||||
* All OSM nodes are processed first, then ways, then relations.
|
* All OSM nodes are processed first, then ways, then relations.
|
||||||
*
|
*
|
||||||
|
@ -84,8 +83,7 @@ public interface Profile {
|
||||||
void processFeature(SourceFeature sourceFeature, FeatureCollector features);
|
void processFeature(SourceFeature sourceFeature, FeatureCollector features);
|
||||||
|
|
||||||
/** Free any resources associated with this profile (i.e. shared data structures) */
|
/** Free any resources associated with this profile (i.e. shared data structures) */
|
||||||
default void release() {
|
default void release() {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply any post-processing to features in an output layer of a tile before writing it to the output file
|
* Apply any post-processing to features in an output layer of a tile before writing it to the output file
|
||||||
|
@ -101,8 +99,8 @@ public interface Profile {
|
||||||
* @param layer the output layer name
|
* @param layer the output layer name
|
||||||
* @param zoom zoom level of the tile
|
* @param zoom zoom level of the tile
|
||||||
* @param items all the output features in this layer in this tile
|
* @param items all the output features in this layer in this tile
|
||||||
* @return the new list of output features or {@code null} to not change anything. Set any elements of the list to
|
* @return the new list of output features or {@code null} to not change anything. Set any elements of the list to
|
||||||
* {@code null} if they should be ignored.
|
* {@code null} if they should be ignored.
|
||||||
* @throws GeometryException for any recoverable geometric operation failures - the framework will log the error, emit
|
* @throws GeometryException for any recoverable geometric operation failures - the framework will log the error, emit
|
||||||
* the original input features, and continue processing other tiles
|
* the original input features, and continue processing other tiles
|
||||||
*/
|
*/
|
||||||
|
@ -131,7 +129,7 @@ public interface Profile {
|
||||||
* Returns the attribution of the generated tileset to put into {@link Mbtiles} metadata
|
* Returns the attribution of the generated tileset to put into {@link Mbtiles} metadata
|
||||||
*
|
*
|
||||||
* @see <a href="https://www.openstreetmap.org/copyright">https://www.openstreetmap.org/copyright</a> for attribution
|
* @see <a href="https://www.openstreetmap.org/copyright">https://www.openstreetmap.org/copyright</a> for attribution
|
||||||
* requirements of any map using OpenStreetMap data
|
* requirements of any map using OpenStreetMap data
|
||||||
* @see <a href="https://github.com/mapbox/mbtiles-spec/blob/master/1.3/spec.md#metadata">MBTiles specification</a>
|
* @see <a href="https://github.com/mapbox/mbtiles-spec/blob/master/1.3/spec.md#metadata">MBTiles specification</a>
|
||||||
*/
|
*/
|
||||||
default String attribution() {
|
default String attribution() {
|
||||||
|
@ -179,8 +177,7 @@ public interface Profile {
|
||||||
* @param next a consumer to pass finished map features to
|
* @param next a consumer to pass finished map features to
|
||||||
*/
|
*/
|
||||||
default void finish(String sourceName, FeatureCollector.Factory featureCollectors,
|
default void finish(String sourceName, FeatureCollector.Factory featureCollectors,
|
||||||
Consumer<FeatureCollector.Feature> next) {
|
Consumer<FeatureCollector.Feature> next) {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this profile will use any of the elements from an input source.
|
* Returns true if this profile will use any of the elements from an input source.
|
||||||
|
@ -224,8 +221,7 @@ public interface Profile {
|
||||||
class NullProfile implements Profile {
|
class NullProfile implements Profile {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processFeature(SourceFeature sourceFeature, FeatureCollector features) {
|
public void processFeature(SourceFeature sourceFeature, FeatureCollector features) {}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<VectorTile.Feature> postProcessLayerFeatures(String layer, int zoom,
|
public List<VectorTile.Feature> postProcessLayerFeatures(String layer, int zoom,
|
||||||
|
|
|
@ -57,12 +57,12 @@ import vector_tile.VectorTileProto;
|
||||||
* Encodes a single output tile containing JTS {@link Geometry} features into the compact binary Mapbox Vector Tile
|
* Encodes a single output tile containing JTS {@link Geometry} features into the compact binary Mapbox Vector Tile
|
||||||
* format.
|
* format.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is copied from
|
* This class is copied from <a href=
|
||||||
* <a href="https://github.com/ElectronicChartCentre/java-vector-tile/blob/master/src/main/java/no/ecc/vectortile/VectorTileEncoder.java">VectorTileEncoder.java</a>
|
* "https://github.com/ElectronicChartCentre/java-vector-tile/blob/master/src/main/java/no/ecc/vectortile/VectorTileEncoder.java">VectorTileEncoder.java</a>
|
||||||
* and
|
* and <a href=
|
||||||
* <a href="https://github.com/ElectronicChartCentre/java-vector-tile/blob/master/src/main/java/no/ecc/vectortile/VectorTileDecoder.java">VectorTileDecoder.java</a>
|
* "https://github.com/ElectronicChartCentre/java-vector-tile/blob/master/src/main/java/no/ecc/vectortile/VectorTileDecoder.java">VectorTileDecoder.java</a>
|
||||||
* and modified to decouple geometry encoding from vector tile encoding so that encoded commands can be stored in the
|
* and modified to decouple geometry encoding from vector tile encoding so that encoded commands can be stored in the
|
||||||
* sorted feature map prior to encoding vector tiles. The internals are also refactored to improve performance by using
|
* sorted feature map prior to encoding vector tiles. The internals are also refactored to improve performance by using
|
||||||
* hppc primitive collections.
|
* hppc primitive collections.
|
||||||
*
|
*
|
||||||
* @see <a href="https://github.com/mapbox/vector-tile-spec/tree/master/2.1">Mapbox Vector Tile Specification</a>
|
* @see <a href="https://github.com/mapbox/vector-tile-spec/tree/master/2.1">Mapbox Vector Tile Specification</a>
|
||||||
|
@ -389,8 +389,9 @@ public class VectorTile {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes a JTS geometry according to <a href="https://github.com/mapbox/vector-tile-spec/tree/master/2.1#43-geometry-encoding">Geometry
|
* Encodes a JTS geometry according to
|
||||||
* Encoding Specification</a>.
|
* <a href="https://github.com/mapbox/vector-tile-spec/tree/master/2.1#43-geometry-encoding">Geometry Encoding
|
||||||
|
* Specification</a>.
|
||||||
*
|
*
|
||||||
* @param geometry the JTS geometry to encoded
|
* @param geometry the JTS geometry to encoded
|
||||||
* @return the geometry type and command array for the encoded geometry
|
* @return the geometry type and command array for the encoded geometry
|
||||||
|
@ -498,6 +499,7 @@ public class VectorTile {
|
||||||
MOVE_TO(1),
|
MOVE_TO(1),
|
||||||
LINE_TO(2),
|
LINE_TO(2),
|
||||||
CLOSE_PATH(7);
|
CLOSE_PATH(7);
|
||||||
|
|
||||||
final int value;
|
final int value;
|
||||||
|
|
||||||
Command(int value) {
|
Command(int value) {
|
||||||
|
@ -506,8 +508,9 @@ public class VectorTile {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A vector tile encoded as a list of commands according to the <a href="https://github.com/mapbox/vector-tile-spec/tree/master/2.1#43-geometry-encoding">vector
|
* A vector tile encoded as a list of commands according to the
|
||||||
* tile specification</a>.
|
* <a href="https://github.com/mapbox/vector-tile-spec/tree/master/2.1#43-geometry-encoding">vector tile
|
||||||
|
* specification</a>.
|
||||||
* <p>
|
* <p>
|
||||||
* To encode extra precision in intermediate feature geometries, the geometry contained in {@code commands} is scaled
|
* To encode extra precision in intermediate feature geometries, the geometry contained in {@code commands} is scaled
|
||||||
* to a tile extent of {@code EXTENT * 2^scale}, so when the {@code scale == 0} the extent is {@link #EXTENT} and when
|
* to a tile extent of {@code EXTENT * 2^scale}, so when the {@code scale == 0} the extent is {@link #EXTENT} and when
|
||||||
|
@ -635,7 +638,7 @@ public class VectorTile {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes a geometry as a sequence of integers according to the
|
* Encodes a geometry as a sequence of integers according to the
|
||||||
* <a href="https://github.com/mapbox/vector-tile-spec/tree/master/2.1#43-geometry-encoding">Geometry * Encoding
|
* <a href="https://github.com/mapbox/vector-tile-spec/tree/master/2.1#43-geometry-encoding">Geometry * Encoding
|
||||||
* Specification</a>.
|
* Specification</a>.
|
||||||
*/
|
*/
|
||||||
private static class CommandEncoder {
|
private static class CommandEncoder {
|
||||||
|
|
|
@ -90,10 +90,8 @@ public final class FeatureGroup implements Consumer<SortableFeature>, Iterable<F
|
||||||
* value contains grouping information.
|
* value contains grouping information.
|
||||||
*/
|
*/
|
||||||
static long encodeKey(int tile, byte layer, int sortKey, boolean hasGroup) {
|
static long encodeKey(int tile, byte layer, int sortKey, boolean hasGroup) {
|
||||||
return ((long) tile << 32L)
|
return ((long) tile << 32L) | ((long) (layer & 0xff) << 24L) | (((sortKey - SORT_KEY_MIN) & SORT_KEY_MASK) << 1L) |
|
||||||
| ((long) (layer & 0xff) << 24L)
|
(hasGroup ? 1 : 0);
|
||||||
| (((sortKey - SORT_KEY_MIN) & SORT_KEY_MASK) << 1L)
|
|
||||||
| (hasGroup ? 1 : 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean extractHasGroupFromKey(long key) {
|
static boolean extractHasGroupFromKey(long key) {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.onthegomap.planetiler.collection;
|
package com.onthegomap.planetiler.collection;
|
||||||
|
|
||||||
|
|
||||||
import com.carrotsearch.hppc.IntObjectHashMap;
|
import com.carrotsearch.hppc.IntObjectHashMap;
|
||||||
import com.carrotsearch.hppc.LongByteHashMap;
|
import com.carrotsearch.hppc.LongByteHashMap;
|
||||||
import com.carrotsearch.hppc.LongByteMap;
|
import com.carrotsearch.hppc.LongByteMap;
|
||||||
|
|
|
@ -99,8 +99,7 @@ public interface LongLongMap extends Closeable, MemoryEstimator.HasEstimate, Dis
|
||||||
static LongLongMap noop() {
|
static LongLongMap noop() {
|
||||||
return new LongLongMap() {
|
return new LongLongMap() {
|
||||||
@Override
|
@Override
|
||||||
public void put(long key, long value) {
|
public void put(long key, long value) {}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long get(long key) {
|
public long get(long key) {
|
||||||
|
@ -113,8 +112,7 @@ public interface LongLongMap extends Closeable, MemoryEstimator.HasEstimate, Dis
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,10 +97,10 @@ public class Arguments {
|
||||||
* <p>
|
* <p>
|
||||||
* Priority order:
|
* Priority order:
|
||||||
* <ol>
|
* <ol>
|
||||||
* <li>command-line arguments: {@code java ... key=value}</li>
|
* <li>command-line arguments: {@code java ... key=value}</li>
|
||||||
* <li>jvm properties: {@code java -Dplanetiler.key=value ...}</li>
|
* <li>jvm properties: {@code java -Dplanetiler.key=value ...}</li>
|
||||||
* <li>environmental variables: {@code PLANETILER_KEY=value java ...}</li>
|
* <li>environmental variables: {@code PLANETILER_KEY=value java ...}</li>
|
||||||
* <li>in a config file from "config" argument from any of the above</li>
|
* <li>in a config file from "config" argument from any of the above</li>
|
||||||
* </ol>
|
* </ol>
|
||||||
*
|
*
|
||||||
* @param args command-line args provide to main entrypoint method
|
* @param args command-line args provide to main entrypoint method
|
||||||
|
@ -253,8 +253,8 @@ public class Arguments {
|
||||||
/**
|
/**
|
||||||
* Returns a {@link Stats} implementation based on the arguments provided.
|
* Returns a {@link Stats} implementation based on the arguments provided.
|
||||||
* <p>
|
* <p>
|
||||||
* If {@code pushgateway} is set then it uses a stats implementation that pushes to prometheus through a <a
|
* If {@code pushgateway} is set then it uses a stats implementation that pushes to prometheus through a
|
||||||
* href="https://github.com/prometheus/pushgateway">push gateway</a> every {@code pushgateway.interval} seconds.
|
* <a href="https://github.com/prometheus/pushgateway">push gateway</a> every {@code pushgateway.interval} seconds.
|
||||||
* Otherwise, uses an in-memory stats implementation.
|
* Otherwise, uses an in-memory stats implementation.
|
||||||
*/
|
*/
|
||||||
public Stats getStats() {
|
public Stats getStats() {
|
||||||
|
|
|
@ -17,9 +17,12 @@ import java.util.stream.Stream;
|
||||||
* <p>
|
* <p>
|
||||||
* Calling {@code toString()} on any expression will generate code that can be used to recreate an identical copy of the
|
* Calling {@code toString()} on any expression will generate code that can be used to recreate an identical copy of the
|
||||||
* original expression, assuming that the generated code includes:
|
* original expression, assuming that the generated code includes:
|
||||||
* <pre>{@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {@code
|
||||||
* import static com.onthegomap.planetiler.expression.Expression.*;
|
* import static com.onthegomap.planetiler.expression.Expression.*;
|
||||||
* }</pre>
|
* }
|
||||||
|
* </pre>
|
||||||
*/
|
*/
|
||||||
public interface Expression {
|
public interface Expression {
|
||||||
|
|
||||||
|
@ -99,10 +102,10 @@ public interface Expression {
|
||||||
* <p>
|
* <p>
|
||||||
* Allowed values:
|
* Allowed values:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>"linestring"</li>
|
* <li>"linestring"</li>
|
||||||
* <li>"point"</li>
|
* <li>"point"</li>
|
||||||
* <li>"polygon"</li>
|
* <li>"polygon"</li>
|
||||||
* <li>"relation_member"</li>
|
* <li>"relation_member"</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
static MatchType matchType(String type) {
|
static MatchType matchType(String type) {
|
||||||
|
@ -190,7 +193,9 @@ public interface Expression {
|
||||||
return replace(a::equals, b);
|
return replace(a::equals, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a copy of this expression where every nested instance matching {@code replace} is replaced with {@code b}. */
|
/**
|
||||||
|
* Returns a copy of this expression where every nested instance matching {@code replace} is replaced with {@code b}.
|
||||||
|
*/
|
||||||
default Expression replace(Predicate<Expression> replace, Expression b) {
|
default Expression replace(Predicate<Expression> replace, Expression b) {
|
||||||
if (replace.test(this)) {
|
if (replace.test(this)) {
|
||||||
return b;
|
return b;
|
||||||
|
|
|
@ -29,7 +29,7 @@ import java.util.function.Predicate;
|
||||||
*
|
*
|
||||||
* @param <T> type of data value associated with each expression
|
* @param <T> type of data value associated with each expression
|
||||||
*/
|
*/
|
||||||
public record MultiExpression<T>(List<Entry<T>> expressions) {
|
public record MultiExpression<T> (List<Entry<T>> expressions) {
|
||||||
|
|
||||||
public static <T> MultiExpression<T> of(List<Entry<T>> expressions) {
|
public static <T> MultiExpression<T> of(List<Entry<T>> expressions) {
|
||||||
return new MultiExpression<>(expressions);
|
return new MultiExpression<>(expressions);
|
||||||
|
@ -94,8 +94,8 @@ public record MultiExpression<T>(List<Entry<T>> expressions) {
|
||||||
if (expressions.isEmpty()) {
|
if (expressions.isEmpty()) {
|
||||||
return new EmptyIndex<>();
|
return new EmptyIndex<>();
|
||||||
}
|
}
|
||||||
boolean caresAboutGeometryType = expressions.stream().anyMatch(entry ->
|
boolean caresAboutGeometryType =
|
||||||
entry.expression.contains(exp -> exp instanceof Expression.MatchType));
|
expressions.stream().anyMatch(entry -> entry.expression.contains(exp -> exp instanceof Expression.MatchType));
|
||||||
return caresAboutGeometryType ? new GeometryTypeIndex<>(this) : new KeyIndex<>(this);
|
return caresAboutGeometryType ? new GeometryTypeIndex<>(this) : new KeyIndex<>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,13 +308,13 @@ public record MultiExpression<T>(List<Entry<T>> expressions) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An expression/value pair with unique ID to store whether we evaluated it yet. */
|
/** An expression/value pair with unique ID to store whether we evaluated it yet. */
|
||||||
private record EntryWithId<T>(T result, Expression expression, int id) {}
|
private record EntryWithId<T> (T result, Expression expression, int id) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@code expression} to evaluate on input elements and {@code result} value to return when the element matches.
|
* An {@code expression} to evaluate on input elements and {@code result} value to return when the element matches.
|
||||||
*/
|
*/
|
||||||
public record Entry<T>(T result, Expression expression) {}
|
public record Entry<T> (T result, Expression expression) {}
|
||||||
|
|
||||||
/** The result when an expression matches, along with the input element tag {@code keys} that triggered the match. */
|
/** The result when an expression matches, along with the input element tag {@code keys} that triggered the match. */
|
||||||
public record Match<T>(T match, List<String> keys) {}
|
public record Match<T> (T match, List<String> keys) {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,8 @@ import org.locationtech.jts.geom.util.GeometryTransformer;
|
||||||
* A utility to simplify geometries using Douglas Peucker simplification algorithm without any attempt to repair
|
* A utility to simplify geometries using Douglas Peucker simplification algorithm without any attempt to repair
|
||||||
* geometries that become invalid due to simplification.
|
* geometries that become invalid due to simplification.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is adapted from <a href="https://github.com/locationtech/jts/blob/master/modules/core/src/main/java/org/locationtech/jts/simplify/DouglasPeuckerSimplifier.java">org.locationtech.jts.simplify.DouglasPeuckerSimplifier</a>
|
* This class is adapted from <a href=
|
||||||
|
* "https://github.com/locationtech/jts/blob/master/modules/core/src/main/java/org/locationtech/jts/simplify/DouglasPeuckerSimplifier.java">org.locationtech.jts.simplify.DouglasPeuckerSimplifier</a>
|
||||||
* with modifications to avoid collapsing small polygons since the subsequent area filter will remove them more
|
* with modifications to avoid collapsing small polygons since the subsequent area filter will remove them more
|
||||||
* accurately and performance improvement to put the results in a {@link MutableCoordinateSequence} which uses a
|
* accurately and performance improvement to put the results in a {@link MutableCoordinateSequence} which uses a
|
||||||
* primitive double array instead of allocating lots of {@link Coordinate} objects.
|
* primitive double array instead of allocating lots of {@link Coordinate} objects.
|
||||||
|
@ -148,4 +149,3 @@ public class DouglasPeuckerSimplifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,12 +90,13 @@ public class GeoUtils {
|
||||||
* right is (1,1).
|
* right is (1,1).
|
||||||
*/
|
*/
|
||||||
public static final Envelope WORLD_BOUNDS = new Envelope(0, 1, 0, 1);
|
public static final Envelope WORLD_BOUNDS = new Envelope(0, 1, 0, 1);
|
||||||
/** Bounds for the entire area of the planet that a web mercator projection covers in latitude/longitude coordinates. */
|
/**
|
||||||
|
* Bounds for the entire area of the planet that a web mercator projection covers in latitude/longitude coordinates.
|
||||||
|
*/
|
||||||
public static final Envelope WORLD_LAT_LON_BOUNDS = toLatLonBoundsBounds(WORLD_BOUNDS);
|
public static final Envelope WORLD_LAT_LON_BOUNDS = toLatLonBoundsBounds(WORLD_BOUNDS);
|
||||||
|
|
||||||
// should not instantiate
|
// should not instantiate
|
||||||
private GeoUtils() {
|
private GeoUtils() {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a copy of {@code geom} transformed from latitude/longitude coordinates to web mercator where top-left
|
* Returns a copy of {@code geom} transformed from latitude/longitude coordinates to web mercator where top-left
|
||||||
|
@ -191,16 +192,16 @@ public class GeoUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the web mercator Y coordinate of the latitude/longitude encoded with {@link #encodeFlatLocation(double,
|
* Returns the web mercator Y coordinate of the latitude/longitude encoded with
|
||||||
* double)}.
|
* {@link #encodeFlatLocation(double, double)}.
|
||||||
*/
|
*/
|
||||||
public static double decodeWorldY(long encoded) {
|
public static double decodeWorldY(long encoded) {
|
||||||
return (((double) (encoded & LOWER_32_BIT_MASK)) / HALF_QUANTIZED_WORLD_SIZE) - 1;
|
return (((double) (encoded & LOWER_32_BIT_MASK)) / HALF_QUANTIZED_WORLD_SIZE) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the web mercator X coordinate of the latitude/longitude encoded with {@link #encodeFlatLocation(double,
|
* Returns the web mercator X coordinate of the latitude/longitude encoded with
|
||||||
* double)}.
|
* {@link #encodeFlatLocation(double, double)}.
|
||||||
*/
|
*/
|
||||||
public static double decodeWorldX(long encoded) {
|
public static double decodeWorldX(long encoded) {
|
||||||
return (((double) (encoded >>> 32)) / HALF_QUANTIZED_WORLD_SIZE) - 1;
|
return (((double) (encoded >>> 32)) / HALF_QUANTIZED_WORLD_SIZE) - 1;
|
||||||
|
|
|
@ -21,10 +21,8 @@ public enum GeometryType {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GeometryType valueOf(Geometry geom) {
|
public static GeometryType valueOf(Geometry geom) {
|
||||||
return geom instanceof Puntal ? POINT
|
return geom instanceof Puntal ? POINT : geom instanceof Lineal ? LINE : geom instanceof Polygonal ? POLYGON :
|
||||||
: geom instanceof Lineal ? LINE
|
UNKNOWN;
|
||||||
: geom instanceof Polygonal ? POLYGON
|
|
||||||
: UNKNOWN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GeometryType valueOf(VectorTileProto.Tile.GeomType geomType) {
|
public static GeometryType valueOf(VectorTileProto.Tile.GeomType geomType) {
|
||||||
|
|
|
@ -21,12 +21,11 @@ import org.locationtech.jts.index.strtree.STRtree;
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
public class PointIndex<T> {
|
public class PointIndex<T> {
|
||||||
|
|
||||||
private record GeomWithData<T>(Coordinate coord, T data) {}
|
private record GeomWithData<T> (Coordinate coord, T data) {}
|
||||||
|
|
||||||
private final STRtree index = new STRtree();
|
private final STRtree index = new STRtree();
|
||||||
|
|
||||||
private PointIndex() {
|
private PointIndex() {}
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> PointIndex<T> create() {
|
public static <T> PointIndex<T> create() {
|
||||||
return new PointIndex<>();
|
return new PointIndex<>();
|
||||||
|
|
|
@ -19,12 +19,11 @@ import org.locationtech.jts.index.strtree.STRtree;
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
public class PolygonIndex<T> {
|
public class PolygonIndex<T> {
|
||||||
|
|
||||||
private record GeomWithData<T>(Polygon poly, T data) {}
|
private record GeomWithData<T> (Polygon poly, T data) {}
|
||||||
|
|
||||||
private final STRtree index = new STRtree();
|
private final STRtree index = new STRtree();
|
||||||
|
|
||||||
private PolygonIndex() {
|
private PolygonIndex() {}
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> PolygonIndex<T> create() {
|
public static <T> PolygonIndex<T> create() {
|
||||||
return new PolygonIndex<>();
|
return new PolygonIndex<>();
|
||||||
|
@ -78,7 +77,7 @@ public class PolygonIndex<T> {
|
||||||
List<?> items = index.query(point.getEnvelopeInternal());
|
List<?> items = index.query(point.getEnvelopeInternal());
|
||||||
// optimization: if there's only one then skip checking contains/distance
|
// optimization: if there's only one then skip checking contains/distance
|
||||||
if (items.size() == 1) {
|
if (items.size() == 1) {
|
||||||
if (items.get(0) instanceof GeomWithData<?> value) {
|
if (items.get(0)instanceof GeomWithData<?> value) {
|
||||||
@SuppressWarnings("unchecked") T t = (T) value.data;
|
@SuppressWarnings("unchecked") T t = (T) value.data;
|
||||||
return List.of(t);
|
return List.of(t);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,8 +38,7 @@ import org.sqlite.SQLiteConfig;
|
||||||
/**
|
/**
|
||||||
* Interface into an mbtiles sqlite file containing tiles and metadata about the tileset.
|
* Interface into an mbtiles sqlite file containing tiles and metadata about the tileset.
|
||||||
*
|
*
|
||||||
* @see <a href="https://github.com/mapbox/mbtiles-spec/blob/master/1.3/spec.md">MBTiles
|
* @see <a href="https://github.com/mapbox/mbtiles-spec/blob/master/1.3/spec.md">MBTiles Specification</a>
|
||||||
* Specification</a>
|
|
||||||
*/
|
*/
|
||||||
public final class Mbtiles implements Closeable {
|
public final class Mbtiles implements Closeable {
|
||||||
|
|
||||||
|
@ -157,8 +156,8 @@ public final class Mbtiles implements Closeable {
|
||||||
return execute(
|
return execute(
|
||||||
"create table " + METADATA_TABLE + " (" + METADATA_COL_NAME + " text, " + METADATA_COL_VALUE + " text);",
|
"create table " + METADATA_TABLE + " (" + METADATA_COL_NAME + " text, " + METADATA_COL_VALUE + " text);",
|
||||||
"create unique index name on " + METADATA_TABLE + " (" + METADATA_COL_NAME + ");",
|
"create unique index name on " + METADATA_TABLE + " (" + METADATA_COL_NAME + ");",
|
||||||
"create table " + TILES_TABLE + " (" + TILES_COL_Z + " integer, " + TILES_COL_X + " integer, " + TILES_COL_Y
|
"create table " + TILES_TABLE + " (" + TILES_COL_Z + " integer, " + TILES_COL_X + " integer, " + TILES_COL_Y +
|
||||||
+ ", " + TILES_COL_DATA + " blob);"
|
", " + TILES_COL_DATA + " blob);"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,11 +236,10 @@ public final class Mbtiles implements Closeable {
|
||||||
* Data contained in the {@code json} row of the metadata table
|
* Data contained in the {@code json} row of the metadata table
|
||||||
*
|
*
|
||||||
* @see <a href="https://github.com/mapbox/mbtiles-spec/blob/master/1.3/spec.md#vector-tileset-metadata">MBtiles
|
* @see <a href="https://github.com/mapbox/mbtiles-spec/blob/master/1.3/spec.md#vector-tileset-metadata">MBtiles
|
||||||
* schema</a>
|
* schema</a>
|
||||||
*/
|
*/
|
||||||
public record MetadataJson(
|
public record MetadataJson(
|
||||||
@JsonProperty("vector_layers")
|
@JsonProperty("vector_layers") List<VectorLayer> vectorLayers
|
||||||
List<VectorLayer> vectorLayers
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
public MetadataJson(VectorLayer... layers) {
|
public MetadataJson(VectorLayer... layers) {
|
||||||
|
@ -265,9 +263,12 @@ public final class Mbtiles implements Closeable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum FieldType {
|
public enum FieldType {
|
||||||
@JsonProperty("Number") NUMBER,
|
@JsonProperty("Number")
|
||||||
@JsonProperty("Boolean") BOOLEAN,
|
NUMBER,
|
||||||
@JsonProperty("String") STRING;
|
@JsonProperty("Boolean")
|
||||||
|
BOOLEAN,
|
||||||
|
@JsonProperty("String")
|
||||||
|
STRING;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Per the spec: attributes whose type varies between features SHOULD be listed as "String"
|
* Per the spec: attributes whose type varies between features SHOULD be listed as "String"
|
||||||
|
@ -352,7 +353,9 @@ public final class Mbtiles implements Closeable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A high-throughput writer that accepts new tiles and queues up the writes to execute them in fewer large-batches. */
|
/**
|
||||||
|
* A high-throughput writer that accepts new tiles and queues up the writes to execute them in fewer large-batches.
|
||||||
|
*/
|
||||||
public class BatchedTileWriter implements AutoCloseable {
|
public class BatchedTileWriter implements AutoCloseable {
|
||||||
|
|
||||||
// max number of parameters in a prepared statements is 999
|
// max number of parameters in a prepared statements is 999
|
||||||
|
@ -374,9 +377,8 @@ public final class Mbtiles implements Closeable {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return connection.prepareStatement(
|
return connection.prepareStatement(
|
||||||
"INSERT INTO " + TILES_TABLE + " (" + TILES_COL_Z + "," + TILES_COL_X + "," + TILES_COL_Y + ","
|
"INSERT INTO " + TILES_TABLE + " (" + TILES_COL_Z + "," + TILES_COL_X + "," + TILES_COL_Y + "," +
|
||||||
+ TILES_COL_DATA
|
TILES_COL_DATA + ") VALUES " + String.join(", ", groups) + ";");
|
||||||
+ ") VALUES " + String.join(", ", groups) + ";");
|
|
||||||
} catch (SQLException throwables) {
|
} catch (SQLException throwables) {
|
||||||
throw new IllegalStateException("Could not create prepared statement", throwables);
|
throw new IllegalStateException("Could not create prepared statement", throwables);
|
||||||
}
|
}
|
||||||
|
@ -443,8 +445,10 @@ public final class Mbtiles implements Closeable {
|
||||||
public Metadata setMetadata(String name, Object value) {
|
public Metadata setMetadata(String name, Object value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
LOGGER.debug("Set mbtiles metadata: " + name + "=" + value);
|
LOGGER.debug("Set mbtiles metadata: " + name + "=" + value);
|
||||||
try (PreparedStatement statement = connection.prepareStatement(
|
try (
|
||||||
"INSERT INTO " + METADATA_TABLE + " (" + METADATA_COL_NAME + "," + METADATA_COL_VALUE + ") VALUES(?, ?);")) {
|
PreparedStatement statement = connection.prepareStatement(
|
||||||
|
"INSERT INTO " + METADATA_TABLE + " (" + METADATA_COL_NAME + "," + METADATA_COL_VALUE + ") VALUES(?, ?);")
|
||||||
|
) {
|
||||||
statement.setString(1, name);
|
statement.setString(1, name);
|
||||||
statement.setString(2, value.toString());
|
statement.setString(2, value.toString());
|
||||||
statement.execute();
|
statement.execute();
|
||||||
|
|
|
@ -99,10 +99,10 @@ public class Verify {
|
||||||
/**
|
/**
|
||||||
* Returns a verification result of a basic set of checks on an mbtiles file:
|
* Returns a verification result of a basic set of checks on an mbtiles file:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>has a metadata and tiles table</li>
|
* <li>has a metadata and tiles table</li>
|
||||||
* <li>has a name metadata attribute</li>
|
* <li>has a name metadata attribute</li>
|
||||||
* <li>has at least one tile</li>
|
* <li>has at least one tile</li>
|
||||||
* <li>all vector tile geometries are valid</li>
|
* <li>all vector tile geometries are valid</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public static Verify verify(Mbtiles mbtiles) {
|
public static Verify verify(Mbtiles mbtiles) {
|
||||||
|
|
|
@ -29,8 +29,9 @@ import org.opengis.referencing.operation.MathTransform;
|
||||||
* <p>
|
* <p>
|
||||||
* Shapefile processing handled by geotools {@link ShapefileDataStore}.
|
* Shapefile processing handled by geotools {@link ShapefileDataStore}.
|
||||||
*
|
*
|
||||||
* @see <a href="https://www.esri.com/content/dam/esrisites/sitecore-archive/Files/Pdfs/library/whitepapers/pdfs/shapefile.pdf">ESRI
|
* @see <a href=
|
||||||
* Shapefile Specification</a>
|
* "https://www.esri.com/content/dam/esrisites/sitecore-archive/Files/Pdfs/library/whitepapers/pdfs/shapefile.pdf">ESRI
|
||||||
|
* Shapefile Specification</a>
|
||||||
*/
|
*/
|
||||||
public class ShapefileReader extends SimpleReader implements Closeable {
|
public class ShapefileReader extends SimpleReader implements Closeable {
|
||||||
|
|
||||||
|
@ -72,8 +73,8 @@ public class ShapefileReader extends SimpleReader implements Closeable {
|
||||||
* Renders map features for all elements from an ESRI Shapefile based on the mapping logic defined in {@code profile}.
|
* Renders map features for all elements from an ESRI Shapefile based on the mapping logic defined in {@code profile}.
|
||||||
* Overrides the coordinate reference system defined in the shapefile.
|
* Overrides the coordinate reference system defined in the shapefile.
|
||||||
*
|
*
|
||||||
* @param sourceProjection code for the coordinate reference system of the input data, to be parsed by {@link
|
* @param sourceProjection code for the coordinate reference system of the input data, to be parsed by
|
||||||
* CRS#decode(String)}
|
* {@link CRS#decode(String)}
|
||||||
* @param sourceName string ID for this reader to use in logs and stats
|
* @param sourceName string ID for this reader to use in logs and stats
|
||||||
* @param input path to the {@code .shp} file on disk, or a {@code .zip} file containing the shapefile
|
* @param input path to the {@code .shp} file on disk, or a {@code .zip} file containing the shapefile
|
||||||
* components
|
* components
|
||||||
|
@ -95,8 +96,7 @@ public class ShapefileReader extends SimpleReader implements Closeable {
|
||||||
* Infers the coordinate reference system from the shapefile.
|
* Infers the coordinate reference system from the shapefile.
|
||||||
*
|
*
|
||||||
* @param sourceName string ID for this reader to use in logs and stats
|
* @param sourceName string ID for this reader to use in logs and stats
|
||||||
* @param input path to the {@code .shp} file on disk, or a {@code .zip} file containing the shapefile
|
* @param input path to the {@code .shp} file on disk, or a {@code .zip} file containing the shapefile components
|
||||||
* components
|
|
||||||
* @param writer consumer for rendered features
|
* @param writer consumer for rendered features
|
||||||
* @param config user-defined parameters controlling number of threads and log interval
|
* @param config user-defined parameters controlling number of threads and log interval
|
||||||
* @param profile logic that defines what map features to emit for each source feature
|
* @param profile logic that defines what map features to emit for each source feature
|
||||||
|
|
|
@ -83,14 +83,14 @@ public class SimpleFeature extends SourceFeature {
|
||||||
return new SimpleFeature(latLonGeometry, null, tags, source, sourceLayer, id, relations) {
|
return new SimpleFeature(latLonGeometry, null, tags, source, sourceLayer, id, relations) {
|
||||||
@Override
|
@Override
|
||||||
public boolean canBePolygon() {
|
public boolean canBePolygon() {
|
||||||
return latLonGeometry instanceof Polygonal || (latLonGeometry instanceof LineString line
|
return latLonGeometry instanceof Polygonal || (latLonGeometry instanceof LineString line &&
|
||||||
&& OsmReader.canBePolygon(line.isClosed(), area, latLonGeometry.getNumPoints()));
|
OsmReader.canBePolygon(line.isClosed(), area, latLonGeometry.getNumPoints()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canBeLine() {
|
public boolean canBeLine() {
|
||||||
return latLonGeometry instanceof MultiLineString || (latLonGeometry instanceof LineString line
|
return latLonGeometry instanceof MultiLineString || (latLonGeometry instanceof LineString line &&
|
||||||
&& OsmReader.canBeLine(line.isClosed(), area, latLonGeometry.getNumPoints()));
|
OsmReader.canBeLine(line.isClosed(), area, latLonGeometry.getNumPoints()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -103,15 +103,14 @@ public class SimpleFeature extends SourceFeature {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Geometry latLonGeometry() {
|
public Geometry latLonGeometry() {
|
||||||
return latLonGeometry != null ? latLonGeometry
|
return latLonGeometry != null ? latLonGeometry : (latLonGeometry = GeoUtils.worldToLatLonCoords(worldGeometry));
|
||||||
: (latLonGeometry = GeoUtils.worldToLatLonCoords(worldGeometry));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Geometry worldGeometry() {
|
public Geometry worldGeometry() {
|
||||||
// we expect outer polygons to appear before inner ones, so process ones with larger areas first
|
// we expect outer polygons to appear before inner ones, so process ones with larger areas first
|
||||||
return worldGeometry != null ? worldGeometry
|
return worldGeometry != null ? worldGeometry :
|
||||||
: (worldGeometry = GeoUtils.sortPolygonsByAreaDescending(GeoUtils.latLonToWorldCoords(latLonGeometry)));
|
(worldGeometry = GeoUtils.sortPolygonsByAreaDescending(GeoUtils.latLonToWorldCoords(latLonGeometry)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -19,11 +19,11 @@ import org.locationtech.jts.geom.Polygon;
|
||||||
/**
|
/**
|
||||||
* Base class for input features read from a data source.
|
* Base class for input features read from a data source.
|
||||||
* <p>
|
* <p>
|
||||||
* Provides cached convenience methods with lazy initialization for geometric attributes derived from {@link
|
* Provides cached convenience methods with lazy initialization for geometric attributes derived from
|
||||||
* #latLonGeometry()} and {@link #worldGeometry()} to avoid computing them if not needed, and recomputing them if needed
|
* {@link #latLonGeometry()} and {@link #worldGeometry()} to avoid computing them if not needed, and recomputing them if
|
||||||
* by multiple features.
|
* needed by multiple features.
|
||||||
* <p>
|
* <p>
|
||||||
* All geometries except for {@link #latLonGeometry()} return elements in world web mercator coordinates where (0,0) is
|
* All geometries except for {@link #latLonGeometry()} return elements in world web mercator coordinates where (0,0) is
|
||||||
* the northwest corner and (1,1) is the southeast corner of the planet.
|
* the northwest corner and (1,1) is the southeast corner of the planet.
|
||||||
*/
|
*/
|
||||||
public abstract class SourceFeature implements WithTags {
|
public abstract class SourceFeature implements WithTags {
|
||||||
|
@ -46,7 +46,7 @@ public abstract class SourceFeature implements WithTags {
|
||||||
* Constructs a new input feature.
|
* Constructs a new input feature.
|
||||||
*
|
*
|
||||||
* @param tags string key/value pairs associated with this element
|
* @param tags string key/value pairs associated with this element
|
||||||
* @param source source name that profile can use to distinguish between elements from different data sources
|
* @param source source name that profile can use to distinguish between elements from different data sources
|
||||||
* @param sourceLayer layer name within {@code source} that profile can use to distinguish between different kinds
|
* @param sourceLayer layer name within {@code source} that profile can use to distinguish between different kinds
|
||||||
* of elements in a given source.
|
* of elements in a given source.
|
||||||
* @param relationInfos relations that this element is contained within
|
* @param relationInfos relations that this element is contained within
|
||||||
|
@ -116,7 +116,7 @@ public abstract class SourceFeature implements WithTags {
|
||||||
return centroid != null ? centroid : (centroid =
|
return centroid != null ? centroid : (centroid =
|
||||||
canBePolygon() ? polygon().getCentroid() :
|
canBePolygon() ? polygon().getCentroid() :
|
||||||
canBeLine() ? line().getCentroid() :
|
canBeLine() ? line().getCentroid() :
|
||||||
worldGeometry().getCentroid());
|
worldGeometry().getCentroid());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns and caches {@link Geometry#getInteriorPoint()} of this geometry in world web mercator coordinates. */
|
/** Returns and caches {@link Geometry#getInteriorPoint()} of this geometry in world web mercator coordinates. */
|
||||||
|
@ -124,13 +124,13 @@ public abstract class SourceFeature implements WithTags {
|
||||||
return pointOnSurface != null ? pointOnSurface : (pointOnSurface =
|
return pointOnSurface != null ? pointOnSurface : (pointOnSurface =
|
||||||
canBePolygon() ? polygon().getInteriorPoint() :
|
canBePolygon() ? polygon().getInteriorPoint() :
|
||||||
canBeLine() ? line().getInteriorPoint() :
|
canBeLine() ? line().getInteriorPoint() :
|
||||||
worldGeometry().getInteriorPoint());
|
worldGeometry().getInteriorPoint());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Geometry computeCentroidIfConvex() throws GeometryException {
|
private Geometry computeCentroidIfConvex() throws GeometryException {
|
||||||
if (!canBePolygon()) {
|
if (!canBePolygon()) {
|
||||||
return centroid();
|
return centroid();
|
||||||
} else if (polygon() instanceof Polygon poly &&
|
} else if (polygon()instanceof Polygon poly &&
|
||||||
poly.getNumInteriorRing() == 0 &&
|
poly.getNumInteriorRing() == 0 &&
|
||||||
GeoUtils.isConvex(poly.getExteriorRing())) {
|
GeoUtils.isConvex(poly.getExteriorRing())) {
|
||||||
return centroid();
|
return centroid();
|
||||||
|
@ -216,7 +216,7 @@ public abstract class SourceFeature implements WithTags {
|
||||||
/**
|
/**
|
||||||
* Returns this feature as a valid {@link Polygon} or {@link MultiPolygon} in world web mercator coordinates.
|
* Returns this feature as a valid {@link Polygon} or {@link MultiPolygon} in world web mercator coordinates.
|
||||||
* <p>
|
* <p>
|
||||||
* Validating and fixing invalid polygons can be expensive, so use only if necessary. Invalid polygons will also be
|
* Validating and fixing invalid polygons can be expensive, so use only if necessary. Invalid polygons will also be
|
||||||
* fixed at render-time.
|
* fixed at render-time.
|
||||||
*
|
*
|
||||||
* @throws GeometryException if an error occurs constructing the geometry, or of this feature should not be
|
* @throws GeometryException if an error occurs constructing the geometry, or of this feature should not be
|
||||||
|
@ -283,7 +283,7 @@ public abstract class SourceFeature implements WithTags {
|
||||||
* @param relationInfoClass class of the processed relation data
|
* @param relationInfoClass class of the processed relation data
|
||||||
* @param <T> type of {@code relationInfoClass}
|
* @param <T> type of {@code relationInfoClass}
|
||||||
* @return A list containing the OSM relation info along with the role that this element is tagged with in that
|
* @return A list containing the OSM relation info along with the role that this element is tagged with in that
|
||||||
* relation
|
* relation
|
||||||
*/
|
*/
|
||||||
// TODO this should be in a specialized OSM subclass, not the generic superclass
|
// TODO this should be in a specialized OSM subclass, not the generic superclass
|
||||||
public <T extends OsmRelationInfo> List<OsmReader.RelationMember<T>> relationInfo(
|
public <T extends OsmRelationInfo> List<OsmReader.RelationMember<T>> relationInfo(
|
||||||
|
@ -295,8 +295,7 @@ public abstract class SourceFeature implements WithTags {
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
result = new ArrayList<>();
|
result = new ArrayList<>();
|
||||||
}
|
}
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked") OsmReader.RelationMember<T> casted = (OsmReader.RelationMember<T>) info;
|
||||||
OsmReader.RelationMember<T> casted = (OsmReader.RelationMember<T>) info;
|
|
||||||
result.add(casted);
|
result.add(casted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,12 +13,11 @@ public interface OsmBlockSource extends Closeable {
|
||||||
void forEachBlock(Consumer<Block> consumer);
|
void forEachBlock(Consumer<Block> consumer);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default void close() {
|
default void close() {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An individual block of raw bytes from an osm.pbf file that can be decompressed/parsed with {@link
|
* An individual block of raw bytes from an osm.pbf file that can be decompressed/parsed with
|
||||||
* #decodeElements()}.
|
* {@link #decodeElements()}.
|
||||||
*/
|
*/
|
||||||
interface Block {
|
interface Block {
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,9 @@ public interface OsmElement extends WithTags {
|
||||||
int cost();
|
int cost();
|
||||||
|
|
||||||
enum Type {
|
enum Type {
|
||||||
NODE, WAY, RELATION
|
NODE,
|
||||||
|
WAY,
|
||||||
|
RELATION
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An un-handled element read from the .osm.pbf file (i.e. file header). */
|
/** An un-handled element read from the .osm.pbf file (i.e. file header). */
|
||||||
|
@ -165,7 +167,9 @@ public interface OsmElement extends WithTags {
|
||||||
return 1 + tags.size() + members.size() * 3;
|
return 1 + tags.size() + members.size() * 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A node, way, or relation contained in a relation with an optional "role" to clarify the purpose of each member. */
|
/**
|
||||||
|
* A node, way, or relation contained in a relation with an optional "role" to clarify the purpose of each member.
|
||||||
|
*/
|
||||||
public record Member(
|
public record Member(
|
||||||
Type type,
|
Type type,
|
||||||
long ref,
|
long ref,
|
||||||
|
|
|
@ -162,15 +162,15 @@ public class OsmReader implements Closeable, MemoryEstimator.HasEstimate {
|
||||||
node.encodedLocation();
|
node.encodedLocation();
|
||||||
if (nodesDone) {
|
if (nodesDone) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Input file must be sorted with nodes first, then ways, then relations. Encountered node " + node.id()
|
"Input file must be sorted with nodes first, then ways, then relations. Encountered node " + node.id() +
|
||||||
+ " after a way or relation");
|
" after a way or relation");
|
||||||
}
|
}
|
||||||
} else if (element instanceof OsmElement.Way way) {
|
} else if (element instanceof OsmElement.Way way) {
|
||||||
nodesDone = true;
|
nodesDone = true;
|
||||||
if (waysDone) {
|
if (waysDone) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Input file must be sorted with nodes first, then ways, then relations. Encountered way " + way.id()
|
"Input file must be sorted with nodes first, then ways, then relations. Encountered way " + way.id() +
|
||||||
+ " after a relation");
|
" after a relation");
|
||||||
}
|
}
|
||||||
} else if (element instanceof OsmElement.Relation) {
|
} else if (element instanceof OsmElement.Relation) {
|
||||||
nodesDone = waysDone = true;
|
nodesDone = waysDone = true;
|
||||||
|
@ -519,7 +519,7 @@ public class OsmReader implements Closeable, MemoryEstimator.HasEstimate {
|
||||||
* @param role "role" of the relation member
|
* @param role "role" of the relation member
|
||||||
* @param relation user-provided data about the relation from pass1
|
* @param relation user-provided data about the relation from pass1
|
||||||
*/
|
*/
|
||||||
public record RelationMember<T extends OsmRelationInfo>(String role, T relation) {}
|
public record RelationMember<T extends OsmRelationInfo> (String role, T relation) {}
|
||||||
|
|
||||||
/** Raw relation membership data that gets encoded/decoded into a long. */
|
/** Raw relation membership data that gets encoded/decoded into a long. */
|
||||||
private record RelationMembership(String role, long relationId) {}
|
private record RelationMembership(String role, long relationId) {}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import org.openstreetmap.osmosis.osmbinary.Osmformat;
|
||||||
* This class is copied from Osmosis.
|
* This class is copied from Osmosis.
|
||||||
*
|
*
|
||||||
* @author Brett Henderson
|
* @author Brett Henderson
|
||||||
* <p>
|
* <p>
|
||||||
*/
|
*/
|
||||||
public class PbfFieldDecoder {
|
public class PbfFieldDecoder {
|
||||||
|
|
||||||
|
|
|
@ -71,8 +71,8 @@ public class FeatureRenderer implements Consumer<FeatureCollector.Feature> {
|
||||||
renderPoint(feature, point.getCoordinates());
|
renderPoint(feature, point.getCoordinates());
|
||||||
} else if (geom instanceof MultiPoint points) {
|
} else if (geom instanceof MultiPoint points) {
|
||||||
renderPoint(feature, points);
|
renderPoint(feature, points);
|
||||||
} else if (geom instanceof Polygon || geom instanceof MultiPolygon || geom instanceof LineString
|
} else if (geom instanceof Polygon || geom instanceof MultiPolygon || geom instanceof LineString ||
|
||||||
|| geom instanceof MultiLineString) {
|
geom instanceof MultiLineString) {
|
||||||
renderLineOrPolygon(feature, geom);
|
renderLineOrPolygon(feature, geom);
|
||||||
} else if (geom instanceof GeometryCollection collection) {
|
} else if (geom instanceof GeometryCollection collection) {
|
||||||
for (int i = 0; i < collection.getNumGeometries(); i++) {
|
for (int i = 0; i < collection.getNumGeometries(); i++) {
|
||||||
|
|
|
@ -22,9 +22,9 @@ import org.locationtech.jts.geom.Polygon;
|
||||||
* <p>
|
* <p>
|
||||||
* The {@code List<List<CoordinateSequence>>} format is:
|
* The {@code List<List<CoordinateSequence>>} format is:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>For linestrings: {@code [[linestring], [linestring], ...]}</li> for each linestring in the collection
|
* <li>For linestrings: {@code [[linestring], [linestring], ...]}</li> for each linestring in the collection
|
||||||
* <li>For polygons: {@code [[outer ring, inner ring, inner ring], [outer ring, inner ring, ...], ...]}</li> for each
|
* <li>For polygons: {@code [[outer ring, inner ring, inner ring], [outer ring, inner ring, ...], ...]}</li> for each
|
||||||
* polygon in the multipolygon
|
* polygon in the multipolygon
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
class GeometryCoordinateSequences {
|
class GeometryCoordinateSequences {
|
||||||
|
@ -36,14 +36,13 @@ class GeometryCoordinateSequences {
|
||||||
* For {@link LineString LineStrings} that means all linestrings over a certain length.
|
* For {@link LineString LineStrings} that means all linestrings over a certain length.
|
||||||
* <p>
|
* <p>
|
||||||
* For {@link Polygon Polygons} that means all lists of [exterior, interior...] ring coordinate sequences where the
|
* For {@link Polygon Polygons} that means all lists of [exterior, interior...] ring coordinate sequences where the
|
||||||
* ring is over a certain area. This utility also ensures that exterior and interior rings use counter-clockwise
|
* ring is over a certain area. This utility also ensures that exterior and interior rings use counter-clockwise
|
||||||
* winding.
|
* winding.
|
||||||
*
|
*
|
||||||
* @param geom one or more linestings or polygons
|
* @param geom one or more linestings or polygons
|
||||||
* @param minSize minimum length of linestrings, or minimum area of exterior/interior rings to include
|
* @param minSize minimum length of linestrings, or minimum area of exterior/interior rings to include
|
||||||
* @return the coordinate sequences of the geometry
|
* @return the coordinate sequences of the geometry
|
||||||
* @throws IllegalArgumentException if {@code geom} contains anything other than linestrings or polygons (i.e.
|
* @throws IllegalArgumentException if {@code geom} contains anything other than linestrings or polygons (i.e. points)
|
||||||
* points)
|
|
||||||
*/
|
*/
|
||||||
static List<List<CoordinateSequence>> extractGroups(Geometry geom, double minSize) {
|
static List<List<CoordinateSequence>> extractGroups(Geometry geom, double minSize) {
|
||||||
List<List<CoordinateSequence>> result = new ArrayList<>();
|
List<List<CoordinateSequence>> result = new ArrayList<>();
|
||||||
|
|
|
@ -200,7 +200,9 @@ class TiledGeometry {
|
||||||
out.addPoint(x, ay + (by - ay) * t);
|
out.addPoint(x, ay + (by - ay) * t);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Adds a new point to {@code out} where the line segment from (ax,ay) to (bx,by) crosses a horizontal line at y=y. */
|
/**
|
||||||
|
* Adds a new point to {@code out} where the line segment from (ax,ay) to (bx,by) crosses a horizontal line at y=y.
|
||||||
|
*/
|
||||||
private static void intersectY(MutableCoordinateSequence out, double ax, double ay, double bx, double by, double y) {
|
private static void intersectY(MutableCoordinateSequence out, double ax, double ay, double bx, double by, double y) {
|
||||||
double t = (y - ay) / (by - ay);
|
double t = (y - ay) / (by - ay);
|
||||||
out.addPoint(ax + (bx - ax) * t, y);
|
out.addPoint(ax + (bx - ax) * t, y);
|
||||||
|
@ -221,15 +223,15 @@ class TiledGeometry {
|
||||||
/**
|
/**
|
||||||
* Slices a geometry into tiles and stores in member fields for a single "copy" of the world.
|
* Slices a geometry into tiles and stores in member fields for a single "copy" of the world.
|
||||||
* <p>
|
* <p>
|
||||||
* Instead of handling content outside -180 to 180 degrees longitude, return {@link Direction#LEFT} or {@link
|
* Instead of handling content outside -180 to 180 degrees longitude, return {@link Direction#LEFT} or
|
||||||
* Direction#RIGHT} to indicate whether this method should be called again with a different {@code xOffset} to process
|
* {@link Direction#RIGHT} to indicate whether this method should be called again with a different {@code xOffset} to
|
||||||
* wrapped content.
|
* process wrapped content.
|
||||||
*
|
*
|
||||||
* @param groups the geometry
|
* @param groups the geometry
|
||||||
* @param xOffset offset to apply to each X coordinate (-2^z handles content that wraps too far east and 2^z handles
|
* @param xOffset offset to apply to each X coordinate (-2^z handles content that wraps too far east and 2^z handles
|
||||||
* content that wraps too far west)
|
* content that wraps too far west)
|
||||||
* @return {@link Direction#LEFT} if there is more content to the west and {@link Direction#RIGHT} if there is more
|
* @return {@link Direction#LEFT} if there is more content to the west and {@link Direction#RIGHT} if there is more
|
||||||
* content to the east.
|
* content to the east.
|
||||||
*/
|
*/
|
||||||
private EnumSet<Direction> sliceWorldCopy(List<List<CoordinateSequence>> groups, int xOffset) {
|
private EnumSet<Direction> sliceWorldCopy(List<List<CoordinateSequence>> groups, int xOffset) {
|
||||||
EnumSet<Direction> overflow = EnumSet.noneOf(Direction.class);
|
EnumSet<Direction> overflow = EnumSet.noneOf(Direction.class);
|
||||||
|
@ -603,5 +605,8 @@ class TiledGeometry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum Direction {RIGHT, LEFT}
|
private enum Direction {
|
||||||
|
RIGHT,
|
||||||
|
LEFT
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,8 +51,7 @@ public interface Counter {
|
||||||
*/
|
*/
|
||||||
class SingleThreadCounter implements Readable {
|
class SingleThreadCounter implements Readable {
|
||||||
|
|
||||||
private SingleThreadCounter() {
|
private SingleThreadCounter() {}
|
||||||
}
|
|
||||||
|
|
||||||
private final AtomicLong counter = new AtomicLong(0);
|
private final AtomicLong counter = new AtomicLong(0);
|
||||||
|
|
||||||
|
@ -75,8 +74,7 @@ public interface Counter {
|
||||||
*/
|
*/
|
||||||
class MultiThreadCounter implements Readable {
|
class MultiThreadCounter implements Readable {
|
||||||
|
|
||||||
private MultiThreadCounter() {
|
private MultiThreadCounter() {}
|
||||||
}
|
|
||||||
|
|
||||||
// keep track of all counters that have been handed out to threads so far
|
// keep track of all counters that have been handed out to threads so far
|
||||||
// and on read, add up the counts from each
|
// and on read, add up the counts from each
|
||||||
|
|
|
@ -37,7 +37,7 @@ public class ProcessInfo {
|
||||||
for (GarbageCollectorMXBean garbageCollectorMXBean : ManagementFactory.getGarbageCollectorMXBeans()) {
|
for (GarbageCollectorMXBean garbageCollectorMXBean : ManagementFactory.getGarbageCollectorMXBeans()) {
|
||||||
if (garbageCollectorMXBean instanceof NotificationEmitter emitter) {
|
if (garbageCollectorMXBean instanceof NotificationEmitter emitter) {
|
||||||
emitter.addNotificationListener((notification, handback) -> {
|
emitter.addNotificationListener((notification, handback) -> {
|
||||||
if (notification.getUserData() instanceof CompositeData compositeData) {
|
if (notification.getUserData()instanceof CompositeData compositeData) {
|
||||||
var info = GarbageCollectionNotificationInfo.from(compositeData);
|
var info = GarbageCollectionNotificationInfo.from(compositeData);
|
||||||
GcInfo gcInfo = info.getGcInfo();
|
GcInfo gcInfo = info.getGcInfo();
|
||||||
postGcMemoryUsage.set(gcInfo.getMemoryUsageAfterGc().entrySet().stream()
|
postGcMemoryUsage.set(gcInfo.getMemoryUsageAfterGc().entrySet().stream()
|
||||||
|
|
|
@ -9,12 +9,15 @@ import java.util.Optional;
|
||||||
* A utility for measuring the wall and CPU time that this JVM consumes between snapshots.
|
* A utility for measuring the wall and CPU time that this JVM consumes between snapshots.
|
||||||
* <p>
|
* <p>
|
||||||
* For example:
|
* For example:
|
||||||
* <pre>{@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {@code
|
||||||
* var start = ProcessTime.now();
|
* var start = ProcessTime.now();
|
||||||
* // do expensive work...
|
* // do expensive work...
|
||||||
* var end - ProcessTime.now();
|
* var end - ProcessTime.now();
|
||||||
* LOGGER.log("Expensive work took " + end.minus(start));
|
* LOGGER.log("Expensive work took " + end.minus(start));
|
||||||
* }</pre>
|
* }
|
||||||
|
* </pre>
|
||||||
*/
|
*/
|
||||||
public record ProcessTime(Duration wall, Optional<Duration> cpu, Duration gc) {
|
public record ProcessTime(Duration wall, Optional<Duration> cpu, Duration gc) {
|
||||||
|
|
||||||
|
|
|
@ -166,8 +166,8 @@ public class ProgressLoggers {
|
||||||
last.set(valueNow);
|
last.set(valueNow);
|
||||||
lastTime.set(now);
|
lastTime.set(now);
|
||||||
String result =
|
String result =
|
||||||
"[ " + formatter.apply(valueNow) + " " + padLeft(format.percent(1f * valueNow / total), 4)
|
"[ " + formatter.apply(valueNow) + " " + padLeft(format.percent(1f * valueNow / total), 4) + " " +
|
||||||
+ " " + formatter.apply(valueDiff / timeDiff) + "/s ]";
|
formatter.apply(valueDiff / timeDiff) + "/s ]";
|
||||||
return (color && valueDiff > 0) ? green(result) : result;
|
return (color && valueDiff > 0) ? green(result) : result;
|
||||||
}));
|
}));
|
||||||
return this;
|
return this;
|
||||||
|
@ -188,12 +188,9 @@ public class ProgressLoggers {
|
||||||
|
|
||||||
/** Adds the current number of items in a queue and the queue's size to the output. */
|
/** Adds the current number of items in a queue and the queue's size to the output. */
|
||||||
public ProgressLoggers addQueueStats(WorkQueue<?> queue) {
|
public ProgressLoggers addQueueStats(WorkQueue<?> queue) {
|
||||||
loggers.add(new WorkerPipelineLogger(() ->
|
loggers.add(new WorkerPipelineLogger(() -> " -> " + padLeft("(" +
|
||||||
" -> " + padLeft("(" +
|
format.numeric(queue.getPending(), false) + "/" +
|
||||||
format.numeric(queue.getPending(), false)
|
format.numeric(queue.getCapacity(), false) + ")", 9)
|
||||||
+ "/" +
|
|
||||||
format.numeric(queue.getCapacity(), false)
|
|
||||||
+ ")", 9)
|
|
||||||
));
|
));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -271,8 +271,8 @@ class PrometheusStats implements Stats {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reports stats on all in-memory objects sizes being monitored through {@link #monitorInMemoryObject(String,
|
* Reports stats on all in-memory objects sizes being monitored through
|
||||||
* MemoryEstimator.HasEstimate)}.
|
* {@link #monitorInMemoryObject(String, MemoryEstimator.HasEstimate)}.
|
||||||
*/
|
*/
|
||||||
private class HeapObjectSizeCollector extends Collector {
|
private class HeapObjectSizeCollector extends Collector {
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,9 @@ import org.slf4j.LoggerFactory;
|
||||||
/**
|
/**
|
||||||
* A utility that collects and reports more detailed statistics about the JVM and running tasks than logs can convey.
|
* A utility that collects and reports more detailed statistics about the JVM and running tasks than logs can convey.
|
||||||
* <p>
|
* <p>
|
||||||
* {@link #inMemory()} stores basic stats in-memory to report at the end of the job and {@link
|
* {@link #inMemory()} stores basic stats in-memory to report at the end of the job and
|
||||||
* #prometheusPushGateway(String, String, Duration)} pushes stats at a regular interval to a <a
|
* {@link #prometheusPushGateway(String, String, Duration)} pushes stats at a regular interval to a
|
||||||
* href="https://github.com/prometheus/pushgateway">prometheus push gateway</a>.
|
* <a href="https://github.com/prometheus/pushgateway">prometheus push gateway</a>.
|
||||||
*/
|
*/
|
||||||
public interface Stats extends AutoCloseable {
|
public interface Stats extends AutoCloseable {
|
||||||
|
|
||||||
|
@ -29,8 +29,8 @@ public interface Stats extends AutoCloseable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new stat collector pushes stats at a regular interval to a <a href="https://github.com/prometheus/pushgateway">prometheus
|
* Returns a new stat collector pushes stats at a regular interval to a
|
||||||
* push gateway</a> at {@code destination}.
|
* <a href="https://github.com/prometheus/pushgateway">prometheus push gateway</a> at {@code destination}.
|
||||||
*/
|
*/
|
||||||
static Stats prometheusPushGateway(String destination, String job, Duration interval) {
|
static Stats prometheusPushGateway(String destination, String job, Duration interval) {
|
||||||
return PrometheusStats.createAndStartPushing(destination, job, interval);
|
return PrometheusStats.createAndStartPushing(destination, job, interval);
|
||||||
|
@ -43,7 +43,7 @@ public interface Stats extends AutoCloseable {
|
||||||
default void printSummary() {
|
default void printSummary() {
|
||||||
Format format = Format.defaultInstance();
|
Format format = Format.defaultInstance();
|
||||||
Logger LOGGER = LoggerFactory.getLogger(getClass());
|
Logger LOGGER = LoggerFactory.getLogger(getClass());
|
||||||
System.out.println();
|
LOGGER.info("");
|
||||||
LOGGER.info("-".repeat(40));
|
LOGGER.info("-".repeat(40));
|
||||||
timers().printSummary();
|
timers().printSummary();
|
||||||
LOGGER.info("-".repeat(40));
|
LOGGER.info("-".repeat(40));
|
||||||
|
@ -145,15 +145,13 @@ public interface Stats extends AutoCloseable {
|
||||||
class InMemory implements Stats {
|
class InMemory implements Stats {
|
||||||
|
|
||||||
/** use {@link #inMemory()} */
|
/** use {@link #inMemory()} */
|
||||||
private InMemory() {
|
private InMemory() {}
|
||||||
}
|
|
||||||
|
|
||||||
private final Timers timers = new Timers();
|
private final Timers timers = new Timers();
|
||||||
private final Map<String, Path> monitoredFiles = new ConcurrentSkipListMap<>();
|
private final Map<String, Path> monitoredFiles = new ConcurrentSkipListMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void wroteTile(int zoom, int bytes) {
|
public void wroteTile(int zoom, int bytes) {}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Timers timers() {
|
public Timers timers() {
|
||||||
|
@ -166,12 +164,10 @@ public interface Stats extends AutoCloseable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void monitorInMemoryObject(String name, MemoryEstimator.HasEstimate object) {
|
public void monitorInMemoryObject(String name, MemoryEstimator.HasEstimate object) {}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void counter(String name, Supplier<Number> supplier) {
|
public void counter(String name, Supplier<Number> supplier) {}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Counter.MultiThreadCounter longCounter(String name) {
|
public Counter.MultiThreadCounter longCounter(String name) {
|
||||||
|
@ -184,24 +180,19 @@ public interface Stats extends AutoCloseable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void counter(String name, String label, Supplier<Map<String, Counter.Readable>> values) {
|
public void counter(String name, String label, Supplier<Map<String, Counter.Readable>> values) {}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processedElement(String elemType, String layer) {
|
public void processedElement(String elemType, String layer) {}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dataError(String errorCode) {
|
public void dataError(String errorCode) {}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void gauge(String name, Supplier<Number> value) {
|
public void gauge(String name, Supplier<Number> value) {}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void emittedFeatures(int z, String layer, int numFeatures) {
|
public void emittedFeatures(int z, String layer, int numFeatures) {}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
|
|
|
@ -95,7 +95,7 @@ public class Timers {
|
||||||
Stage stage = new Stage(timer);
|
Stage stage = new Stage(timer);
|
||||||
timers.put(name, stage);
|
timers.put(name, stage);
|
||||||
Stage last = currentStage.getAndSet(stage);
|
Stage last = currentStage.getAndSet(stage);
|
||||||
System.out.println();
|
LOGGER.info("");
|
||||||
LOGGER.info("Starting...");
|
LOGGER.info("Starting...");
|
||||||
return () -> {
|
return () -> {
|
||||||
LOGGER.info("Finished in " + timers.get(name).timer.stop());
|
LOGGER.info("Finished in " + timers.get(name).timer.stop());
|
||||||
|
|
|
@ -77,13 +77,11 @@ public class AwsOsm {
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
record IndexXml(
|
record IndexXml(
|
||||||
@JacksonXmlProperty(localName = "Contents")
|
@JacksonXmlProperty(localName = "Contents")
|
||||||
@JacksonXmlElementWrapper(useWrapping = false)
|
@JacksonXmlElementWrapper(useWrapping = false) List<ContentXml> contents
|
||||||
List<ContentXml> contents
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
record ContentXml(
|
record ContentXml(
|
||||||
@JacksonXmlProperty(localName = "Key")
|
@JacksonXmlProperty(localName = "Key") String key
|
||||||
String key
|
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,20 +46,23 @@ import org.slf4j.LoggerFactory;
|
||||||
* changes.
|
* changes.
|
||||||
* <p>
|
* <p>
|
||||||
* For example:
|
* For example:
|
||||||
* <pre>{@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {@code
|
||||||
* Downloader.create(PlanetilerConfig.defaults())
|
* Downloader.create(PlanetilerConfig.defaults())
|
||||||
* .add("natural_earth", "http://url/of/natural_earth.zip", Path.of("natural_earth.zip"))
|
* .add("natural_earth", "http://url/of/natural_earth.zip", Path.of("natural_earth.zip"))
|
||||||
* .add("osm", "http://url/of/file.osm.pbf", Path.of("file.osm.pbf"))
|
* .add("osm", "http://url/of/file.osm.pbf", Path.of("file.osm.pbf"))
|
||||||
* .run();
|
* .run();
|
||||||
* }</pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* As a shortcut to find the URL of a file to download from the <a href="https://download.geofabrik.de/">Geofabrik
|
* As a shortcut to find the URL of a file to download from the <a href="https://download.geofabrik.de/">Geofabrik
|
||||||
* download site</a>, you can use "geofabrik:extract name" (i.e. "geofabrik:monaco" or "geofabrik:australia") to look up
|
* download site</a>, you can use "geofabrik:extract name" (i.e. "geofabrik:monaco" or "geofabrik:australia") to look up
|
||||||
* a {@code .osm.pbf} download URL in the <a href="https://download.geofabrik.de/technical.html">Geofabrik JSON
|
* a {@code .osm.pbf} download URL in the <a href="https://download.geofabrik.de/technical.html">Geofabrik JSON
|
||||||
* index</a>.
|
* index</a>.
|
||||||
* <p>
|
* <p>
|
||||||
* You can also use "aws:latest" to download the latest {@code planet.osm.pbf} file from the <a
|
* You can also use "aws:latest" to download the latest {@code planet.osm.pbf} file from the
|
||||||
* href="https://registry.opendata.aws/osm/">AWS Open Data Registry</a>.
|
* <a href="https://registry.opendata.aws/osm/">AWS Open Data Registry</a>.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("UnusedReturnValue")
|
@SuppressWarnings("UnusedReturnValue")
|
||||||
public class Downloader {
|
public class Downloader {
|
||||||
|
@ -198,9 +201,8 @@ public class Downloader {
|
||||||
LOGGER.info("Skipping " + resourceToDownload.id + ": " + resourceToDownload.output + " already up-to-date");
|
LOGGER.info("Skipping " + resourceToDownload.id + ": " + resourceToDownload.output + " already up-to-date");
|
||||||
return CompletableFuture.completedFuture(null);
|
return CompletableFuture.completedFuture(null);
|
||||||
} else {
|
} else {
|
||||||
String redirectInfo = metadata.canonicalUrl.equals(resourceToDownload.url)
|
String redirectInfo = metadata.canonicalUrl.equals(resourceToDownload.url) ? "" :
|
||||||
? ""
|
" (redirected to " + metadata.canonicalUrl + ")";
|
||||||
: " (redirected to " + metadata.canonicalUrl + ")";
|
|
||||||
LOGGER.info("Downloading " + resourceToDownload.url + redirectInfo + " to " + resourceToDownload.output);
|
LOGGER.info("Downloading " + resourceToDownload.url + redirectInfo + " to " + resourceToDownload.output);
|
||||||
FileUtils.delete(resourceToDownload.output);
|
FileUtils.delete(resourceToDownload.output);
|
||||||
FileUtils.createParentDirectories(resourceToDownload.output);
|
FileUtils.createParentDirectories(resourceToDownload.output);
|
||||||
|
@ -237,8 +239,8 @@ public class Downloader {
|
||||||
if (totalPendingBytes > availableBytes) {
|
if (totalPendingBytes > availableBytes) {
|
||||||
var format = Format.defaultInstance();
|
var format = Format.defaultInstance();
|
||||||
String warning =
|
String warning =
|
||||||
"Attempting to download " + format.storage(totalPendingBytes) + " to " + fs + " which only has "
|
"Attempting to download " + format.storage(totalPendingBytes) + " to " + fs + " which only has " +
|
||||||
+ format.storage(availableBytes) + " available";
|
format.storage(availableBytes) + " available";
|
||||||
if (config.force()) {
|
if (config.force()) {
|
||||||
LOGGER.warn(warning + ", will probably fail.");
|
LOGGER.warn(warning + ", will probably fail.");
|
||||||
} else {
|
} else {
|
||||||
|
@ -254,9 +256,8 @@ public class Downloader {
|
||||||
if (redirects > MAX_REDIRECTS) {
|
if (redirects > MAX_REDIRECTS) {
|
||||||
throw new IllegalStateException("Exceeded " + redirects + " redirects for " + url);
|
throw new IllegalStateException("Exceeded " + redirects + " redirects for " + url);
|
||||||
}
|
}
|
||||||
return httpHead(url).thenComposeAsync(response -> response.redirect.isPresent()
|
return httpHead(url).thenComposeAsync(response -> response.redirect.isPresent() ?
|
||||||
? httpHeadFollowRedirects(response.redirect.get(), redirects + 1)
|
httpHeadFollowRedirects(response.redirect.get(), redirects + 1) : CompletableFuture.completedFuture(response));
|
||||||
: CompletableFuture.completedFuture(response));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CompletableFuture<ResourceMetadata> httpHead(String url) {
|
CompletableFuture<ResourceMetadata> httpHead(String url) {
|
||||||
|
@ -280,7 +281,8 @@ public class Downloader {
|
||||||
boolean supportsRangeRequest = headers.allValues(ACCEPT_RANGES).contains("bytes");
|
boolean supportsRangeRequest = headers.allValues(ACCEPT_RANGES).contains("bytes");
|
||||||
ResourceMetadata metadata = new ResourceMetadata(location, url, contentLength, supportsRangeRequest);
|
ResourceMetadata metadata = new ResourceMetadata(location, url, contentLength, supportsRangeRequest);
|
||||||
return HttpResponse.BodyHandlers.replacing(metadata).apply(responseInfo);
|
return HttpResponse.BodyHandlers.replacing(metadata).apply(responseInfo);
|
||||||
}).thenApply(HttpResponse::body);
|
})
|
||||||
|
.thenApply(HttpResponse::body);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompletableFuture<?> httpDownload(ResourceToDownload resource, Path tmpPath) {
|
private CompletableFuture<?> httpDownload(ResourceToDownload resource, Path tmpPath) {
|
||||||
|
@ -320,9 +322,8 @@ public class Downloader {
|
||||||
try (var fileChannel = FileChannel.open(tmpPath, WRITE)) {
|
try (var fileChannel = FileChannel.open(tmpPath, WRITE)) {
|
||||||
while (range.size() > 0) {
|
while (range.size() > 0) {
|
||||||
try (
|
try (
|
||||||
var inputStream = (ranges || range.start > 0)
|
var inputStream = (ranges || range.start > 0) ? openStreamRange(canonicalUrl, range.start, range.end) :
|
||||||
? openStreamRange(canonicalUrl, range.start, range.end)
|
openStream(canonicalUrl);
|
||||||
: openStream(canonicalUrl);
|
|
||||||
var input = new ProgressChannel(Channels.newChannel(inputStream), resource.progress)
|
var input = new ProgressChannel(Channels.newChannel(inputStream), resource.progress)
|
||||||
) {
|
) {
|
||||||
// ensure this file has been allocated up to the start of this block
|
// ensure this file has been allocated up to the start of this block
|
||||||
|
@ -333,8 +334,8 @@ public class Downloader {
|
||||||
throw new IOException("Transferred 0 bytes but " + range.size() + " expected: " + canonicalUrl);
|
throw new IOException("Transferred 0 bytes but " + range.size() + " expected: " + canonicalUrl);
|
||||||
} else if (transferred != range.size() && !metadata.acceptRange) {
|
} else if (transferred != range.size() && !metadata.acceptRange) {
|
||||||
throw new IOException(
|
throw new IOException(
|
||||||
"Transferred " + transferred + " bytes but " + range.size() + " expected: " + canonicalUrl
|
"Transferred " + transferred + " bytes but " + range.size() + " expected: " + canonicalUrl +
|
||||||
+ " and server does not support range requests");
|
" and server does not support range requests");
|
||||||
}
|
}
|
||||||
range = new Range(range.start + transferred, range.end);
|
range = new Range(range.start + transferred, range.end);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,7 @@ public class FileUtils {
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(FileUtils.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(FileUtils.class);
|
||||||
|
|
||||||
private FileUtils() {
|
private FileUtils() {}
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns a stream that lists all files in {@code fileSystem}. */
|
/** Returns a stream that lists all files in {@code fileSystem}. */
|
||||||
public static Stream<Path> walkFileSystem(FileSystem fileSystem) {
|
public static Stream<Path> walkFileSystem(FileSystem fileSystem) {
|
||||||
|
|
|
@ -31,7 +31,7 @@ public class Geofabrik {
|
||||||
* Fetches the Geofabrik index and searches for a {@code .osm.pbf} resource to download where ID or name field
|
* Fetches the Geofabrik index and searches for a {@code .osm.pbf} resource to download where ID or name field
|
||||||
* contains all the tokens in {@code searchQuery}.
|
* contains all the tokens in {@code searchQuery}.
|
||||||
* <p>
|
* <p>
|
||||||
* If an exact match is found, returns that. Otherwise, looks for a resource that contains {@code searchQuery} as a
|
* If an exact match is found, returns that. Otherwise, looks for a resource that contains {@code searchQuery} as a
|
||||||
* substring.
|
* substring.
|
||||||
* <p>
|
* <p>
|
||||||
* The index is only fetched once and cached after that.
|
* The index is only fetched once and cached after that.
|
||||||
|
@ -48,8 +48,10 @@ public class Geofabrik {
|
||||||
|
|
||||||
private synchronized static IndexJson getAndCacheIndex(PlanetilerConfig config) {
|
private synchronized static IndexJson getAndCacheIndex(PlanetilerConfig config) {
|
||||||
if (index == null) {
|
if (index == null) {
|
||||||
try (InputStream inputStream = Downloader.openStream("https://download.geofabrik.de/index-v1-nogeom.json",
|
try (
|
||||||
config)) {
|
InputStream inputStream = Downloader.openStream("https://download.geofabrik.de/index-v1-nogeom.json",
|
||||||
|
config)
|
||||||
|
) {
|
||||||
index = parseIndexJson(inputStream);
|
index = parseIndexJson(inputStream);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IllegalStateException(e);
|
throw new IllegalStateException(e);
|
||||||
|
|
|
@ -19,12 +19,12 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse utilities ported to Java from <a href="https://github.com/omniscale/imposm3/blob/master/mapping/columns.go">omniscale/imposm3:mapping/columns.go</a>
|
* Parse utilities ported to Java from <a href=
|
||||||
|
* "https://github.com/omniscale/imposm3/blob/master/mapping/columns.go">omniscale/imposm3:mapping/columns.go</a>
|
||||||
*/
|
*/
|
||||||
public class Imposm3Parsers {
|
public class Imposm3Parsers {
|
||||||
|
|
||||||
private Imposm3Parsers() {
|
private Imposm3Parsers() {}
|
||||||
}
|
|
||||||
|
|
||||||
private static String string(Object object) {
|
private static String string(Object object) {
|
||||||
return object == null ? null : object.toString();
|
return object == null ? null : object.toString();
|
||||||
|
|
|
@ -8,8 +8,7 @@ import org.slf4j.MDC;
|
||||||
*/
|
*/
|
||||||
public class LogUtil {
|
public class LogUtil {
|
||||||
|
|
||||||
private LogUtil() {
|
private LogUtil() {}
|
||||||
}
|
|
||||||
|
|
||||||
private static final String STAGE_KEY = "stage";
|
private static final String STAGE_KEY = "stage";
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,7 @@ import java.util.regex.Pattern;
|
||||||
*/
|
*/
|
||||||
public class Parse {
|
public class Parse {
|
||||||
|
|
||||||
private Parse() {
|
private Parse() {}
|
||||||
}
|
|
||||||
|
|
||||||
private static final Pattern INT_SUBSTRING_PATTERN = Pattern.compile("^(-?\\d+)(\\D|$)");
|
private static final Pattern INT_SUBSTRING_PATTERN = Pattern.compile("^(-?\\d+)(\\D|$)");
|
||||||
private static final Pattern TO_ROUND_INT_SUBSTRING_PATTERN = Pattern.compile("^(-?[\\d.]+)(\\D|$)");
|
private static final Pattern TO_ROUND_INT_SUBSTRING_PATTERN = Pattern.compile("^(-?[\\d.]+)(\\D|$)");
|
||||||
|
|
|
@ -8,20 +8,24 @@ import com.onthegomap.planetiler.collection.FeatureGroup;
|
||||||
* ordering approximates the desired ordering.
|
* ordering approximates the desired ordering.
|
||||||
* <p>
|
* <p>
|
||||||
* Sort keys get packed into {@link FeatureGroup#SORT_KEY_BITS} bits, so sort key components need to specify the range
|
* Sort keys get packed into {@link FeatureGroup#SORT_KEY_BITS} bits, so sort key components need to specify the range
|
||||||
* and number of levels the range gets packed into. Requests that exceed the total number of available levels will
|
* and number of levels the range gets packed into. Requests that exceed the total number of available levels will fail.
|
||||||
* fail.
|
|
||||||
* <p>
|
* <p>
|
||||||
* To sort by a field descending, specify its range from high to low.
|
* To sort by a field descending, specify its range from high to low.
|
||||||
* <p>
|
* <p>
|
||||||
* For example this SQL ordering:
|
* For example this SQL ordering:
|
||||||
* <pre>{@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {@code
|
||||||
* ORDER BY rank ASC,
|
* ORDER BY rank ASC,
|
||||||
* population DESC,
|
* population DESC,
|
||||||
* length(name) ASC
|
* length(name) ASC
|
||||||
* }</pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* would become:
|
* would become:
|
||||||
* <pre>{@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {@code
|
||||||
* feature.setSortKey(
|
* feature.setSortKey(
|
||||||
* SortKey
|
* SortKey
|
||||||
* .orderByInt(rank, MIN_RANK, MAX_RANK)
|
* .orderByInt(rank, MIN_RANK, MAX_RANK)
|
||||||
|
@ -29,7 +33,8 @@ import com.onthegomap.planetiler.collection.FeatureGroup;
|
||||||
* .thenByInt(name.length(), 0, MAX_LENGTH)
|
* .thenByInt(name.length(), 0, MAX_LENGTH)
|
||||||
* .get()
|
* .get()
|
||||||
* )
|
* )
|
||||||
* }</pre>
|
* }
|
||||||
|
* </pre>
|
||||||
*/
|
*/
|
||||||
public class SortKey {
|
public class SortKey {
|
||||||
|
|
||||||
|
@ -37,8 +42,7 @@ public class SortKey {
|
||||||
private long possibleValues = 1;
|
private long possibleValues = 1;
|
||||||
private int result = 0;
|
private int result = 0;
|
||||||
|
|
||||||
private SortKey() {
|
private SortKey() {}
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns a new sort key where elements with {@code value == true} sort after ones where {@code value == false} */
|
/** Returns a new sort key where elements with {@code value == true} sort after ones where {@code value == false} */
|
||||||
public static SortKey orderByTruesLast(boolean value) {
|
public static SortKey orderByTruesLast(boolean value) {
|
||||||
|
|
|
@ -51,8 +51,8 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A utility to download name translations from wikidata for all OSM elements with a <a
|
* A utility to download name translations from wikidata for all OSM elements with a
|
||||||
* href="https://wiki.openstreetmap.org/wiki/Key:wikidata">wikidata tag</a>.
|
* <a href="https://wiki.openstreetmap.org/wiki/Key:wikidata">wikidata tag</a>.
|
||||||
*/
|
*/
|
||||||
public class Wikidata {
|
public class Wikidata {
|
||||||
|
|
||||||
|
@ -371,8 +371,7 @@ public class Wikidata {
|
||||||
|
|
||||||
private final LongObjectMap<Map<String, String>> data = Hppc.newLongObjectHashMap();
|
private final LongObjectMap<Map<String, String>> data = Hppc.newLongObjectHashMap();
|
||||||
|
|
||||||
public WikidataTranslations() {
|
public WikidataTranslations() {}
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns a map from language code to translated name for {@code qid}. */
|
/** Returns a map from language code to translated name for {@code qid}. */
|
||||||
public Map<String, String> get(long qid) {
|
public Map<String, String> get(long qid) {
|
||||||
|
|
|
@ -64,15 +64,14 @@ public interface ZoomFunction<T> extends IntFunction<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A zoom function that lets you set the value to return for a zoom level in meters and when called, it returns how
|
* A zoom function that lets you set the value to return for a zoom level in meters and when called, it returns how
|
||||||
* many pixels long that number of meters is at the equator.
|
* many pixels long that number of meters is at the equator.
|
||||||
*/
|
*/
|
||||||
class MeterToPixelThresholds implements ZoomFunction<Number> {
|
class MeterToPixelThresholds implements ZoomFunction<Number> {
|
||||||
|
|
||||||
private final TreeMap<Integer, Number> levels = new TreeMap<>();
|
private final TreeMap<Integer, Number> levels = new TreeMap<>();
|
||||||
|
|
||||||
private MeterToPixelThresholds() {
|
private MeterToPixelThresholds() {}
|
||||||
}
|
|
||||||
|
|
||||||
/** Sets the value to return at {@code zoom} in meters. */
|
/** Sets the value to return at {@code zoom} in meters. */
|
||||||
public MeterToPixelThresholds put(int zoom, double meters) {
|
public MeterToPixelThresholds put(int zoom, double meters) {
|
||||||
|
|
|
@ -13,20 +13,24 @@ import javax.annotation.concurrent.ThreadSafe;
|
||||||
* When a group of worker threads are processing large blocks, some may finish early, resulting in idle time at the end
|
* When a group of worker threads are processing large blocks, some may finish early, resulting in idle time at the end
|
||||||
* waiting for the "long pole in the tent" to finish:
|
* waiting for the "long pole in the tent" to finish:
|
||||||
*
|
*
|
||||||
* <pre>{@code
|
* <pre>
|
||||||
|
* {@code
|
||||||
* busy idle | done
|
* busy idle | done
|
||||||
* worker1: ===========>xxxxxx|
|
* worker1: ===========>xxxxxx|
|
||||||
* worker2: ===============>xx|
|
* worker2: ===============>xx|
|
||||||
* worker3: =================>|
|
* worker3: =================>|
|
||||||
* worker4: =============>xxxx|
|
* worker4: =============>xxxx|
|
||||||
* }</pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* This utility wraps the operation to perform on each element and then works through items in 3 phases:
|
* This utility wraps the operation to perform on each element and then works through items in 3 phases:
|
||||||
*
|
*
|
||||||
* <ol>
|
* <ol>
|
||||||
* <li>If all threads are still busy, process it in the same thread</li>
|
* <li>If all threads are still busy, process it in the same thread</li>
|
||||||
* <li>If some threads are done, enqueue the item onto a work queue (but if it is full, just process it in the same thread)</li>
|
* <li>If some threads are done, enqueue the item onto a work queue (but if it is full, just process it in the same
|
||||||
* <li>When the thread is done processing input elements, then process items off of the work queue until it is empty and all other workers are finished</li>
|
* thread)</li>
|
||||||
|
* <li>When the thread is done processing input elements, then process items off of the work queue until it is empty and
|
||||||
|
* all other workers are finished</li>
|
||||||
* </ol>
|
* </ol>
|
||||||
*
|
*
|
||||||
* @param <T> The type of element being processed
|
* @param <T> The type of element being processed
|
||||||
|
|
|
@ -104,4 +104,3 @@ public class WeightedHandoffQueue<T> implements AutoCloseable, IterableOnce<T> {
|
||||||
return itemBatch == null ? null : itemBatch.poll();
|
return itemBatch == null ? null : itemBatch.poll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,9 @@ import java.util.function.Consumer;
|
||||||
* <p>
|
* <p>
|
||||||
* Wraps a standard {@link BlockingDeque}, with a few customizations:
|
* Wraps a standard {@link BlockingDeque}, with a few customizations:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>items are buffered into configurable-sized batches before putting on the actual queue to reduce contention</li>
|
* <li>items are buffered into configurable-sized batches before putting on the actual queue to reduce contention</li>
|
||||||
* <li>writers can mark the queue "finished" with {@link #close()} and readers will get {@code null} when there are
|
* <li>writers can mark the queue "finished" with {@link #close()} and readers will get {@code null} when there are no
|
||||||
* no more items to read</li>
|
* more items to read</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* Once a thread starts reading from this queue, it needs to finish otherwise all items might not be read.
|
* Once a thread starts reading from this queue, it needs to finish otherwise all items might not be read.
|
||||||
|
@ -123,7 +123,9 @@ public class WorkQueue<T> implements AutoCloseable, IterableOnce<T>, Consumer<T>
|
||||||
return (pendingBatchesCapacity + writers.size() + readers.size()) * batchSize;
|
return (pendingBatchesCapacity + writers.size() + readers.size()) * batchSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Caches thread-local values so that a single thread can accept new items without having to do thread-local lookups. */
|
/**
|
||||||
|
* Caches thread-local values so that a single thread can accept new items without having to do thread-local lookups.
|
||||||
|
*/
|
||||||
private class WriterForThread implements Consumer<T> {
|
private class WriterForThread implements Consumer<T> {
|
||||||
|
|
||||||
final AtomicReference<Queue<T>> writeBatchRef = new AtomicReference<>(null);
|
final AtomicReference<Queue<T>> writeBatchRef = new AtomicReference<>(null);
|
||||||
|
@ -173,7 +175,9 @@ public class WorkQueue<T> implements AutoCloseable, IterableOnce<T>, Consumer<T>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Caches thread-local values so that a single thread can read new items without having to do thread-local lookups. */
|
/**
|
||||||
|
* Caches thread-local values so that a single thread can read new items without having to do thread-local lookups.
|
||||||
|
*/
|
||||||
private class ReaderForThread implements IterableOnce<T> {
|
private class ReaderForThread implements IterableOnce<T> {
|
||||||
|
|
||||||
Queue<T> readBatch = null;
|
Queue<T> readBatch = null;
|
||||||
|
@ -221,4 +225,3 @@ public class WorkQueue<T> implements AutoCloseable, IterableOnce<T>, Consumer<T>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,9 @@ import java.util.function.Consumer;
|
||||||
* A mini-framework for chaining sequential steps that run in dedicated threads with a queue between each.
|
* A mini-framework for chaining sequential steps that run in dedicated threads with a queue between each.
|
||||||
* <p>
|
* <p>
|
||||||
* For example:
|
* For example:
|
||||||
* <pre>{@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {@code
|
||||||
* WorkerPipeline.start("name", stats)
|
* WorkerPipeline.start("name", stats)
|
||||||
* .readFrom("reader", List.of(1, 2, 3))
|
* .readFrom("reader", List.of(1, 2, 3))
|
||||||
* .addBuffer("reader_queue", 10)
|
* .addBuffer("reader_queue", 10)
|
||||||
|
@ -24,13 +26,14 @@ import java.util.function.Consumer;
|
||||||
* .addBuffer("writer_queue", 10)
|
* .addBuffer("writer_queue", 10)
|
||||||
* .sinkToConsumer("writer", 1, result -> writeToDisk(result))
|
* .sinkToConsumer("writer", 1, result -> writeToDisk(result))
|
||||||
* .await();
|
* .await();
|
||||||
* }</pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* NOTE: to do any forking/joining, you must construct and wire-up queues and each sequence of steps manually.
|
* NOTE: to do any forking/joining, you must construct and wire-up queues and each sequence of steps manually.
|
||||||
*
|
*
|
||||||
* @param <T> input type of this pipeline
|
* @param <T> input type of this pipeline
|
||||||
*/
|
*/
|
||||||
public record WorkerPipeline<T>(
|
public record WorkerPipeline<T> (
|
||||||
String name,
|
String name,
|
||||||
WorkerPipeline<?> previous,
|
WorkerPipeline<?> previous,
|
||||||
WorkQueue<T> inputQueue,
|
WorkQueue<T> inputQueue,
|
||||||
|
@ -213,7 +216,7 @@ public record WorkerPipeline<T>(
|
||||||
*
|
*
|
||||||
* @param <O> type of elements that the next step must process
|
* @param <O> type of elements that the next step must process
|
||||||
*/
|
*/
|
||||||
public record Builder<O>(
|
public record Builder<O> (
|
||||||
String prefix,
|
String prefix,
|
||||||
String name,
|
String name,
|
||||||
// keep track of previous elements so that build can wire-up the computation graph
|
// keep track of previous elements so that build can wire-up the computation graph
|
||||||
|
|
Plik diff jest za duży
Load Diff
|
@ -90,8 +90,7 @@ public class PlanetilerTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {}
|
||||||
}
|
|
||||||
}.process(featureGroup, config);
|
}.process(featureGroup, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1507,8 +1506,7 @@ public class PlanetilerTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void release() {
|
public void release() {}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<VectorTile.Feature> postProcessLayerFeatures(String layer, int zoom,
|
public List<VectorTile.Feature> postProcessLayerFeatures(String layer, int zoom,
|
||||||
|
@ -1577,9 +1575,9 @@ public class PlanetilerTests {
|
||||||
Path tempOsm = tempDir.resolve("monaco-temp.osm.pbf");
|
Path tempOsm = tempDir.resolve("monaco-temp.osm.pbf");
|
||||||
Files.copy(originalOsm, tempOsm);
|
Files.copy(originalOsm, tempOsm);
|
||||||
Planetiler.create(Arguments.fromArgs(
|
Planetiler.create(Arguments.fromArgs(
|
||||||
"--tmpdir", tempDir.toString(),
|
"--tmpdir", tempDir.toString(),
|
||||||
"--free-osm-after-read"
|
"--free-osm-after-read"
|
||||||
))
|
))
|
||||||
.setProfile(new Profile.NullProfile() {
|
.setProfile(new Profile.NullProfile() {
|
||||||
@Override
|
@Override
|
||||||
public void processFeature(SourceFeature source, FeatureCollector features) {
|
public void processFeature(SourceFeature source, FeatureCollector features) {
|
||||||
|
@ -1625,25 +1623,25 @@ public class PlanetilerTests {
|
||||||
@Test
|
@Test
|
||||||
public void testPlanetilerMemoryCheck(@TempDir Path tempDir) {
|
public void testPlanetilerMemoryCheck(@TempDir Path tempDir) {
|
||||||
assertThrows(Exception.class, () -> runWithProfile(tempDir, new Profile.NullProfile() {
|
assertThrows(Exception.class, () -> runWithProfile(tempDir, new Profile.NullProfile() {
|
||||||
@Override
|
@Override
|
||||||
public long estimateIntermediateDiskBytes(long osmSize) {
|
public long estimateIntermediateDiskBytes(long osmSize) {
|
||||||
return Long.MAX_VALUE / 10L;
|
return Long.MAX_VALUE / 10L;
|
||||||
}
|
}
|
||||||
}, false)
|
}, false)
|
||||||
);
|
);
|
||||||
assertThrows(Exception.class, () -> runWithProfile(tempDir, new Profile.NullProfile() {
|
assertThrows(Exception.class, () -> runWithProfile(tempDir, new Profile.NullProfile() {
|
||||||
@Override
|
@Override
|
||||||
public long estimateOutputBytes(long osmSize) {
|
public long estimateOutputBytes(long osmSize) {
|
||||||
return Long.MAX_VALUE / 10L;
|
return Long.MAX_VALUE / 10L;
|
||||||
}
|
}
|
||||||
}, false)
|
}, false)
|
||||||
);
|
);
|
||||||
assertThrows(Exception.class, () -> runWithProfile(tempDir, new Profile.NullProfile() {
|
assertThrows(Exception.class, () -> runWithProfile(tempDir, new Profile.NullProfile() {
|
||||||
@Override
|
@Override
|
||||||
public long estimateRamRequired(long osmSize) {
|
public long estimateRamRequired(long osmSize) {
|
||||||
return Long.MAX_VALUE / 10L;
|
return Long.MAX_VALUE / 10L;
|
||||||
}
|
}
|
||||||
}, false)
|
}, false)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -504,11 +504,9 @@ public class TestUtils {
|
||||||
public record Way(
|
public record Way(
|
||||||
long id,
|
long id,
|
||||||
@JacksonXmlProperty(localName = "nd")
|
@JacksonXmlProperty(localName = "nd")
|
||||||
@JacksonXmlElementWrapper(useWrapping = false)
|
@JacksonXmlElementWrapper(useWrapping = false) List<NodeRef> nodeRefs,
|
||||||
List<NodeRef> nodeRefs,
|
|
||||||
@JacksonXmlProperty(localName = "tag")
|
@JacksonXmlProperty(localName = "tag")
|
||||||
@JacksonXmlElementWrapper(useWrapping = false)
|
@JacksonXmlElementWrapper(useWrapping = false) List<Tag> tags
|
||||||
List<Tag> tags
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@JacksonXmlRootElement(localName = "member")
|
@JacksonXmlRootElement(localName = "member")
|
||||||
|
@ -520,11 +518,9 @@ public class TestUtils {
|
||||||
public record Relation(
|
public record Relation(
|
||||||
long id,
|
long id,
|
||||||
@JacksonXmlProperty(localName = "member")
|
@JacksonXmlProperty(localName = "member")
|
||||||
@JacksonXmlElementWrapper(useWrapping = false)
|
@JacksonXmlElementWrapper(useWrapping = false) List<RelationMember> members,
|
||||||
List<RelationMember> members,
|
|
||||||
@JacksonXmlProperty(localName = "tag")
|
@JacksonXmlProperty(localName = "tag")
|
||||||
@JacksonXmlElementWrapper(useWrapping = false)
|
@JacksonXmlElementWrapper(useWrapping = false) List<Tag> tags
|
||||||
List<Tag> tags
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
// @JsonIgnoreProperties(ignoreUnknown = true)
|
// @JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
@ -535,14 +531,11 @@ public class TestUtils {
|
||||||
String attribution,
|
String attribution,
|
||||||
String license,
|
String license,
|
||||||
@JacksonXmlProperty(localName = "node")
|
@JacksonXmlProperty(localName = "node")
|
||||||
@JacksonXmlElementWrapper(useWrapping = false)
|
@JacksonXmlElementWrapper(useWrapping = false) List<Node> nodes,
|
||||||
List<Node> nodes,
|
|
||||||
@JacksonXmlProperty(localName = "way")
|
@JacksonXmlProperty(localName = "way")
|
||||||
@JacksonXmlElementWrapper(useWrapping = false)
|
@JacksonXmlElementWrapper(useWrapping = false) List<Way> ways,
|
||||||
List<Way> ways,
|
|
||||||
@JacksonXmlProperty(localName = "relation")
|
@JacksonXmlProperty(localName = "relation")
|
||||||
@JacksonXmlElementWrapper(useWrapping = false)
|
@JacksonXmlElementWrapper(useWrapping = false) List<Relation> relation
|
||||||
List<Relation> relation
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
private static final XmlMapper xmlMapper = new XmlMapper();
|
private static final XmlMapper xmlMapper = new XmlMapper();
|
||||||
|
@ -594,8 +587,7 @@ public class TestUtils {
|
||||||
int minzoom, int maxzoom) {
|
int minzoom, int maxzoom) {
|
||||||
try {
|
try {
|
||||||
List<String> failures = new ArrayList<>();
|
List<String> failures = new ArrayList<>();
|
||||||
outer:
|
outer: for (int zoom = 0; zoom <= 14; zoom++) {
|
||||||
for (int zoom = 0; zoom <= 14; zoom++) {
|
|
||||||
boolean shouldFind = zoom >= minzoom && zoom <= maxzoom;
|
boolean shouldFind = zoom >= minzoom && zoom <= maxzoom;
|
||||||
var coord = TileCoord.aroundLngLat(lng, lat, zoom);
|
var coord = TileCoord.aroundLngLat(lng, lat, zoom);
|
||||||
Geometry tilePoint = GeoUtils.point(coord.lngLatToTileCoords(lng, lat));
|
Geometry tilePoint = GeoUtils.point(coord.lngLatToTileCoords(lng, lat));
|
||||||
|
|
|
@ -48,7 +48,8 @@ import org.locationtech.jts.precision.GeometryPrecisionReducer;
|
||||||
import vector_tile.VectorTileProto;
|
import vector_tile.VectorTileProto;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is copied from https://github.com/ElectronicChartCentre/java-vector-tile/blob/master/src/test/java/no/ecc/vectortile/VectorTileEncoderTest.java
|
* This class is copied from
|
||||||
|
* https://github.com/ElectronicChartCentre/java-vector-tile/blob/master/src/test/java/no/ecc/vectortile/VectorTileEncoderTest.java
|
||||||
* and modified based on the changes in VectorTileEncoder, and adapted to junit 5.
|
* and modified based on the changes in VectorTileEncoder, and adapted to junit 5.
|
||||||
*/
|
*/
|
||||||
public class VectorTileTest {
|
public class VectorTileTest {
|
||||||
|
@ -366,59 +367,58 @@ public class VectorTileTest {
|
||||||
var scaleUp = AffineTransformation.scaleInstance(256d / 4096, 256d / 4096);
|
var scaleUp = AffineTransformation.scaleInstance(256d / 4096, 256d / 4096);
|
||||||
var scaleDown = scaleUp.getInverse();
|
var scaleDown = scaleUp.getInverse();
|
||||||
return Stream.of(
|
return Stream.of(
|
||||||
newPoint(0, 0),
|
newPoint(0, 0),
|
||||||
newPoint(0.25, -0.25),
|
newPoint(0.25, -0.25),
|
||||||
|
newPoint(1.25, 1.25),
|
||||||
|
newPoint(1.5, 1.5),
|
||||||
|
newMultiPoint(
|
||||||
newPoint(1.25, 1.25),
|
newPoint(1.25, 1.25),
|
||||||
newPoint(1.5, 1.5),
|
newPoint(1.5, 1.5)
|
||||||
newMultiPoint(
|
),
|
||||||
newPoint(1.25, 1.25),
|
newLineString(0, 0, 1.2, 1.2),
|
||||||
newPoint(1.5, 1.5)
|
newLineString(0, 0, 0.1, 0.1),
|
||||||
),
|
newLineString(0, 0, 1, 1, 1.2, 1.2, 2, 2),
|
||||||
newLineString(0, 0, 1.2, 1.2),
|
newLineString(8000, 8000, 8000, 8001, 8001, 8001),
|
||||||
|
newLineString(-4000, -4000, -4000, -4001, -4001, -4001),
|
||||||
|
newMultiLineString(
|
||||||
|
newLineString(0, 0, 1, 1),
|
||||||
|
newLineString(1.1, 1.1, 2, 2)
|
||||||
|
),
|
||||||
|
newMultiLineString(
|
||||||
newLineString(0, 0, 0.1, 0.1),
|
newLineString(0, 0, 0.1, 0.1),
|
||||||
newLineString(0, 0, 1, 1, 1.2, 1.2, 2, 2),
|
newLineString(1.1, 1.1, 2, 2)
|
||||||
newLineString(8000, 8000, 8000, 8001, 8001, 8001),
|
),
|
||||||
newLineString(-4000, -4000, -4000, -4001, -4001, -4001),
|
newMultiLineString(
|
||||||
newMultiLineString(
|
newLineString(-10, -10, -9, -9),
|
||||||
newLineString(0, 0, 1, 1),
|
newLineString(0, 0, 0.1, 0.1),
|
||||||
newLineString(1.1, 1.1, 2, 2)
|
newLineString(1.1, 1.1, 2, 2)
|
||||||
),
|
),
|
||||||
newMultiLineString(
|
newPolygon(0, 0, 1, 0, 1, 1, 0, 1, 0, 0),
|
||||||
newLineString(0, 0, 0.1, 0.1),
|
newPolygon(0, 0, 0.1, 0, 0.1, 0.1, 0, 0.1, 0, 0),
|
||||||
newLineString(1.1, 1.1, 2, 2)
|
newPolygon(0, 0, 1, 0, 1, 0.1, 1, 1, 0, 1, 0, 0),
|
||||||
),
|
newMultiPolygon(
|
||||||
newMultiLineString(
|
|
||||||
newLineString(-10, -10, -9, -9),
|
|
||||||
newLineString(0, 0, 0.1, 0.1),
|
|
||||||
newLineString(1.1, 1.1, 2, 2)
|
|
||||||
),
|
|
||||||
newPolygon(0, 0, 1, 0, 1, 1, 0, 1, 0, 0),
|
newPolygon(0, 0, 1, 0, 1, 1, 0, 1, 0, 0),
|
||||||
newPolygon(0, 0, 0.1, 0, 0.1, 0.1, 0, 0.1, 0, 0),
|
newPolygon(0, 0, -1, 0, -1, -1, 0, -1, 0, 0)
|
||||||
newPolygon(0, 0, 1, 0, 1, 0.1, 1, 1, 0, 1, 0, 0),
|
),
|
||||||
newMultiPolygon(
|
newPolygon(0, 0, 1, 0, 1, 1, 0, 1, 0, 0.1, 0, 0)
|
||||||
newPolygon(0, 0, 1, 0, 1, 1, 0, 1, 0, 0),
|
).map(scaleUp::transform)
|
||||||
newPolygon(0, 0, -1, 0, -1, -1, 0, -1, 0, 0)
|
.flatMap(geometry -> scales.stream().flatMap(scale -> Stream.of(
|
||||||
),
|
dynamicTest(scaleDown.transform(geometry) + " scale: " + scale, () -> {
|
||||||
newPolygon(0, 0, 1, 0, 1, 1, 0, 1, 0, 0.1, 0, 0)
|
PrecisionModel pm = new PrecisionModel((4096 << scale) / 256d);
|
||||||
).map(scaleUp::transform)
|
assertSameGeometry(
|
||||||
.flatMap(geometry -> scales.stream().flatMap(scale ->
|
GeometryPrecisionReducer.reduce(geometry, pm),
|
||||||
Stream.of(
|
VectorTile.encodeGeometry(geometry, scale).decode()
|
||||||
dynamicTest(scaleDown.transform(geometry) + " scale: " + scale, () -> {
|
);
|
||||||
PrecisionModel pm = new PrecisionModel((4096 << scale) / 256d);
|
}),
|
||||||
assertSameGeometry(
|
dynamicTest(scaleDown.transform(geometry) + " unscale: " + scale, () -> {
|
||||||
GeometryPrecisionReducer.reduce(geometry, pm),
|
PrecisionModel pm = new PrecisionModel((4096 << scale) / 256d);
|
||||||
VectorTile.encodeGeometry(geometry, scale).decode()
|
PrecisionModel pm0 = new PrecisionModel(4096d / 256);
|
||||||
);
|
assertSameGeometry(
|
||||||
}),
|
GeometryPrecisionReducer.reduce(GeometryPrecisionReducer.reduce(geometry, pm), pm0),
|
||||||
dynamicTest(scaleDown.transform(geometry) + " unscale: " + scale, () -> {
|
VectorTile.encodeGeometry(geometry, scale).unscale().decode()
|
||||||
PrecisionModel pm = new PrecisionModel((4096 << scale) / 256d);
|
);
|
||||||
PrecisionModel pm0 = new PrecisionModel(4096d / 256);
|
})
|
||||||
assertSameGeometry(
|
)
|
||||||
GeometryPrecisionReducer.reduce(GeometryPrecisionReducer.reduce(geometry, pm), pm0),
|
|
||||||
VectorTile.encodeGeometry(geometry, scale).unscale().decode()
|
|
||||||
);
|
|
||||||
})
|
|
||||||
)
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -279,9 +279,8 @@ public class FeatureGroupTest {
|
||||||
int tileB, byte layerB, int sortKeyB, boolean hasGroupB
|
int tileB, byte layerB, int sortKeyB, boolean hasGroupB
|
||||||
) {
|
) {
|
||||||
assertTrue(
|
assertTrue(
|
||||||
FeatureGroup.encodeKey(tileA, layerA, sortKeyA, hasGroupA)
|
FeatureGroup.encodeKey(tileA, layerA, sortKeyA, hasGroupA) < FeatureGroup.encodeKey(tileB, layerB, sortKeyB,
|
||||||
<
|
hasGroupB)
|
||||||
FeatureGroup.encodeKey(tileB, layerB, sortKeyB, hasGroupB)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,15 +62,15 @@ public class OsmInputFileTest {
|
||||||
@Test
|
@Test
|
||||||
public void testGetHeader() {
|
public void testGetHeader() {
|
||||||
assertEquals(new OsmHeader(
|
assertEquals(new OsmHeader(
|
||||||
expectedBounds,
|
expectedBounds,
|
||||||
List.of("OsmSchema-V0.6", "DenseNodes"),
|
List.of("OsmSchema-V0.6", "DenseNodes"),
|
||||||
List.of(),
|
List.of(),
|
||||||
"osmium/1.8.0",
|
"osmium/1.8.0",
|
||||||
"",
|
"",
|
||||||
Instant.parse("2021-04-21T20:21:46Z"),
|
Instant.parse("2021-04-21T20:21:46Z"),
|
||||||
2947,
|
2947,
|
||||||
"http://download.geofabrik.de/europe/monaco-updates"
|
"http://download.geofabrik.de/europe/monaco-updates"
|
||||||
),
|
),
|
||||||
new OsmInputFile(path).getHeader()
|
new OsmInputFile(path).getHeader()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Ładowanie…
Reference in New Issue