Metadata-Version: 2.4
Name: plangeom
Version: 0.1.0a6
Summary: Read construction floor plans from vector PDFs by geometry alone and write a checked JSON description. No model training.
Keywords: pdf,floor plan,bim,cad,vector,geometry
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: numpy>=1.26
Requires-Dist: scipy>=1.11
Requires-Dist: shapely>=2.0
Requires-Dist: opencv-python-headless>=4.8
Requires-Dist: scikit-image>=0.22
Requires-Dist: pypdfium2>=4.30
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: jsonschema>=4; extra == "dev"
Requires-Dist: reportlab>=4; extra == "dev"

# plangeom

Reads construction floor plans from vector PDFs by geometry alone and writes a checked JSON description. No model training.

```bash
pip install plangeom
plangeom plan.pdf --page 0 --summary -o sheet.json
```

`--summary` prints the short answer: scale, rooms by type, wet rooms with their fixtures, doors, windows, stairs, risers, and `doubts`, what not to take on trust, item by item. The full description goes to the file.

```python
from plangeom import parse_page
sheet = parse_page("plan.pdf", 0)
print(sheet["summary"])
```

## For AI agents

`plangeom --guide` says how to use it and how far to trust it; `help(plangeom)` is the same text. `plangeom --fields` gives the meaning of every field. Importing the library shows nothing by itself. To change the library, not only use it: `plangeom-dev get plangeom_code`, then `AGENTS.md` in that folder.

- Start from `summary`. The full JSON is hundreds of kilobytes: filter it, do not print it.
- `verdict: accepted` means the geometric checks passed, not that fixtures and room types are complete. Pass `summary.doubts` on to your reader.
- Drain routes, extract points, heaters: `plangeom.mep.plan_services(sheet)`, planning defaults, not a design.

A whole set of drawings, one PDF or several volumes of a project:

```bash
plangeom ar.pdf kr.pdf --all --summary -o building.json
```

```python
from plangeom import parse_document
result = parse_document(["ar.pdf", "kr.pdf"], workers=4)
print(result["summary"])
```

## What it does

- **Scale from the axis grid.** Axes are found as circles of paper-fixed size with a long line through the centre. Values printed between axes give millimetres. With no text, axis spacing as multiples of a building module does, with door leaves and round wall thickness settling the harmonic.
- **Walls** from filled bodies, thickness from opposite edges, centrelines from parallel edge pairs.
- **Materials** as clusters of hatch geometry, without reading colour. Clusters have no names until a legend or a person names them.
- **Doors** as a circular arc plus a radial leaf. The sweep angle is deliberately not a criterion.
- **Rooms** as exact planar faces where walls close them, a watershed from room tags where they do not, and a clearance watershed when the sheet has no text.
- **Repeated symbols** by D2 shape distribution and size, confirmed by modified Hausdorff distance.
- **Windows and openings** as gaps between wall ends, in a belt along the slab edge, looking out.
- **Stairs** as rows of treads, drawn or painted, with flights, landings and the hole in the slab.
- **Fixtures and cars** by real sizes and shape; a room's type from its name or from what stands in it.
- **Whole sets.** Stamps give the section, floor, typical floors and level. Sheets on one axis grid under one name are one building; risers, stair wells and lifts run through its floors, and what a floor could not read is taken from the floors around it and marked as taken. Structural sheets judge the wall roles of architectural ones.

## Sections of the documentation

A sheet goes to the reader of its section by the code on its stamp. `core` is shared by all. `ar` (architecture) is working. `kr`, `ov`, `vk` and `eo` are placeholders: axes, scale, stamp and wall bodies are read, the section's own elements are not, and `summary.reader` says so. To work on a section with no accounts and no version control: `plangeom-dev`, see `CONTRIBUTING.md`.

## It does not guess silently

Every stroke ends in one row of a ledger. Whatever no rule owns goes to `queue`. Checks come from the sheet itself: printed values against axes, room areas against the schedule, thickness and door plausibility. A sheet that fails any of them gets `"verdict": "needs_review"`.

## Status: alpha

Tested on synthetic drawings in `tests/`, and by hand on a private corpus of real sheets. Known limits today:

- Most real sheets end as `needs_review`: read them with their checks, not as finished models.
- Room areas agree with schedules at a median error of 4 to 9 % on real projects, and much worse on garages.
- Stamps are read in Russian.
- The scale from axes without text can land on a harmonic of the true scale.
- Scanned pages are not handled: a page with no vector strokes returns `not_a_vector_drawing`.
- The plan for services in `plangeom.mep` is a first pass with planning defaults, not a design.

## Output

JSON Schema with the meaning of every field: `plangeom.schema.SCHEMA`. Lengths are millimetres in a sheet frame with y down.

## License

No license has been granted yet: all rights reserved.
