geojac 0.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. geojac-0.2.2/.dockerignore +10 -0
  2. geojac-0.2.2/.envrc +1 -0
  3. geojac-0.2.2/.github/workflows/wheels.yml +139 -0
  4. geojac-0.2.2/.gitignore +53 -0
  5. geojac-0.2.2/CMakeLists.txt +80 -0
  6. geojac-0.2.2/Dockerfile +67 -0
  7. geojac-0.2.2/Makefile +79 -0
  8. geojac-0.2.2/PKG-INFO +234 -0
  9. geojac-0.2.2/README.md +216 -0
  10. geojac-0.2.2/examples/example_acj.py +108 -0
  11. geojac-0.2.2/examples/example_crime_osm.py +250 -0
  12. geojac-0.2.2/examples/example_crime_visualization.py +254 -0
  13. geojac-0.2.2/examples/example_minkowski_osm.py +92 -0
  14. geojac-0.2.2/examples/example_multimodal_evaluation.py +83 -0
  15. geojac-0.2.2/examples/example_realtime.py +205 -0
  16. geojac-0.2.2/examples/example_simplification.py +125 -0
  17. geojac-0.2.2/examples/example_simplification_osm.py +246 -0
  18. geojac-0.2.2/examples/example_simplification_visual.py +208 -0
  19. geojac-0.2.2/flake.lock +27 -0
  20. geojac-0.2.2/flake.nix +57 -0
  21. geojac-0.2.2/pyproject.toml +33 -0
  22. geojac-0.2.2/requirements.txt +42 -0
  23. geojac-0.2.2/scripts/run_benchmark.py +350 -0
  24. geojac-0.2.2/src/geojac/__init__.py +77 -0
  25. geojac-0.2.2/src/geojac/algorithms/__init__.py +0 -0
  26. geojac-0.2.2/src/geojac/algorithms/graph.py +472 -0
  27. geojac-0.2.2/src/geojac/algorithms/map_index.py +204 -0
  28. geojac-0.2.2/src/geojac/algorithms/minkowski.py +91 -0
  29. geojac-0.2.2/src/geojac/core/CMakeLists.txt +42 -0
  30. geojac-0.2.2/src/geojac/core/__init__.py +3 -0
  31. geojac-0.2.2/src/geojac/core/network.py +105 -0
  32. geojac-0.2.2/src/geojac/core/semantics.py +51 -0
  33. geojac-0.2.2/src/geojac/core/src/bindings.cpp +68 -0
  34. geojac-0.2.2/src/geojac/core/src/graph_simplify.cpp +1003 -0
  35. geojac-0.2.2/src/geojac/core/src/graph_simplify.hpp +43 -0
  36. geojac-0.2.2/src/geojac/core/src/spatial_index.cpp +147 -0
  37. geojac-0.2.2/src/geojac/core/src/spatial_index.hpp +17 -0
  38. geojac-0.2.2/src/geojac/core/src/types.hpp +85 -0
  39. geojac-0.2.2/src/geojac/data/__init__.py +0 -0
  40. geojac-0.2.2/src/geojac/data/io.py +219 -0
  41. geojac-0.2.2/src/geojac/evaluation/__init__.py +0 -0
  42. geojac-0.2.2/src/geojac/evaluation/base.py +28 -0
  43. geojac-0.2.2/src/geojac/evaluation/evaluators.py +53 -0
  44. geojac-0.2.2/src/geojac/evaluation/metrics.py +364 -0
  45. geojac-0.2.2/src/geojac/evaluation/reporting.py +281 -0
  46. geojac-0.2.2/src/geojac/utils/__init__.py +0 -0
  47. geojac-0.2.2/src/geojac/utils/render.py +394 -0
  48. geojac-0.2.2/tests/__init__.py +0 -0
  49. geojac-0.2.2/tests/conftest.py +103 -0
  50. geojac-0.2.2/tests/test_core_engine.py +399 -0
  51. geojac-0.2.2/tests/test_data.py +44 -0
  52. geojac-0.2.2/tests/test_evaluation.py +45 -0
  53. geojac-0.2.2/tests/test_integration.py +151 -0
  54. geojac-0.2.2/tests/test_network.py +129 -0
  55. geojac-0.2.2/tests/test_parsers.py +55 -0
  56. geojac-0.2.2/tests/test_semantics.py +58 -0
  57. geojac-0.2.2/tests/test_simplification.py +77 -0
  58. geojac-0.2.2/tests/test_spatial_index.py +65 -0
@@ -0,0 +1,10 @@
1
+ build/
2
+ .venv/
3
+ outputs/
4
+ __pycache__/
5
+ **/__pycache__/
6
+ *.pyc
7
+ *.pyo
8
+ *.egg-info/
9
+ .git/
10
+ .pytest_cache/
geojac-0.2.2/.envrc ADDED
@@ -0,0 +1 @@
1
+ use flake
@@ -0,0 +1,139 @@
1
+ name: Build Wheels
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ - develop
8
+ tags:
9
+ - 'v*'
10
+ pull_request:
11
+
12
+ jobs:
13
+ build_wheels:
14
+ name: Build wheels on ${{ matrix.os }}
15
+ runs-on: ${{ matrix.os }}
16
+ strategy:
17
+ fail-fast: false
18
+ matrix:
19
+ os: [ubuntu-latest, windows-latest, macos-latest]
20
+
21
+ steps:
22
+ - uses: actions/checkout@v4
23
+
24
+ - name: Set up Python
25
+ uses: actions/setup-python@v5
26
+ with:
27
+ python-version: '3.10'
28
+
29
+ # cibuildwheel automatically downloads the cibuildwheel docker images for linux
30
+ # and runs the build process across different python versions.
31
+ - name: Cache vcpkg installed packages
32
+ uses: actions/cache@v4
33
+ if: runner.os == 'Windows'
34
+ with:
35
+ path: C:\vcpkg\installed
36
+ key: ${{ runner.os }}-vcpkg-boost-full
37
+ restore-keys: |
38
+ ${{ runner.os }}-vcpkg-
39
+
40
+ # Homebrew bottles are compiled against the runner's OS version.
41
+ # Capture it so cibuildwheel's deployment target matches exactly,
42
+ # preventing delocate-wheel from rejecting mismatched LC_BUILD_VERSION.
43
+ - name: Detect macOS deployment target
44
+ if: runner.os == 'macOS'
45
+ id: macos-target
46
+ run: echo "version=$(sw_vers -productVersion | cut -d. -f1)" >> $GITHUB_OUTPUT
47
+
48
+ - name: Build wheels
49
+ uses: pypa/cibuildwheel@v2.22.0
50
+ env:
51
+ CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28
52
+ CIBW_BEFORE_ALL_LINUX: "dnf install -y gmp-devel mpfr-devel boost-devel"
53
+ CIBW_BEFORE_ALL_MACOS: "brew install gmp mpfr boost"
54
+ CIBW_ENVIRONMENT_MACOS: >-
55
+ MACOSX_DEPLOYMENT_TARGET=${{ steps.macos-target.outputs.version }}
56
+ CMAKE_OSX_DEPLOYMENT_TARGET=${{ steps.macos-target.outputs.version }}
57
+ CIBW_BEFORE_ALL_WINDOWS: "vcpkg install boost:x64-windows gmp:x64-windows mpfr:x64-windows"
58
+ CIBW_BEFORE_BUILD_WINDOWS: "pip install delvewheel"
59
+ CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: "delvewheel repair --add-path C:\\vcpkg\\installed\\x64-windows\\bin -w {dest_dir} {wheel}"
60
+ CIBW_SKIP: "cp36-* cp37-* cp38-* pp* *-musllinux_* *i686* *win32*" # Omitir versiones muy viejas o 32 bits
61
+
62
+ - uses: actions/upload-artifact@v4
63
+ with:
64
+ name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
65
+ path: ./wheelhouse/*.whl
66
+
67
+ build_sdist:
68
+ name: Build source distribution
69
+ runs-on: ubuntu-latest
70
+ steps:
71
+ - uses: actions/checkout@v4
72
+ - name: Build sdist
73
+ run: pipx run build --sdist
74
+ - uses: actions/upload-artifact@v4
75
+ with:
76
+ name: cibw-sdist
77
+ path: dist/*.tar.gz
78
+
79
+ benchmark:
80
+ name: Run thesis benchmark
81
+ runs-on: ubuntu-24.04
82
+ if: github.event_name == 'push'
83
+ steps:
84
+ - uses: actions/checkout@v4
85
+
86
+ - name: Cache OSM network data
87
+ uses: actions/cache@v4
88
+ with:
89
+ path: cache/
90
+ key: osm-cache-barranco-v1
91
+
92
+ - name: Install system dependencies
93
+ run: |
94
+ sudo apt-get update
95
+ sudo apt-get install -y \
96
+ python3 python3-pip python3-dev \
97
+ build-essential cmake git pkg-config \
98
+ pybind11-dev \
99
+ libboost-all-dev libgmp-dev libmpfr-dev libcgal-dev \
100
+ libspatialindex-dev libgeos-dev libproj-dev \
101
+ libgl1 libglib2.0-0
102
+ pip3 install -r requirements.txt --break-system-packages
103
+
104
+ - name: Build C++ extension
105
+ run: |
106
+ mkdir -p build
107
+ cd build
108
+ cmake ..
109
+ make -j$(nproc)
110
+
111
+ - name: Run benchmark
112
+ env:
113
+ PYTHONPATH: ${{ github.workspace }}/build:${{ github.workspace }}/src
114
+ run: python3 scripts/run_benchmark.py
115
+
116
+ - name: Upload benchmark outputs
117
+ uses: actions/upload-artifact@v4
118
+ with:
119
+ name: tesis-benchmark-results
120
+ path: outputs/
121
+ retention-days: 90
122
+
123
+ upload_pypi:
124
+ name: Upload to PyPI
125
+ needs: [build_wheels, build_sdist]
126
+ runs-on: ubuntu-latest
127
+ # Se ejecutará automáticamente al pushear a main o al crear un Tag
128
+ if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/'))
129
+ steps:
130
+ - uses: actions/download-artifact@v4
131
+ with:
132
+ pattern: cibw-*
133
+ path: dist
134
+ merge-multiple: true
135
+
136
+ - uses: pypa/gh-action-pypi-publish@release/v1
137
+ with:
138
+ password: ${{ secrets.PYPI_API_TOKEN }}
139
+ skip-existing: true
@@ -0,0 +1,53 @@
1
+ # Build artifacts
2
+ build/
3
+ *.so
4
+ *.o
5
+ *.a
6
+ *.dylib
7
+
8
+ # Python cache
9
+ __pycache__/
10
+ *.py[cod]
11
+ *$py.class
12
+ *.egg-info/
13
+ dist/
14
+ .eggs/
15
+
16
+ # Testing
17
+ .pytest_cache/
18
+ .coverage
19
+ htmlcov/
20
+
21
+ # IDEs
22
+ .vscode/
23
+ .idea/
24
+ *.swp
25
+ *.swo
26
+ *~
27
+ .env
28
+
29
+ # OS
30
+ .DS_Store
31
+ Thumbs.db
32
+
33
+ # CMake
34
+ CMakeCache.txt
35
+ CMakeFiles/
36
+ cmake_install.cmake
37
+ build/Makefile
38
+ *.cmake
39
+
40
+ # Keep only the main CMakeLists.txt files and root Makefile
41
+ !CMakeLists.txt
42
+ !acj/core/CMakeLists.txt
43
+ !Makefile
44
+
45
+ # ACJ specific
46
+ cache/
47
+ output/
48
+ outputs/
49
+ *.tar.xz
50
+
51
+ # NixOs / direnv
52
+ .direnv/
53
+ .venv/
@@ -0,0 +1,80 @@
1
+ cmake_minimum_required(VERSION 3.15)
2
+ project(acj_project LANGUAGES CXX)
3
+
4
+ set(CMAKE_CXX_STANDARD 17)
5
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
6
+
7
+ if(NOT CMAKE_BUILD_TYPE)
8
+ set(CMAKE_BUILD_TYPE Release)
9
+ endif()
10
+
11
+ find_package(Python3 COMPONENTS Interpreter Development.Module REQUIRED)
12
+ find_package(pybind11 CONFIG REQUIRED)
13
+
14
+ # Use FetchContent to extract the local CGAL tarball during build
15
+ include(FetchContent)
16
+ FetchContent_Declare(
17
+ CGAL
18
+ URL https://github.com/CGAL/cgal/releases/download/v6.0.1/CGAL-6.0.1.tar.xz
19
+ )
20
+ FetchContent_Populate(CGAL)
21
+
22
+ # PATCH CGAL BUG in AABB_traits_2.h
23
+ file(READ "${cgal_SOURCE_DIR}/include/CGAL/AABB_traits_2.h" AABB_TRAITS_CONTENT)
24
+ string(REPLACE "bb,true)?" "bb)?" AABB_TRAITS_CONTENT "${AABB_TRAITS_CONTENT}")
25
+ file(WRITE "${cgal_SOURCE_DIR}/include/CGAL/AABB_traits_2.h" "${AABB_TRAITS_CONTENT}")
26
+ # CGAL is header-only from 5.0+, just add the include directories
27
+ add_library(CGAL::CGAL INTERFACE IMPORTED)
28
+ target_include_directories(CGAL::CGAL INTERFACE "${cgal_SOURCE_DIR}/include")
29
+
30
+ # Find Boost (strictly required by CGAL)
31
+ if(NOT WIN32)
32
+ find_package(Boost REQUIRED)
33
+ endif()
34
+
35
+ if(WIN32)
36
+ # === WINDOWS LOGIC ===
37
+ # Include vcpkg globally for gmp/mpfr and EXACTLY inject Boost include path like the experiment!
38
+ include_directories("C:/vcpkg/installed/x64-windows/include")
39
+
40
+ find_library(GMP_LIBRARY gmp PATHS "C:/vcpkg/installed/x64-windows/lib" NO_DEFAULT_PATH)
41
+ find_library(MPFR_LIBRARY mpfr PATHS "C:/vcpkg/installed/x64-windows/lib" NO_DEFAULT_PATH)
42
+ if(GMP_LIBRARY AND MPFR_LIBRARY)
43
+ target_link_libraries(CGAL::CGAL INTERFACE ${GMP_LIBRARY} ${MPFR_LIBRARY})
44
+ endif()
45
+
46
+ elseif(APPLE)
47
+ # === MACOS LOGIC ===
48
+ if(TARGET Boost::headers)
49
+ target_link_libraries(CGAL::CGAL INTERFACE Boost::headers)
50
+ elseif(TARGET Boost::boost)
51
+ target_link_libraries(CGAL::CGAL INTERFACE Boost::boost)
52
+ elseif(Boost_INCLUDE_DIRS)
53
+ target_include_directories(CGAL::CGAL INTERFACE "${Boost_INCLUDE_DIRS}")
54
+ endif()
55
+
56
+ find_library(GMP_LIBRARY gmp)
57
+ find_library(MPFR_LIBRARY mpfr)
58
+ if(GMP_LIBRARY AND MPFR_LIBRARY)
59
+ target_link_libraries(CGAL::CGAL INTERFACE ${GMP_LIBRARY} ${MPFR_LIBRARY})
60
+ endif()
61
+
62
+ else()
63
+ # === LINUX (UBUNTU) LOGIC ===
64
+ if(TARGET Boost::headers)
65
+ target_link_libraries(CGAL::CGAL INTERFACE Boost::headers)
66
+ elseif(TARGET Boost::boost)
67
+ target_link_libraries(CGAL::CGAL INTERFACE Boost::boost)
68
+ elseif(Boost_INCLUDE_DIRS)
69
+ target_include_directories(CGAL::CGAL INTERFACE "${Boost_INCLUDE_DIRS}")
70
+ endif()
71
+
72
+ find_library(GMP_LIBRARY gmp)
73
+ find_library(MPFR_LIBRARY mpfr)
74
+ if(GMP_LIBRARY AND MPFR_LIBRARY)
75
+ target_link_libraries(CGAL::CGAL INTERFACE ${GMP_LIBRARY} ${MPFR_LIBRARY})
76
+ endif()
77
+ endif()
78
+
79
+ add_compile_definitions(CGAL_DO_NOT_USE_BOOST_MP)
80
+ add_subdirectory(src/geojac/core)
@@ -0,0 +1,67 @@
1
+ FROM ubuntu:noble
2
+
3
+ ARG DEBIAN_FRONTEND=noninteractive
4
+ ARG uid
5
+ ARG gid
6
+ ARG user
7
+ ARG group
8
+
9
+ # Ubuntu 24.04 enforces PEP 668 (externally-managed Python).
10
+ # This env var allows pip to install into the system Python without a venv.
11
+ ENV PIP_BREAK_SYSTEM_PACKAGES=1
12
+
13
+ RUN apt-get update
14
+ RUN apt-get install -y tzdata
15
+ RUN apt-get upgrade -y
16
+
17
+ RUN echo 'alias ll="ls -l --color -a"' >> /root/.bashrc
18
+
19
+ # Python 3.12 is the default on ubuntu:noble
20
+ RUN apt-get install -y python3 python3-pip python3-dev python3-venv
21
+
22
+ # C++ build tools
23
+ RUN apt-get install -y build-essential cmake git pkg-config
24
+ RUN apt-get install -y pybind11-dev
25
+ RUN apt-get install -y xz-utils
26
+ RUN apt-get install -y g++
27
+
28
+ # CGAL arithmetic dependencies (CGAL headers are downloaded by CMake FetchContent)
29
+ RUN apt-get install -y libboost-all-dev
30
+ RUN apt-get install -y libgmp-dev
31
+ RUN apt-get install -y libmpfr-dev
32
+ # System CGAL satisfies any residual cmake detection; FetchContent supplies v6.0.1 headers
33
+ RUN apt-get install -y libcgal-dev
34
+
35
+ # Geospatial system libraries
36
+ RUN apt-get install -y libspatialindex-dev libgeos-dev libproj-dev
37
+
38
+ # Display / Qt libraries (libgl1 replaces libgl1-mesa-glx on ubuntu:noble)
39
+ RUN apt-get install -y libgl1 libglib2.0-0 libsm6 libxrender1 libxext6 libfontconfig1
40
+ RUN apt-get install -y python3-pyqt5 python3-pyqt5.qtopengl
41
+
42
+ RUN rm -rf /var/lib/apt/lists/*
43
+
44
+ RUN mkdir -p /workspace
45
+
46
+ # ubuntu:noble ships a default 'ubuntu' user at UID 1000 — remove it before
47
+ # creating our own user so useradd does not fail on a duplicate UID.
48
+ RUN userdel -r ubuntu 2>/dev/null || true
49
+ RUN groupadd -g ${gid} ${group} || true
50
+ RUN useradd -m -u ${uid} -g ${gid} -s /bin/bash ${user} || true
51
+
52
+ RUN echo 'alias ll="ls -l --color -a"' >> /home/${user}/.bashrc || true
53
+
54
+ RUN chown -R ${uid}:${gid} /workspace
55
+
56
+ USER ${user}
57
+ WORKDIR /workspace
58
+
59
+ COPY --chown=${user}:${group} . /workspace/
60
+
61
+ RUN pip3 install -r requirements.txt
62
+
63
+ RUN mkdir -p build
64
+ WORKDIR /workspace/build
65
+ RUN cmake .. && make -j$(nproc)
66
+
67
+ WORKDIR /workspace
geojac-0.2.2/Makefile ADDED
@@ -0,0 +1,79 @@
1
+ .PHONY: build shell shell-user test example example-realtime example-simplification example-simplification-visual example-crime example-crime-osm example-simplification-osm example-minkowski-osm clean clean-all help
2
+
3
+ .DEFAULT_GOAL := help
4
+
5
+ help:
6
+ @echo "ACJ Library - Makefile Commands"
7
+ @echo "================================"
8
+ @echo ""
9
+ @echo "Main commands:"
10
+ @echo " make build - Build Docker image with all dependencies"
11
+ @echo " make test - Run ACJ library tests"
12
+ @echo ""
13
+ @echo "Examples with synthetic data:"
14
+ @echo " make example - Basic ACJ example"
15
+ @echo " make example-simplification-visual - Graph simplification demo (synthetic)"
16
+ @echo " make example-crime - Crime heatmap demo (synthetic)"
17
+ @echo ""
18
+ @echo "Examples with real OSM data (configurable city):"
19
+ @echo " make example-realtime - Real-time crime heatmap"
20
+ @echo " make example-simplification - Graph simplification comparison"
21
+ @echo " make example-minkowski-osm - Minkowski simplification (configurable location)"
22
+ @echo " make example-crime-osm - Crime heatmap (configurable location)"
23
+ @echo " make example-simplification-osm - Simplification (configurable location)"
24
+ @echo ""
25
+ @echo "Cleanup commands:"
26
+ @echo " make clean - Clean build artifacts"
27
+ @echo " make clean-all - Clean everything including Docker cache"
28
+ @echo ""
29
+ @echo "Development commands:"
30
+ @echo " make shell - Open Docker shell as root"
31
+ @echo " make shell-user - Open Docker shell as user"
32
+
33
+ # Build Docker image
34
+ build:
35
+ docker build -f Dockerfile -t ubuntu-geojac:1 --build-arg uid="$(shell id -u)" --build-arg gid="$(shell id -g)" --build-arg user=dockeruser --build-arg group=dockergroup .
36
+
37
+ # Interactive shells
38
+ shell:
39
+ docker run -v $(shell pwd):/workspace -w /workspace -it ubuntu-geojac:1 /bin/bash
40
+
41
+ shell-user:
42
+ docker run --user $(shell id -u):$(shell id -g) -v $(shell pwd):/workspace -w /workspace -it ubuntu-geojac:1 /bin/bash
43
+
44
+ # ACJ Library commands (Actualizado para Arquitectura src/)
45
+ test: ## Run ACJ library test suite
46
+ docker run --user $(shell id -u):$(shell id -g) -v $(shell pwd):/workspace ubuntu-geojac:1 sh -c "cd /workspace && mkdir -p build && cd build && cmake .. && make -j\$$(nproc) && cd .. && PYTHONPATH=/workspace/build:/workspace/src python3 -m pytest tests/ -v"
47
+
48
+ example: ## Run basic ACJ library example
49
+ docker run --user $(shell id -u):$(shell id -g) -v $(shell pwd):/workspace ubuntu-geojac:1 sh -c "cd /workspace && mkdir -p build && cd build && cmake .. && make -j\$$(nproc) && cd .. && PYTHONPATH=/workspace/build:/workspace/src python3 examples/example_acj.py"
50
+
51
+ example-realtime: ## Run real-time interactive visualization with VisPy
52
+ docker run --user $(shell id -u):$(shell id -g) -v $(shell pwd):/workspace -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$$DISPLAY ubuntu-geojac:1 sh -c "cd /workspace && mkdir -p build && cd build && cmake .. && make -j\$$(nproc) && cd .. && PYTHONPATH=/workspace/build:/workspace/src python3 examples/example_realtime.py"
53
+
54
+ example-simplification: ## Run graph simplification comparison
55
+ docker run --user $(shell id -u):$(shell id -g) -v $(shell pwd):/workspace -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$$DISPLAY ubuntu-geojac:1 sh -c "cd /workspace && mkdir -p build && cd build && cmake .. && make -j\$$(nproc) && cd .. && PYTHONPATH=/workspace/build:/workspace/src python3 examples/example_simplification.py"
56
+
57
+ example-simplification-visual: ## Run visual graph simplification demo with interactive comparison
58
+ docker run --user $(shell id -u):$(shell id -g) -v $(shell pwd):/workspace -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$$DISPLAY ubuntu-geojac:1 sh -c "cd /workspace && mkdir -p build && cd build && cmake .. && make -j\$$(nproc) && cd .. && PYTHONPATH=/workspace/build:/workspace/src python3 examples/example_simplification_visual.py"
59
+
60
+ example-crime: ## Run crime heatmap visualization demo with interactive comparison
61
+ docker run --user $(shell id -u):$(shell id -g) -v $(shell pwd):/workspace -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$$DISPLAY ubuntu-geojac:1 sh -c "cd /workspace && mkdir -p build && cd build && cmake .. && make -j\$$(nproc) && cd .. && PYTHONPATH=/workspace/build:/workspace/src python3 examples/example_crime_visualization.py"
62
+
63
+ example-crime-osm: ## Run crime heatmap with real OSM data (configurable location)
64
+ docker run --user $(shell id -u):$(shell id -g) -v $(shell pwd):/workspace -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$$DISPLAY ubuntu-geojac:1 sh -c "cd /workspace && mkdir -p build && cd build && cmake .. && make -j\$$(nproc) && cd .. && PYTHONPATH=/workspace/build:/workspace/src python3 examples/example_crime_osm.py"
65
+
66
+ example-simplification-osm: ## Run simplification comparison with real OSM data (configurable location)
67
+ docker run --user $(shell id -u):$(shell id -g) -v $(shell pwd):/workspace -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$$DISPLAY ubuntu-geojac:1 sh -c "cd /workspace && mkdir -p build && cd build && cmake .. && make -j\$$(nproc) && cd .. && PYTHONPATH=/workspace/build:/workspace/src python3 examples/example_simplification_osm.py"
68
+
69
+ example-minkowski-osm: ## Run Minkowski simplification with real OSM data (configurable location)
70
+ docker run --user $(shell id -u):$(shell id -g) -v $(shell pwd):/workspace -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$$DISPLAY ubuntu-geojac:1 sh -c "cd /workspace && mkdir -p build && cd build && cmake .. && make -j\$$(nproc) && cd .. && PYTHONPATH=/workspace/build:/workspace/src python3 examples/example_minkowski_osm.py"
71
+
72
+
73
+ # Cleanup
74
+ clean: ## Clean build artifacts
75
+ rm -rf build/ cache/ output/
76
+
77
+ clean-all: ## Clean everything including Docker cache
78
+ rm -rf build/ cache/ output/
79
+ docker rmi ubuntu-geojac:1 || true
geojac-0.2.2/PKG-INFO ADDED
@@ -0,0 +1,234 @@
1
+ Metadata-Version: 2.2
2
+ Name: geojac
3
+ Version: 0.2.2
4
+ Summary: Simplificacion de grafos urbanos y analisis de criminalidad
5
+ Author-Email: ACJ Team <acj-team@utec.edu.pe>
6
+ Requires-Python: >=3.10
7
+ Requires-Dist: numpy
8
+ Requires-Dist: pandas
9
+ Requires-Dist: networkx
10
+ Requires-Dist: geopandas
11
+ Requires-Dist: osmnx
12
+ Provides-Extra: viz
13
+ Requires-Dist: vispy; extra == "viz"
14
+ Requires-Dist: PyQt5; extra == "viz"
15
+ Provides-Extra: test
16
+ Requires-Dist: pytest; extra == "test"
17
+ Description-Content-Type: text/markdown
18
+
19
+ # ACJ: Urban Graph Acceleration & Simplification Framework
20
+
21
+ ![Python](https://img.shields.io/badge/Python-3.10+-blue.svg?logo=python&logoColor=white)
22
+ ![C++](https://img.shields.io/badge/C++-17-00599C.svg?logo=c%2B%2B&logoColor=white)
23
+ ![PyPI](https://img.shields.io/pypi/v/geojac.svg)
24
+ ![License](https://img.shields.io/badge/License-MIT-green.svg)
25
+
26
+ **ACJ** is a high-performance hybrid C++/Python framework for the semantic and topological simplification of large-scale urban street networks. It safely decouples topology from semantic metadata (speed limits, road names, etc.) so that both survive massive graph reductions powered by a CGAL-accelerated C++ core.
27
+
28
+ ---
29
+
30
+ ## Installation
31
+
32
+ ACJ is published on PyPI and ships with pre-compiled wheels for Linux, macOS (Apple Silicon & Intel), and Windows. No C++ compilation required.
33
+
34
+ ```bash
35
+ pip install geojac
36
+ ```
37
+
38
+ For GPU-accelerated real-time visualization, install the optional extras:
39
+
40
+ ```bash
41
+ pip install "geojac[viz]"
42
+ ```
43
+
44
+ > We recommend working inside a virtual environment: `python -m venv venv && source venv/bin/activate`
45
+
46
+ ---
47
+
48
+ ## Quick Start — End-to-End Pipeline
49
+
50
+ ```python
51
+ import osmnx as ox
52
+ from geojac import UrbanNetwork, ACJTopologicalEvaluator
53
+ from geojac import CompressionRatioMetric, SemanticSpeedDistortionMetric
54
+
55
+ # 1. Fetch a raw street network
56
+ G = ox.graph_from_place("Barranco, Lima, Peru", network_type="drive")
57
+
58
+ # 2. Parse into the ACJ registry
59
+ network = UrbanNetwork.from_networkx(G)
60
+ print(network)
61
+ # <UrbanNetwork | Nodes: 312 (Meta: True) | Edges: 847 (Meta: True)>
62
+
63
+ # 3. Configure metrics and run the evaluator
64
+ metrics = [CompressionRatioMetric(), SemanticSpeedDistortionMetric()]
65
+ evaluator = ACJTopologicalEvaluator(network, metrics)
66
+ results = evaluator.evaluate()
67
+
68
+ print(results)
69
+ print(evaluator.simplified_network)
70
+ ```
71
+
72
+ ---
73
+
74
+ ## API Reference
75
+
76
+ ### `UrbanNetwork` — Core Data Container
77
+
78
+ The central data structure. Stores topology in Pandas DataFrames and semantic attributes in dictionaries, keeping them decoupled for safe C++ operations.
79
+
80
+ ```python
81
+ from geojac import UrbanNetwork
82
+
83
+ # From an OSMnx / NetworkX graph
84
+ network = UrbanNetwork.from_networkx(G)
85
+
86
+ # From raw DataFrames
87
+ # nodes_df must have columns: node_id, x, y (+ any metadata columns)
88
+ # edges_df must have columns: segment_id, node_start, node_end (+ any metadata columns)
89
+ network = UrbanNetwork.from_dataframe(nodes_df, edges_df)
90
+ ```
91
+
92
+ **Key attributes:**
93
+
94
+ | Attribute | Type | Description |
95
+ |---|---|---|
96
+ | `nodes_df` | `pd.DataFrame` | Node topology: `node_id`, `x`, `y` |
97
+ | `edges_df` | `pd.DataFrame` | Edge topology: `segment_id`, `node_start`, `node_end` |
98
+ | `node_metadata` | `dict` | Per-node semantic attributes keyed by `node_id` |
99
+ | `edge_metadata` | `dict` | Per-edge semantic attributes keyed by `segment_id` |
100
+
101
+ ---
102
+
103
+ ### `MapIndex` — Spatial Queries
104
+
105
+ CGAL-backed spatial index for fast nearest-neighbor point-to-graph assignment. Useful for correlating events (e.g., crime incidents) with street segments or intersections.
106
+
107
+ ```python
108
+ from geojac import MapIndex, load_graph
109
+ import pandas as pd
110
+
111
+ graph_data = load_graph(nodes_df, edges_df)
112
+ index = MapIndex(graph_data)
113
+
114
+ # Assign point events to the nearest node
115
+ points = pd.DataFrame({'point_id': [1, 2], 'x': [-77.02, -77.03], 'y': [-12.15, -12.14]})
116
+ node_assignments = index.assign_to_endpoints(points)
117
+ # Returns original DataFrame + 'assigned_node_id' and 'distance' columns
118
+
119
+ # Assign point events to the nearest edge segment
120
+ segment_assignments = index.assign_to_segments(points)
121
+ # Returns original DataFrame + 'assigned_segment_id' and 'distance' columns
122
+ ```
123
+
124
+ ---
125
+
126
+ ### `ACJTopologicalEvaluator` — Simplification Lifecycle
127
+
128
+ Automates the full pipeline: injects the network into the C++ core, receives the simplified topology with lineage maps, runs semantic resolution, and applies metrics.
129
+
130
+ ```python
131
+ from geojac import ACJTopologicalEvaluator, CompressionRatioMetric, SemanticSpeedDistortionMetric
132
+
133
+ evaluator = ACJTopologicalEvaluator(network, metrics=[
134
+ CompressionRatioMetric(),
135
+ SemanticSpeedDistortionMetric(),
136
+ ])
137
+ results = evaluator.evaluate()
138
+
139
+ simplified = evaluator.simplified_network # UrbanNetwork
140
+ ```
141
+
142
+ **Built-in metrics:**
143
+
144
+ | Class | Measures |
145
+ |---|---|
146
+ | `CompressionRatioMetric` | Node/edge reduction ratio after simplification |
147
+ | `SemanticSpeedDistortionMetric` | Speed-limit distribution distortion introduced by edge merging |
148
+
149
+ ---
150
+
151
+ ### Visualization (optional `viz` extra)
152
+
153
+ GPU-accelerated interactive tools built on VisPy/OpenGL. Requires `pip install "geojac[viz]"`.
154
+
155
+ ```python
156
+ from geojac import MapIndex, load_graph
157
+ from geojac import render_graph, render_heatmap, render_comparison
158
+
159
+ graph_data = load_graph(nodes_df, edges_df)
160
+ index = MapIndex(graph_data)
161
+
162
+ # Render the raw street network
163
+ render_graph(index)
164
+
165
+ # Render a heatmap of point assignments over the network
166
+ render_heatmap(index, assignments=node_assignments)
167
+
168
+ # Side-by-side comparison of two networks (e.g., original vs. simplified)
169
+ render_comparison(
170
+ index_original, index_simplified,
171
+ title_left="Original", title_right="Simplified"
172
+ )
173
+ ```
174
+
175
+ **Interactive controls (all render functions):**
176
+
177
+ | Key | Action |
178
+ |---|---|
179
+ | `N` | Toggle node layer |
180
+ | `L` | Toggle segment layer |
181
+ | `G` | Toggle grid |
182
+ | `R` | Reset camera view |
183
+ | `Q` / `Esc` | Close window |
184
+
185
+ ---
186
+
187
+ ### `load_graph` / `load_map` — Data IO
188
+
189
+ ```python
190
+ from geojac import load_graph, load_map
191
+
192
+ # Build a GraphData object from DataFrames (required input for MapIndex)
193
+ graph_data = load_graph(nodes_df, edges_df)
194
+
195
+ # Load from a file path (GeoJSON, Shapefile, etc.)
196
+ graph_data = load_map("path/to/network.geojson")
197
+ ```
198
+
199
+ ---
200
+
201
+ ## Developer Installation (From Source)
202
+
203
+ Required: CMake ≥ 3.15, C++17, CGAL, Boost, pybind11.
204
+
205
+ ```bash
206
+ # Ubuntu/Debian
207
+ sudo apt-get install cmake libcgal-dev libboost-all-dev
208
+
209
+ # Arch Linux
210
+ sudo pacman -S cmake cgal boost pybind11
211
+ ```
212
+
213
+ ```bash
214
+ git clone https://github.com/CdeCasurpie/CS5351-acj.git
215
+ cd CS5351-acj
216
+ python -m venv venv && source venv/bin/activate
217
+ pip install -U pip setuptools wheel
218
+ pip install -e .
219
+ ```
220
+
221
+ ---
222
+
223
+ ## Academic Team & Acknowledgements
224
+
225
+ This framework was developed as part of a thesis research project at the Universidad de Ingeniería y Tecnología (UTEC).
226
+
227
+ **Lead Researchers & Engineers:**
228
+ * Alejandro Calizaya
229
+ * Cesar Perales
230
+ * Jerimy Sandoval
231
+
232
+ **Thesis Advisors:**
233
+ * **Eric Javier Biagioli** - Academic Director, Department of Computer and Data Science, UTEC ([ORCID: 0009-0000-2027-0647](https://orcid.org/0009-0000-2027-0647))
234
+ * **Germain García Zanabria** - Researcher, Artificial Intelligence Research Group (GINIA), UTEC ([ORCID: 0000-0003-3266-9043](https://orcid.org/0000-0003-3266-9043))