$3f
You convert product images into DXF block files with embedded FF&E attributes. The result is a
.dxf file containing a named block definition — clean CAD geometry derived from the product
image, plus attribute tags populated with product data — ready to insert into any CAD drawing.
A single .dxf file containing:
0-OUTLINE, 0-DETAIL, 0-CENTERLINE)PRODUCT_NAME, MANUFACTURER, MODEL_NUMBER, FINISH, DIMENSIONS,
PRICE, CATEGORY_CODEThe file opens in AutoCAD, Revit, Rhino, BricsCAD, and any other DXF-compatible application.
.md file) — same format as the moodboard/room-schedule skills;
read with parse_product_data.pyIf the user provides a markdown file path, read it now using scripts/parse_product_data.py.
If they provide details inline, extract them from the conversation.
See references/attribute-schema.md for the complete attribute field definitions and formatting
rules, including category code lookup.
Run the parser if a markdown file was provided:
python scripts/parse_product_data.py --input "/path/to/product.md"
This prints a JSON object with all FF&E fields. Use those values to populate the block attributes.
If data comes from conversation text, extract: name, manufacturer, model, finish, dimensions
(W×D×H), price, and category code. Refer to references/attribute-schema.md for category codes.
Before writing any geometry, study the image carefully. This analysis step is what separates clean CAD output from noisy traced outlines — you're reasoning about the product's intended geometry, not just tracing pixels.
2a. Identify the view type:
When given a perspective photo, decide which view to produce and note it in your output filename
(e.g., chair-front-elevation.dxf). A front elevation is usually most useful for furniture;
a plan view most useful for tables, rugs, and area elements.
2b. Establish the coordinate system: Use product dimensions to set up the drawing space. If dimensions are provided (e.g., 24"W × 18"D × 36"H):
If no dimensions are provided, use a normalized space where the longest dimension = 100 units, and note this in the block attributes.
2c. Identify geometric zones: Break the product into logical regions. Think structurally, not decoratively:
Each zone maps to one or more geometric entities. See references/product-patterns.md for
common patterns by product category.
2d. Identify geometric primitives: For each zone, choose the right primitive:
2e. Apply symmetry: Most products are bilaterally symmetric. Draw one side accurately, then mirror the geometry for the other. This keeps the geometry mathematically consistent.
Build a geometry description JSON object. This is the input to build_block.py:
{
"block_name": "FURN-1-CHAIR-SAARINEN",
"units": "inches",
"width": 26.0,
"height": 31.0,
"entities": [
{"type": "lwpolyline", "points": [[0,0],[26,0],[26,18],[0,18]], "closed": true, "layer": "0-OUTLINE"},
{"type": "lwpolyline", "points": [[3,18],[5,31],[21,31],[23,18]], "closed": true, "layer": "0-DETAIL"},
{"type": "arc", "center": [13,0], "radius": 10, "start_angle": 180, "end_angle": 360, "layer": "0-DETAIL"},
{"type": "line", "start": [13,0], "end": [13,31], "layer": "0-CENTERLINE"}
]
}
Layer assignments:
0-OUTLINE — outer silhouette and primary bounding geometry0-DETAIL — internal features, secondary structure, decorative elements0-CENTERLINE — symmetry axes and reference lines (use sparingly)Entity types supported by build_block.py:
lwpolyline → points: [[x,y],...], closed: true/falsecircle → center: [x,y], radius: rarc → center: [x,y], radius: r, start_angle: deg, end_angle: degline → start: [x,y], end: [x,y]Save this JSON to a temp file at /tmp/geometry.json.
Run the build script:
pip install ezdxf --break-system-packages -q
python scripts/build_block.py \
--geometry /tmp/geometry.json \
--name "PRODUCT NAME" \
--manufacturer "MANUFACTURER" \
--model "MODEL-SKU" \
--finish "Finish / Material" \
--dimensions "24\"W × 18\"D × 36\"H" \
--price "$1,200" \
--category "FURN" \
--output "/path/to/output.dxf"
The script creates the DXF with the full block definition, ATTDEF fields, and a block insert
with populated ATTRIB values. It also sets $INSUNITS to inches (or mm) in the file header.
Save the .dxf file to the user's workspace folder. Use a descriptive filename based on the
category code and product name — for example:
AP-1-solis-pendant-front-elev.dxfFURN-2-saarinen-chair-front-elev.dxfCAB-1-shaker-upper-plan.dxfTell the user which view was generated (front elevation, plan, etc.) and note any significant simplifications made during geometry construction.
If the user explicitly requests automated tracing, or the product has complex organic geometry where interpretation is difficult (sculptural objects, irregular hand-crafted forms), use the tracing pipeline instead of manual geometry construction:
pip install vtracer --break-system-packages -q
python scripts/trace_image.py --input "/path/to/image.jpg" --output /tmp/traced.svg
python scripts/svg_to_dxf.py --input /tmp/traced.svg --output /tmp/traced_geometry.json \
--width 24 --height 36
Then feed the resulting traced_geometry.json to build_block.py as the --geometry argument.
Note that automated tracing produces noisier, less geometrically clean output than manual interpretation — warn the user that cleanup in CAD may be needed.
Before delivering, verify:
CATEGORY-NUM-PRODUCTNAME (e.g., PF-1-SOLIS-PENDANT)0-OUTLINE.dxf file was created without errors from build_block.pyreferences/attribute-schema.md — FF&E attribute field definitions, category code list,
formatting rules for each field. Read this when you need the full category code lookup or
are unsure how to format a field value.references/product-patterns.md — Common geometry patterns for furniture, lighting, plumbing,
cabinetry, and accessories. Read this when you're unsure how to break down a specific product
type into geometric primitives.