PlotMeasure is an Android app for measuring land/plot distance, perimeter, and area directly from cadastral PDF maps. It is built in Kotlin with Jetpack Compose and keeps all measurement points in PDF page coordinates so overlays stay accurate during zoom and pan.
Android app for measuring plot and land area from cadastral, survey, and revisional map PDFs using calibration and polygon tracing.
Releases: https://github.com/tanik-kumar/plotmeasure-android/releases
Topics: android, kotlin, jetpack-compose, pdf, pdf-renderer, land-measurement, cadastral-maps, survey-maps, revisional-map
- Platform: Android
- Minimum Android version:
minSdk 24(Android 7.0) - Latest signed release APK:
PlotMeasure-v1.1.0-release.apk - GitHub releases: https://github.com/tanik-kumar/plotmeasure-android/releases
- SHA-256:
c2531adc0b3e21f1ba22e800652386af79137c9a06a9d93c9bb599382c5d4bbf
Direct install steps:
- Download the signed APK from the GitHub Releases page.
- Allow installation from the browser or file manager if Android asks.
- Open the APK and install.
- Launch
PlotMeasure v1.1.0.
Screenshot files are stored under docs/screenshots/README.md.
- Kotlin
- Jetpack Compose
- MVVM
- Repository pattern
- Android
PdfRenderer - JSON-based local persistence with
kotlinx.serialization
The MVP layer in this codebase includes:
- PDF import with Storage Access Framework
- Multi-page selection
- PDF rendering with visible-region high-detail rerendering
- Smooth zoom and pan
- Distance, path, and polygon area modes
- Manual, ratio, and text-scale calibration
- Live segment length, perimeter, area, and centroid
- Multiple plots on the same page
- JSON project persistence
The improved layer adds:
- Edit mode with point dragging
- Long-press vertex insertion
- Selected-point deletion
- Undo/redo
- Calibration presets
- Export to JSON, CSV, and annotated PDF
- Layer visibility toggles
- Configurable Bihar land-unit conversions
- Magnifier loupe
- Local edge snapping based on PDF bitmap gradients
app/src/main/java/com/tanik/biharmapmeasure
├── MainActivity.kt
└── plotmeasure
├── core
│ ├── calibration
│ ├── export
│ ├── geometry
│ ├── pdf
│ └── UndoManager.kt
├── data
│ ├── JsonProjectRepository.kt
│ └── SettingsRepository.kt
├── model
│ └── PlotMeasureModels.kt
└── ui
├── components
├── theme
├── PlotMeasureApp.kt
├── PlotMeasureUiState.kt
└── PlotMeasureViewModel.kt
Compose UI
-> PlotMeasureViewModel
-> JsonProjectRepository
-> SettingsRepository
-> PdfRenderEngine
-> ReportExporter
-> GeometryEngine
-> CalibrationEngine
UI viewer gestures
-> page-space points / viewport
-> ViewModel state update
-> repositories + geometry + export
-> Compose redraw
The viewer never stores interaction in screen pixels.
PdfRenderEngineexposes page size and rendered bitmap tiles.- The viewer keeps a transform:
screenX = pageX * scale + offsetXscreenY = pageY * scale + offsetY
- Screen taps are converted back into page coordinates:
pageX = (screenX - offsetX) / scalepageY = (screenY - offsetY) / scale
- Only page coordinates are persisted in projects.
Because of that, zooming to a new tile resolution never changes stored points or computed measurements.
If the user picks two points on the PDF with page distance d_page, and enters real distance d_real in meters:
metersPerPageUnit = d_real / d_page
Android PdfRenderer page units behave like PDF points, where:
1 page unit = 1/72 inch
So for ratio 1:N:
metersPerPageUnit = N * (0.0254 / 72)
For a printed statement like 16 inches = 1 mile:
pageUnitsForMapDistance = mapDistanceMeters / (0.0254 / 72)
metersPerPageUnit = groundDistanceMeters / pageUnitsForMapDistance
- Distance uses Euclidean distance in page space
- Path length sums segment lengths
- Area uses the shoelace formula
- Concave polygons are supported
- Self-intersecting polygons are detected and flagged
- Area is blocked when the polygon is invalid
Large PDFs are handled with two render layers:
- A full-page render for immediate viewing and global navigation
- A viewport tile render that rerenders only the visible region at higher density during deep zoom
This reduces memory pressure versus rendering the full page at extreme zoom while keeping point placement sharp enough for cadastral work.
- PDF files are accessed from device storage only after user selection.
- Measurement projects and settings are stored locally on device.
- Data is not uploaded by the app unless the user explicitly exports files or shares artifacts outside the app.
- Release signing files must remain private and must not be committed.
- OCR-based automatic scale extraction is not included in
v1.1.0. - Measurement accuracy depends on PDF quality, page calibration, and point placement precision.
- Edge snapping is bitmap-based and may be less reliable on noisy scans.
- Very large or highly detailed PDFs can still require more render time during deep zoom.
- OCR-assisted scale detection
- Better snapped boundary detection for scanned maps
- Richer export layouts with annotated preview images
- Improved project management across multiple sheets
- More regional unit presets and conversion templates
- Open the project in Android Studio Giraffe+ or Hedgehog+.
- Ensure the Android SDK for API 34 is installed.
- Build with:
./gradlew assembleDebugFor a signed release build:
./gradlew assembleRelease copyNamedReleaseApk- Tap
Openand choose a PDF map. - Choose the page.
- Open
Calibrateand pick one of:- manual
- ratio
1:N - text scale
- saved preset
- Tap around the plot boundary.
- Switch to
Editto drag or insert points. - Export PDF, JSON, or CSV from the top bar.
Run:
./gradlew testDebugUnitTestCurrent release: v1.1.0
- Annotated PDF export with one extra details page
- Calibration overlay included in exported PDF when manual calibration points are stored
- Thin-outline, small-label export styling for printed map output
- Existing JSON/CSV export and large-view editing remain available
See CHANGELOG.md for the detailed history.




