Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
17d7015
feat: add DXF generation pipeline with TOML parser and CLI
May 29, 2026
52f3973
test: add end-to-end integration tests for project compilation
May 29, 2026
118f804
feat: add polyline lineweight and linear dimension (RotatedDimension)…
May 29, 2026
bdc7216
feat: default build to current dir with user-friendly error on missin…
May 29, 2026
f265e77
feat: add cadforge check command to validate project without DXF gene…
May 29, 2026
e036191
feat: add cadforge new command to scaffold project structure
May 29, 2026
ee8a8d5
feat: add cadforge layers command to list project layers with entity …
May 29, 2026
58f2a5d
feat: add --layer flag to build command for single-layer compilation
May 29, 2026
5781536
feat: support hex color on individual entities via DXF 24-bit true color
May 29, 2026
635d0ca
feat: generate .gitignore with output.dxf and target/ in scaffold
May 29, 2026
a08155c
feat: add cadforge init command to initialize project in existing dir…
May 29, 2026
d6576da
docs: update README with CLI usage and .cf format examples
May 29, 2026
192eff2
refactor: extract color module, unify DxfWriter API, DRY compiler wit…
May 29, 2026
1d18fe8
feat: add line styles (dashed/dotted/dashdot), hatch patterns, and im…
May 29, 2026
1ea915a
feat: add solid fill primitive using DXF Solid entities with fan tria…
May 29, 2026
5bdfb9b
feat: add cadforge preview command generating PNG + metadata JSON for…
May 30, 2026
d3576ab
refactor: DRY preview renderer with Bounds accumulator, stroke helper…
May 30, 2026
7f2f495
feat: render fills and hatches in preview, reusing shared boundary re…
May 30, 2026
d1a6b8e
chore(release): bump version to 0.1.0-beta.1
JheisonMB Jun 3, 2026
2f4f7ee
feat(scaffold): generate multi-layer project (muros, puertas, mobilia…
JheisonMB Jun 3, 2026
e393e66
feat(preview): support custom width, height, and layer filter
JheisonMB Jun 3, 2026
34397b2
feat(constraints): add parent, belongs_to, and spatial_dependency val…
JheisonMB Jun 3, 2026
5a4a4a7
refactor(workspace): split into cadforge-cli and cadforge-view crates
JheisonMB Jun 3, 2026
2322ad2
feat(cli): add fmt, watch, view, config, and import subcommands
JheisonMB Jun 3, 2026
c15219c
ci: replace shared workflow with per-job steps and pin triggers
JheisonMB Jun 3, 2026
9b5df14
test(integration): cover constraints and DXF round-trip import
JheisonMB Jun 3, 2026
f5957f1
docs(examples): expand vivienda with full architectural layout
JheisonMB Jun 3, 2026
99afabb
docs(readme): document CLI, layout examples, and DXF/PNG output flow
JheisonMB Jun 3, 2026
d063b38
test(integration): write example compile output to /tmp to keep the p…
JheisonMB Jun 3, 2026
553b2c4
chore: migrate CI to shared UniverLab workflows
JheisonMB Jun 3, 2026
fd7ca27
chore(publish): mark all workspace crates as publishable to crates.io
JheisonMB Jun 3, 2026
6b0ecb2
Merge pull request #1 from UniverLab/dev
JheisonMB Jun 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* text=auto eol=lf
10 changes: 10 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,17 @@ name: CI

on:
pull_request:
workflow_dispatch:
push:
branches: [main]

jobs:
rust-ci:
name: Format, Lint & Test
uses: UniverLab/workflows/.github/workflows/rust-ci.yml@main
with:
run-tests: true
run-clippy: true
check-fmt: true
publish-check: true
main-pr-checks: true
34 changes: 34 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,37 @@ target
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

# AI coding agents
.kiro/
.cursor/
.windsurf/
.claude/
.continue/
.copilot/
.kilocode/
.zencoder/
.qwen/
.agents/
skills-lock.json
# Created by https://www.toptal.com/developers/gitignore/api/rust
# Edit at https://www.toptal.com/developers/gitignore?templates=rust

### Rust ###
# Generated by Cargo
# will have compiled files and executables
debug/
target/

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock

# These are backup files generated by rustfmt

# MSVC Windows builds of rustc generate these, which store debugging information

# End of https://www.toptal.com/developers/gitignore/api/rust
output.dxf
preview.png
preview.meta.json
20 changes: 17 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
[workspace]
members = ["crates/cadforge-cli", "crates/cadforge-view"]
resolver = "2"

[package]
name = "cadforge"
version = "0.1.0"
version = "0.1.0-beta.1"
edition = "2021"
description = ""
publish = false
description = "Architecture as Code — deterministic geometry engine for reproducible architectural design"
license = "MIT"
publish = true

[dependencies]
dxf = "0.6.1"
anyhow = "1.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
toml = "0.8"
toml_edit = "0.22"
indexmap = { version = "2", features = ["serde"] }
tiny-skia = "0.11"
notify = "6.1"
240 changes: 218 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,46 +1,242 @@
# cadforge

>
██████ ████████ ██████ ████████ ██ ██ ██ ███████ ████████
██░░███ ░░███░░███░░░░░███ ░░███░░███░███ ░███ ██░███░░░░░░░███░
░███ ░░░ ░███ ░███ ███████ ░███ ░░░ ░███ ░██████░░█████ ░███
░███ ███ ░███ ░███ ███░░███ ░███ ░███ ░███░░░ ░███░░█ ░███
░░██████ ░███████░░████████ ░███ ░███████████ ███████ ░████████
░░░░░░ ░░░░░░░ ░░░░░░░░ ░░░ ░░░░░░░░░░░ ░░░░░░ ░░░░░░░

<p align="center">
<a href="https://github.com/UniverLab/cadforge/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/UniverLab/cadforge/ci.yml?branch=main&style=for-the-badge&label=CI" alt="CI"/></a>
<a href="https://crates.io/crates/cadforge"><img src="https://img.shields.io/crates/v/cadforge?style=for-the-badge&logo=rust&logoColor=white" alt="Crates.io"/></a>
<img src="https://img.shields.io/badge/Status-Active-27AE60?style=for-the-badge" alt="Status"/>
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-2E8B57?style=for-the-badge" alt="License"/></a>
</p>

cadforge is an **Architecture as Code** CLI tool and Rust library for declarative 2D CAD modeling. Write geometry as code in `.cf` TOML format, compile to DXF, and generate PNG previews for AI agents.

---

## Features

### 🎯 Core Platform

- **📐 Declarative Geometry** — Define architectural elements (lines, rects, circles, arcs, polylines, text, dimensions) in TOML `.cf` files. Deterministic, reproducible, version-controlled.
- **🔗 Layer System** — Organize geometry by layer with custom names, colors, and line weights. Compile single layers or full projects.
- **📄 DXF Export** — Compile `.cf` → DXF (AutoCAD-compatible). Full layer support, LWPOLYLINE for polylines, HATCH for solid fills, MTEXT for annotations.
- **🖼️ PNG Preview** — Generate raster previews with metadata JSON for AI agent integration. Renders fills, hatches, strokes, and text with boundary resolution. Configurable resolution and layer filtering.
- **✅ Validation Engine** — `cadforge check` validates geometry without generating output. Shows project metadata, layer colors, and entity counts.

### 🏗️ Project Management

- **Project Scaffolding** — `cadforge new` creates a complete multi-layer project (muros, puertas, mobiliario, cotas) with meaningful architectural examples.
- **Multi-Layer Compilation** — Compile all layers or target specific layers with `--layer`. Custom output path with `--output`.
- **Auto-Rebuild** — `cadforge watch` monitors `.cf` and `.toml` files and auto-rebuilds on changes with 300ms debounce.
- **Code Formatting** — `cadforge fmt` normalizes `.cf` files. `--check` mode for CI validation.
- **Boundary Resolution** — Automatic detection of closed boundaries for hatch generation. Shared boundary resolution across overlapping entities.
- **Polyline Support** — Full LWPOLYLINE support with bulge factors for arcs. Proper vertex handling and closure detection.

### 🔧 Architecture

- **Compiler Pipeline** — Parse → Resolve → Compile → Emit. Modular design for easy extension.
- **DXF Writer** — Direct DXF entity writing with proper AutoCAD compatibility. Layer/color/lineweight mapping.
- **Preview Renderer** — Tiny-skia based raster rendering with anti-aliasing. PNG + JSON metadata output.
- **Error Reporting** — Structured errors with file, line, and context. Fast-fail on validation errors.

---

## Commands

| Command | Description |
|---------|-------------|
| `cadforge new <name>` | Create a new project with multi-layer scaffold |
| `cadforge init` | Initialize CADforge in current directory |
| `cadforge build` | Compile project to DXF |
| `cadforge build --check` | Validate project and constraints without generating DXF |
| `cadforge build --output <path>` | Compile to custom output path |
| `cadforge build --layer <name>` | Compile specific layer only |
| `cadforge check` | Validate with project metadata and layer colors |
| `cadforge layers` | List layers with entity counts and colors |
| `cadforge preview` | Generate PNG preview + metadata JSON |
| `cadforge preview --width 1024 --height 768` | Custom resolution preview |
| `cadforge preview --layer <name>` | Preview specific layer only |
| `cadforge fmt` | Format .cf files (normalize whitespace) |
| `cadforge fmt --check` | Check formatting without modifying (CI) |
| `cadforge watch` | Auto-rebuild on file changes |
| `cadforge import <file.dxf>` | Import DXF into `.cf` layers + `project.toml` |
| `cadforge import <file.dxf> --layer <name>` | Import only one DXF layer |
| `cadforge view` | Open the dedicated `cadforge-view` viewer |
| `cadforge view --layer <name>` | Open only one layer in the viewer |
| `cadforge config set <key> <value>` | Set global defaults (`author`, `units`) |
| `cadforge config show` | Show global defaults |

### Viewer controls (MVP)

- HUD flotante en pantalla con proyecto, vista, distancia, capas, selección y ayuda de atajos
- `T` / `F` / `V` / `R` → top / front / right / isometric preset views
- `Q` / `E` / `W` / `S` → orbit camera
- Mouse left-drag → orbit
- Mouse right-drag / arrows → pan
- Mouse wheel / `+` / `-` → zoom
- `1`..`9` → toggle layer visibility
- Click entity edge → select primitive id
- Selected entity is highlighted in amber in the viewport HUD context
- `C` → copy selected id to clipboard

---

## .cf Format

```toml
[layer]
name = "muros"
color = "#FFFFFF"

[[line]]
id = "ln-001"
from = [0.0, 0.0]
to = [8.5, 0.0]
weight = 0.50

[[rect]]
id = "rc-001"
origin = [1.0, 1.0]
width = 3.5
height = 4.0

[[circle]]
id = "ci-001"
center = [4.0, 3.0]
radius = 0.5

[[arc]]
id = "ac-001"
center = [2.0, 2.0]
radius = 0.9
from_angle = 0.0
to_angle = 90.0

[[polyline]]
id = "pl-001"
vertices = [[0, 0], [5, 0], [5, 3], [0, 3]]
closed = true

[[text]]
id = "tx-001"
position = [4.0, 3.0]
content = "SALA"
size = 0.2

[[dim]]
id = "dm-001"
from = [0, 0]
to = [5, 0]
offset = 0.5
```

## Getting started
### Supported Primitives

### Prerequisites
`line`, `polyline`, `rect`, `circle`, `arc`, `text`, `point`, `dim`, `hatch`, `solid`

- Rust 1.70+
- Cargo
---

### Build
## Architecture Overview

```bash
cargo build --release
```
.cf file (TOML)
┌─────────┐ ┌──────────┐ ┌─────────┐ ┌─────────┐
│ Parser │───▶│ Resolver │───▶│Compiler │───▶│ DXF Emit│
└─────────┘ └──────────┘ └─────────┘ └─────────┘
┌──────────┐ ┌─────────────┐
│ Boundary │───▶│ Preview PNG │
│ Resolver │ │ + JSON meta │
└──────────┘ └─────────────┘
```

### Run
- **Parser** — TOML parsing with custom array-of-tables detection, primitive validation
- **Resolver** — Layer dependency resolution, coordinate validation, boundary detection
- **Compiler** — Entity compilation to DXF format, hatch generation, polyline closure
- **DXF Writer** — Direct DXF entity emission with proper layer/color/lineweight mapping
- **Preview Renderer** — Tiny-skia raster rendering with hatch/fill support

```bash
cargo run
```
---

## Main Modules

- `compiler/` — Project compilation pipeline, layer targeting, validation, build stats
- `dxf_writer/` — DXF entity writing, LWPOLYLINE, HATCH, MTEXT generation
- `preview/` — PNG rendering with configurable resolution, layer filtering, metadata JSON
- `parser/` — TOML parsing, primitive extraction, array-of-tables handling
- `model/` — Data structures: Layer, Primitive, Project
- `scaffold/` — Multi-layer project creation with architectural examples
- `fmt/` — .cf file formatting and normalization
- `watch/` — File system watcher with auto-rebuild and debounce
- `color/` — Color parsing and DXF color mapping

---

## Data Storage

| Data | Location | Format |
|------|----------|--------|
| Project files | `./` | TOML (`.cf` + `project.toml`) |
| Build output | `output/` | DXF |
| Preview output | `output/preview.png` | PNG |
| Preview metadata | `output/preview.json` | JSON |
| Build cache | `target/` | Cargo build |

### Test
---

## Usage

**Create a new project:**
```bash
cargo test
cadforge new mi-proyecto
cd mi-proyecto
```

## Development
**Edit `.cf` files** (TOML format with your geometry)

### Format code
**Format and validate:**
```bash
cadforge fmt # normalize .cf files
cadforge check # validate without generating DXF
```

**Compile to DXF:**
```bash
cargo fmt
cadforge build # default output.dxf
cadforge build --output plano.dxf # custom output path
cadforge build --layer muros # compile single layer
```

### Lint with Clippy
**Preview:**
```bash
cadforge preview # default 2048x1536
cadforge preview --width 1024 --height 768 # custom resolution
cadforge preview --layer muros # single layer preview
```

**Auto-rebuild on changes:**
```bash
cargo clippy -- -D warnings
cadforge watch # monitors .cf and .toml files
```

---

## Tech Stack

| Rust 2021 | clap | toml | toml_edit | tiny-skia | dxf | notify | anyhow | serde |

---

## License

This project is licensed under the MIT License — see LICENSE for details.
MIT — see [LICENSE](LICENSE) for details.

---

Made with ❤️ by [JheisonMB](https://github.com/JheisonMB) and [UniverLab](https://github.com/UniverLab)
17 changes: 17 additions & 0 deletions crates/cadforge-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "cadforge-cli"
version = "0.1.0-beta.1"
edition = "2021"
description = "CLI binary for cadforge"
license = "MIT"
publish = true

[[bin]]
name = "cadforge"
path = "src/main.rs"

[dependencies]
anyhow = "1.0"
clap = { version = "4.6", features = ["derive"] }
cadforge = { path = "../.." }
cadforge-view = { path = "../cadforge-view" }
Loading
Loading