Simple Text‑to‑CAD Converter (Python)

A beginner‑friendly clone of text‑to‑cad using only Python’s standard library

Welcome to another official UVF IT guide! In this quick build you’ll create a minimal text‑to‑CAD converter that parses simple shape commands and outputs an OpenSCAD file you can view locally. It’s inspired by the real text‑to‑cad project but stripped down to the essentials so you can finish in about 45 minutes.

The stack is pure Python (no external CAD kernels) and SQLite for storing generated snippets. All tools are free‑tier and run on any modern OS.

Before you start

Minimal Text‑to‑CAD Architecture
LOCAL ENVIRONMENT save snippet write .scad Python Converter SQLite Store OpenSCAD Viewer
1

Phase 1: Scaffold the project

Create a clean workspace so later steps don’t interfere with other Python work. We’ll spin up a virtual environment, activate it, and add a single file called converter.py where all our logic will live. This keeps dependencies isolated and mirrors professional projects.

The scaffold is tiny: just the env and an empty source file. You’ll later add a tiny SQLite helper, but for now we only need the file to exist so the parser can be imported without errors.

python3 -m venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate
pip install --upgrade pip
touch converter.py
2

Phase 2: Core model – parse simple commands

Now we give the converter its brain. The parser reads a line like cube 10 or cylinder 5 20 and turns it into an OpenSCAD snippet. We keep the logic straightforward: split the line, validate the shape, and format the appropriate OpenSCAD call.

The function returns a string so the caller can either write it to a file or store it in SQLite later. Errors raise a clear ValueError so the user knows what went wrong.

converter.py

import sqlite3

def parse_line(line: str) -> str:
    """Convert a simple shape command into an OpenSCAD string.
    Supported commands:
        cube <size>
        cylinder <radius> <height>
    """
    parts = line.strip().split()
    if not parts:
        raise ValueError("Empty command")
    shape = parts[0].lower()
    if shape == "cube" and len(parts) == 2:
        size = float(parts[1])
        return f"cube({size});"
    if shape == "cylinder" and len(parts) == 3:
        r, h = map(float, parts[1:])
        return f"cylinder(r={r}, h={h});"
    raise ValueError(f"Unsupported or malformed command: {line}")

# Tiny helper to persist snippets – not used yet but handy for later phases
def save_snippet(db_path: str, snippet: str) -> None:
    conn = sqlite3.connect(db_path)
    cur = conn.cursor()
    cur.execute("CREATE TABLE IF NOT EXISTS snippets(id INTEGER PRIMARY KEY AUTOINCREMENT, code TEXT)")
    cur.execute("INSERT INTO snippets(code) VALUES(?)", (snippet,))
    conn.commit()
    conn.close()
3

Phase 3: Simple UI – run from terminal

We now give the user a tiny command‑line interface. By passing a shape description as a single argument the script parses it, writes the corresponding OpenSCAD code to output.scad, and stores the raw line in a tiny SQLite log for later inspection. This keeps the tool usable without any GUI while still persisting what was generated.

Running the script is as easy as typing python converter.py "cube 10". The quotes protect the space‑separated parameters from the shell, and the script will echo a short success message so you know the file was created.

python converter.py "cube 10"
4

Phase 4: Verify locally

After the file is written, open it in the free OpenSCAD application to see the actual 3‑D model. OpenSCAD reads the .scad script and renders the geometry instantly, giving you visual confirmation that the parser worked correctly.

If you are on macOS, the open command will launch the default app for .scad files. On Linux you can use xdg-open, and on Windows start. Adjust the command for your platform.

# macOS
open output.scad
# Linux
# xdg-open output.scad
# Windows
# start output.scad
5

Phase 5: Extend (optional)

Want to expose the converter over HTTP? A minimal Flask stub can turn the same parsing logic into a tiny web service. You can POST a shape string to /convert and receive the generated OpenSCAD code as plain text. This is a convenient way to integrate the tool into other pipelines or front‑ends without rewriting the core logic.

The Flask app re‑uses the parse_line function from converter.py, so all existing shapes continue to work. You can later add more routes, authentication, or even a tiny HTML form if you wish.

app.py

from flask import Flask, request, jsonify
import subprocess, os, sys

# Import the parsing function from our existing script
sys.path.append(os.path.dirname(__file__))
from converter import parse_line, write_scad

app = Flask(__name__)

@app.route('/convert', methods=['POST'])
def convert():
    # Expect a JSON payload like {"shape": "cube 10"}
    data = request.get_json(silent=True) or {}
    shape_cmd = data.get('shape', '')
    if not shape_cmd:
        return jsonify({'error': 'No shape provided'}), 400
    # Reuse the core parser
    scad_line = parse_line(shape_cmd)
    if not scad_line:
        return jsonify({'error': 'Unsupported shape'}), 400
    # Write a temporary file for visual debugging (optional)
    write_scad(scad_line, filename='temp_output.scad')
    return jsonify({'scad': scad_line})

if __name__ == '__main__':
    app.run(debug=True)

Verifying the Stack

CheckCommand / Why it matters
Run python converter.py "cube 10" without errorsShows 'Wrote output.scad' and creates snippets.db
cat output.scad displays cube(10);Confirms correct OpenSCAD generation
Open output.scad in OpenSCAD and see a 10×10×10 cubeVisual verification of the shape

You did it!

Your minimal text‑to‑CAD clone is now functional. Feel free to grow it by adding more geometry, a web UI, or integration with real CAD kernels like build123d. Happy coding!