Initial infrastructure documentation - comprehensive homelab reference

This commit is contained in:
Funky (OpenClaw)
2026-02-23 03:42:22 +00:00
commit 0682c79580
169 changed files with 63913 additions and 0 deletions

View File

@@ -0,0 +1 @@
C:/Users/Fred/claude-shared/commands

View File

@@ -0,0 +1,16 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Directory listing for /Printing/Nameplates/.claude/</title>
</head>
<body>
<h1>Directory listing for /Printing/Nameplates/.claude/</h1>
<hr>
<ul>
<li><a href="commands">commands</a></li>
<li><a href="settings.local.json">settings.local.json</a></li>
</ul>
<hr>
</body>
</html>

View File

@@ -0,0 +1,36 @@
{
"permissions": {
"allow": [
"Bash(python:*)",
"Bash(dir:*)",
"Bash(\"C:\\Program Files\\OpenSCAD\\openscad.exe\" -D \"name=\"\"Test\"\"\" -o test_output.stl nameplate_template.scad)",
"Bash(\"C:\\Program Files\\OpenSCAD\\openscad.exe\" -o checkmark_test.stl checkmark_template.scad)",
"Bash(\"C:\\Program Files\\OpenSCAD\\openscad.exe\" -D \"name=\"\"Test\"\"\" -o test_hole_position.stl zipper_pull_template.scad)",
"Bash(\"C:\\Program Files\\OpenSCAD\\openscad.exe\" -D \"name=\"\"Christopher\"\"\" -o test_christopher.stl zipper_pull_template.scad)",
"Bash(\"C:\\Program Files\\OpenSCAD\\openscad.exe\" -D \"name=\"\"Christopher\"\"\" -o test_christopher_13pt.stl zipper_pull_template.scad)",
"Bash(\"C:\\Program Files\\OpenSCAD\\openscad.exe\" -D \"name=\"\"Fred\"\"\" -o test_fred_bold.stl zipper_pull_template.scad)",
"Bash(\"C:\\Program Files\\OpenSCAD\\openscad.exe\" -D \"name=\"\"Zoe\"\"\" -o test_zoe.stl zipper_pull_template.scad)",
"Bash(\"C:\\Program Files\\OpenSCAD\\openscad.exe\" -D \"name=\"\"Fred\"\"\" -o test_fred_dynamic.stl zipper_pull_template.scad)",
"Bash(\"C:\\Program Files\\OpenSCAD\\openscad.exe\" -D \"name=\"\"Christopher\"\"\" -o test_christopher_dynamic.stl zipper_pull_template.scad)",
"Bash(timeout:*)",
"Bash(\"C:\\Program Files\\OpenSCAD\\openscad.exe\" -D \"name=\"\"Zoe\"\"\" -o test_zoe_raised.stl zipper_pull_raised_text_template.scad)",
"Bash(\"C:\\Program Files\\OpenSCAD\\openscad.exe\" -D \"name=\"\"Fred\"\"\" -o test_fred_raised.stl zipper_pull_raised_text_template.scad)",
"Bash(\"C:\\Program Files\\OpenSCAD\\openscad.exe\" -D \"name=\"\"Christopher\"\"\" -o test_christopher_raised.stl zipper_pull_raised_text_template.scad)",
"Bash(\"C:\\Program Files\\OpenSCAD\\openscad.exe\" -D \"name=\"\"Fred\"\"\" -D \"base_text_size=13\" -o test_fred_debug.stl zipper_pull_raised_text_template.scad)",
"Bash(\"C:\\Program Files\\OpenSCAD\\openscad.exe\" -o test_simple_fred.stl test_simple_fred.scad)",
"Bash(\"C:\\Program Files\\OpenSCAD\\openscad.exe\" -D \"name=\"\"Fred\"\"\" -o test_fred_reduced_bold.stl zipper_pull_raised_text_template_REDUCED_BOLD.scad)",
"Bash(\"C:\\Program Files\\OpenSCAD\\openscad.exe\" -D \"name=\"\"Bennet\"\"\" -o test_bennet_facedown.stl zipper_pull_raised_text_template.scad)",
"Bash(\"C:\\Program Files\\OpenSCAD\\openscad.exe\" -D \"name=\"\"Bennett\"\"\" -o test_bennett_facedown.stl zipper_pull_raised_text_template.scad)",
"Bash(\"C:\\Program Files\\OpenSCAD\\openscad.exe\" -D \"name=\"\"Bennett\"\"\" -o test_bennett_facedown.3mf zipper_pull_raised_text_template.scad)",
"Bash(\"C:\\Program Files\\OpenSCAD\\openscad.exe\" -o test_font.stl test_font.scad)",
"Bash(\"C:\\Program Files\\OpenSCAD\\openscad.exe\" -o test_debug.3mf test_debug.scad)",
"Bash(\"C:\\Program Files\\OpenSCAD\\openscad.exe\" -o test_blue_only.3mf test_blue_only.scad)"
],
"deny": [],
"ask": []
},
"enableAllProjectMcpServers": true,
"enabledMcpjsonServers": [
"n8n-mcp"
]
}

View File

@@ -0,0 +1,278 @@
# AI Coding Instructions for Nameplates Generator
## Project Overview
A batch 3D nameplate generator using **Python + OpenSCAD**. Reads names from text file, generates parametric two-layer oval nameplates with engraved text, outputs STL files for 3D printing.
**Design**: White base (1.5mm) + blue top layer (1mm) with text engraved through blue layer to expose white underneath.
## Critical Dependencies
### OpenSCAD Installation
- **Path**: `C:\Program Files\OpenSCAD\openscad.exe` (hardcoded in line 36 of `generate_nameplates.py`)
- Download: https://openscad.org/downloads.html
- **Must update path** if installed elsewhere
### Font Requirements (CRITICAL)
- **Font**: Fordscript cursive font (`Fordscript.ttf` in project root)
- **Installation**: Must be installed in Windows (right-click → Install for all users)
- **Why**: OpenSCAD references fonts by name, not file path
- **Reference in SCAD**: `font="Fordscript"` (line 44 of `nameplate_template.scad`)
- **Path hardcoded**: `font_file = "C:/Users/Fred/claude/Fordscript.ttf"` in SCAD (line 10) - informational only, not used by OpenSCAD
## Architecture & Data Flow
```
names.txt → generate_nameplates.py → OpenSCAD CLI → output_stl/*.stl
nameplate_template.scad
```
### Pipeline
1. **Input**: `names.txt` (one name per line, UTF-8 encoded)
2. **Processing**: Python script iterates, calling OpenSCAD for each name
3. **OpenSCAD**: Renders 3D model from parametric template
4. **Output**: Individual STL files in `output_stl/` directory
### Key Files
- `generate_nameplates.py` - Batch processor, subprocess orchestration
- `nameplate_template.scad` - Parametric OpenSCAD template
- `names.txt` - Input data (plain text, one name per line)
- `output_stl/` - Generated STL files (created automatically)
- `Fordscript.ttf` - Custom font (must be installed)
## Critical Developer Workflows
### Generate All Nameplates
```bash
python generate_nameplates.py
```
### Test Single Nameplate (Manual)
```powershell
# PowerShell syntax
& "C:\Program Files\OpenSCAD\openscad.exe" -D 'name="TestName"' -o test_output.stl nameplate_template.scad
# Or from CMD
"C:\Program Files\OpenSCAD\openscad.exe" -D "name=\"TestName\"" -o test_output.stl nameplate_template.scad
```
### Preview in OpenSCAD GUI
```powershell
# Open template in GUI for visual editing
& "C:\Program Files\OpenSCAD\openscad.exe" nameplate_template.scad
```
Then manually edit `name` parameter at top of file to preview different text.
### Validate Font Installation
```powershell
# Check if font is installed
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts" | Select-String "Fordscript"
# Or check fonts directory
ls $env:WINDIR\Fonts\Fordscript*
```
## Project-Specific Conventions
### Name Sanitization
Python script converts names to safe filenames:
- Removes special characters (keeps alphanumeric, spaces, hyphens, underscores)
- Replaces spaces with underscores
- Example: `"John Doe"``John_Doe.stl`
### OpenSCAD Command Pattern
```python
cmd = [
r'C:\Program Files\OpenSCAD\openscad.exe',
'-D', f'name="{escaped_name}"', # Set variable
'-o', output_file, # Output file
template_file # Input SCAD file
]
```
**Key flags**:
- `-D name="value"` - Override parameter in SCAD file
- `-o file.stl` - Output file path
- No flag for input file (positional argument)
### SCAD Template Structure
```scad
// Parameters (overridable via -D flag)
name = "NAME";
oval_width = 100;
oval_height = 38;
// ... more parameters
// Modules (functions)
module oval(width, height, depth) { ... }
module base_layer() { ... }
module top_layer() { ... }
module nameplate() { ... }
// Execution (builds the model)
nameplate();
```
## Common Pitfalls
### Font Not Found Error
**Symptom**: OpenSCAD renders but text is missing or uses default font.
**Causes**:
1. Font not installed in Windows (right-click TTF → Install)
2. Font name mismatch (must be exactly "Fordscript" in SCAD)
3. OpenSCAD needs restart after font installation
**Fix**: Install font, restart OpenSCAD, verify with manual test.
### Special Characters in Names
**Symptom**: Subprocess error or malformed STL.
**Cause**: Shell escaping issues with quotes, backslashes, etc.
**Current handling**: `escaped_name = name.replace('"', '\\"')` (line 33)
**Extension**: Add more sanitization if needed:
```python
# Escape more shell-sensitive characters
escaped_name = name.replace('"', '\\"').replace('\\', '\\\\')
```
### OpenSCAD Path Issues
**Symptom**: `FileNotFoundError: OpenSCAD not found`.
**Fix**: Update hardcoded path in `generate_nameplates.py:36`:
```python
cmd = [
r'C:\Program Files\OpenSCAD\openscad.exe', # ← Update this
# ...
]
```
**Better approach**: Use environment variable or config file:
```python
OPENSCAD_PATH = os.getenv('OPENSCAD_PATH', r'C:\Program Files\OpenSCAD\openscad.exe')
```
## Modifying Dimensions
All dimensions in `nameplate_template.scad` (lines 6-12):
| Parameter | Current Value | Purpose |
|-----------|---------------|---------|
| `oval_width` | 100mm | Overall width |
| `oval_height` | 38mm | Overall height (proportional) |
| `base_thickness` | 1.5mm | White layer thickness |
| `top_thickness` | 1mm | Blue layer thickness |
| `base_offset` | 2mm | White extension beyond blue |
| `text_size` | 15mm | Font size |
| `text_depth` | 1mm | Engraving depth (full blue layer) |
### Maintaining Proportions
Height typically 38% of width for aesthetic oval shape:
```scad
oval_height = oval_width * 0.38;
```
### Text Depth Critical
`text_depth` must equal `top_thickness` to engrave through entire blue layer:
```scad
text_depth = 1; // Must match top_thickness for full engraving
```
If `text_depth < top_thickness`, text won't reach white base. If `text_depth > top_thickness`, text cuts into white base (undesirable).
## Extending the Template
### Add New Shape Option
```scad
// Add rectangle module
module rectangle(width, height, depth) {
cube([width, height, depth], center=true);
}
// Add shape parameter at top
shape = "oval"; // or "rectangle"
// Use conditional in base_layer
module base_layer() {
if (shape == "rectangle")
rectangle(oval_width + base_offset*2, oval_height + base_offset*2, base_thickness);
else
oval(oval_width + base_offset*2, oval_height + base_offset*2, base_thickness);
}
```
### Add Logo/Icon
```scad
// Import SVG or PNG
module logo() {
translate([0, -oval_height/3, base_thickness + top_thickness - text_depth])
linear_extrude(height=text_depth)
import("logo.svg", center=true);
}
// Add to top_layer difference
difference() {
// ... existing blue oval
logo(); // Cut logo
}
```
### Batch Different Sizes
Modify Python script to pass multiple parameters:
```python
cmd = [
r'C:\Program Files\OpenSCAD\openscad.exe',
'-D', f'name="{escaped_name}"',
'-D', f'oval_width={width}', # Variable width
'-D', f'text_size={text_size}', # Variable text size
'-o', output_file,
template_file
]
```
## Troubleshooting Commands
```powershell
# Check OpenSCAD version
& "C:\Program Files\OpenSCAD\openscad.exe" --version
# Test SCAD syntax (no output, just validation)
& "C:\Program Files\OpenSCAD\openscad.exe" --check nameplate_template.scad
# Render with verbose output
& "C:\Program Files\OpenSCAD\openscad.exe" -D 'name="Test"' -o test.stl nameplate_template.scad --verbose
# List available fonts in OpenSCAD (run in OpenSCAD console)
# Help → Font List
```
## 3D Printing Notes
- **Material**: Two colors required (white + blue recommended)
- **Layer Height**: 0.1-0.2mm for clean text
- **Infill**: 20-30% sufficient for thin nameplates
- **Supports**: Not needed (flat design)
- **Orientation**: Print flat (as modeled)
- **Bed Adhesion**: Brim or raft recommended for thin parts
## Quick Reference
### Add New Name
1. Edit `names.txt`, add line with new name
2. Run `python generate_nameplates.py`
3. Find STL in `output_stl/` directory
### Change All Dimensions
1. Edit parameters at top of `nameplate_template.scad`
2. Run `python generate_nameplates.py` to regenerate all
3. Or manually test with single name first
### Install Font on New Machine
1. Copy `Fordscript.ttf` to new machine
2. Right-click → "Install for all users"
3. Restart OpenSCAD if running
4. Test with manual OpenSCAD command

15
Printing/Nameplates/.github/index.html vendored Normal file
View File

@@ -0,0 +1,15 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Directory listing for /Printing/Nameplates/.github/</title>
</head>
<body>
<h1>Directory listing for /Printing/Nameplates/.github/</h1>
<hr>
<ul>
<li><a href="copilot-instructions.md">copilot-instructions.md</a></li>
</ul>
<hr>
</body>
</html>

Binary file not shown.

View File

@@ -0,0 +1,68 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
This is a 3D nameplate generator that creates two-layer oval nameplates with engraved text using OpenSCAD. The system batch-processes names from a text file and outputs STL files ready for 3D printing.
## Architecture
**Pipeline:**
1. Python script (`generate_nameplates.py`) reads names from `names.txt`
2. For each name, it invokes OpenSCAD CLI with the parametric template
3. OpenSCAD renders the 3D model using `nameplate_template.scad`
4. STL files are output to `output_stl/` directory
**Design Structure:**
- Two-layer design: white base (1.5mm) + blue top layer (1mm)
- Text is engraved completely through the blue layer to expose white underneath
- Oval shape created by scaling a cylinder
- All dimensions parametric for easy customization
## Key Commands
**Generate nameplates:**
```bash
python generate_nameplates.py
```
**Test single nameplate (manual):**
```bash
"C:\Program Files\OpenSCAD\openscad.exe" -D "name=\"TestName\"" -o output.stl nameplate_template.scad
```
## Critical Configuration
**OpenSCAD Path:**
The script uses hardcoded path: `C:\Program Files\OpenSCAD\openscad.exe`
Update in `generate_nameplates.py:36` if OpenSCAD is installed elsewhere.
**Font Requirements:**
- Uses Fordscript font (Fordscript.ttf in project root)
- Font MUST be installed in Windows (right-click → Install) for OpenSCAD to access it
- OpenSCAD references fonts by name, not file path
- Referenced in template as `font="Fordscript"` (line 44)
**Dimensions:**
Default nameplate size: 3" tall × 8" wide (76mm × 200mm)
All dimensions in `nameplate_template.scad:6-12`
## File Purposes
- `nameplate_template.scad` - OpenSCAD parametric template defining the 3D geometry
- `generate_nameplates.py` - Batch processor that calls OpenSCAD for each name
- `names.txt` - Input file with one name per line
- `Fordscript.ttf` - Custom cursive font (must be installed in Windows)
- `output_stl/` - Generated STL files (one per name)
## Modifying Dimensions
Key parameters in `nameplate_template.scad`:
- `oval_height` - Overall height (currently 76mm = 3 inches)
- `oval_width` - Overall width (currently 200mm ≈ 8 inches)
- `base_thickness` - White layer thickness (1.5mm)
- `top_thickness` - Blue layer thickness (1mm)
- `text_depth` - Engraving depth (1mm - cuts through entire blue layer)
- `text_size` - Font size (30mm)
- `base_offset` - How much white extends beyond blue (2mm)

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 720 570.9" style="enable-background:new 0 0 720 570.9;" xml:space="preserve">
<style type="text/css">
.st0{fill:#7E4E8C;}
.st1{fill:#9C6BAD;}
</style>
<g id="XMLID_3_">
<path id="XMLID_188_" d="M717.3,120.1l-1.3-2.8l-0.3-0.8l-0.3-0.5l-0.5-1l-0.5-1l-0.3-0.5v-0.3c-0.5-1-0.3-0.5-0.5-0.8l-1.6-2.3
c-1-1.6-2.3-2.8-3.4-4.4c-1.3-1.3-2.6-2.6-3.9-3.9c-11.1-9.8-27.4-13.2-41.4-8.8c-1.8,0.5-3.9,1.3-5.7,2.1l-1.8,1l-1,0.5l-0.8,0.5
l-0.5,0.3l-7.2,4.4l-14.8,8.5l-29.2,17.1L582.3,139c0-11.9,0-24.1,0.3-36.2c0-7.2,0-14.2,0-21.5c0-3.6,0-7.2,0-10.9
c0-2.1-0.3-4.1-0.3-6.2s-0.5-4.1-0.8-6.2c-2.8-16.8-12.2-32.6-26.1-43.2c-7-5.4-14.8-9.3-23.3-11.9c-2.1-0.5-4.1-1.3-6.5-1.6
c-2.3-0.3-4.9-0.8-7-1L512.9,0h-6.2c-15.3,0-30.5,0.3-46.1,0.3c-62.1,0.3-126.3,1.3-191.5,1.8c-65.2,0.8-131.5,1-197.7,1
c-18.6-0.3-37,8-49.4,21.5c-6.2,6.7-11.1,14.8-14.2,23.5c-1.6,4.4-2.6,8.8-3.4,13.7c0,0.5-0.3,1.3-0.3,1.8v1.6l-0.3,3.1v0.8v1v4.7
c0,33.1-0.5,65.7-0.8,98.6C2.3,238.6,1.8,302.8,1,364.9c-0.3,31.1-0.5,61.6-0.8,91.6C0,471.5,0,486.2,0,501
c0,8.5,1.8,17.3,4.9,25.4c3.1,8,7.8,15.3,13.5,21.5c5.7,6.2,12.4,11.4,19.7,15.3l5.7,2.6c2.1,0.8,3.9,1.3,6,2.1
c3.9,1,7.8,2.1,12.4,2.6c1,0.3,2.3,0.3,3.1,0.5h2.6h2.6h0.8c1.3,0,0.8,0,1.3,0h1.3c3.4,0,6.7,0,10.4,0c6.7,0,13.7,0,20.2-0.3
c26.9-0.3,52.8-0.5,77.6-0.8c49.7-0.5,95.2-1,135.6-1.6c40.4-0.5,75.6-0.8,104.5-0.8c58-0.3,91.1-0.5,91.1-0.5s2.3,0,6.7-0.3
c4.4-0.8,11.1-1.6,19.1-4.9s17.3-9.3,25.4-18.9c3.9-4.9,7.8-10.6,10.6-17.1c0.5-1.8,1.3-3.4,1.8-5.2c0.5-1.8,1-3.6,1.6-5.4
c0.5-1.8,0.8-3.9,1-6c0.3-1,0.3-2.1,0.5-3.1c0-0.8,0-1.8,0-2.6s0-1.8,0.3-2.8v-1v-2.1c0-1.8,0-3.6,0-5.7c0-3.9,0-7.8,0-11.6
c0-8,0-16.3,0-25.1c0-17.6,0.3-36.5,0.3-56.7c0.3-40.4,0.8-85.9,1-135.6c0-7.5,0.3-15.3,0.3-23l24.6-14.2l58.7-34.2l29.2-17.1
l3.6-2.1c1.3-0.8,3.1-2.1,4.7-3.1c2.8-2.3,5.7-4.9,8-7.8c4.7-5.7,7.8-12.9,9.1-20.2C720.4,134.6,719.9,127.1,717.3,120.1z
M368.2,265.5l-111.5,66c-8.5-11.1-17.1-22.3-25.6-33.1l-29.5-38.3l-7.5-9.3c-0.8-0.8-1-1.6-2.1-2.6c-0.8-1-1.6-2.1-2.6-2.8
l-2.8-2.6c-1-0.8-2.1-1.6-3.1-2.3c-8.5-6-19.1-8.8-29.2-7.5c-5.2,0.5-10.4,2.1-15,4.4c-1.3,0.8-2.6,1.3-3.9,2.1
c-0.8,0.5-1,0.8-1.3,1l-1.3,0.8l-0.5,0.5l-0.5,0.5l-0.5,0.5l-1.6,1.3c-1,0.8-1.8,1.8-2.8,2.8c-7.2,7.8-11.4,17.9-11.6,28.5
c0,5.2,0.8,10.6,2.6,15.5c0.3,1.3,1,2.6,1.6,3.6l0.8,1.8l1,2.1l1,1.8c0.5,0.8,0.5,0.8,1,1.3l0.8,1.3l0.3,0.3v0.3l0.5,0.5l0.5,0.5
l15,18.9l30,37.5l30.3,37.5l7.5,9.3l3.9,4.7c1.6,2.1,3.4,3.9,5.4,5.7c4.1,3.6,8.8,6.5,13.7,8.3c2.6,1,5.2,1.6,7.8,2.1
c1.3,0.3,2.6,0.5,4.1,0.5h1c0.3,0,0.8,0,1,0h1.6h0.3c7.5,0,15.3-2.1,21.7-5.7l14.8-8.5l29.2-17.1l58.7-34.2L488.6,295l7.5-4.4
L494,482.9c-5.2,0-10.4,0-15.5,0l-26.7,0.3l-53.6,0.5l-106.9,1L84.6,487c0.5-32.3,0.8-64.7,1.3-97l0.8-104.3l0.5-52v-52.3l0.3-94.2
h43.5l53.6-0.3l106.9-0.3l106.9-1l53.6-0.8c15.5-0.3,30.8-0.5,46.3-0.8l-1,105.1l-12.4,7.2L368.2,265.5z"/>
<path id="XMLID_28_" class="st0" d="M565.4,498.4c0-1.8,0-3.6,0-5.7c0-3.9,0-7.8,0-11.6c0-8,0-16.3,0-25.1
c0-17.6-0.3-36.5-0.5-56.7c-0.3-40.4-0.8-85.9-1-135.6c0-4.1,0-8.3,0-12.4l-48.7,28.5l2.3,214.3c0,6.2-4.9,11.4-11.1,11.4l0,0h-0.3
c-8.8,0-17.9,0-26.7,0l-26.7-0.3l-53.6-0.5L78.4,501c-3.9,0-7-3.1-7-7l0,0c-0.5-34.7-1-69.6-1.3-104.3l-0.8-104.3l-0.3-52v-52
L68.8,77.1c0-5.4,4.4-9.8,9.8-10.1l0,0h53.6l53.6,0.3l106.9,0.3l106.9,1l53.6,0.8c17.9,0.3,35.7,0.5,53.6,0.8l0,0c3.9,0,7,3.1,7,7
l1,102.5l49.2-28.7c0-15.5,0-31.6-0.3-47.6c0-7.2,0-14.2,0-21.5c0-3.6,0-7.2,0-10.9c0-1.8-0.3-3.1-0.3-4.7c0-1.6-0.5-3.1-0.5-4.4
c-2.1-11.9-8.8-23.3-18.9-30.8c-4.9-3.9-10.6-6.7-16.6-8.5c-1.6-0.3-3.1-0.8-4.4-1c-1.6-0.3-2.6-0.5-4.4-0.8l-5.7-0.3h-5.2
c-15.3,0-30.5-0.3-46.1-0.3c-62.1-0.3-126.3-1.3-191.5-1.8c-65.2-0.8-131.5-1-197.7-1c-14.8,0-29,6.5-38.8,17.3
c-4.9,5.4-8.8,11.6-11.1,18.6c-1.3,3.4-2.1,7-2.3,10.4c0,0.5-0.3,0.8-0.3,1.3v1.6l-0.3,3.9c0,0.3,0,0.3,0,0.3l0,0v1.6v3.1
c0,33.1,0.3,66,0.8,98.6c0.8,65.2,1.3,129.4,2.1,191.5c0.3,31.1,0.5,61.6,0.8,91.6c0.3,15,0.3,29.8,0.5,44.3
c0,11.9,4.7,23.3,12.4,32.1c3.9,4.4,8.3,8,13.5,10.9l3.9,1.8l3.9,1.6c2.6,0.8,5.4,1.6,8,1.8c0.5,0,1.3,0.3,1.8,0.3l2.6,0.3l2.6,0.3
H73h0.3h1.3c3.4,0,6.7,0,10.4,0c6.7,0,13.5,0.3,20.2,0.3c26.9,0.3,52.8,0.5,77.6,0.8c49.7,0.5,95.2,1,135.6,1.6
c40.4,0.5,75.6,0.8,104.5,0.8c58,0.3,91.1,0.3,91.1,0.3s1.8,0,5.4-0.3c3.4-0.5,8.8-1,15-3.9c6.2-2.6,13.7-7.2,20.2-14.8
c3.1-3.9,6-8.3,8.3-13.7c0.5-1.3,1-2.6,1.6-4.1c0.5-1.3,0.8-2.8,1.3-4.4c0.5-1.6,0.5-2.8,0.8-4.4c0-0.8,0.3-1.3,0.3-2.1
s0-1.8,0-2.6s0-1.8,0-2.8v-0.3l0,0v-0.8L565.4,498.4z"/>
<path id="XMLID_29_" class="st1" d="M691.5,117.5c-5.7-5.2-14.5-7.2-22-4.9c-0.5,0-0.8,0.3-1.3,0.5c-0.3,0.3-0.8,0.3-1,0.3l-1.8,1
l-1,0.5l0,0l0,0l-0.5,0.3l-7.2,4.1l-14.8,8.5l-29.5,16.8l-117.7,67.5l-118,67.3l-118,67.3c-3.1,1.8-7,1-9.1-1.6l0,0l0,0
c-10.4-12.2-20.7-24.3-31.1-36.7l-31.1-36.7l-7.8-9.3c-0.5-0.8-1.3-1.6-1.8-2.1l-1.6-1.6l-1.6-1.3c-0.5-0.5-1.3-0.8-1.8-1.3
c-4.7-3.1-10.6-4.4-16.3-3.9c-2.8,0.3-5.4,1.3-8,2.6c-0.5,0.3-1,0.5-1.6,0.8c-0.3,0-0.8,0.5-1,0.8l-1.3,0.8l-0.3,0.3l0,0l0,0
l-0.3,0.3l-0.8,0.8c-0.5,0.5-1,1-1.6,1.6c-3.6,4.1-5.7,9.6-5.7,15.3c0,2.8,0.5,5.4,1.6,8c0.3,0.8,0.5,1.3,0.8,1.8l0.5,1l0.5,0.8
l0.3,0.8c0,0.3,0.5,0.8,0.8,1l0.8,1.3l0.3,0.3l0.5,0.5l15.3,18.6l30.5,37.3l30.3,37.3l7.5,9.3l3.9,4.7c1,1,1.8,2.1,2.8,2.8
c2.1,1.8,4.4,3.1,6.7,3.9c1.3,0.5,2.6,0.8,3.9,1c0.5,0,1.3,0.3,1.8,0.3h0.3c0,0,0.3,0,0.5,0h1.3c3.6,0,7.5-1,10.6-2.8l14.5-8.3
l29.5-17.1l58.7-33.9l117.5-68.1l117.5-68.1l58.7-33.9l29.5-16.8l3.6-2.1c1-0.8,1.8-1,2.6-1.6c1.6-1.3,3.1-2.6,4.1-3.9
c2.6-2.8,4.1-6.7,4.9-10.6c0.5-3.9,0.3-8-1-11.4C696.6,123.4,694.3,120.1,691.5,117.5z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.7 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 720 570.7" style="enable-background:new 0 0 720 570.7;" xml:space="preserve">
<path id="XMLID_42_" d="M717.1,120l-1.3-2.8l-0.3-0.8l-0.3-0.5l-0.5-1l-0.5-1l-0.3-0.5V113c-0.5-1-0.3-0.5-0.5-0.8l-1.6-2.3
c-1-1.6-2.3-2.8-3.4-4.4c-1.3-1.3-2.6-2.6-3.9-3.9c-11.1-9.8-27.4-13.2-41.4-8.8c-1.8,0.5-3.9,1.3-5.7,2.1l-1.8,1l-1,0.5l-1,0.5
l-0.5,0.3l-7.2,4.4l-14.7,8.5L602,127.3l-20.2,11.6c0-11.9,0-24.1,0.3-36.2c0-7.2,0-14.2,0-21.5c0-3.6,0-7.2,0-10.9
c0-1.8-0.3-4.1-0.3-6.2c0-2.1-0.5-4.1-0.8-6.2c-2.8-16.8-12.2-32.6-26.1-43.2c-7-5.4-14.7-9.3-23.3-11.9c-2.1-0.5-4.1-1-6.5-1.6
c-2.3-0.3-4.9-0.8-7-1L512.5,0h-6.2c-15.3,0-30.5,0.3-46,0.3C398.1,0.5,334,1.6,268.8,2.1c-65.2,0.8-131.4,1-197.6,1
c-18.6-0.3-37,8-49.4,21.5c-6.2,6.7-11.1,14.7-14.2,23.5c-1.6,4.4-2.6,8.8-3.1,13.7c0,0.5-0.3,1.3-0.3,1.8v1.6l-0.3,3.1v0.8v1v1.6
v3.1c0,33.1-0.3,66-0.8,98.6C2.3,238.5,1.8,302.7,1,364.8c-0.3,31-0.5,61.6-0.8,91.6c0,15-0.3,29.7-0.3,44.5
c0,8.8,1.8,17.3,4.9,25.4c3.1,8,7.8,15.3,13.5,21.5c5.7,6.2,12.4,11.4,19.7,15.3l5.7,2.6c1.8,0.8,3.9,1.3,5.9,2.1
c3.9,1,7.8,2.1,12.4,2.6c1,0.3,2.3,0.3,3.1,0.5h2.6h2.6h0.5c1.3,0,0.8,0,1.3,0h1.3c3.4,0,6.7,0,10.3,0c6.7,0,13.5-0.3,20.2-0.3
c26.9-0.3,52.8-0.5,77.6-0.8c49.7-0.5,95.2-1,135.6-1.6c40.4-0.5,75.5-0.8,104.5-0.8c57.9-0.3,91.1-0.3,91.1-0.3s2.3,0,6.7-0.3
c4.4-0.5,11.1-1.6,19.1-4.9s17.3-9.3,25.6-18.6c3.9-4.9,7.8-10.6,10.6-17.1c0.5-1.8,1.3-3.4,1.8-5.2c0.5-1.8,1-3.6,1.6-5.4
c0.5-1.8,0.8-3.9,1-5.9c0.3-1,0.3-2.1,0.5-3.1c0-0.8,0-1.8,0.3-2.6c0-0.8,0-1.8,0.3-2.8v-1v-0.8V498c0-1.8,0-3.6,0-5.7
c0-3.9,0-7.8,0-11.6c0-8,0-16.3,0-25.1c0-17.6,0.3-36.5,0.5-56.7c0.3-40.4,0.8-85.9,1-135.6c0-7.5,0-15.3,0.3-23l24.6-14.2
l58.7-34.1l29.2-17.1l3.6-2.1c1.3-0.8,3.1-1.8,4.7-3.1c2.8-2.3,5.7-4.9,8-7.8c4.7-5.7,7.8-12.9,9.1-20.2
C720.2,134.5,719.7,127,717.1,120z M563.7,263.6c0.5,49.7,0.8,95.2,1,135.6c0.3,20.2,0.3,39.1,0.5,56.7c0,8.8,0,17.1,0,25.1
c0,3.9,0,8,0,11.6c0,1.8,0,3.9,0,5.7v1.3v0.8l0,0v0.3c0,1,0,1.8,0,2.8c0,0.8,0,1.8,0,2.6c0,0.8-0.3,1.6-0.3,2.1
c-0.3,1.6-0.3,2.8-0.8,4.4c-0.5,1.6-0.8,2.8-1.3,4.4c-0.5,1.3-1,2.8-1.6,4.1c-2.3,5.2-5.2,9.8-8.3,13.7
c-6.5,7.5-13.7,12.2-20.2,14.7c-6.2,2.6-11.6,3.4-15,3.9c-3.6,0.3-5.4,0.3-5.4,0.3s-33.1-0.3-91.1-0.3c-29,0-64.2-0.3-104.5-0.8
c-40.4-0.5-85.9-1-135.6-1.6c-24.8-0.3-50.7-0.5-77.6-0.8c-6.7,0-13.5-0.3-20.2-0.3c-3.4,0-6.7,0-10.3,0h-1.3c0,0,0,0-0.3,0h-0.5
l-2.6-0.3l-2.6-0.3c-0.8,0-1.3-0.3-1.8-0.3c-2.3-0.3-5.2-1-8-1.8l-3.9-1.6l-3.9-1.8c-4.9-2.8-9.6-6.5-13.5-10.9
c-7.5-8.8-12.2-20.2-12.4-32.1c-0.3-14.5-0.3-29.2-0.5-44.2c-0.3-30-0.5-60.5-0.8-91.6c-0.8-62.1-1.3-126.2-2.1-191.4
c-0.3-32.6-0.5-65.4-0.8-98.6v-3.1v-1.6l0,0c0,0,0,0,0-0.3l0.3-3.9v-1.6c0-0.5,0.3-0.8,0.3-1.3c0.5-3.1,1.3-6.7,2.3-10.3
c2.3-6.7,6.2-13.2,11.1-18.6c9.8-10.9,24.1-17.3,38.8-17.3c66.2,0,132.5,0.3,197.6,1c65.2,0.5,129.3,1.3,191.4,1.8
c15.5,0,31,0.3,46,0.3h5.2l5.7,0.3c1.6,0.3,2.8,0.5,4.4,0.8c1.6,0.3,3.1,0.8,4.4,1c5.9,1.8,11.6,4.7,16.6,8.5
c9.8,7.5,16.6,18.9,18.9,30.8c0.3,1.6,0.5,3.1,0.5,4.4c0,1.6,0.3,2.8,0.3,4.7c0,3.6,0,7.2,0,10.9c0,7.2,0,14.5,0,21.5
c0,16,0,32.1,0.3,47.6l-49.2,28.7l-1-102.4c0-3.9-3.1-7-7-7l0,0c-17.8-0.3-35.7-0.5-53.5-0.8l-53.5-0.8l-106.8-1l-106.8-0.3
L130.9,67H77.3l0,0c-5.4,0-9.8,4.4-9.8,10.1l0.3,104.3v52l0.3,52l0.8,104.3c0.5,34.7,0.8,69.6,1.3,104.3l0,0c0,3.9,3.1,7,7,7
l320.8,3.6l53.5,0.5l26.6,0.3c8.8,0,17.8,0,26.6,0h0.3l0,0c6.2,0,11.1-5.2,11.1-11.4l-2.3-214.2l48.6-28.5
C563.4,255.3,563.4,259.5,563.7,263.6z M256.6,331.1c-8.5-11.1-17.1-22.2-25.6-33.1l-29.5-38l-7.5-9.3c-0.8-0.8-1-1.6-2.1-2.3
c-0.8-1-1.6-1.8-2.6-2.8l-2.8-2.6c-1-0.8-2.1-1.6-3.1-2.3c-8.5-5.9-19.1-8.8-29.2-7.5c-5.2,0.5-10.3,2.1-15,4.4
c-1.3,0.8-2.6,1.3-3.9,2.1c-0.8,0.5-1,0.5-1.3,1l-1.3,0.8l-0.5,0.5l-0.5,0.5l-0.3,0.3l-0.3,0.3l-1.6,1.3c-1,0.8-1.8,1.8-2.8,2.8
c-7.2,7.8-11.4,17.8-11.6,28.5c0,5.2,0.8,10.6,2.3,15.5c0.3,1.3,1,2.6,1.6,3.6l0.8,1.8l1,1.8l1,1.8c0.5,0.8,0.5,0.8,1,1.3l0.8,1.3
l0.3,0.3v0.3l0.5,0.5l0.5,0.5l15,18.9l30,37.5l30,37.5l7.5,9.3l3.9,4.7c1.6,1.8,3.4,3.9,5.4,5.7c4.1,3.6,8.8,6.5,13.7,8.3
c2.6,1,5.2,1.6,7.8,2.1c1.3,0.3,2.6,0.5,4.1,0.5h1c0.5,0,0.8,0,1,0h1.6h0.3c7.5,0,15.3-2.1,21.7-5.7l14.7-8.5l29.2-17.1l58.7-34.1
l117.4-68.3l7.5-4.4l-2.1,192.2c-5.2,0-10.3,0-15.5,0l-26.6,0.3l-53.5,0.5L291,484.8l-206.7,2.3c0.5-32.3,0.8-64.7,1.3-97l0.8-104.3
l0.3-52v-52l0.3-94.2h43.5l53.5-0.3l106.8-0.3l106.8-1l53.5-0.8c15.5-0.3,30.8-0.5,46.3-0.8l-1,105l-12.4,7.2l-116.9,69.1
L256.6,331.1z M698.7,138.7c-0.8,3.9-2.3,7.5-4.9,10.6c-1.3,1.6-2.6,2.8-4.1,3.9c-0.8,0.5-1.6,1-2.6,1.6l-3.6,2.1L654,173.6
l-58.7,33.9l-117.4,68.3l-117.4,68l-58.7,33.9l-29.5,17.1l-14.5,8.3c-3.4,1.8-7,2.8-10.6,2.8h-1.3c-0.3,0-0.5,0-0.5,0H245
c-0.5,0-1.3-0.3-1.8-0.3c-1.3-0.3-2.6-0.5-3.9-1c-2.6-0.8-4.7-2.3-6.7-3.9c-1-1-1.8-1.8-2.8-2.8l-3.9-4.7l-7.5-9.3l-30.3-37.3
l-30.8-37.5L142,290.5l-0.5-0.5l-0.3-0.3l-0.8-1.3c-0.3-0.3-0.8-0.8-0.8-1l-0.3-0.8l-0.5-0.8l-0.5-1c-0.3-0.5-0.5-1.3-0.8-1.8
c-1-2.6-1.6-5.2-1.6-8c0-5.4,2.1-11.1,5.7-15.3c0.5-0.5,1-1,1.6-1.6l0.8-0.8l0.3-0.3l0,0l0,0l0.3-0.3l1.3-0.8c0.3-0.3,0.8-0.8,1-0.8
c0.5-0.3,1-0.5,1.6-0.8c2.6-1.3,5.2-2.1,8-2.6c5.7-0.8,11.6,0.5,16.3,3.9c0.5,0.5,1.3,0.8,1.8,1.3l1.6,1.3l1.6,1.6
c0.5,0.5,1.3,1.6,1.8,2.1l7.8,9.3l31,36.7c10.3,12.2,20.7,24.6,31,36.7l0,0l0,0c2.1,2.6,5.9,3.4,9.1,1.6l118-67.3l118-67.3
l117.7-67.5l29.5-16.8l14.7-8.5l7.2-4.1l0.5-0.3l0,0l0,0l1-0.5l1.8-1c0.3,0,0.8-0.3,1-0.3c0.3-0.3,0.8-0.3,1.3-0.5
c7.5-2.3,16.3-0.5,22,4.9c2.8,2.6,5.2,5.9,6.5,9.8C699,130.6,699.2,134.8,698.7,138.7z"/>
</svg>

After

Width:  |  Height:  |  Size: 5.6 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Directory listing for /Printing/Nameplates/Check-Mark/</title>
</head>
<body>
<h1>Directory listing for /Printing/Nameplates/Check-Mark/</h1>
<hr>
<ul>
<li><a href="CF00089-08%20Check%20Mark%2001.dxf">CF00089-08 Check Mark 01.dxf</a></li>
<li><a href="CF00089-08%20Check%20Mark%2001.eps">CF00089-08 Check Mark 01.eps</a></li>
<li><a href="CF00089-08%20Check%20Mark%2001.png">CF00089-08 Check Mark 01.png</a></li>
<li><a href="CF00089-08%20Check%20Mark%2001.svg">CF00089-08 Check Mark 01.svg</a></li>
<li><a href="CF00089-08%20Check%20Mark%2002.dxf">CF00089-08 Check Mark 02.dxf</a></li>
<li><a href="CF00089-08%20Check%20Mark%2002.eps">CF00089-08 Check Mark 02.eps</a></li>
<li><a href="CF00089-08%20Check%20Mark%2002.png">CF00089-08 Check Mark 02.png</a></li>
<li><a href="CF00089-08%20Check%20Mark%2002.svg">CF00089-08 Check Mark 02.svg</a></li>
<li><a href="CF00089-08%20Check%20Mark%2003.dxf">CF00089-08 Check Mark 03.dxf</a></li>
<li><a href="CF00089-08%20Check%20Mark%2003.eps">CF00089-08 Check Mark 03.eps</a></li>
<li><a href="CF00089-08%20Check%20Mark%2003.png">CF00089-08 Check Mark 03.png</a></li>
<li><a href="CF00089-08%20Check%20Mark%2003.svg">CF00089-08 Check Mark 03.svg</a></li>
<li><a href="Note.txt">Note.txt</a></li>
</ul>
<hr>
</body>
</html>

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

View File

@@ -0,0 +1,174 @@
#!/usr/bin/env python3
"""
Add M600 filament change command to all objects in an Orca Slicer 3MF file.
This script modifies a 3MF file (which is a ZIP archive containing XML) to add
a height range modifier at 1.5mm (end of blue base layer) with M600 command
for all zipper pull objects.
Usage:
python add_filament_change_to_3mf.py input.3mf [output.3mf]
If output.3mf is not specified, creates input_modified.3mf
"""
import sys
import zipfile
import xml.etree.ElementTree as ET
from pathlib import Path
import shutil
import tempfile
import os
def add_height_range_to_3mf(input_file, output_file=None, height_mm=1.5):
"""
Add height range modifier with M600 at specified height to all objects in 3MF.
Args:
input_file: Path to input 3MF file
output_file: Path to output 3MF file (optional)
height_mm: Height in mm where filament change occurs (default: 1.5)
"""
input_path = Path(input_file)
if not input_path.exists():
print(f"Error: Input file '{input_file}' not found!")
return False
# Determine output filename
if output_file is None:
output_path = input_path.parent / f"{input_path.stem}_modified.3mf"
else:
output_path = Path(output_file)
print(f"Processing: {input_path}")
print(f"Output will be: {output_path}")
print(f"Filament change height: {height_mm}mm")
print("-" * 50)
# Create a temporary directory to work in
with tempfile.TemporaryDirectory() as temp_dir:
temp_path = Path(temp_dir)
# Extract the 3MF (it's a ZIP file)
print("Extracting 3MF file...")
with zipfile.ZipFile(input_path, 'r') as zip_ref:
zip_ref.extractall(temp_path)
# Find and modify the 3D model file (usually 3D/3dmodel.model)
model_file = temp_path / "3D" / "3dmodel.model"
if not model_file.exists():
print("Error: Could not find 3dmodel.model in 3MF file!")
return False
print(f"Modifying {model_file}...")
# Parse the XML
tree = ET.parse(model_file)
root = tree.getroot()
# Define namespaces (3MF uses namespaces)
namespaces = {
'': 'http://schemas.microsoft.com/3dmanufacturing/core/2015/02',
'p': 'http://schemas.microsoft.com/3dmanufacturing/production/2015/06',
's': 'http://schemas.orca-3d.com/3mf/2023/06'
}
# Register namespaces for output
for prefix, uri in namespaces.items():
if prefix:
ET.register_namespace(prefix, uri)
else:
ET.register_namespace('', uri)
# Find all objects (build items)
# In Orca Slicer 3MF, objects are in <build><item> tags
build_elem = root.find('.//build', namespaces)
if build_elem is None:
print("Warning: No <build> element found. Looking for items directly...")
items = root.findall('.//item', namespaces)
else:
items = build_elem.findall('.//item', namespaces)
if not items:
print("Error: No items found in 3MF file!")
return False
print(f"Found {len(items)} object(s) in the file")
# Count modified items
modified_count = 0
# Add height range modifier to each item
for idx, item in enumerate(items, 1):
object_id = item.get('objectid', f'unknown_{idx}')
print(f" Processing object {idx}/{len(items)} (ID: {object_id})...")
# Check if this item already has metadata for height range
# In Orca Slicer, this is typically stored as metadata
# We need to add the height range modifier metadata
# Note: The exact XML structure for height range modifiers in Orca Slicer
# may vary. This is a generic approach that adds metadata.
# You may need to adjust based on actual Orca Slicer 3MF structure.
# Create or find metadata container
metadata_group = item.find('metadatagroup', namespaces)
if metadata_group is None:
metadata_group = ET.SubElement(item, 'metadatagroup')
# Add height range modifier metadata
# Format: height range from 0 to height_mm = blue (original)
# height range from height_mm to top = white (with M600)
height_modifier = ET.SubElement(metadata_group, 'metadata')
height_modifier.set('name', 'height_range_modifier')
height_modifier.text = f'{{"ranges":[{{"min":0,"max":{height_mm},"color":"RoyalBlue"}},{{"min":{height_mm},"max":999,"color":"white","gcode":"M600"}}]}}'
modified_count += 1
print(f"\nModified {modified_count} object(s)")
# Save the modified XML back to the file
print("Saving modified model file...")
tree.write(model_file, encoding='utf-8', xml_declaration=True)
# Re-create the 3MF (ZIP) file with all contents
print("Creating new 3MF file...")
with zipfile.ZipFile(output_path, 'w', zipfile.ZIP_DEFLATED) as zip_out:
# Walk through the temp directory and add all files
for root_dir, dirs, files in os.walk(temp_path):
for file in files:
file_path = Path(root_dir) / file
arcname = file_path.relative_to(temp_path)
zip_out.write(file_path, arcname)
print(f"\nSuccess! Modified 3MF saved to: {output_path}")
print(f"\nNext steps:")
print(f"1. Open {output_path.name} in Orca Slicer")
print(f"2. Verify the height range modifiers are present")
print(f"3. Slice and check for M600 commands in the G-code")
return True
def main():
if len(sys.argv) < 2:
print("Usage: python add_filament_change_to_3mf.py input.3mf [output.3mf]")
print("\nAdds M600 filament change at 1.5mm to all objects in a 3MF file.")
print("If output.3mf is not specified, creates input_modified.3mf")
sys.exit(1)
input_file = sys.argv[1]
output_file = sys.argv[2] if len(sys.argv) > 2 else None
success = add_height_range_to_3mf(input_file, output_file)
if not success:
sys.exit(1)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,179 @@
#!/usr/bin/env python3
"""
Add M600 filament change to Orca Slicer 3MF file.
Based on actual Orca Slicer format analysis.
Adds global height_range_modifier metadata that applies to all objects.
Usage:
python add_height_modifier_orca.py input.3mf [output.3mf]
"""
import sys
import zipfile
import xml.etree.ElementTree as ET
from pathlib import Path
import tempfile
import os
def add_height_modifier(input_file, output_file=None, height_mm=1.5):
"""
Add height range modifier metadata to 3MF file.
Args:
input_file: Path to input 3MF file
output_file: Path to output 3MF file (optional)
height_mm: Height in mm where filament change occurs
"""
input_path = Path(input_file)
if not input_path.exists():
print(f"Error: Input file '{input_file}' not found!")
return False
if output_file is None:
output_path = input_path.parent / f"{input_path.stem}_modified.3mf"
else:
output_path = Path(output_file)
print(f"Processing: {input_path}")
print(f"Output: {output_path}")
print(f"Filament change at: {height_mm}mm")
print("-" * 60)
with tempfile.TemporaryDirectory() as temp_dir:
temp_path = Path(temp_dir)
# Extract 3MF
print("Extracting 3MF...")
with zipfile.ZipFile(input_path, 'r') as zip_ref:
zip_ref.extractall(temp_path)
# Find model file
model_file = temp_path / "3D" / "3dmodel.model"
if not model_file.exists():
print("Error: Could not find 3dmodel.model!")
return False
print("Modifying model file...")
# Parse XML
tree = ET.parse(model_file)
root = tree.getroot()
# Register namespaces
namespaces = {
'': 'http://schemas.microsoft.com/3dmanufacturing/core/2015/02',
'BambuStudio': 'http://schemas.bambulab.com/package/2021',
'p': 'http://schemas.microsoft.com/3dmanufacturing/production/2015/06'
}
for prefix, uri in namespaces.items():
if prefix:
ET.register_namespace(prefix, uri)
else:
ET.register_namespace('', uri)
# Find or create metadata section (should be at root level, before <resources>)
# Check if height_range_modifier already exists
existing_modifier = None
for metadata in root.findall('.//metadata[@name="height_range_modifier"]', namespaces):
existing_modifier = metadata
break
if existing_modifier is not None:
print(" Found existing height_range_modifier, replacing...")
root.remove(existing_modifier)
# Create the height range modifier metadata
# Format: JSON string - we'll manually insert it to avoid auto-escaping
metadata_json = (
'{"ranges":['
f'{{"min":0,"max":{height_mm},"color":"RoyalBlue"}},'
f'{{"min":{height_mm},"max":999,"color":"white","gcode":"M600"}}'
']}'
)
# Create metadata element - we'll manually set the text with proper escaping
metadata_elem = ET.Element('metadata')
metadata_elem.set('name', 'height_range_modifier')
# Don't use .text = ... as it will auto-escape
# We'll replace this after writing
# Insert after the last existing metadata element (before <resources>)
resources = root.find('.//resources', namespaces)
if resources is not None:
resources_index = list(root).index(resources)
root.insert(resources_index, metadata_elem)
else:
# No resources found, just append
root.append(metadata_elem)
print(f" Added height_range_modifier metadata")
print(f" Blue layer: 0mm to {height_mm}mm")
print(f" White layer: {height_mm}mm to top (with M600)")
# Save modified XML
tree.write(model_file, encoding='utf-8', xml_declaration=True)
# Post-process the file to fix the escaping
# Python's ET auto-escapes, but we need &amp;quot; not &amp;amp;quot;
with open(model_file, 'r', encoding='utf-8') as f:
content = f.read()
# Replace the empty metadata element with our properly escaped version
escaped_json = metadata_json.replace('"', '&amp;quot;')
content = content.replace(
'<metadata name="height_range_modifier" />',
f'<metadata name="height_range_modifier">{escaped_json}</metadata>'
)
content = content.replace(
'<metadata name="height_range_modifier"></metadata>',
f'<metadata name="height_range_modifier">{escaped_json}</metadata>'
)
with open(model_file, 'w', encoding='utf-8') as f:
f.write(content)
# Re-create 3MF file
print("Creating modified 3MF...")
with zipfile.ZipFile(output_path, 'w', zipfile.ZIP_DEFLATED) as zip_out:
for root_dir, dirs, files in os.walk(temp_path):
for file in files:
file_path = Path(root_dir) / file
arcname = file_path.relative_to(temp_path)
zip_out.write(file_path, arcname)
print()
print("Success! Modified 3MF saved.")
print()
print("Next steps:")
print("1. Open the modified file in Orca Slicer")
print("2. Check if height range modifier appears")
print("3. Slice and verify M600 in G-code")
print()
print("Note: This adds a GLOBAL height modifier that applies to")
print(" all objects in the build plate.")
return True
def main():
if len(sys.argv) < 2:
print("Usage: python add_height_modifier_orca.py input.3mf [output.3mf]")
print()
print("Adds M600 filament change at 1.5mm (global, applies to all objects)")
sys.exit(1)
input_file = sys.argv[1]
output_file = sys.argv[2] if len(sys.argv) > 2 else None
success = add_height_modifier(input_file, output_file)
if not success:
sys.exit(1)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,56 @@
// Two-Layer Check Mark Design
// Black base (box + check mark) + White fill layer on top
// Based on CF00089-08 Check Mark 01.svg
// Parameters - adjust these to customize
black_base_thickness = 0.5; // Black base layer (thin, bottom)
white_fill_thickness = 1.5; // White fill layer (middle)
black_top_thickness = 0.5; // Black top (check mark shows through)
desired_size = 14; // Desired box size (mm) - makes design square
// SVG file path
svg_file = "Check-Mark/CF00089-08 Check Mark 01.svg";
// Calculate dimensions from SVG viewBox (720 x 570.9)
svg_width = 720;
svg_height = 570.9;
// Scale factors to make the design exactly square
scale_x = desired_size / svg_width; // Scale for width
scale_y = desired_size / svg_height; // Scale for height
design_width = desired_size;
design_height = desired_size;
// White fill inset (how much smaller than the outer box)
white_inset = 1.5; // mm inset from edges (adjusted for 14mm box)
white_width = design_width - (white_inset * 2);
white_height = design_height - (white_inset * 2);
// Total thickness
total_thickness = black_base_thickness + white_fill_thickness + black_top_thickness;
echo(str("Design size: ", design_width, "mm x ", design_height, "mm"));
echo(str("White fill size: ", white_width, "mm x ", white_height, "mm"));
echo(str("Total thickness: ", total_thickness, "mm"));
// Build the two-layer design
module checkmark_design() {
// Layer 1: Black base - full SVG design (box + check mark)
color("black")
translate([0, 0, 0])
linear_extrude(height = total_thickness)
// Center the SVG design
translate([-design_width/2, -design_height/2, 0])
scale([scale_x, scale_y, 1])
import(svg_file, center = false);
// Layer 2: White fill - sits on top of black base, inside the box
color("white")
translate([0, 0, black_base_thickness])
linear_extrude(height = white_fill_thickness)
offset(r = 1) // Slightly round the corners
square([white_width, white_height], center = true);
}
// Render the complete design
checkmark_design();

Binary file not shown.

View File

@@ -0,0 +1,107 @@
#!/usr/bin/env python3
"""
Generate 3D nameplate STL files from a list of names using OpenSCAD.
This script reads names from a text file and generates individual STL files
for each name using an OpenSCAD template.
"""
import subprocess
import os
import sys
from pathlib import Path
def generate_stl(name, template_file, output_dir):
"""
Generate an STL file for a given name using OpenSCAD.
Args:
name: The name to put on the nameplate
template_file: Path to the OpenSCAD template file
output_dir: Directory where STL files will be saved
"""
# Create a safe filename from the name (remove special characters)
safe_name = "".join(c for c in name if c.isalnum() or c in (' ', '-', '_')).strip()
safe_name = safe_name.replace(' ', '_')
output_file = os.path.join(output_dir, f"{safe_name}.stl")
# Escape quotes in the name for the command line
escaped_name = name.replace('"', '\\"')
# Build the OpenSCAD command
# -D sets a variable, -o specifies output file
cmd = [
r'C:\Program Files\OpenSCAD\openscad.exe',
'-D', f'name="{escaped_name}"',
'-o', output_file,
template_file
]
print(f"Generating: {safe_name}.stl for '{name}'...")
try:
# Run OpenSCAD
result = subprocess.run(
cmd,
capture_output=True,
text=True,
check=True
)
print(f" [OK] Successfully created {safe_name}.stl")
return True
except subprocess.CalledProcessError as e:
print(f" [ERROR] Error generating {safe_name}.stl")
print(f" {e.stderr}")
return False
except FileNotFoundError:
print("Error: OpenSCAD not found. Please install OpenSCAD and ensure it's in your PATH.")
print("Download from: https://openscad.org/downloads.html")
sys.exit(1)
def main():
# Configuration
template_file = "nameplate_template.scad"
names_file = "names.txt"
output_dir = "output_stl"
# Check if template exists
if not os.path.exists(template_file):
print(f"Error: Template file '{template_file}' not found!")
sys.exit(1)
# Check if names file exists
if not os.path.exists(names_file):
print(f"Error: Names file '{names_file}' not found!")
sys.exit(1)
# Create output directory if it doesn't exist
Path(output_dir).mkdir(exist_ok=True)
# Read names from file
with open(names_file, 'r', encoding='utf-8') as f:
names = [line.strip() for line in f if line.strip()]
if not names:
print(f"Error: No names found in '{names_file}'")
sys.exit(1)
print(f"Found {len(names)} name(s) to process")
print(f"Output directory: {output_dir}")
print("-" * 50)
# Generate STL for each name
success_count = 0
for name in names:
if generate_stl(name, template_file, output_dir):
success_count += 1
print("-" * 50)
print(f"Complete! Generated {success_count}/{len(names)} STL files")
print(f"Files saved in: {output_dir}/")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,107 @@
#!/usr/bin/env python3
"""
Generate 3D zipper pull STL files from a list of names using OpenSCAD.
This script reads names from a text file and generates individual STL files
for each name using the zipper pull OpenSCAD template.
"""
import subprocess
import os
import sys
from pathlib import Path
def generate_stl(name, template_file, output_dir):
"""
Generate an STL file for a given name using OpenSCAD.
Args:
name: The name to put on the zipper pull
template_file: Path to the OpenSCAD template file
output_dir: Directory where STL files will be saved
"""
# Create a safe filename from the name (remove special characters)
safe_name = "".join(c for c in name if c.isalnum() or c in (' ', '-', '_')).strip()
safe_name = safe_name.replace(' ', '_')
output_file = os.path.join(output_dir, f"{safe_name}.stl")
# Escape quotes in the name for the command line
escaped_name = name.replace('"', '\\"')
# Build the OpenSCAD command
# -D sets a variable, -o specifies output file
cmd = [
r'C:\Program Files\OpenSCAD\openscad.exe',
'-D', f'name="{escaped_name}"',
'-o', output_file,
template_file
]
print(f"Generating: {safe_name}.stl for '{name}'...")
try:
# Run OpenSCAD
result = subprocess.run(
cmd,
capture_output=True,
text=True,
check=True
)
print(f" [OK] Successfully created {safe_name}.stl")
return True
except subprocess.CalledProcessError as e:
print(f" [ERROR] Error generating {safe_name}.stl")
print(f" {e.stderr}")
return False
except FileNotFoundError:
print("Error: OpenSCAD not found. Please install OpenSCAD and ensure it's in your PATH.")
print("Download from: https://openscad.org/downloads.html")
sys.exit(1)
def main():
# Configuration
template_file = "zipper_pull_template.scad"
names_file = "names.txt"
output_dir = "zipper-pulls"
# Check if template exists
if not os.path.exists(template_file):
print(f"Error: Template file '{template_file}' not found!")
sys.exit(1)
# Check if names file exists
if not os.path.exists(names_file):
print(f"Error: Names file '{names_file}' not found!")
sys.exit(1)
# Create output directory if it doesn't exist
Path(output_dir).mkdir(exist_ok=True)
# Read names from file
with open(names_file, 'r', encoding='utf-8') as f:
names = [line.strip() for line in f if line.strip()]
if not names:
print(f"Error: No names found in '{names_file}'")
sys.exit(1)
print(f"Found {len(names)} name(s) to process")
print(f"Output directory: {output_dir}")
print("-" * 50)
# Generate STL for each name
success_count = 0
for name in names:
if generate_stl(name, template_file, output_dir):
success_count += 1
print("-" * 50)
print(f"Complete! Generated {success_count}/{len(names)} STL files")
print(f"Files saved in: {output_dir}/")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,107 @@
#!/usr/bin/env python3
"""
Generate 3D zipper pull STL files with raised text from a list of names using OpenSCAD.
This script reads names from a text file and generates individual STL files
for each name using the raised text zipper pull OpenSCAD template.
"""
import subprocess
import os
import sys
from pathlib import Path
def generate_stl(name, template_file, output_dir):
"""
Generate an STL file for a given name using OpenSCAD.
Args:
name: The name to put on the zipper pull
template_file: Path to the OpenSCAD template file
output_dir: Directory where STL files will be saved
"""
# Create a safe filename from the name (remove special characters)
safe_name = "".join(c for c in name if c.isalnum() or c in (' ', '-', '_')).strip()
safe_name = safe_name.replace(' ', '_')
output_file = os.path.join(output_dir, f"{safe_name}.stl")
# Escape quotes in the name for the command line
escaped_name = name.replace('"', '\\"')
# Build the OpenSCAD command
# -D sets a variable, -o specifies output file
cmd = [
r'C:\Program Files\OpenSCAD\openscad.exe',
'-D', f'name="{escaped_name}"',
'-o', output_file,
template_file
]
print(f"Generating: {safe_name}.stl for '{name}'...")
try:
# Run OpenSCAD
result = subprocess.run(
cmd,
capture_output=True,
text=True,
check=True
)
print(f" [OK] Successfully created {safe_name}.stl")
return True
except subprocess.CalledProcessError as e:
print(f" [ERROR] Error generating {safe_name}.stl")
print(f" {e.stderr}")
return False
except FileNotFoundError:
print("Error: OpenSCAD not found. Please install OpenSCAD and ensure it's in your PATH.")
print("Download from: https://openscad.org/downloads.html")
sys.exit(1)
def main():
# Configuration
template_file = "zipper_pull_raised_text_template.scad"
names_file = "names.txt"
output_dir = "zipper-pulls-raised-text"
# Check if template exists
if not os.path.exists(template_file):
print(f"Error: Template file '{template_file}' not found!")
sys.exit(1)
# Check if names file exists
if not os.path.exists(names_file):
print(f"Error: Names file '{names_file}' not found!")
sys.exit(1)
# Create output directory if it doesn't exist
Path(output_dir).mkdir(exist_ok=True)
# Read names from file
with open(names_file, 'r', encoding='utf-8') as f:
names = [line.strip() for line in f if line.strip()]
if not names:
print(f"Error: No names found in '{names_file}'")
sys.exit(1)
print(f"Found {len(names)} name(s) to process")
print(f"Output directory: {output_dir}")
print("-" * 50)
# Generate STL for each name
success_count = 0
for name in names:
if generate_stl(name, template_file, output_dir):
success_count += 1
print("-" * 50)
print(f"Complete! Generated {success_count}/{len(names)} STL files")
print(f"Files saved in: {output_dir}/")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,113 @@
#!/usr/bin/env python3
"""
Generate 3D zipper pull STL files with raised text from a list of names using OpenSCAD.
This script reads names from a text file and generates individual STL files
for each name using the raised text zipper pull OpenSCAD template.
Version 2: Improved apostrophe handling - preserves apostrophes in both filenames and text rendering.
"""
import subprocess
import os
import sys
from pathlib import Path
def generate_stl(name, template_file, output_dir):
"""
Generate an STL file for a given name using OpenSCAD.
Args:
name: The name to put on the zipper pull
template_file: Path to the OpenSCAD template file
output_dir: Directory where STL files will be saved
"""
# Create a safe filename from the name
# Keep apostrophes in filename for accurate representation
safe_name = "".join(c for c in name if c.isalnum() or c in (' ', '-', '_', "\'")).strip()
safe_name = safe_name.replace(' ', '_')
output_file = os.path.join(output_dir, f"{safe_name}.stl")
# Escape the name for OpenSCAD command line
# Need to escape both quotes and apostrophes properly
escaped_name = name.replace('\\', '\\\\') # Escape backslashes first
escaped_name = escaped_name.replace('"', '\\"') # Escape double quotes
escaped_name = escaped_name.replace("'", "\\'") # Escape single quotes/apostrophes
# Build the OpenSCAD command
# -D sets a variable, -o specifies output file
cmd = [
r'C:\Program Files\OpenSCAD\openscad.exe',
'-D', f'name="{escaped_name}"',
'-o', output_file,
template_file
]
print(f"Generating: {safe_name}.stl for '{name}'...")
try:
# Run OpenSCAD
result = subprocess.run(
cmd,
capture_output=True,
text=True,
check=True
)
print(f" [OK] Successfully created {safe_name}.stl")
return True
except subprocess.CalledProcessError as e:
print(f" [ERROR] Error generating {safe_name}.stl")
print(f" {e.stderr}")
return False
except FileNotFoundError:
print("Error: OpenSCAD not found. Please install OpenSCAD and ensure it's in your PATH.")
print("Download from: https://openscad.org/downloads.html")
sys.exit(1)
def main():
# Configuration
template_file = "zipper_pull_raised_text_template.scad"
names_file = "names.txt"
output_dir = "zipper-pulls-raised-text-2"
# Check if template exists
if not os.path.exists(template_file):
print(f"Error: Template file '{template_file}' not found!")
sys.exit(1)
# Check if names file exists
if not os.path.exists(names_file):
print(f"Error: Names file '{names_file}' not found!")
sys.exit(1)
# Create output directory if it doesn't exist
Path(output_dir).mkdir(exist_ok=True)
# Read names from file
with open(names_file, 'r', encoding='utf-8') as f:
names = [line.strip() for line in f if line.strip()]
if not names:
print(f"Error: No names found in '{names_file}'")
sys.exit(1)
print(f"Found {len(names)} name(s) to process")
print(f"Output directory: {output_dir}")
print("-" * 50)
# Generate STL for each name
success_count = 0
for name in names:
if generate_stl(name, template_file, output_dir):
success_count += 1
print("-" * 50)
print(f"Complete! Generated {success_count}/{len(names)} STL files")
print(f"Files saved in: {output_dir}/")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,61 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Directory listing for /Printing/Nameplates/</title>
</head>
<body>
<h1>Directory listing for /Printing/Nameplates/</h1>
<hr>
<ul>
<li><a href=".claude/">.claude/</a></li>
<li><a href=".github/">.github/</a></li>
<li><a href="300.103.pdf">300.103.pdf</a></li>
<li><a href="add_filament_change_to_3mf.py">add_filament_change_to_3mf.py</a></li>
<li><a href="add_height_modifier_orca.py">add_height_modifier_orca.py</a></li>
<li><a href="Check-Mark/">Check-Mark/</a></li>
<li><a href="checkmark_template.scad">checkmark_template.scad</a></li>
<li><a href="CLAUDE.md">CLAUDE.md</a></li>
<li><a href="Fordscript.ttf">Fordscript.ttf</a></li>
<li><a href="fred_bennett_facedown.3mf">fred_bennett_facedown.3mf</a></li>
<li><a href="generate_nameplates.py">generate_nameplates.py</a></li>
<li><a href="generate_zipper_pulls.py">generate_zipper_pulls.py</a></li>
<li><a href="generate_zipper_pulls_raised_text.py">generate_zipper_pulls_raised_text.py</a></li>
<li><a href="generate_zipper_pulls_raised_text_2.py">generate_zipper_pulls_raised_text_2.py</a></li>
<li><a href="nameplate_template.scad">nameplate_template.scad</a></li>
<li><a href="names.txt">names.txt</a></li>
<li><a href="nul">nul</a></li>
<li><a href="output_stl/">output_stl/</a></li>
<li><a href="Screenshot%202025-11-07%20082805.png">Screenshot 2025-11-07 082805.png</a></li>
<li><a href="test_bennet_facedown.stl">test_bennet_facedown.stl</a></li>
<li><a href="test_bennett_facedown.3mf">test_bennett_facedown.3mf</a></li>
<li><a href="test_blue_only.3mf">test_blue_only.3mf</a></li>
<li><a href="test_blue_only.scad">test_blue_only.scad</a></li>
<li><a href="test_christopher.stl">test_christopher.stl</a></li>
<li><a href="test_christopher_13pt.stl">test_christopher_13pt.stl</a></li>
<li><a href="test_christopher_dynamic.stl">test_christopher_dynamic.stl</a></li>
<li><a href="test_christopher_raised.stl">test_christopher_raised.stl</a></li>
<li><a href="test_debug.3mf">test_debug.3mf</a></li>
<li><a href="test_debug.scad">test_debug.scad</a></li>
<li><a href="test_font.scad">test_font.scad</a></li>
<li><a href="test_font.stl">test_font.stl</a></li>
<li><a href="test_fred_bold.stl">test_fred_bold.stl</a></li>
<li><a href="test_fred_debug.stl">test_fred_debug.stl</a></li>
<li><a href="test_fred_dynamic.stl">test_fred_dynamic.stl</a></li>
<li><a href="test_fred_raised.stl">test_fred_raised.stl</a></li>
<li><a href="TEST_Fred_raised_text.stl">TEST_Fred_raised_text.stl</a></li>
<li><a href="test_fred_reduced_bold.stl">test_fred_reduced_bold.stl</a></li>
<li><a href="test_hole_position.stl">test_hole_position.stl</a></li>
<li><a href="test_simple_fred.scad">test_simple_fred.scad</a></li>
<li><a href="test_simple_fred.stl">test_simple_fred.stl</a></li>
<li><a href="test_zoe.stl">test_zoe.stl</a></li>
<li><a href="test_zoe_raised.stl">test_zoe_raised.stl</a></li>
<li><a href="zipper-pulls-raised-text/">zipper-pulls-raised-text/</a></li>
<li><a href="zipper-pulls-raised-text-2/">zipper-pulls-raised-text-2/</a></li>
<li><a href="zipper_pull_raised_text_template.scad">zipper_pull_raised_text_template.scad</a></li>
<li><a href="zipper_pull_raised_text_template_REDUCED_BOLD.scad">zipper_pull_raised_text_template_REDUCED_BOLD.scad</a></li>
<li><a href="zipper_pull_template.scad">zipper_pull_template.scad</a></li>
</ul>
<hr>
</body>
</html>

View File

@@ -0,0 +1,57 @@
// Two-Layer Oval Nameplate Template with Engraved Text
// Creates a white base oval with a blue top oval and engraved text
// Parameters - these can be overridden from command line
name = "NAME"; // Text to display on nameplate
oval_width = 100; // Width of the oval (mm) - max 100mm
oval_height = 38; // Height of the oval (mm) - proportional to width
base_thickness = 1.5; // Thickness of white base layer (mm)
top_thickness = 1; // Thickness of blue top layer (mm)
base_offset = 2; // How much larger the white base is (mm)
text_size = 15; // Font size for the text
text_depth = 1; // How deep the text is engraved (mm) - cuts through blue to show white
font_file = "C:/Users/Fred/claude/Fordscript.ttf"; // Path to the custom font file
// Module to create an oval (ellipse)
module oval(width, height, depth) {
scale([width/2, height/2, 1])
cylinder(h=depth, r=1, $fn=100);
}
// White base layer (larger oval)
module base_layer() {
color("white")
oval(
oval_width + base_offset*2,
oval_height + base_offset*2,
base_thickness
);
}
// Blue top layer with engraved text
module top_layer() {
color("RoyalBlue")
difference() {
// Blue oval
translate([0, 0, base_thickness])
oval(oval_width, oval_height, top_thickness);
// Engraved text (cuts into the blue layer)
translate([0, 0, base_thickness + top_thickness - text_depth + 0.01])
linear_extrude(height=text_depth)
text(name,
size=text_size,
font="Fordscript",
halign="center",
valign="center");
}
}
// Main nameplate assembly
module nameplate() {
base_layer();
top_layer();
}
// Generate the nameplate
nameplate();

View File

@@ -0,0 +1,58 @@
Skylar
Aaron
Kathrynn
Alice
Jaxxin
Sydney
Blake
Ayden
Bentley
Landon
Silas
Aniah
Silas
Donald
Hunter
Harper
Keith
Karleigh
Michael
Taylor
Adalynn
Harley
Danny
Carson
Aur'heir
Kinleigh
Bennett
Lucy
Grayson
Leon
Charlotte
Landon
Aiden
Nevaeh
Ayla
Leah
William
Lane
Liberty
Karter
Wyatt
Clare
Bryant
Cole
Jordan
Max
Zoey
Eli
Oliver
Jack
Tyler
Annabella
Amaya
Shane
Nicholas
Clay
Jayden
Alexis

View File

@@ -0,0 +1,15 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Directory listing for /Printing/Nameplates/output_stl/</title>
</head>
<body>
<h1>Directory listing for /Printing/Nameplates/output_stl/</h1>
<hr>
<ul>
<li><a href="2names%27.3mf">2names'.3mf</a></li>
</ul>
<hr>
</body>
</html>

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,61 @@
// Test - only blue layer from main template
name = "Bennett";
oval_width = 96;
oval_height = 30;
blue_thickness = 1;
white_thickness = 1.5;
base_text_size = 13;
name_length = len(name);
text_size = name_length <= 3 ? 18 :
name_length <= 5 ? 13 :
name_length <= 8 ? 11 :
11;
border_width = 2;
hole_diameter = 4;
hole_clearance = 4;
total_width = oval_width + border_width*2;
total_height = oval_height + border_width*2;
hole_x = -(total_width/2) + (hole_diameter/2) + hole_clearance;
module oval(width, height, depth) {
scale([width/2, height/2, 1])
cylinder(h=depth, r=1, $fn=100);
}
module bold_text() {
for (x = [-0.3, 0, 0.3]) {
for (y = [-0.3, 0, 0.3]) {
translate([x, y, 0])
linear_extrude(height=blue_thickness + 0.1)
text(name,
size=text_size,
font="Fordscript",
halign="center",
valign="center");
}
}
}
// Blue layer only
color("RoyalBlue")
difference() {
oval(total_width, total_height, blue_thickness);
// Cut out the border ring channel
translate([0, 0, -0.05])
difference() {
oval(total_width, total_height, blue_thickness + 0.1);
oval(oval_width, oval_height, blue_thickness + 0.2);
}
// Cut out text channels
translate([0, 0, -0.05])
bold_text();
// Cut out hole
translate([hole_x, 0, -0.05])
cylinder(h=blue_thickness + 0.1, d=hole_diameter, $fn=50);
}

Binary file not shown.

View File

@@ -0,0 +1,43 @@
// Debug - just show the blue layer with text cut out
name = "Bennett";
oval_width = 96;
oval_height = 30;
blue_thickness = 1;
border_width = 2;
name_length = len(name);
text_size = name_length <= 3 ? 18 :
name_length <= 5 ? 13 :
name_length <= 8 ? 11 :
11;
total_width = oval_width + border_width*2;
total_height = oval_height + border_width*2;
module oval(width, height, depth) {
scale([width/2, height/2, 1])
cylinder(h=depth, r=1, $fn=100);
}
module bold_text() {
for (x = [-0.3, 0, 0.3]) {
for (y = [-0.3, 0, 0.3]) {
translate([x, y, 0])
linear_extrude(height=blue_thickness + 0.1)
text(name,
size=text_size,
font="Fordscript",
halign="center",
valign="center");
}
}
}
// Just the blue with text cut - no border cut
color("RoyalBlue")
difference() {
oval(total_width, total_height, blue_thickness);
translate([0, 0, -0.05])
bold_text();
}

View File

@@ -0,0 +1,3 @@
// Test if Fordscript font renders
linear_extrude(height=2)
text("Bennett", size=11, font="Fordscript", halign="center", valign="center");

View File

@@ -0,0 +1,12 @@
// Simple test for Fred text rendering
name = "Fred";
text_size = 13;
color("white")
translate([0, 0, 1.5])
linear_extrude(height=1)
text(name,
size=text_size,
font="Fordscript",
halign="center",
valign="center");

View File

@@ -0,0 +1,70 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Directory listing for /Printing/Nameplates/zipper-pulls-raised-text-2/</title>
</head>
<body>
<h1>Directory listing for /Printing/Nameplates/zipper-pulls-raised-text-2/</h1>
<hr>
<ul>
<li><a href="Aaron.stl">Aaron.stl</a></li>
<li><a href="Adalynn.stl">Adalynn.stl</a></li>
<li><a href="Aiden.stl">Aiden.stl</a></li>
<li><a href="Alexis.stl">Alexis.stl</a></li>
<li><a href="Alice.stl">Alice.stl</a></li>
<li><a href="Amaya.stl">Amaya.stl</a></li>
<li><a href="Aniah.stl">Aniah.stl</a></li>
<li><a href="Annabella.stl">Annabella.stl</a></li>
<li><a href="Aur%27heir.stl">Aur'heir.stl</a></li>
<li><a href="Ayden.stl">Ayden.stl</a></li>
<li><a href="Ayla.stl">Ayla.stl</a></li>
<li><a href="Bennett.stl">Bennett.stl</a></li>
<li><a href="Bentley.stl">Bentley.stl</a></li>
<li><a href="Blake.stl">Blake.stl</a></li>
<li><a href="Bryant.stl">Bryant.stl</a></li>
<li><a href="Carson.stl">Carson.stl</a></li>
<li><a href="Charlotte.stl">Charlotte.stl</a></li>
<li><a href="Clare.stl">Clare.stl</a></li>
<li><a href="Clay.stl">Clay.stl</a></li>
<li><a href="Cole.stl">Cole.stl</a></li>
<li><a href="Danny.stl">Danny.stl</a></li>
<li><a href="Donald.stl">Donald.stl</a></li>
<li><a href="Eli.stl">Eli.stl</a></li>
<li><a href="Grayson.stl">Grayson.stl</a></li>
<li><a href="Harley.stl">Harley.stl</a></li>
<li><a href="Harper.stl">Harper.stl</a></li>
<li><a href="Hunter.stl">Hunter.stl</a></li>
<li><a href="Jack.stl">Jack.stl</a></li>
<li><a href="Jaxxin.stl">Jaxxin.stl</a></li>
<li><a href="Jayden.stl">Jayden.stl</a></li>
<li><a href="Jordan.stl">Jordan.stl</a></li>
<li><a href="Karleigh.stl">Karleigh.stl</a></li>
<li><a href="Karter.stl">Karter.stl</a></li>
<li><a href="Kathrynn.stl">Kathrynn.stl</a></li>
<li><a href="Keith.stl">Keith.stl</a></li>
<li><a href="Kinleigh.stl">Kinleigh.stl</a></li>
<li><a href="Landon.stl">Landon.stl</a></li>
<li><a href="Lane.stl">Lane.stl</a></li>
<li><a href="Leah.stl">Leah.stl</a></li>
<li><a href="Leon.stl">Leon.stl</a></li>
<li><a href="Liberty.stl">Liberty.stl</a></li>
<li><a href="Lucy.stl">Lucy.stl</a></li>
<li><a href="Max.stl">Max.stl</a></li>
<li><a href="Michael.stl">Michael.stl</a></li>
<li><a href="Nevaeh.stl">Nevaeh.stl</a></li>
<li><a href="Nicholas.stl">Nicholas.stl</a></li>
<li><a href="Oliver.stl">Oliver.stl</a></li>
<li><a href="Shane.stl">Shane.stl</a></li>
<li><a href="Silas.stl">Silas.stl</a></li>
<li><a href="Skylar.stl">Skylar.stl</a></li>
<li><a href="Sydney.stl">Sydney.stl</a></li>
<li><a href="Taylor.stl">Taylor.stl</a></li>
<li><a href="Tyler.stl">Tyler.stl</a></li>
<li><a href="William.stl">William.stl</a></li>
<li><a href="Wyatt.stl">Wyatt.stl</a></li>
<li><a href="Zoey.stl">Zoey.stl</a></li>
</ul>
<hr>
</body>
</html>

View File

@@ -0,0 +1,82 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Directory listing for /Printing/Nameplates/zipper-pulls-raised-text/</title>
</head>
<body>
<h1>Directory listing for /Printing/Nameplates/zipper-pulls-raised-text/</h1>
<hr>
<ul>
<li><a href="111.stl">111.stl</a></li>
<li><a href="aaron.3mf">aaron.3mf</a></li>
<li><a href="Aaron.stl">Aaron.stl</a></li>
<li><a href="Adalynn.stl">Adalynn.stl</a></li>
<li><a href="Aiden.stl">Aiden.stl</a></li>
<li><a href="Alexis.stl">Alexis.stl</a></li>
<li><a href="Alice.stl">Alice.stl</a></li>
<li><a href="Amaya.stl">Amaya.stl</a></li>
<li><a href="Aniah.stl">Aniah.stl</a></li>
<li><a href="Annabella.stl">Annabella.stl</a></li>
<li><a href="Aurheir.stl">Aurheir.stl</a></li>
<li><a href="Ayden.stl">Ayden.stl</a></li>
<li><a href="Ayla.stl">Ayla.stl</a></li>
<li><a href="Bennett.stl">Bennett.stl</a></li>
<li><a href="Bentley.stl">Bentley.stl</a></li>
<li><a href="Blake.stl">Blake.stl</a></li>
<li><a href="Bryant.stl">Bryant.stl</a></li>
<li><a href="Carson.stl">Carson.stl</a></li>
<li><a href="Charlotte.stl">Charlotte.stl</a></li>
<li><a href="Clare.stl">Clare.stl</a></li>
<li><a href="Clay.stl">Clay.stl</a></li>
<li><a href="Cole.stl">Cole.stl</a></li>
<li><a href="Daniel.stl">Daniel.stl</a></li>
<li><a href="Danny.stl">Danny.stl</a></li>
<li><a href="Donald.stl">Donald.stl</a></li>
<li><a href="Eli.stl">Eli.stl</a></li>
<li><a href="first%20plate.gcode">first plate.gcode</a></li>
<li><a href="Ford-Fred%20%282%29.stl">Ford-Fred (2).stl</a></li>
<li><a href="Grayson.stl">Grayson.stl</a></li>
<li><a href="Harley.stl">Harley.stl</a></li>
<li><a href="Harper.stl">Harper.stl</a></li>
<li><a href="Hunter.stl">Hunter.stl</a></li>
<li><a href="Jack.stl">Jack.stl</a></li>
<li><a href="Jaxxin.stl">Jaxxin.stl</a></li>
<li><a href="Jayden.stl">Jayden.stl</a></li>
<li><a href="Jordan.stl">Jordan.stl</a></li>
<li><a href="Karleigh.stl">Karleigh.stl</a></li>
<li><a href="Karter.stl">Karter.stl</a></li>
<li><a href="Kathrynn.stl">Kathrynn.stl</a></li>
<li><a href="Keith.stl">Keith.stl</a></li>
<li><a href="Kinleigh.stl">Kinleigh.stl</a></li>
<li><a href="Landon.stl">Landon.stl</a></li>
<li><a href="Lane.stl">Lane.stl</a></li>
<li><a href="Leah.stl">Leah.stl</a></li>
<li><a href="Leon.stl">Leon.stl</a></li>
<li><a href="Liberty.stl">Liberty.stl</a></li>
<li><a href="Lucy.stl">Lucy.stl</a></li>
<li><a href="Max.stl">Max.stl</a></li>
<li><a href="Michael.stl">Michael.stl</a></li>
<li><a href="Nevaeh.stl">Nevaeh.stl</a></li>
<li><a href="New%20Names.3mf">New Names.3mf</a></li>
<li><a href="Nicholas.stl">Nicholas.stl</a></li>
<li><a href="Oliver.stl">Oliver.stl</a></li>
<li><a href="pLATE%201.3mf">pLATE 1.3mf</a></li>
<li><a href="Shane.stl">Shane.stl</a></li>
<li><a href="Silas.stl">Silas.stl</a></li>
<li><a href="Skylar.stl">Skylar.stl</a></li>
<li><a href="Sydney.stl">Sydney.stl</a></li>
<li><a href="Taylor.stl">Taylor.stl</a></li>
<li><a href="top4.3mf">top4.3mf</a></li>
<li><a href="Tyler.stl">Tyler.stl</a></li>
<li><a href="William.stl">William.stl</a></li>
<li><a href="Wyatt.stl">Wyatt.stl</a></li>
<li><a href="zipper%20pulls.3mf">zipper pulls.3mf</a></li>
<li><a href="zipper%20pulls_FINAL.3mf">zipper pulls_FINAL.3mf</a></li>
<li><a href="zipper%20pulls_modified.3mf">zipper pulls_modified.3mf</a></li>
<li><a href="zipper%20pulls_with_M600.3mf">zipper pulls_with_M600.3mf</a></li>
<li><a href="Zoey.stl">Zoey.stl</a></li>
</ul>
<hr>
</body>
</html>

View File

@@ -0,0 +1,117 @@
// Face-Down Oval Zipper Pull Template
// Designed for face-down printing: text and border are channels in blue layer (printed first),
// then white backing fills the channels and covers the back.
// When flipped over, shows white text/border on blue background.
// Parameters - these can be overridden from command line
name = "NAME"; // Text to display on zipper pull
oval_width = 96; // Width of blue oval (mm) - total with border will be 100mm (96 + 2*2)
oval_height = 30; // Height of blue oval (mm) - total with border will be 34mm (30 + 2*2)
blue_thickness = 1; // Thickness of blue layer (mm) - this is the "show" side
white_thickness = 1.5; // Thickness of white backing layer (mm)
base_text_size = 13; // Base font size for medium names
// Dynamic font sizing based on name length (mimics Ford oval proportions)
// "Fred" (4 chars) at 13mm gives ~20% coverage - our target
name_length = len(name);
text_size = name_length <= 3 ? 18 : // Short names (Zoe, Sam, Al) - larger (~21% coverage)
name_length <= 5 ? 13 : // Medium names (Fred, John, Mary) - standard (~20% coverage)
name_length <= 8 ? 11 : // Longer names (Michael, Jessica) - smaller (~25% coverage)
11; // Very long names (Christopher) - increased to 11mm (~35% coverage)
// Border parameters
border_width = 2; // Width of the white border around the oval (mm)
// Hole parameters for zipper pull
hole_diameter = 4; // Diameter of the hole (mm)
hole_clearance = 4; // Minimum clearance from edge of outer border (mm)
// Total dimensions
total_width = oval_width + border_width*2; // 100mm
total_height = oval_height + border_width*2; // 34mm
// Hole position - on LEFT side when viewed from show side
// Since we print face-down, hole appears on RIGHT during printing
// When flipped, it will be on the left as expected
hole_x = -(total_width/2) + (hole_diameter/2) + hole_clearance;
// Module to create an oval (ellipse)
module oval(width, height, depth) {
scale([width/2, height/2, 1])
cylinder(h=depth, r=1, $fn=100);
}
// Module for text with fake bold effect
module bold_text() {
for (x = [-0.3, 0, 0.3]) {
for (y = [-0.3, 0, 0.3]) {
translate([x, y, 0])
linear_extrude(height=blue_thickness + 0.1)
text(name,
size=text_size,
font="Fordscript",
halign="center",
valign="center");
}
}
}
// Blue layer with channels for text and border (prints first, face-down)
// The channels will be filled with white when the white layer is printed
module blue_layer() {
color("RoyalBlue")
difference() {
// Full blue oval
oval(total_width, total_height, blue_thickness);
// Cut out the border ring channel (will be filled with white)
translate([0, 0, -0.05])
difference() {
oval(total_width, total_height, blue_thickness + 0.1);
oval(oval_width, oval_height, blue_thickness + 0.2);
}
// Cut out text channels (will be filled with white)
translate([0, 0, -0.05])
bold_text();
// Cut out hole
translate([hole_x, 0, -0.05])
cylinder(h=blue_thickness + 0.1, d=hole_diameter, $fn=50);
}
}
// White backing layer (prints second, on top of blue)
// Also fills the text and border channels
module white_layer() {
color("white")
difference() {
union() {
// Main backing layer on top of blue
translate([0, 0, blue_thickness])
oval(total_width, total_height, white_thickness);
// Fill the border channel
difference() {
oval(total_width, total_height, blue_thickness);
oval(oval_width, oval_height, blue_thickness + 0.1);
}
// Fill the text channels
bold_text();
}
// Cut out hole through entire white layer
translate([hole_x, 0, -0.05])
cylinder(h=blue_thickness + white_thickness + 0.2, d=hole_diameter, $fn=50);
}
}
// Main zipper pull assembly
module zipper_pull() {
blue_layer();
white_layer();
}
// Generate the zipper pull
zipper_pull();

View File

@@ -0,0 +1,88 @@
// Single-Layer Oval Zipper Pull Template with Raised Text
// Creates a blue base oval with raised white text and a hole for zipper attachment
// Parameters - these can be overridden from command line
name = "NAME"; // Text to display on zipper pull
oval_width = 96; // Width of blue oval (mm) - total with border will be 100mm (96 + 2*2)
oval_height = 30; // Height of blue oval (mm) - total with border will be 34mm (30 + 2*2)
base_thickness = 1.5; // Thickness of blue base layer (mm)
text_thickness = 1; // Thickness of raised white text (mm)
base_text_size = 13; // Base font size for medium names
font_file = "C:/Users/Fred/claude/Fordscript.ttf"; // Path to the custom font file
// Dynamic font sizing based on name length (mimics Ford oval proportions)
// "Fred" (4 chars) at 13mm gives ~20% coverage - our target
name_length = len(name);
text_size = name_length <= 3 ? 18 : // Short names (Zoe, Sam, Al) - larger
name_length <= 5 ? 13 : // Medium names (Fred, John, Mary) - standard
name_length <= 8 ? 11 : // Longer names (Michael, Jessica) - smaller
9; // Very long names (Christopher) - smallest
// Border parameters
border_width = 2; // Width of the white border around the oval (mm)
border_thickness = 1; // Thickness of the white border (mm)
// Hole parameters for zipper pull
hole_diameter = 4; // Diameter of the hole (mm)
hole_clearance = 3; // Minimum clearance from edge of outer border (mm) - increased to fully clear white border
// Module to create an oval (ellipse)
module oval(width, height, depth) {
scale([width/2, height/2, 1])
cylinder(h=depth, r=1, $fn=100);
}
// Blue base layer with hole
module base_layer() {
color("RoyalBlue")
difference() {
// Blue base matches the outer size of the white border
oval(oval_width + border_width*2, oval_height + border_width*2, base_thickness);
// Hole for zipper pull - positioned relative to outer edge
// Total width = oval_width + border_width*2
// Position: left edge + hole_radius + clearance
total_width = oval_width + border_width*2;
hole_x = -(total_width/2) + (hole_diameter/2) + hole_clearance;
translate([hole_x, 0, -0.05])
cylinder(h=base_thickness + 0.1, d=hole_diameter, $fn=50);
}
}
// White border around the oval
module white_border() {
color("white")
translate([0, 0, base_thickness])
difference() {
// Outer oval (larger)
oval(oval_width + border_width*2, oval_height + border_width*2, border_thickness);
// Inner oval (cut out the center)
translate([0, 0, -0.05])
oval(oval_width, oval_height, border_thickness + 0.1);
}
}
// Raised white text on top of base - REDUCED bold effect (3 renders instead of 9)
module raised_text() {
color("white")
// Reduced bold effect - only 3 offsets
for (x = [-0.4, 0, 0.4]) {
translate([x, 0, base_thickness])
linear_extrude(height=text_thickness)
text(name,
size=text_size,
font="Fordscript",
halign="center",
valign="center");
}
}
// Main zipper pull assembly
module zipper_pull() {
base_layer();
white_border();
raised_text();
}
// Generate the zipper pull
zipper_pull();

View File

@@ -0,0 +1,90 @@
// Two-Layer Oval Zipper Pull Template with Engraved Text
// Creates a white base oval with a blue top oval, engraved text, and a hole for zipper attachment
// Parameters - these can be overridden from command line
name = "NAME"; // Text to display on zipper pull
oval_width = 96; // Width of blue oval (mm) - white base will be 100mm total (96 + 2*2)
oval_height = 30; // Height of blue oval (mm) - white base will be 34mm total (30 + 2*2)
base_thickness = 1.5; // Thickness of white base layer (mm)
top_thickness = 1; // Thickness of blue top layer (mm)
base_offset = 2; // How much larger the white base is (mm)
base_text_size = 13; // Base font size for medium names (reduced to prevent interference with hole)
text_depth = 1; // How deep the text is engraved (mm) - cuts through blue to show white
font_file = "C:/Users/Fred/claude/Fordscript.ttf"; // Path to the custom font file
// Dynamic font sizing based on name length (mimics Ford oval proportions)
// "Fred" (4 chars) at 13mm gives ~20% coverage - our target
name_length = len(name);
text_size = name_length <= 3 ? 18 : // Short names (Zoe, Sam, Al) - larger
name_length <= 5 ? 13 : // Medium names (Fred, John, Mary) - standard
name_length <= 8 ? 11 : // Longer names (Michael, Jessica) - smaller
9; // Very long names (Christopher) - smallest
// Hole parameters for zipper pull
hole_diameter = 4; // Diameter of the hole (mm)
hole_clearance = 1; // Minimum clearance from edge of white base layer (mm)
// Module to create an oval (ellipse)
module oval(width, height, depth) {
scale([width/2, height/2, 1])
cylinder(h=depth, r=1, $fn=100);
}
// White base layer (larger oval) with hole
module base_layer() {
color("white")
difference() {
oval(
oval_width + base_offset*2,
oval_height + base_offset*2,
base_thickness
);
// Hole for zipper pull - positioned relative to white base edge
// Calculate from white base width: (oval_width + base_offset*2)
white_width = oval_width + base_offset*2;
hole_x = -(white_width/2) + (hole_diameter/2) + hole_clearance;
translate([hole_x, 0, -0.05])
cylinder(h=base_thickness + 0.1, d=hole_diameter, $fn=50);
}
}
// Blue top layer with engraved text and hole
module top_layer() {
color("RoyalBlue")
difference() {
// Blue oval
translate([0, 0, base_thickness])
oval(oval_width, oval_height, top_thickness);
// Engraved text (cuts into the blue layer)
// Multiple offset renders create a "fake bold" effect
for (x = [-0.3, 0, 0.3]) {
for (y = [-0.3, 0, 0.3]) {
translate([x, y, base_thickness + top_thickness - text_depth + 0.01])
linear_extrude(height=text_depth)
text(name,
size=text_size,
font="Fordscript",
halign="center",
valign="center");
}
}
// Hole for zipper pull (positioned on left side)
// Position: matches white base layer hole position
white_width = oval_width + base_offset*2;
hole_x = -(white_width/2) + (hole_diameter/2) + hole_clearance;
translate([hole_x, 0, base_thickness])
cylinder(h=top_thickness + 0.1, d=hole_diameter, $fn=50);
}
}
// Main zipper pull assembly
module zipper_pull() {
base_layer();
top_layer();
}
// Generate the zipper pull
zipper_pull();