Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
8a56778
feat: add standalone H3-based boundary importer with RocksDB support
dgraf-gh Jul 11, 2026
882e5cc
feat: add --boundary-import mode to utilize StandaloneBoundaryImporter
dgraf-gh Jul 11, 2026
7bc128f
added multi file suport for boundaries import
dgraf-gh Jul 11, 2026
6bcbf82
feat: add BoundaryImportStatistics with progress tracking and error r…
dgraf-gh Jul 11, 2026
2b8645a
feat: add multi-threading to StandaloneBoundaryImporter for H3 cell g…
dgraf-gh Jul 11, 2026
66f3016
refactor: implement parallel processing with temporary databases for …
dgraf-gh Jul 11, 2026
f9a4704
refactor: implement producer-consumer pattern for memory-efficient re…
dgraf-gh Jul 11, 2026
938465e
feat: make geometry simplification tolerances configurable
dgraf-gh Jul 11, 2026
31d44b4
feat: enhance boundary importer with detailed geometry validation and…
dgraf-gh Jul 12, 2026
ee5fe5e
feat: implement variable H3 resolution by admin level for boundary im…
dgraf-gh Jul 12, 2026
3d0c369
refactor: replace polygonToCellsStream with polygonToCells method
dgraf-gh Jul 12, 2026
186fc67
fix: count administrative boundary relations in first pass for accura…
dgraf-gh Jul 12, 2026
eda7501
downgrade: reduce logging verbosity in StandaloneBoundaryImporter and…
dgraf-gh Jul 12, 2026
db46990
feat: add BoundaryLookupService for H3-based administrative boundary …
dgraf-gh Jul 12, 2026
d043d85
test: add integration test for BoundaryLookupService with Lübeck coor…
dgraf-gh Jul 12, 2026
e68842b
feat: expand boundary lookup tests and improve database flexibility
dgraf-gh Jul 12, 2026
c47bf1a
feat: add osm_to_h3 database support for boundary cell lookup
dgraf-gh Jul 12, 2026
5628155
refactor: align BoundaryLookupService resolutions with importer logic
dgraf-gh Jul 12, 2026
5e8ffc4
feat: add getCellsWithBoundaries method for visit tracking
dgraf-gh Jul 12, 2026
4a10042
test: add test for getCellsForPoint method in BoundaryLookupService
dgraf-gh Jul 12, 2026
9e1ac29
test: add tests for getCellsWithBoundaries method
dgraf-gh Jul 12, 2026
d434e09
perf: optimize boundary importer with thread-local batching and geome…
dgraf-gh Jul 12, 2026
a21a09d
refactor: replace deprecated list methods and add RocksDBException ha…
dgraf-gh Jul 13, 2026
5fa646b
fix: revert thread-local batching and enhance compression to prevent OOM
dgraf-gh Jul 13, 2026
3aced51
refactor: replace thread-local H3 processing with batched approach
dgraf-gh Jul 13, 2026
cdacd0f
finished h3 index generation
dgraf-gh Jul 28, 2026
382fafb
feat: add H3 bundle pipeline script for streamlined data processing a…
dgraf-gh Jul 28, 2026
329c3dd
feat: add H3 bundle pipeline script with Docker integration
dgraf-gh Jul 28, 2026
16e47f9
feat: add support for boundary preparation and streamline cleanup
dgraf-gh Jul 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,5 @@ build/
.aider*
/data/
/.idea/
/data-boundaries/
/.env
10 changes: 9 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,14 @@ COPY --chown=paikka:paikka target/*.jar $APP_HOME/app.jar
COPY scripts/* $APP_HOME/

RUN ln -s $APP_HOME/filter_osm.sh /usr/bin/prepare
RUN ln -s $APP_HOME/filter_boundaries.sh /usr/bin/prepare-boundaries
RUN ln -s $APP_HOME/import.sh /usr/bin/import
RUN ln -s $APP_HOME/import-boundaries.sh /usr/bin/import-boundaries

RUN chmod +x /usr/bin/prepare
RUN chmod +x /usr/bin/prepare-boundaries
RUN chmod +x /usr/bin/import
RUN chmod +x /usr/bin/import-boundaries

# Create a script to start the application with configurable UID/GID
RUN cat <<'EOF' > /entrypoint.sh
Expand All @@ -54,14 +58,18 @@ chown -R paikka:paikka $STATS_DIR
cd $DATA_DIR

# Check if the first argument is a known script
if [ "$1" = "prepare" ]; then
if [ "$1" = "prepare" ] || [ "$1" = "prepare-boundaries" ]; then
echo "Running script: $1"
shift
exec runuser -u paikka -- prepare "$@"
elif [ "$1" = "import" ]; then
echo "Running script: $1"
shift
exec runuser -u paikka -- import --jar-file "$APP_HOME/app.jar" "$@"
elif [ "$1" = "import-boundaries" ]; then
echo "Running script: $1"
shift
exec runuser -u paikka -- import-boundaries --jar-file "$APP_HOME/app.jar" "$@"
fi

# Default: Execute the Java application
Expand Down
8 changes: 7 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,13 @@
<artifactId>s2-geometry</artifactId>
<version>2.0.0</version>
</dependency>


<dependency>
<groupId>com.uber</groupId>
<artifactId>h3</artifactId>
<version>4.4.0</version>
</dependency>

<!-- RocksDB -->
<dependency>
<groupId>org.rocksdb</groupId>
Expand Down
128 changes: 128 additions & 0 deletions scripts/create-h3-bundle.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#!/usr/bin/env bash

#
# This file is part of paikka.
#
# Paikka is free software: you can redistribute it and/or
# modify it under the terms of the GNU Affero General Public License
# as published by the Free Software Foundation, either version 3 or
# any later version.
#
# Paikka is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
# You should have received a copy of the GNU Affero General Public License
# along with Paikka. If not, see <https://www.gnu.org/licenses/>.
#

# Exit immediately if a command exits with a non-zero status
set -e

# Default values
VERSION=$(date +%Y-%m-%d)-v1
DOWNLOAD_BASE_URL="https://h3-osm.dedicatedcode.com"
OUTPUT_DIR="./dist"

# Function to display usage instructions
usage() {
echo "Usage: $0 -d <rocksdb_parent_directory> [OPTIONS]"
echo ""
echo "Required:"
echo " -d, --db-dir Path to the directory containing h3_to_osm, region_metadata, and region_geometry"
echo ""
echo "Options:"
echo " -v, --version Version string for the bundle (default: $VERSION)"
echo " -u, --url Base CDN URL where the zip will be hosted (default: $DOWNLOAD_BASE_URL)"
echo " -o, --output-dir Where to write the ZIP and manifest.json (default: $OUTPUT_DIR)"
echo " -h, --help Show this help message"
exit 1
}

# Parse command line arguments
while [[ "$#" -gt 0 ]]; do
case $1 in
-d|--db-dir) DB_DIR="$2"; shift ;;
-v|--version) VERSION="$2"; shift ;;
-u|--url) DOWNLOAD_BASE_URL="$2"; shift ;;
-o|--output-dir) OUTPUT_DIR="$2"; shift ;;
-h|--help) usage ;;
*) echo "Unknown parameter passed: $1"; usage ;;
esac
shift
done

# Validate required argument
if [ -z "$DB_DIR" ]; then
echo "Error: Database source directory (-d / --db-dir) is required."
usage
fi

# Ensure absolute paths
DB_DIR_ABS=$(cd "$DB_DIR" && pwd)
mkdir -p "$OUTPUT_DIR"
OUTPUT_DIR_ABS=$(cd "$OUTPUT_DIR" && pwd)

# Check that the three essential database directories actually exist
REQUIRED_DIRS=("h3_to_osm" "region_metadata" "region_geometry")
for dir in "${REQUIRED_DIRS[@]}"; do
if [ ! -d "$DB_DIR_ABS/$dir" ]; then
echo "Error: Required directory '$dir' not found inside $DB_DIR_ABS"
exit 1
fi
done

echo "=========================================="
echo "Preparing H3 RocksDB Bundle"
echo "Version: $VERSION"
echo "Source: $DB_DIR_ABS"
echo "Output: $OUTPUT_DIR_ABS"
echo "=========================================="

ZIP_FILENAME="h3-rocksdb-${VERSION}.zip"
ZIP_PATH="$OUTPUT_DIR_ABS/$ZIP_FILENAME"

# 1. Clean up any pre-existing zip at the target location to avoid mixing versions
rm -f "$ZIP_PATH"

echo "Creating ZIP archive..."
# We run zip inside the source directory so that the subfolders are at the ROOT of the zip.
# -r: recursive
# -q: quiet
# -x "**/LOCK": IMPORTANT. Excludes RocksDB native file system locks which prevent startup on target systems.
(
cd "$DB_DIR_ABS"
zip -r -q "$ZIP_PATH" h3_to_osm region_metadata region_geometry osm_names.tsv -x "**/LOCK"
)

echo "Calculating bundle metadata..."
# Check OS to use the correct parameters for 'stat' and 'sha256' tools (Mac vs Linux)
if [[ "$OSTYPE" == "darwin"* ]]; then
# macOS
SIZE_BYTES=$(stat -f%z "$ZIP_PATH")
SHA256=$(shasum -a 256 "$ZIP_PATH" | awk '{print $1}')
else
# Linux / WSL
SIZE_BYTES=$(stat -c%s "$ZIP_PATH")
SHA256=$(sha256sum "$ZIP_PATH" | awk '{print $1}')
fi

# 2. Build the exact Manifest structure the Spring Boot Lifecycle Manager expects
MANIFEST_PATH="$OUTPUT_DIR_ABS/manifest.json"
DOWNLOAD_URL="${DOWNLOAD_BASE_URL}/${ZIP_FILENAME}"

cat <<EOF > "$MANIFEST_PATH"
{
"version": "${VERSION}",
"downloadUrl": "${DOWNLOAD_URL}",
"sha256": "${SHA256}",
"sizeBytes": ${SIZE_BYTES}
}
EOF

echo "=========================================="
echo "Success! Package files generated:"
echo "Archive: $ZIP_PATH ($(numfmt --to=iec --suffix=B $SIZE_BYTES) / $SIZE_BYTES bytes)"
echo "Checksum: $SHA256"
echo "Manifest: $MANIFEST_PATH"
echo "=========================================="
75 changes: 75 additions & 0 deletions scripts/filter_boundaries.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/bin/bash

# Project Paikka - Lite PBF Filter
# Filters OSM PBF files to keep only POIs and Administrative Boundaries

# Usage function
usage() {
echo "Usage: $0 <input_file> <output_file>"
echo ""
echo "Filters an OSM PBF file to keep only boundaries relevant for REITTI:"
echo " - Points of Interest (amenity, shop, tourism, leisure, etc.)"
echo " - Administrative boundaries"
echo ""
echo "Arguments:"
echo " input_file Path to the input OSM PBF file"
echo " output_file Path for the filtered output PBF file"
echo ""
echo "Examples:"
echo " $0 planet-latest.osm.pbf planet-filtered.osm.pbf"
echo " $0 europe-latest.osm.pbf europe-paikka.osm.pbf"
echo ""
echo "Requirements:"
echo " - osmium-tool must be installed"
echo " - Sufficient disk space for output file"
exit 1
}

# Check if correct number of arguments provided
if [ $# -ne 2 ]; then
echo "Error: Incorrect number of arguments"
echo ""
usage
fi

INPUT_FILE="$1"
OUTPUT_FILE="$2"

# Check if input file exists
if [ ! -f "$INPUT_FILE" ]; then
echo "Error: Input file '$INPUT_FILE' does not exist"
exit 1
fi

# Check if osmium is available
if ! command -v osmium &> /dev/null; then
echo "Error: osmium-tool is not installed"
echo "Install with: sudo apt-get install osmium-tool (Ubuntu/Debian)"
echo "Or: brew install osmium-tool (macOS)"
exit 1
fi

echo "Starting OSM PBF filtering for PAIKKA..."
echo "Input file: $INPUT_FILE"
echo "Output file: $OUTPUT_FILE"
echo ""
osmium tags-filter "$INPUT_FILE" r/boundary=administrative -o "$OUTPUT_FILE" --overwrite

if [ $? -eq 0 ]; then
echo ""
echo "✓ Filter complete: $OUTPUT_FILE created"
echo "✓ Input file size: $(du -h "$INPUT_FILE" | cut -f1)"
echo "✓ Output file size: $(du -h "$OUTPUT_FILE" | cut -f1)"

# Calculate size reduction
INPUT_SIZE=$(stat -c%s "$INPUT_FILE" 2>/dev/null || stat -f%z "$INPUT_FILE" 2>/dev/null)
OUTPUT_SIZE=$(stat -c%s "$OUTPUT_FILE" 2>/dev/null || stat -f%z "$OUTPUT_FILE" 2>/dev/null)

if [ -n "$INPUT_SIZE" ] && [ -n "$OUTPUT_SIZE" ] && [ "$INPUT_SIZE" -gt 0 ]; then
REDUCTION=$(( (INPUT_SIZE - OUTPUT_SIZE) * 100 / INPUT_SIZE ))
echo "✓ Size reduction: ${REDUCTION}%"
fi
else
echo "Error: Filtering failed"
exit 1
fi
Loading
Loading