DWG and DXF Drawings Now Get a Browser-Native Diff Tool
Compare DWG/DXF Drawings in the Browser — @mlightcad/cad-diff-viewer
Side-by-side and overlay comparison, all done client-side — no AutoCAD, no server uploads, no waiting for a conversion backend.
Why CAD "diff" is harder than text diff
Engineers are long accustomed to git diff. Drawings are different: geometry, handles, layers, block references, and floating-point coordinates can't be aligned line-by-line like source code. Most teams still switch back and forth between two AutoCAD windows or export PDFs and compare them by eye.
We wanted to build a tool for CAD that feels closer to code review, while keeping the promise of cad-viewer: DWG/DXF parsing and rendering happen entirely in the browser, and drawings never leave the user's device. That's @mlightcad/cad-diff-viewer: a reusable drawing comparison component built on @mlightcad/cad-simple-viewer.
Live demo: https://mlightcad.com/cad-viewer/cad-diff-viewer/
Drag the old drawing into the left pane and the new one into the right. The viewer marks deleted / added / modified entities and colors them in a gray / red / green compare display mode.
What's in the demo page
The online page is a thin host for AcApDiffViewer. You don't need to assemble two viewers yourself — just provide a container, and the component creates the two WebGL canvases.
| Capability | Description |
|---|---|
| Side-by-side | Left old, right new; unchanged geometry stays gray |
| Overlay | New drawing overlaid as a read-only layer on the old canvas, making displacements easy to spot |
| Results panel | Grouped by change type or entity type; supports previous / next navigation |
| Change-set cloud lines | Revision cloud annotations generated by clustering nearby differences |
| Annotation tools | Cloud lines, callout boxes, text, rectangles, circles, arrows, stamps, etc. |
| Settings | Compare colors + AutoCAD-like COMPARE* system variables, with live preview |
| Privacy | DWG/DXF stays in the tab, parsed locally by LibreDWG WASM |
The UI strings use shared i18n (en / zh / tr / cs, etc.).
Architecture in three steps
AcApDiffViewer does not reimplement CAD conversion. It:
- Creates an
AcApDocManagerwith two canvases (left = old, right = new). - Opens each file into its own document session.
- Runs
acapCompareDrawingsagainst the two model-space databases, maps the hits to compare roles, and enables compare display mode — replacing ACI / TrueColor with GPU shading for review.
import { AcApDiffViewer } from '@mlightcad/cad-diff-viewer'
const viewer = new AcApDiffViewer({
container: document.getElementById('diff-host')!,
compareColors: {
unchanged: 0x9ca3af,
deleted: 0xe11d48, // left / old
added: 0x22c55e, // right / new
modified: 0xe11d48
},
webworkerFileUrls: {
mtextRender: './workers/mtext-renderer-worker.js',
dwgParser: './workers/libredwg-parser-worker.js'
}
})
await viewer.openDocument('left', file.name, await file.arrayBuffer())
The host only needs to register a DWG converter (see cad-diff-viewer-example) and mount the component. Parsing still happens in Workers, so the UI stays responsive.
How compare display works (and why it looks "one color")
Normal viewing preserves each entity's CAD color. Compare display does the opposite:
- Every batched fragment is first forced to a base color (default gray
#9ca3af). - Entities with a role override are then swapped to the deleted / added / modified color.
- Selection and hover still take priority over compare coloring.
The coloring happens in the batch highlight shader, not by rewriting materials on the CPU. Each slot's mask texture carries the role in the B channel; R/G are still used for selection / hover.
- Side-by-side: left side marks deletions (and left-side modifications); right side marks additions (and right-side modifications).
- Overlay: the right database is converted again and placed as a read-only overlay on the left canvas (GPU scenes are not moved between canvases). Left modifications are drawn as deleted (red); right modifications as added (green). Unchanged geometry on both sides falls onto the gray base color, making movement easy to see.
Diff algorithm (inspired by AutoCAD COMPARE)
acapCompareDrawings(leftDb, rightDb, options) compares model-space, top-level entities. Options align with common COMPARE system variables:
| System variable | Default | Effect |
|---|---|---|
COMPAREPROPS |
0 |
Property-difference bitmask (color, layer, linetype, etc.). 0 means ignore property-only changes |
COMPAREHATCH |
0 |
Whether to include hatches |
COMPARETEXT |
1 |
Whether to include TEXT / MTEXT / ATTRIB / ATTDEF |
COMPARETOLERANCE |
6 |
Geometric tolerance (6 → 1e-6) |
COMPARERCMARGIN |
5 |
Change-set clustering and cloud-line margin |
Each entity gets:
- A fingerprint — DXF type + quantized geometry (endpoints, center/radius, text content, INSERT transform, etc.; falls back to bounding box when necessary);
- A property key — only includes enabled COMPAREPROPS bits.
Matching order: first by same handle and same DXF type (typical for in-place edits), then among remaining entities by same type (plus layer when layers are enabled) and fingerprint.
Classification:
| Fingerprint | Properties | Result |
|---|---|---|
| Same | Same | Unchanged |
| Same | Different | Modified (property only, requires COMPAREPROPS ≠ 0) |
| Different (handle match) | — | Modified |
| No match | — | Deleted (left only) or Added (right only) |
Nearby hits are grouped into change sets. The toolbar can generate revision cloud lines from these; the results panel navigates by Deleted → Modified → Added.
Honest limitations (in the spirit of AutoCAD COMPARE)
A good open-source tool needs to be clear about its scope:
- Model space, top-level entities only — no paper space, no nesting inside block definitions, and no layout-only work.
- INSERT is treated as a single object (name + transform + own properties). Edits inside block definitions are not traversed.
- Comparison looks at stored entity values, not the resolved ByLayer / ByBlock final appearance. Changing a layer color in the layer table will not mark every entity on that layer as "modified."
- Fingerprints cover common geometry; rare types fall back to bounding boxes, which may miss matches or over-match.
- Overlay mode has no separate "modified" color — modifications are folded into red / green.
Full details are in the package README, so integrators can align expectations.
Where it fits in the cad-viewer stack
@mlightcad/data-model → database and entity model
@mlightcad/cad-simple-viewer → DocManager, WebGL views, annotations, i18n
@mlightcad/cad-diff-viewer → AcApDiffViewer + acapCompareDrawings
npm: @mlightcad/cad-diff-viewer (MIT)
Source: packages/cad-diff-viewer
API docs: cad-viewer.readthedocs.io
Or open the hosted demo directly: CAD Diff Viewer.
Who it's for
- Drawing review workflows — architecture / MEP teams comparing revision sets without desktop COMPARE.
- SaaS and CMS embedding — add drawing review next to a work order or PR; files stay client-side.
- Privacy-sensitive organizations — no "upload first, then convert" hop.
- Open-source integrators — mount one component; or call
acapCompareDrawingsdirectly for headless comparison and bring your own UI.
If you build a product on top of this, we'd love to hear about it in GitHub Discussions / Issues or on X @mlightcad.
Closing
Text has diff, spreadsheets have collaborative review, but drawings are still often "open two files and look carefully." CAD Diff Viewer is our step toward browser-native drawing review: the same serverless stack as cad-viewer, comparison semantics borrowed from AutoCAD, and a UI that drops into any host with a single container.
Online demo: https://mlightcad.com/cad-viewer/cad-diff-viewer/ Repository: https://github.com/mlightcad/cad-viewer
Stars, issues, and PRs are welcome.