A single-file, fully offline AS9102 ballooning tool — and a worked example of how I build and measure document extraction.
Drop an engineering drawing on it, get an AS9102 Form 3 as a CSV. One 440 KB executable, no installer, no runtime, no account, no network calls. Free, MIT.
Download FirstArticle.exe · Windows 10/11 64-bit
There are mature commercial tools that do more than this. QA-CAD is $1,195 as a one-time perpetual licence, runs on-premise, supports air-gapped deployment, reads DWG, DXF, HPGL/2, DWF, TIFF and PDF, and auto-captures GD&T feature control frames. High QA, DISCUS, Ideagen Quality Control and SolidWorks Inspection all run on the desktop too.
So "offline" is not a gap in this market, and this project does not pretend to be a better product than any of them. It reads PDF text layers and, optionally, images via a local vision model. It reads no DWG or DXF at all. It cannot resolve a GD&T frame's symbol or datum references from a PDF, and flags those rows as unverified rather than guessing. It does not expand fit classes, inherit general-note tolerances, or resolve requirements across sheets — which is, by most accounts, exactly where automated ballooning actually struggles.
If you balloon drawings for a living, buy one of the tools above. I would.
What this is worth your time for:
- It is free and it is one file. If you need to check a drawing occasionally and cannot justify a licence or an install on a locked-down machine, that is a real gap and this fills it.
- On a born-digital PDF — which is what nearly every CAD package exports — it transcribes the callouts directly out of the PDF's text layer in about 150 ms, with no model and no OCR anywhere in the path. A parser cannot invent a tolerance.
- It shows its work. The accuracy numbers come with the script that produces them and a log of every defect found, including the ones my own test harness caused.
python tools/score_all.py
| Dimensional characteristics recalled | 92 / 92 — 100% |
| GD&T frame tolerances captured and flagged for review | 24 / 24 — 100% |
| Form rows traceable to a real characteristic | 136 / 136 — 100% |
| Multi-sheet attribution, 3-sheet package | 50 / 50 / 12, correct sheet each |
| Born-digital PDF, no GPU | ~150 ms |
Now the caveat that makes those numbers honest: the test drawings in samples/ are
drawings I generated. They are a fair test of the parser — subset fonts where bytes
are glyph indices rather than characters, chained /ASCII85Decode + /FlateDecode
filters, rotated dimension text inside a rotated transform, multi-sheet packages, hole
charts, title blocks, GD&T frames, notes — but they are not your drawings, and 100% on a
synthetic sheet is not a promise about a real one. One real CAD export has been tested
and agreed with an independent parser (PyMuPDF) to within 1–3 tokens per sheet. That is
the entire extent of the real-world evidence.
docs/ACCURACY.md lists every defect found by scoring the output
rather than by the build succeeding — diameters silently classified as lengths, a
tolerance that lost its ±, hole-chart cells emitted as characteristics, feature control
frame tolerances typed as linear dimensions, a prose filter that deleted a real callout,
and the fix for over-capture that immediately caused under-capture. Every one of those
produced a clean build and a successful run.
It also records the two occasions the scoring harness itself was wrong before the code was. A benchmark is a program and it fails the way programs do.
| PDF with a text layer | Callouts transcribed exactly, straight out of the file. No model, no OCR, ~150 ms. |
| PNG / JPG | Routed to a local vision model on 127.0.0.1. Slower; every row flagged for review. |
| Scanned PDF | Not read. Export as PNG first. |
Two columns carry the honesty: Extraction Source (text layer = transcribed,
vision = a model read it) and Needs Review (YES on anything inferred rather than
transcribed). The program never presents a guess as a fact.
Hole charts, revision blocks and BOMs are made of the same text as dimension callouts, so
content alone cannot separate them — 6.680 is either a hole's X ordinate or a 6.68 inch
length. They are separated by column alignment and listed in a second CSV section
rather than deleted, because on some drawings the hole chart is the only place a diameter
is written and quietly dropping it would hand you a short form that looked complete. A
chart cell that is a complete requirement on its own — Ø0.3125 ±.003 — stays in the form.
Not a differentiator — several commercial tools offer the same — but it is a property you may need to verify rather than take on trust:
- No network calls at all on the deterministic path.
- The only address the program can reach is
127.0.0.1, and only for the optional local vision model. - No account, licence server, telemetry, phone-home or update check.
- Static CRT, so no Visual C++ redistributable. Dependencies are Windows itself:
USER32,GDI32,SHELL32,WINHTTP,COMCTL32,KERNEL32. - The source is here and it is one translation unit. Read it, build it, diff the binary.
FirstArticle.exe --report YOURDRAWING.pdf
Writes a counts-only summary: characteristics by kind, how many flagged, how the tolerances are written, and how many text strings the reader walked past grouped by why. No requirement value, no part number, and not even the file name — that is reduced to a digest, because a file name is frequently a part number. It is plain text so you can read it before sending it anywhere.
Visual Studio 2022 Build Tools, then build.bat. One translation unit, no package
manager, no third-party dependency to audit.
The PDF stack is written from scratch in src/pdftext.h: a DEFLATE
decoder (RFC 1951), an ASCII85 decoder, ToUnicode CMap parsing so subset fonts decode to
real characters instead of glyph indices, and a content-stream text extractor that tracks
the graphics state so rotated dimension text lands at the right coordinates.
Linking MuPDF or pdfium would have been far less work and would have destroyed the one property that makes this usable on a locked-down machine: that it is a single file you can copy.
MIT. See LICENSE.
I build offline document-extraction pipelines for organisations whose documents cannot go to a cloud API — export-controlled data, contractual restrictions, air-gapped networks.
This repository is the part of that work I can show you. Not a portfolio screenshot: the source, the benchmark, the script that reproduces it, and a written log of every defect including the ones I caused and the ones my own measurements invented. If you are deciding whether to trust someone with a document pipeline, that log tells you more than a client list would.
If your documents can go to a cloud API and your volume is low, use a cloud API. It is cheaper and I will tell you so. Where it gets interesting is when that is not allowed, or per-page pricing has become the problem, or OCR keeps failing on your scans.
Issues and pull requests welcome. If it fails on your drawing, a bug report with the
--report output is more useful to me than a feature request.