From e108e04a870a44bc16643c39a7c25e42766812cf Mon Sep 17 00:00:00 2001 From: Kyle Heath Date: Fri, 3 Oct 2025 19:54:15 -0700 Subject: [PATCH 1/4] Bootstrap docs with mkdocs --- .github/workflows/docs.yml | 79 + .gitignore | 4 + .vscode/settings.json | 6 + README.md | 221 +-- docs-site/README.md | 259 +++ docs-site/assets/favicon.png | Bin 0 -> 515 bytes docs-site/assets/logo.svg | 116 ++ docs-site/concepts/coordinates-and-origin.md | 502 +++++ docs-site/concepts/gcode-basics.md | 629 ++++++ docs-site/concepts/index.md | 220 +++ docs-site/concepts/laser-safety.md | 198 ++ docs-site/concepts/power-vs-speed.md | 561 ++++++ .../concepts/understanding-operations.md | 420 ++++ docs-site/contributing/index.md | 57 + docs-site/documentation-plan.md | 875 +++++++++ docs-site/features/camera.md | 384 ++++ docs-site/features/holding-tabs.md | Bin 0 -> 9594 bytes docs-site/features/index.md | 93 + docs-site/features/kerf.md | 429 +++++ docs-site/features/macros-hooks.md | 459 +++++ docs-site/features/multi-layer.md | 399 ++++ docs-site/features/operations/contour.md | 336 ++++ docs-site/features/operations/depth.md | 410 ++++ docs-site/features/operations/index.md | 206 ++ .../features/operations/material-test-grid.md | 335 ++++ docs-site/features/operations/raster.md | 373 ++++ docs-site/features/operations/shrink-wrap.md | Bin 0 -> 9568 bytes docs-site/features/overscan-kerf.md | Bin 0 -> 10833 bytes docs-site/features/overscan.md | 358 ++++ docs-site/features/simulation-mode.md | 336 ++++ docs-site/files/exporting.md | 482 +++++ docs-site/files/formats.md | 304 +++ docs-site/files/importing.md | 423 ++++ docs-site/files/index.md | 112 ++ docs-site/getting-started/first-time-setup.md | 158 ++ docs-site/getting-started/index.md | 41 + docs-site/getting-started/installation.md | 122 ++ docs-site/getting-started/quick-start.md | 169 ++ docs-site/guides/batch-production-workflow.md | 457 +++++ .../guides/calibrating-your-workspace.md | 425 ++++ .../guides/creating-material-test-grid.md | 432 +++++ docs-site/guides/index.md | 45 + docs-site/guides/using-camera-alignment.md | 392 ++++ {docs => docs-site/images}/3d-preview.png | Bin .../images}/camera-alignment.png | Bin {docs => docs-site/images}/camera-image.png | Bin {docs => docs-site/images}/camera-overlay.png | Bin .../images}/contour-settings.png | Bin .../images}/machine-advanced.png | Bin {docs => docs-site/images}/machine-camera.png | Bin {docs => docs-site/images}/machine-device.png | Bin {docs => docs-site/images}/machine-laser.png | Bin {docs => docs-site/images}/machine-logs.png | Bin .../images}/machine-settings.png | Bin {docs => docs-site/images}/ss-main.png | Bin docs-site/includes/abbreviations.md | 8 + docs-site/index.md | 95 + docs-site/machine/device-config.md | 521 +++++ docs-site/machine/grbl-settings.md | 625 ++++++ docs-site/machine/index.md | 163 ++ docs-site/machine/multi-laser.md | 546 ++++++ docs-site/machine/profiles.md | 470 +++++ docs-site/reference/firmware.md | 463 +++++ docs-site/reference/gcode-dialects.md | 26 + docs-site/reference/index.md | 108 ++ docs-site/reference/shortcuts.md | 362 ++++ docs-site/stylesheets/extra.css | 84 + docs-site/troubleshooting/common.md | 382 ++++ docs-site/troubleshooting/connection.md | 306 +++ docs-site/troubleshooting/index.md | 97 + docs-site/troubleshooting/performance.md | 411 ++++ docs-site/troubleshooting/snap-permissions.md | 366 ++++ docs-site/ui/3d-preview.md | 151 ++ docs-site/ui/canvas-tools.md | 149 ++ docs-site/ui/index.md | 45 + docs-site/ui/main-window.md | 103 + docs-site/ui/settings.md | 147 ++ docs/README.md | 183 ++ docs/user-docs-site.md | 224 +++ mkdocs.yml | 191 ++ pixi.lock | 1703 ++++++++++++++--- pixi.toml | 31 +- scripts/scrub_non_utf8.py | 49 + 83 files changed, 19341 insertions(+), 495 deletions(-) create mode 100644 .github/workflows/docs.yml create mode 100644 .vscode/settings.json create mode 100644 docs-site/README.md create mode 100644 docs-site/assets/favicon.png create mode 100644 docs-site/assets/logo.svg create mode 100644 docs-site/concepts/coordinates-and-origin.md create mode 100644 docs-site/concepts/gcode-basics.md create mode 100644 docs-site/concepts/index.md create mode 100644 docs-site/concepts/laser-safety.md create mode 100644 docs-site/concepts/power-vs-speed.md create mode 100644 docs-site/concepts/understanding-operations.md create mode 100644 docs-site/contributing/index.md create mode 100644 docs-site/documentation-plan.md create mode 100644 docs-site/features/camera.md create mode 100644 docs-site/features/holding-tabs.md create mode 100644 docs-site/features/index.md create mode 100644 docs-site/features/kerf.md create mode 100644 docs-site/features/macros-hooks.md create mode 100644 docs-site/features/multi-layer.md create mode 100644 docs-site/features/operations/contour.md create mode 100644 docs-site/features/operations/depth.md create mode 100644 docs-site/features/operations/index.md create mode 100644 docs-site/features/operations/material-test-grid.md create mode 100644 docs-site/features/operations/raster.md create mode 100644 docs-site/features/operations/shrink-wrap.md create mode 100644 docs-site/features/overscan-kerf.md create mode 100644 docs-site/features/overscan.md create mode 100644 docs-site/features/simulation-mode.md create mode 100644 docs-site/files/exporting.md create mode 100644 docs-site/files/formats.md create mode 100644 docs-site/files/importing.md create mode 100644 docs-site/files/index.md create mode 100644 docs-site/getting-started/first-time-setup.md create mode 100644 docs-site/getting-started/index.md create mode 100644 docs-site/getting-started/installation.md create mode 100644 docs-site/getting-started/quick-start.md create mode 100644 docs-site/guides/batch-production-workflow.md create mode 100644 docs-site/guides/calibrating-your-workspace.md create mode 100644 docs-site/guides/creating-material-test-grid.md create mode 100644 docs-site/guides/index.md create mode 100644 docs-site/guides/using-camera-alignment.md rename {docs => docs-site/images}/3d-preview.png (100%) rename {docs => docs-site/images}/camera-alignment.png (100%) rename {docs => docs-site/images}/camera-image.png (100%) rename {docs => docs-site/images}/camera-overlay.png (100%) rename {docs => docs-site/images}/contour-settings.png (100%) rename {docs => docs-site/images}/machine-advanced.png (100%) rename {docs => docs-site/images}/machine-camera.png (100%) rename {docs => docs-site/images}/machine-device.png (100%) rename {docs => docs-site/images}/machine-laser.png (100%) rename {docs => docs-site/images}/machine-logs.png (100%) rename {docs => docs-site/images}/machine-settings.png (100%) rename {docs => docs-site/images}/ss-main.png (100%) create mode 100644 docs-site/includes/abbreviations.md create mode 100644 docs-site/index.md create mode 100644 docs-site/machine/device-config.md create mode 100644 docs-site/machine/grbl-settings.md create mode 100644 docs-site/machine/index.md create mode 100644 docs-site/machine/multi-laser.md create mode 100644 docs-site/machine/profiles.md create mode 100644 docs-site/reference/firmware.md create mode 100644 docs-site/reference/gcode-dialects.md create mode 100644 docs-site/reference/index.md create mode 100644 docs-site/reference/shortcuts.md create mode 100644 docs-site/stylesheets/extra.css create mode 100644 docs-site/troubleshooting/common.md create mode 100644 docs-site/troubleshooting/connection.md create mode 100644 docs-site/troubleshooting/index.md create mode 100644 docs-site/troubleshooting/performance.md create mode 100644 docs-site/troubleshooting/snap-permissions.md create mode 100644 docs-site/ui/3d-preview.md create mode 100644 docs-site/ui/canvas-tools.md create mode 100644 docs-site/ui/index.md create mode 100644 docs-site/ui/main-window.md create mode 100644 docs-site/ui/settings.md create mode 100644 docs/README.md create mode 100644 docs/user-docs-site.md create mode 100644 mkdocs.yml create mode 100644 scripts/scrub_non_utf8.py diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 000000000..6a5e57b86 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,79 @@ +name: Documentation + +on: + push: + branches: + - main + tags: + - 'v*' + pull_request: + branches: + - main + workflow_dispatch: + +permissions: + contents: write + pages: write + id-token: write + +jobs: + build-and-deploy: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Fetch all history for mike versioning + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install mkdocs-material mike pillow cairosvg + + - name: Configure Git for mike + run: | + git config user.name github-actions + git config user.email github-actions@github.com + + - name: Extract version from tag or use 'dev' + id: get_version + run: | + if [[ $GITHUB_REF == refs/tags/v* ]]; then + VERSION=${GITHUB_REF#refs/tags/v} + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "alias=latest" >> $GITHUB_OUTPUT + echo "is_release=true" >> $GITHUB_OUTPUT + else + echo "version=dev" >> $GITHUB_OUTPUT + echo "alias=dev" >> $GITHUB_OUTPUT + echo "is_release=false" >> $GITHUB_OUTPUT + fi + + - name: Build documentation for pull request + if: github.event_name == 'pull_request' + run: mkdocs build --strict + + - name: Deploy development docs + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + run: | + mike deploy --push --update-aliases dev development + + - name: Deploy release docs with versioning + if: steps.get_version.outputs.is_release == 'true' + run: | + VERSION=${{ steps.get_version.outputs.version }} + mike deploy --push --update-aliases $VERSION latest + mike set-default --push latest + + - name: Upload artifact for Pages (optional, for review) + if: github.event_name == 'pull_request' + uses: actions/upload-artifact@v4 + with: + name: documentation + path: site/ diff --git a/.gitignore b/.gitignore index 3d95ce6c5..d354cf18c 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,7 @@ debian/.debhelper *.mo *.po~ *.mo~ + +# MkDocs +site/ +.cache/ diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..88b727224 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "editor.rulers": [ + { "column": 80, "color": "#ff0000" } + ], + "editor.wordWrap": "off" +} \ No newline at end of file diff --git a/README.md b/README.md index 83c7ffa68..f4b96987f 100644 --- a/README.md +++ b/README.md @@ -10,227 +10,12 @@ Rayforge is a modern, cross-platform G-code sender and control software for GRBL ![Screenshot](docs/ss-main.png) -## Key Features -| Feature | Description | -| :--------------------------- | :------------------------------------------------------------------------------------------------- | -| **Modern UI** | Polished and modern UI built with Gtk4 and Libadwaita. Supports system, light, and dark themes. | -| **Multi-Layer Operations** | Assign different operations (e.g., engrave then cut) to layers in your design. | -| **Versatile Operations** | Supports Contour, Raster Engraving (with cross-hatch fill), Shrink Wrap, and Depth Engraving. | -| **Overscan & Kerf Comp.** | Improve engraving quality with overscan and ensure dimensional accuracy with kerf compensation. | -| **2.5D Cutting** | Perform multi-pass cuts with a configurable step-down between each pass for thick materials. | -| **3D G-code Preview** | Visualize G-code toolpaths in 3D to verify the job before sending it to the machine. | -| **Multi-Machine Profiles** | Configure and instantly switch between multiple machine profiles. | -| **GRBL Firmware Settings** | Read and write firmware parameters (`$$`) directly from the UI. | -| **Comprehensive 2D Canvas** | Full suite of tools: alignment, transformation, measurement, zoom, pan, and more. | -| **Advanced Path Generation** | High-quality image tracing, travel time optimization, path smoothing, and spot size interpolation. | -| **Holding Tabs** | Add tabs to contour cuts to hold pieces in place. Supports manual and automatic placement. | -| **G-code Macros & Hooks** | Run custom G-code snippets before/after jobs. Supports variable substitution. | -| **Broad File Support** | Import from SVG, DXF, PDF, JPEG, PNG, BMP, and even Ruida files (`.rd`). | -| **Multi-Laser Operations** | Choose different lasers for each operation in a job | -| **Camera Integration** | Use a USB camera for workpiece alignment, positioning, and background tracing. | -| **Cross-Platform** | Native builds for Linux and Windows. | -| **Extensible** | Open development model makes it easy to [add support for new devices](docs/driver.md). | -| **Multi-Language** | Available in English, Portuguese, Spanish, and German. | -| **G-code Dialects** | Supports GRBL, Smoothieware, and other GRBL-compatible firmwares. | +## Documentation -## Device Support +- User documentation at [rayforge.org](https://rayforge.org). +- Developer documentation in [docs](docs/README.md). -| Device Type | Connection Method | Notes | -| :--------------- | :---------------------- | :------------------------------------------------------------- | -| **GRBL** | Serial Port | Supported since version 0.13. The most common connection type. | -| **GRBL** | Network (WiFi/Ethernet) | Connect to any GRBL device on your network. | -| **Smoothieware** | Telnet | Supported since version 0.15. | - -## Installation - -### Windows - -Download the latest installer from the **[Releases Page](https://github.com/barebaric/rayforge/releases/)**. - -### Linux - -We offer several installation methods for Linux. - -#### Ubuntu & Derivatives (via PPA) - -For users on Ubuntu and its derivatives (like Linux Mint, Pop!\_OS), the recommended -method is our official PPA. This integrates directly with your system's package -manager and provides automatic updates. - -> [!NOTE] -> The PPA supports **Ubuntu 24.04 LTS and newer**. - -Open a terminal and run the following commands: - -```bash -sudo add-apt-repository ppa:knipknap/rayforge -sudo apt update -sudo apt install rayforge -``` - -#### Cross-Distro (Snap) - -The Snap package includes all dependencies and runs in a sandbox. It is the recommended -method for most other Linux distributions. - -[![Get it from the Snap Store](https://snapcraft.io/en/light/install.svg)](https://snapcraft.io/rayforge) - -> [!IMPORTANT] -> The Snap is sandboxed and requires you to manually grant permissions for hardware -> access. Run these commands after installation. - -For camera access: - -```bash -sudo snap connect rayforge:camera -``` - -For USB serial port access: - -```bash -# First, enable experimental hotplug support -sudo snap set system experimental.hotplug=true - -# Connect your laser via USB, then run this command -sudo snap connect rayforge:serial-port -``` - -#### From Source (pip) - -This method is for developers and advanced users. You must install system dependencies manually. - -On Debian/Ubuntu-based systems: - -```bash -sudo apt update -sudo apt install python3-pip python3-gi gir1.2-gtk-3.0 gir1.2-adw-1 gir1.2-gdkpixbuf-2.0 libgirepository-1.0-dev libgirepository-2.0-0 libvips42t64 libadwaita-1-0 libopencv-dev - -pip3 install rayforge -``` - -_(Package names may differ on other distributions.)_ - -### Other Operating Systems (e.g., macOS) - -There are no official builds for other platforms, but Rayforge may run from source via -the `pip` method. Contributions for packaging on other platforms are welcome. - -## Screenshots - -
-Click to expand screenshots - -**Operation Settings** -![Contour Settings](docs/contour-settings.png) - -**Machine & Device Configuration** -![General Settings](docs/machine-settings.png) -![Device Settings](docs/machine-device.png) -![Advanced Settings](docs/machine-advanced.png) -![Laser Settings](docs/machine-laser.png) - -**Integrated Camera Support** -![Camera Settings](docs/machine-camera.png) -![Camera Alignment](docs/camera-alignment.png) -![Camera Image](docs/camera-image.png) -![Camera Overlay on Worksurface](docs/camera-overlay.png) - -
- -## Contributing - -We welcome contributions of all kinds! Whether you're fixing a bug, adding -a feature, or improving documentation, your help is appreciated. - -- **Report a Bug:** Open an [issue](https://github.com/barebaric/rayforge/issues) - with a clear description and steps to reproduce. -- **Suggest a Feature:** Start a discussion or open a feature request issue. -- **Submit a Pull Request:** Please discuss major changes in an issue first. -- **Add a Driver:** See the [driver development guide](docs/driver.md) to add - support for your hardware. - -### Packaging Help Wanted - -We are actively seeking help to create and maintain a **[Flatpak](flatpak/)** package. -If you have experience with Flatpak, your contribution would be highly valuable! - -## Development - -This project uses [**Pixi**](https://pixi.sh/) to manage dependencies and -development environments for a reproducible setup. - -### Prerequisites - -First, install Pixi by following the instructions on the -[official website](https://pixi.sh/latest/installation/). - -### 1. Setup Environment - -Clone the repository and install dependencies. - -```bash -# Install Gtk/Adwaita system dependency (Debian/Ubuntu) -sudo apt install gir1.2-adw-1 - -# Let Pixi handle the rest -pixi install -``` - -This command reads `pixi.toml` and installs all conda and pip dependencies into a local -`.pixi` virtual environment. - -### 2. Run the Application - -```bash -pixi run rayforge -``` - -### 3. Run Tests and Lint - -```bash -pixi run test -pixi run lint -``` - -### 4. Activate the Development Shell - -For an interactive workflow, you can activate a shell within the project's environment. - -```bash -pixi shell -``` - -Inside this shell, you can run commands directly without the `pixi run` prefix -(e.g., `rayforge`, `pytest`). Type `exit` to leave the shell. - -### 5. Manage Dependencies - -Always use Pixi to manage dependencies to ensure the `pixi.lock` file is updated. - -```bash -# Add a conda package -pixi add numpy - -# Add a PyPI package -pixi add --pypi requests -``` - -### 6. Translation Workflow - -The following tasks are available for managing language translations: - -#### Update `.po` files from source code - -```bash -pixi run update-translations -``` - -#### Compile `.po` files to binary `.mo` files - -```bash -pixi run compile-translations -``` ## License diff --git a/docs-site/README.md b/docs-site/README.md new file mode 100644 index 000000000..df9e3eb39 --- /dev/null +++ b/docs-site/README.md @@ -0,0 +1,259 @@ +# Rayforge Documentation + +This directory contains the source files for the Rayforge end-user documentation, built with [MkDocs Material](https://squidfunk.github.io/mkdocs-material/). + +## Documentation Structure + +The documentation is organized into the following sections: + +- **Getting Started**: Installation, first-time setup, and quick start guide +- **User Interface**: Main window, canvas tools, 3D preview, and settings +- **Features**: All operations, multi-layer workflow, camera integration, etc. +- **Machine Setup**: Machine profiles, device configuration, and GRBL settings +- **File Formats**: Importing files, supported formats, and exporting G-code +- **Troubleshooting**: Common issues and their solutions +- **Reference**: Keyboard shortcuts, G-code dialects, firmware compatibility +- **Contributing**: Development setup and how to contribute + +## Building the Documentation + +### Prerequisites + +Install the documentation dependencies: + +```bash +# Using pixi (recommended) +pixi install -e docs + +# Or using pip +pip install mkdocs-material mike pillow cairosvg +``` + +### Local Development + +Serve the documentation locally with live reload: + +```bash +# Simple command (recommended) +pixi run docs-serve + +# Or activate the docs environment first +pixi shell -e docs +mkdocs serve +``` + +The documentation will be available at http://127.0.0.1:8000/ + +### Building Static Site + +Build the documentation to the `site/` directory: + +```bash +# Simple command (recommended) +pixi run docs-build + +# Or manually with environment +pixi shell -e docs +mkdocs build +``` + +## Versioning + +Documentation versioning is managed using [mike](https://github.com/jimporter/mike), which creates separate version directories and allows users to switch between documentation for different Rayforge versions. + +### Deploying Versions + +Deploy documentation for a specific version: + +```bash +# Deploy using pixi (simple) +VERSION=dev pixi run docs-deploy + +# Or manually with mike +pixi shell -e docs +mike deploy dev development --update-aliases +mike deploy 1.0.0 latest --update-aliases +mike set-default latest +``` + +### Version Workflow + +- **Development (`dev`)**: Built from `main` branch, represents work-in-progress +- **Releases (`X.Y.Z`)**: Built from version tags (e.g., `v1.0.0`) +- **Latest**: Alias that points to the most recent stable release + +## Automated Deployment + +Documentation is automatically built and deployed via GitHub Actions: + +- **Pull Requests**: Documentation is built to verify no errors +- **Main Branch**: Development docs deployed to `dev` version +- **Version Tags**: Release docs deployed with version number and `latest` alias + +## Adding Content + +### Creating New Pages + +1. Create a new Markdown file in the appropriate section directory +2. Add the page to the `nav` section in `mkdocs.yml` +3. Use relative links to reference other pages and images + +### Using Screenshots + +Screenshots enhance the documentation and help users understand the interface: + +1. Take clear, high-resolution screenshots (PNG format preferred) +2. Save to `../docs/` directory (shared with README screenshots) +3. Reference in Markdown: `![Description](../images/screenshot-name.png)` +4. Add descriptive alt text for accessibility + +### Markdown Extensions + +MkDocs Material supports many useful extensions: + +#### Admonitions + +```markdown +!!! note "Optional Title" + This is a note admonition. + +!!! tip + This is a tip. + +!!! warning + This is a warning. + +!!! danger + This is a danger/error message. +``` + +#### Keyboard Shortcuts + +```markdown +Press ++ctrl+c++ to copy. +Press ++ctrl+shift+v++ to paste. +``` + +#### Code Blocks + +```markdown +​```bash +pixi run rayforge +​``` + +​```python +def hello(): + print("Hello, Rayforge!") +​``` +``` + +#### Tabs + +```markdown +=== "Linux" + Linux instructions here + +=== "Windows" + Windows instructions here +``` + +#### Tables + +```markdown +| Header 1 | Header 2 | +|:---------|:---------| +| Cell 1 | Cell 2 | +``` + +## Style Guidelines + +### Writing Style + +- **Audience**: End-users, not developers +- **Tone**: Friendly, clear, and concise +- **Voice**: Use second person ("you") and active voice +- **Examples**: Provide concrete examples and screenshots + +### Page Structure + +Each page should include: + +1. **Title**: Clear, descriptive H1 heading +2. **Introduction**: Brief overview of the page content +3. **Body**: Detailed information with examples +4. **Navigation**: Links to related pages at the end + +### Screenshots + +- Use consistent window themes (prefer default theme) +- Crop to relevant area +- Annotate if necessary to highlight specific elements +- Keep file sizes reasonable (use PNG with compression) + +### Code Examples + +- Provide complete, working examples +- Use syntax highlighting +- Include explanatory comments +- Show expected output when relevant + +## Documentation Standards + +### Links + +- Use relative links for internal pages: `[text](../section/page.md)` +- Use descriptive link text (not "click here") +- Verify all links work before committing + +### Images + +- Alt text is required for all images +- Use descriptive file names (e.g., `machine-settings-device-tab.png`) +- Optimize images for web (compress without losing quality) + +### Consistency + +- Use consistent terminology throughout +- Follow the same structure across similar pages +- Use the same heading hierarchy (H1 for title, H2 for sections, etc.) + +## Testing Documentation + +Before submitting changes: + +1. **Build locally**: Ensure no build errors + ```bash + pixi run -e docs docs-build + ``` + +2. **Check links**: Verify all internal links work + +3. **Review formatting**: Check that Markdown renders correctly + +4. **Test on mobile**: Verify mobile responsiveness (Material theme is responsive by default) + +5. **Proofread**: Check spelling and grammar + +## Deployment + +Documentation is automatically deployed when: + +- Changes are pushed to `main` branch (deploys to `dev` version) +- Version tags are pushed (e.g., `v1.0.0`, deploys to version and `latest`) + +Manual deployment is not typically necessary, but can be done with: + +```bash +# Deploy and push to gh-pages branch +pixi run -e docs docs-deploy +``` + +## Need Help? + +- **MkDocs Material**: https://squidfunk.github.io/mkdocs-material/ +- **Mike (versioning)**: https://github.com/jimporter/mike +- **Markdown Guide**: https://www.markdownguide.org/ + +## Contributing + +Documentation improvements are always welcome! Please see [Contributing Guide](contributing/index.md) for details on how to contribute. diff --git a/docs-site/assets/favicon.png b/docs-site/assets/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..62f4551963a96ba124c71b7d654ad967146d1804 GIT binary patch literal 515 zcmWIWbLZuf;$mQ6;Pv!y2?EjzAk4uAB#W!6fFxUzx4R3FW?*3Qba4!c2=(_636xPb zaW$}#v#LzZcjRy^SCq3U)$+0`sq(c7abb}ya^N&|KD0$hM>n!8F)jV(OmlAII>}I( zzz|^xMFvhL4~BfEf;vv?3f_Vu83qo9stR_65Pxp&ERigUK$$8BgQ8f;v_RpIq$qQB zGe;pl>jXhn(etgGER50d4oum1_r97jBOt}mK=sJZYytihXJaeAQf&q1WREPS1P>Qe z#!LmXzvsU4&U@D0mVG~!>gG>O?+f{W1>PzeSA)A zVKI&o%jC4;s}jyKQBh%6X3VjROJg!;zqFgrAW|oriC4ylMLM;lietNV-Bs)>c4>lbhrs$ncTv);zAlF!yI#K_b$G`_~_;sU7@Z-r{}h&sy( yGcTc>q(T{H0q@{QhJZ>-dxMY)E;-9w&tO(J1?xCAUFD~nT0s%&>FVd=lmGzl1B$=^ literal 0 HcmV?d00001 diff --git a/docs-site/assets/logo.svg b/docs-site/assets/logo.svg new file mode 100644 index 000000000..8b04fb707 --- /dev/null +++ b/docs-site/assets/logo.svg @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs-site/concepts/coordinates-and-origin.md b/docs-site/concepts/coordinates-and-origin.md new file mode 100644 index 000000000..9e495c21b --- /dev/null +++ b/docs-site/concepts/coordinates-and-origin.md @@ -0,0 +1,502 @@ +# Coordinate Systems and Origins + +Understanding how RayForge handles coordinate systems is essential for positioning your work correctly and avoiding common mistakes. + +## Overview + +RayForge uses multiple coordinate systems and origin points to manage positioning. This can seem confusing at first, but each serves a specific purpose. + +**Key concepts:** + +- **Canvas coordinates** - Where you design (screen space) +- **Machine coordinates** - Physical machine position +- **Job origin** - Where the job starts on the machine +- **Workpiece coordinates** - Position within a design element + +--- + +## Coordinate Systems Explained + +### Canvas Coordinates + +**What it is:** The design space where you arrange workpieces and layers. + +**Characteristics:** +- **Units:** Millimeters (mm) by default +- **Origin:** Top-left corner of the canvas (0, 0) +- **X-axis:** Increases to the right +- **Y-axis:** Increases downward +- **Purpose:** Visual design and layout + +**Example:** +``` +(0,0) -----> X + | + | Your design + v elements here + Y +``` + +Canvas coordinates are what you see and interact with in the RayForge interface. + +--- + +### Machine Coordinates + +**What it is:** The physical coordinate system of your laser machine. + +**Characteristics:** +- **Units:** Millimeters (mm) +- **Origin:** Machine home position (usually top-left or bottom-left) +- **X-axis:** Increases to the right +- **Y-axis:** Direction depends on machine configuration (up or down) +- **Purpose:** Physical movement commands + +**Common machine origins:** + +| Origin Position | Description | Common In | +|----------------|-------------|-----------| +| **Top-left** | (0,0) at back-left | Diode lasers | +| **Bottom-left** | (0,0) at front-left | CO2 lasers, CNC routers | +| **Center** | (0,0) at bed center | Some 3-axis machines | + +**Machine coordinate example (top-left origin):** +``` +(0,0) ----------------> X (max) + | + | Work area + | + v + Y (max) +``` + +--- + +### Job Origin + +**What it is:** The reference point where your job will be positioned on the machine. + +**Why it matters:** +- Determines where the laser starts cutting/engraving +- Allows you to position jobs anywhere on the bed +- Makes it easy to reposition or repeat jobs + +**Setting job origin:** + +1. **Design your work** in RayForge +2. **Position the job** on the canvas +3. **Set the origin mode** (absolute, current position, etc.) +4. **Frame the job** to verify position on the machine + +**Job origin modes:** + +| Mode | Description | Use Case | +|------|-------------|----------| +| **Absolute** | Job placed at specified machine coordinates | Repeatable positioning | +| **Current Position** | Job starts at current laser head position | Quick alignment | +| **User Origin** | Custom reference point | Advanced workflows | + +--- + +### Workpiece Coordinates + +**What it is:** The local coordinate system of each individual design element. + +**Characteristics:** +- Each workpiece has its own origin (typically its bounding box corner) +- Transformations (rotate, scale, move) affect workpiece coordinates +- Operations reference workpiece coordinates + +**Example:** + +If you import an SVG logo: +- The logo has its own internal coordinate system +- RayForge places it on the canvas +- You can move/rotate/scale it +- The logo's local coordinates remain consistent + +--- + +## Origin Points in Practice + +### Job Origin vs Machine Origin + +**Scenario:** You want to engrave a logo 50mm from the left edge and 100mm from the top of your machine bed. + +**Solution:** + +1. **Set machine origin** to top-left (if not already) +2. **Set job origin mode** to "Absolute" +3. **Position your job** at canvas coordinates (50, 100) +4. **Export G-code** - RayForge generates commands like: + ```gcode + G0 X50 Y100 ; Move to job start position + ``` + +**Result:** The logo appears exactly where you specified on the machine. + +--- + +### Current Position Origin + +**Scenario:** You want to start a job wherever the laser head currently is. + +**Solution:** + +1. **Manually jog** the laser head to desired position +2. **Set job origin mode** to "Current Position" +3. **Run the job** - it starts from the current head position + +**Use cases:** +- Quick test cuts without precise positioning +- Aligning to physical marks on material +- Iterative prototyping + +--- + +### Repeating Jobs + +**Scenario:** You need to cut 10 identical parts in a grid. + +**Solution:** + +1. **Design one part** in RayForge +2. **Duplicate the workpiece** 10 times +3. **Arrange in a grid** using alignment tools +4. **Set job origin** to absolute mode +5. **Export once** - all parts cut in sequence + +**Benefit:** Canvas coordinates translate directly to machine coordinates, ensuring perfect spacing. + +--- + +## Common Coordinate Mistakes + +### Mistake 1: Wrong Machine Origin + +**Problem:** Job appears in wrong location, possibly off the bed. + +**Cause:** Machine origin configuration doesn't match actual machine. + +**Example:** +- RayForge configured for top-left origin +- Machine actually has bottom-left origin +- Y-coordinates are inverted + +**Solution:** + +1. Check machine settings: **Settings > Machine > Profile** +2. Verify **Y-axis direction** setting +3. Test with a small frame job to confirm + +--- + +### Mistake 2: Absolute vs Relative Positioning + +**Problem:** Job moves from unexpected position. + +**Cause:** Confusion between absolute (G90) and incremental (G91) modes. + +**G-code modes:** +- **G90 (Absolute):** Coordinates are absolute positions + ```gcode + G0 X10 Y10 ; Move to position (10, 10) + G0 X20 Y20 ; Move to position (20, 20) + ``` +- **G91 (Incremental):** Coordinates are relative movements + ```gcode + G0 X10 Y10 ; Move 10mm right, 10mm down from current position + G0 X20 Y20 ; Move another 20mm right, 20mm down + ``` + +**RayForge default:** G90 (absolute mode) for predictable positioning. + +**Solution:** Check generated G-code preamble - should include `G90` command. + +--- + +### Mistake 3: Job Exceeds Machine Bounds + +**Problem:** Job starts but crashes into machine limits or fails with alarm. + +**Cause:** Job positioned such that it extends beyond work area. + +**Example:** +- Machine work area: 300mm x 200mm +- Job size: 100mm x 100mm +- Job origin: (250, 150) +- Job endpoint: (350, 250) - **exceeds bounds!** + +**Prevention:** + +1. Configure correct work area in **Settings > Machine > Profile** +2. RayForge will warn if job exceeds bounds +3. Use **Frame Job** feature to verify before cutting + +--- + +### Mistake 4: Ignoring Overscan + +**Problem:** Job positioned at very edge of work area, but overscan causes it to exceed bounds. + +**Explanation:** + +Overscan extends raster operations beyond the visible work area for quality: + +``` + Visible area + |<--------------->| +----|===============--|---- Raster line + ^ ^ + Overscan Overscan +``` + +**Effective area:** +``` +Work area: 300mm +Overscan: 5mm on each side +Usable area: 290mm (300 - 5 - 5) +``` + +**Solution:** Account for overscan when positioning jobs near edges. + +--- + +## Coordinate Transformations + +### Translation (Moving) + +**What happens:** Workpiece coordinates shift by a fixed amount. + +**Example:** +- Original position: (10, 20) +- Move by: (5, -3) +- New position: (15, 17) + +**In RayForge:** Drag workpieces to move them, or use arrow keys for precise nudging. + +--- + +### Rotation + +**What happens:** Workpiece coordinates rotate around a center point. + +**Example:** +- Square at (50, 50), size 20x20 +- Rotate 45 degrees around center +- Corners move to new positions + +**In RayForge:** Select workpiece and use rotation handles or transform tools. + +**G-code impact:** +- RayForge pre-computes rotated coordinates +- G-code contains final absolute positions (no rotation commands) + +--- + +### Scaling + +**What happens:** Workpiece coordinates multiply by a scale factor. + +**Example:** +- Original size: 50mm x 50mm +- Scale by 2x +- New size: 100mm x 100mm + +**In RayForge:** Select workpiece and use scale handles or specify dimensions. + +--- + +## Advanced Topics + +### Work Coordinate Systems (G54-G59) + +**What they are:** GRBL supports multiple coordinate systems for advanced workflows. + +**G-codes:** +- **G54** - Work Coordinate System 1 (default) +- **G55** - Work Coordinate System 2 +- **G56** - Work Coordinate System 3 +- ... (up to G59) + +**Use case:** +- Set up multiple fixture positions on the bed +- Switch between them with G-code commands +- Run same job at different locations + +**RayForge support:** Limited. Primarily uses G54 (default). Advanced users can inject other coordinate systems via macros. + +--- + +### Coordinate Offsets + +**What they are:** Temporary shifts in the coordinate system. + +**G-code commands:** +- **G92** - Set current position to specified coordinates (offset) + ```gcode + G92 X0 Y0 ; Define current position as (0,0) + ``` + +**Caution:** Offsets can be confusing and lead to positioning errors. RayForge avoids them in favor of explicit absolute positioning. + +--- + +### Homing and Machine Coordinates + +**Homing ($H in GRBL):** +- Machine moves to physical limit switches +- Sets machine zero position +- Ensures repeatable positioning + +**Why homing matters:** +- Without homing, machine doesn't know where it is +- Absolute positioning requires a known reference +- Homing provides that reference + +**Best practice:** Home your machine before each session for consistent results. + +--- + +## Practical Workflows + +### Workflow 1: Centering a Job + +**Goal:** Place a logo in the center of the work area. + +**Steps:** + +1. **Know your work area:** e.g., 300mm x 200mm +2. **Calculate center:** (150, 100) +3. **Know your logo size:** e.g., 50mm x 30mm +4. **Calculate logo origin:** Center - (logo size / 2) + - X: 150 - (50/2) = 125mm + - Y: 100 - (30/2) = 85mm +5. **Position logo** at (125, 85) on canvas +6. **Set job origin** to absolute +7. **Frame and run** + +**Shortcut:** RayForge has alignment tools - select logo and use "Align Center" commands. + +--- + +### Workflow 2: Aligning to Material + +**Goal:** Align design to a pre-cut piece of material. + +**Steps:** + +1. **Place material** on machine bed +2. **Jog laser head** to bottom-left corner of material +3. **Set user origin** with G92 or controller command +4. **Set job origin** to current position +5. **Run job** - starts from the material corner + +**Alternative (camera-based):** +1. **Use camera** to see material +2. **Align design** visually in RayForge +3. **Set job origin** based on camera reference +4. **Run job** + +--- + +### Workflow 3: Production Grid + +**Goal:** Cut multiple parts in a grid for production. + +**Steps:** + +1. **Design one part** +2. **Duplicate** to create grid (e.g., 3x3 grid, 10mm spacing) +3. **Position entire grid** on canvas to start at (10, 10) +4. **Set job origin** to absolute +5. **Export G-code** - all parts cut sequentially + +**Coordinates in G-code:** +```gcode +; Part 1 at (10, 10) +G0 X10 Y10 +; ...cut commands... + +; Part 2 at (70, 10) [10 + 50mm part + 10mm spacing] +G0 X70 Y10 +; ...cut commands... +``` + +--- + +## Troubleshooting Coordinate Issues + +### Job Positioned Incorrectly + +**Diagnosis:** + +1. **Frame the job** - does the frame match your expectation? +2. **Check machine origin** - top-left, bottom-left, or center? +3. **Check Y-axis direction** - does Y increase up or down? +4. **Check job origin mode** - absolute, current, or user? + +**Solution:** Adjust machine settings to match your actual hardware. + +--- + +### Job Runs Backwards or Mirrored + +**Problem:** Design appears flipped on the machine. + +**Cause:** Y-axis or X-axis direction mismatch. + +**Solutions:** + +- **In machine settings:** Toggle Y-axis direction +- **In design:** Manually flip the workpiece before export +- **In G-code:** Edit commands (advanced) + +--- + +### Coordinates Off by Constant Amount + +**Problem:** Job always off by same distance (e.g., 10mm to the right). + +**Cause:** Job origin offset or work coordinate system offset. + +**Solutions:** + +1. **Check for G92 offset** - send `G92.1` to clear offsets +2. **Re-home machine** - ensure machine zero is correct +3. **Verify job origin position** - check canvas coordinates + +--- + +### Random Position Each Time + +**Problem:** Same job runs at different positions each time. + +**Cause:** Using "Current Position" origin without consistent starting position. + +**Solutions:** + +- **Home machine** before each job +- **Use absolute positioning** instead of current position +- **Manually jog** to consistent position if needed + +--- + +## Best Practices + +1. **Always home your machine** at the start of each session +2. **Use absolute positioning (G90)** for repeatable jobs +3. **Configure machine settings** once and test thoroughly +4. **Frame jobs before running** to verify position +5. **Keep designs within work area** - account for overscan +6. **Use consistent origin modes** - don't switch mid-project +7. **Document your setup** - note origin position and Y-axis direction for future reference + +--- + +## Related Pages + +- [Machine Setup](../machine/device-config.md) - Configure machine dimensions and origin +- [GRBL Settings](../machine/grbl-settings.md) - Firmware coordinate settings +- [Exporting G-code](../files/exporting.md) - Job positioning options +- [Understanding Operations](understanding-operations.md) - How operations use coordinates diff --git a/docs-site/concepts/gcode-basics.md b/docs-site/concepts/gcode-basics.md new file mode 100644 index 000000000..081e86915 --- /dev/null +++ b/docs-site/concepts/gcode-basics.md @@ -0,0 +1,629 @@ +# G-code Basics + +Understanding G-code helps you troubleshoot issues, optimize performance, and customize RayForge output for your specific machine. + +## What is G-code? + +**G-code** is a standardized programming language for CNC machines (including laser cutters). It tells the machine exactly where to move, how fast to move, and what to do (laser on/off, power level, etc.). + +**Key points:** + +- **Text-based** - Human-readable commands +- **Line-by-line** - Machine executes one command at a time +- **Standardized** - Based on ISO 6983 and RS-274 standards +- **Dialect variations** - Different firmware (GRBL, Marlin, etc.) have slight differences + +**Example G-code:** +```gcode +G21 ; Set units to millimeters +G90 ; Use absolute positioning +G0 X10 Y10 ; Rapid move to position (10, 10) +M4 S500 ; Turn laser on at 50% power +G1 X50 Y10 F3000 ; Linear move to (50, 10) at 3000 mm/min +M5 ; Turn laser off +``` + +--- + +## How RayForge Generates G-code + +RayForge converts your designs into G-code through a multi-step process: + +**Generation pipeline:** + +``` +Design (Workpieces + Layers) + | + v +Operations (Contour, Raster, etc.) + | + v +Toolpaths (Lines, arcs, points) + | + v +G-code Commands (GRBL dialect) + | + v +Output File (.gcode) +``` + +**What RayForge does:** + +1. **Analyzes your design** - Extracts geometry from workpieces +2. **Applies operations** - Determines cut/engrave paths +3. **Optimizes toolpaths** - Reorders paths, minimizes travel +4. **Generates commands** - Converts paths to G-code +5. **Injects hooks** - Adds user-defined macros at specified points +6. **Writes file** - Outputs complete G-code ready for machine + +--- + +## G-code Command Structure + +### Command Format + +**Basic syntax:** +``` + [ ...] +``` + +**Examples:** +- `G0` - G command, number 0 (rapid positioning) +- `G1 X50 Y20 F3000` - G command with parameters X, Y, F +- `M4 S500` - M command with parameter S + +**Line structure:** +```gcode +G1 X50.0 Y20.5 F3000 ; Move to (50, 20.5) at 3000 mm/min +^ ^ ^ ^ ^ +| | | | | +| | | | +-- Comment (optional) +| | | +---------- F parameter (feed rate) +| | +---------------- Y parameter (Y coordinate) +| +--------------------- X parameter (X coordinate) ++------------------------ G command (linear move) +``` + +### Command Types + +| Letter | Type | Purpose | Examples | +|--------|------|---------|----------| +| **G** | Motion/Setup | Movement, positioning mode | G0, G1, G2, G3, G21, G90 | +| **M** | Machine | Laser on/off, air assist, coolant | M3, M4, M5, M8, M9 | +| **S** | Parameter | Spindle/laser power | S0-S1000 | +| **F** | Parameter | Feed rate (speed) | F3000 | +| **X/Y/Z** | Parameter | Coordinates | X50 Y20 | +| **I/J/K** | Parameter | Arc center offsets | I10 J5 | + +--- + +## Essential G-code Commands + +### Motion Commands (G-codes) + +#### G0 - Rapid Positioning + +**Purpose:** Fast movement without cutting (laser off) + +**Format:** `G0 X Y [Z] [F]` + +**Example:** +```gcode +G0 X100 Y50 ; Move quickly to (100, 50) +``` + +**When RayForge uses it:** +- Moving between cut paths +- Returning to origin +- Positioning before cutting + +--- + +#### G1 - Linear Interpolation + +**Purpose:** Controlled linear movement (cutting/engraving) + +**Format:** `G1 X Y [Z] F` + +**Example:** +```gcode +G1 X100 Y50 F2000 ; Move to (100, 50) at 2000 mm/min +``` + +**When RayForge uses it:** +- Cutting straight lines +- Engraving raster lines +- Any controlled movement with laser on + +--- + +#### G2 / G3 - Arc Interpolation + +**Purpose:** Circular/arc movements + +**Format:** `G2/G3 X Y I J F` + +- **G2** - Clockwise arc +- **G3** - Counter-clockwise arc +- **I, J** - Arc center offsets from start point + +**Example:** +```gcode +G2 X50 Y50 I10 J0 F1500 ; Clockwise arc to (50,50), center offset (10,0) +``` + +**When RayForge uses it:** +- Cutting circles and curves +- Rounded corners +- Optimized smooth curves + +--- + +#### G4 - Dwell (Pause) + +**Purpose:** Pause for specified time + +**Format:** `G4 P` + +**Example:** +```gcode +G4 P0.5 ; Pause for 0.5 seconds +``` + +**When used:** +- Allowing laser to burn at a point (rare) +- Custom macros for material settling + +--- + +### Setup Commands + +#### G21 / G20 - Units + +**Purpose:** Set measurement units + +- **G21** - Millimeters (RayForge default) +- **G20** - Inches + +**Example:** +```gcode +G21 ; All coordinates in millimeters +``` + +--- + +#### G90 / G91 - Positioning Mode + +**Purpose:** Set absolute or incremental positioning + +- **G90** - Absolute (coordinates are absolute positions) +- **G91** - Incremental (coordinates are relative movements) + +**Example:** +```gcode +G90 ; Absolute mode +G0 X10 ; Move to position X=10 +G0 X20 ; Move to position X=20 + +G91 ; Incremental mode +G0 X10 ; Move 10mm in +X direction +G0 X10 ; Move another 10mm in +X direction (now at X=30 total) +``` + +**RayForge default:** G90 (absolute mode) + +--- + +### Machine Commands (M-codes) + +#### M3 / M4 - Spindle/Laser On + +**Purpose:** Turn laser on + +- **M3** - Spindle mode (power varies with speed) +- **M4** - Laser mode (constant power, GRBL 1.1+) + +**Format:** `M3/M4 S` + +**Example:** +```gcode +M4 S500 ; Laser on at power 500 (50% for 0-1000 range) +``` + +**RayForge uses:** M4 for predictable laser power + +--- + +#### M5 - Spindle/Laser Off + +**Purpose:** Turn laser off + +**Format:** `M5` + +**Example:** +```gcode +M5 ; Laser off +``` + +**When RayForge uses it:** +- End of each cut path +- Between operations +- End of job (safety) + +--- + +#### M8 / M9 - Coolant/Air Assist + +**Purpose:** Control air assist or coolant + +- **M8** - Air assist on +- **M9** - Air assist off + +**Example:** +```gcode +M8 ; Air assist on +; ...cutting... +M9 ; Air assist off +``` + +--- + +### Parameters + +#### S - Spindle/Laser Power + +**Format:** `S` + +**Range:** 0-1000 (GRBL), 0-255 (some firmwares) + +**Example:** +```gcode +M4 S250 ; 25% power (for 0-1000 range) +M4 S750 ; 75% power +M4 S1000 ; 100% power +``` + +--- + +#### F - Feed Rate (Speed) + +**Format:** `F` + +**Units:** mm/min (or inches/min if G20) + +**Example:** +```gcode +G1 X100 F3000 ; Move to X=100 at 3000 mm/min +``` + +**Modal:** Feed rate persists until changed +```gcode +G1 X10 F3000 ; Set speed to 3000 +G1 X20 ; Still uses 3000 (no F needed) +G1 X30 F1500 ; Change speed to 1500 +``` + +--- + +## RayForge G-code Structure + +### Typical File Structure + +**Complete example:** + +```gcode +; ========================================== +; Generated by RayForge +; Job: test-project +; Date: 2025-10-03 15:30:00 +; ========================================== + +; === PREAMBLE === +G21 ; Set units to mm +G90 ; Absolute positioning + +; === JOB START HOOK (user-defined) === +$H ; Home machine +M8 ; Air assist on + +; === LAYER 1: Engrave Layer === +; Layer Start Hook (if defined) +G0 X10.000 Y10.000 ; Rapid to start position +M4 S400 ; Laser on at 40% power +G1 X50.000 F3000 ; Engrave line +G1 Y50.000 ; Engrave line +G1 X10.000 ; Engrave line +G1 Y10.000 ; Engrave line +M5 ; Laser off +; Layer End Hook (if defined) + +; === LAYER 2: Cut Layer === +; Layer Start Hook (if defined) +G0 X20.000 Y20.000 ; Rapid to start position +M4 S900 ; Laser on at 90% power +G1 X60.000 F800 ; Cut line at slower speed +G1 Y60.000 +G1 X20.000 +G1 Y20.000 +M5 ; Laser off +; Layer End Hook (if defined) + +; === JOB END HOOK (user-defined) === +M5 ; Ensure laser is off +M9 ; Air assist off +G0 X0 Y0 ; Return to origin + +; === END OF JOB === +``` + +--- + +### Components Explained + +#### 1. Header Comments + +```gcode +; ========================================== +; Generated by RayForge +; Job: test-project +; Date: 2025-10-03 15:30:00 +; ========================================== +``` + +**Purpose:** +- Identify the file +- Track when it was generated +- Document job name + +--- + +#### 2. Preamble + +```gcode +G21 ; Set units to mm +G90 ; Absolute positioning +``` + +**Purpose:** +- Ensure machine is in correct mode +- Set up coordinate system +- Prevent mode confusion + +--- + +#### 3. Job Start Hook + +```gcode +$H ; Home machine +M8 ; Air assist on +``` + +**Purpose:** +- User-defined setup commands +- Machine initialization +- Safety preparation + +**Configured in:** Settings > Machine > Hooks + +--- + +#### 4. Layer Operations + +```gcode +; === LAYER 1: Engrave Layer === +G0 X10.000 Y10.000 ; Rapid to start +M4 S400 ; Laser on +G1 X50.000 F3000 ; Cut +M5 ; Laser off +``` + +**Purpose:** +- Execute each layer's operations +- Organized by layer order +- Comments indicate layer names + +--- + +#### 5. Job End Hook + +```gcode +M5 ; Ensure laser is off +M9 ; Air assist off +G0 X0 Y0 ; Return to origin +``` + +**Purpose:** +- User-defined cleanup commands +- Safety (laser off) +- Return to known position + +--- + +## When to Edit G-code Manually + +### Good Reasons to Edit + +1. **Add pauses** for material changes or inspection + ```gcode + G4 P5 ; Pause 5 seconds + ``` + +2. **Adjust power mid-job** for testing + ```gcode + M4 S300 ; Change to 30% power + ``` + +3. **Fine-tune positions** for alignment + ```gcode + G0 X10.5 Y20.3 ; Shift by 0.5mm + ``` + +4. **Insert custom commands** not supported by RayForge UI + +--- + +### Bad Reasons to Edit + +1. **Complex changes** - Re-design in RayForge instead +2. **Changing toolpaths** - Error-prone, use RayForge operations +3. **Major restructuring** - Better to regenerate from source + +--- + +### Editing Tips + +**Before editing:** +- **Backup the file** - Keep original +- **Understand the commands** - Don't guess +- **Test on scrap** - Verify changes work + +**Common edits:** +```gcode +; Add pause before cut +G4 P2 + +; Reduce power for testing +M4 S100 ; Was S500, testing at 10% + +; Shift entire job by offset +; Find: G0 X10 +; Replace: G0 X15 (shift 5mm right) +``` + +--- + +## Advanced G-code Topics + +### Modal Commands + +**Modal** means a command stays active until explicitly changed. + +**Examples:** +- **G90** - Absolute mode (modal, stays until G91) +- **F3000** - Feed rate (modal, stays until changed) +- **M4** - Laser on (modal until M5) + +**Implication:** +```gcode +G90 ; Set absolute mode (stays active) +F3000 ; Set feed rate (stays active) +G1 X10 ; Uses absolute mode and F3000 +G1 X20 ; Still uses same mode and feed rate +G1 X30 F1500 ; Change feed rate, still absolute mode +``` + +--- + +### Coordinate Systems (G54-G59) + +**What they are:** Multiple work coordinate systems for advanced setups. + +**Commands:** +- **G54** - Work Coordinate System 1 (default) +- **G55** - Work Coordinate System 2 +- **G56** - Work Coordinate System 3 +- ... up to G59 + +**Use case:** +- Multiple fixture positions on bed +- Switch between jobs without re-homing + +**RayForge support:** Limited; primarily uses G54. + +--- + +### Offsets (G92) + +**Purpose:** Temporarily redefine coordinate zero. + +**Format:** `G92 X Y` + +**Example:** +```gcode +G92 X0 Y0 ; Set current position as (0, 0) +``` + +**Caution:** +- Can cause confusion +- Easy to forget offsets are active +- **Clear with:** `G92.1` (GRBL) + +**RayForge:** Avoids offsets, uses absolute positioning instead. + +--- + +## Troubleshooting G-code Issues + +### Commands Rejected by Machine + +**Problem:** Machine sends error or alarm. + +**Diagnosis:** + +1. **Check G-code dialect** - GRBL vs Marlin vs Smoothieware +2. **Verify command syntax** - Typos or invalid parameters +3. **Check firmware version** - Some commands require newer firmware + +**Solutions:** + +- Use correct dialect in RayForge settings +- Validate G-code with online checker (NCViewer, CAMotics) +- Update firmware if needed + +--- + +### Unexpected Movement + +**Problem:** Machine moves to wrong positions. + +**Diagnosis:** + +1. **Check positioning mode** - G90 (absolute) vs G91 (incremental) +2. **Check for offsets** - G92 may be active +3. **Check coordinates** - Out of range or incorrect + +**Solutions:** + +- Ensure G90 in preamble +- Clear offsets with G92.1 +- Re-home machine + +--- + +### Laser Not Turning On/Off + +**Problem:** Laser stays on or doesn't activate. + +**Diagnosis:** + +1. **Check M commands** - M4/M5 present? +2. **Check S parameter** - Power value correct? +3. **Check firmware laser mode** - `$32=1` for GRBL + +**Solutions:** + +- Verify M4 S before cuts +- Verify M5 after cuts +- Enable laser mode in firmware settings + +--- + +## Best Practices + +1. **Always include preamble** - G21, G90 to set modes +2. **Always end with M5** - Laser off for safety +3. **Use comments** - Document your changes +4. **Test on scrap** - Before production runs +5. **Validate G-code** - Use online simulators +6. **Keep backups** - Of working G-code files +7. **Know your firmware** - GRBL, Marlin, etc. differences + +--- + +## Related Pages + +- [G-code Dialects](../reference/gcode-dialects.md) - Firmware differences +- [Exporting G-code](../files/exporting.md) - Export settings and options +- [Firmware Compatibility](../reference/firmware.md) - Firmware versions and features +- [Macros & Hooks](../features/macros-hooks.md) - Custom G-code injection +- [GRBL Settings](../machine/grbl-settings.md) - Controller configuration diff --git a/docs-site/concepts/index.md b/docs-site/concepts/index.md new file mode 100644 index 000000000..b723a6e5e --- /dev/null +++ b/docs-site/concepts/index.md @@ -0,0 +1,220 @@ +# Concepts + +This section explains fundamental concepts for understanding laser cutting and engraving with RayForge. + +## Why Read This Section? + +Understanding the underlying concepts helps you: + +- Make better decisions about settings +- Troubleshoot problems independently +- Optimize quality and efficiency +- Understand why things work the way they do + +**If you want to:** Just follow tutorials - See [How-To Guides](../guides/index.md) +**If you want to:** Understand the fundamentals - Read the concepts below + +--- + +## Core Concepts + +### [Understanding Operations](understanding-operations.md) + +Learn what operations are and when to use each type. + +**Topics covered:** +- Contour vs Raster vs Depth operations +- When to use each operation type +- How operations process geometry +- Operation execution order + +**Read this if:** You're confused about which operation to choose, or want to understand how RayForge generates toolpaths. + +--- + +### [Coordinates and Origin](coordinates-and-origin.md) + +Understand how RayForge handles coordinate systems and positioning. + +**Topics covered:** +- Job origin vs machine origin vs workpiece origin +- Coordinate transformations +- Absolute vs relative positioning +- Common coordinate-related mistakes + +**Read this if:** Your jobs appear in the wrong position, or you don't understand how positioning works. + +--- + +### [Power vs Speed](power-vs-speed.md) + +Learn the relationship between laser power, cutting speed, and material interaction. + +**Topics covered:** +- How power and speed affect cutting +- Multi-pass strategies for thick materials +- Finding optimal settings +- Reading burn marks and adjusting + +**Read this if:** You're struggling to find the right settings for your material, or cuts aren't going through. + +--- + +### [G-code Basics](gcode-basics.md) + +Understand what G-code is and how RayForge generates it. + +**Topics covered:** +- What is G-code and how it controls machines +- Common G-code commands explained +- How RayForge generates G-code from operations +- When and how to edit G-code manually + +**Read this if:** You want to understand the output, customize G-code, or troubleshoot machine behavior. + +--- + +### [Laser Safety](laser-safety.md) + +Essential safety practices for laser cutting and engraving. + +**Topics covered:** +- Eye safety and laser classes +- Material hazards (never cut PVC!) +- Fire prevention and emergency procedures +- Proper ventilation and PPE +- Emergency stop procedures + +**Read this if:** You're new to laser work, or want a safety refresher. **Everyone should read this.** + +--- + +## Learning Paths + +### For Beginners + +1. Start with [Laser Safety](laser-safety.md) - **Mandatory** +2. Read [Understanding Operations](understanding-operations.md) - Understand what operations do +3. Read [Power vs Speed](power-vs-speed.md) - Learn to find settings +4. Skim [Coordinates and Origin](coordinates-and-origin.md) - Know it exists for troubleshooting +5. Skip [G-code Basics](gcode-basics.md) for now - Come back when curious + +### For Intermediate Users + +1. Review [Laser Safety](laser-safety.md) - Refresh your knowledge +2. Deep dive into [Power vs Speed](power-vs-speed.md) - Optimize your workflow +3. Read [Understanding Operations](understanding-operations.md) - Master operation selection +4. Study [G-code Basics](gcode-basics.md) - Understand the output +5. Read [Coordinates and Origin](coordinates-and-origin.md) as needed + +### For Advanced Users + +1. All articles - Deep understanding enables creative solutions +2. Focus on [G-code Basics](gcode-basics.md) - For customization +3. Master [Coordinates and Origin](coordinates-and-origin.md) - Complex positioning +4. Use [Power vs Speed](power-vs-speed.md) - Material science optimization + +--- + +## Complementary Resources + +### Practical Guides + +Once you understand the concepts, apply them: + +- [How-To Guides](../guides/index.md) - Step-by-step tutorials +- [Quick Start](../getting-started/quick-start.md) - First job walkthrough +- [Troubleshooting](../troubleshooting/index.md) - Solving problems + +### Reference Documentation + +Look up specific details: + +- [Keyboard Shortcuts](../reference/shortcuts.md) - Quick reference +- [G-code Dialects](../reference/gcode-dialects.md) - Dialect differences +- [Firmware Compatibility](../reference/firmware.md) - Controller support + +### Feature Documentation + +Learn about specific features: + +- [Operations](../features/operations/index.md) - Detailed operation docs +- [Multi-Layer Workflow](../features/multi-layer.md) - Layer organization +- [Simulation Mode](../features/simulation-mode.md) - Preview execution + +--- + +## How to Use This Section + +### Quick Reference + +**Jump directly to the concept** you need - each article is self-contained. + +### Sequential Reading + +**Read in order** for a structured learning experience: + +1. Laser Safety (essential) +2. Understanding Operations +3. Power vs Speed +4. Coordinates and Origin +5. G-code Basics + +### Problem-Driven Learning + +**Use the index** to find concepts relevant to your current problem: + +- **Job in wrong position?** → Coordinates and Origin +- **Not cutting through?** → Power vs Speed +- **Wrong operation type?** → Understanding Operations +- **Customize G-code?** → G-code Basics + +--- + +## Contributing to Concepts + +Found an explanation unclear? Have a better way to explain something? + +**Help improve the documentation:** + +1. Click "Edit this page" at the top +2. Make your improvements +3. Submit a pull request + +Or open an issue on GitHub with suggestions. + +--- + +## Glossary + +Quick definitions of key terms: + +**Operation** - A processing step that converts geometry to toolpaths (Contour, Raster, etc.) + +**Toolpath** - The actual path the laser head follows + +**G-code** - Machine control language that tells the controller what to do + +**Origin** - The reference point (0,0) for positioning + +**Power** - Laser intensity, typically 0-100% + +**Speed** - How fast the laser head moves, in mm/min + +**Feed rate** - Same as speed (CNC terminology) + +**Workpiece** - An imported shape or image + +**Layer** - A container for workpieces with a workflow + +**Workflow** - The operation and transformers applied to a layer + +For more terms, see the full glossary (if available) or search the documentation. + +--- + +## Related Sections + +- [Getting Started](../getting-started/index.md) - First steps with RayForge +- [Features](../features/index.md) - Feature documentation +- [Troubleshooting](../troubleshooting/index.md) - Problem solving diff --git a/docs-site/concepts/laser-safety.md b/docs-site/concepts/laser-safety.md new file mode 100644 index 000000000..f6a983d21 --- /dev/null +++ b/docs-site/concepts/laser-safety.md @@ -0,0 +1,198 @@ +# Laser Safety + +Laser cutting and engraving equipment poses serious safety risks including fire, toxic fumes, and permanent eye damage. + +!!! danger "Critical Safety Warning" + **Always follow your laser manufacturer's safety guidelines and operating instructions.** This page provides general safety principles but is not a substitute for proper training and your machine's specific safety documentation. + +## Your Primary Safety Resource + +**Read your laser manufacturer's manual completely** before operating any laser equipment. It contains: + +- Specific safety requirements for your machine +- Required personal protective equipment (PPE) +- Emergency procedures +- Maintenance and inspection schedules +- Warranty and liability information + +RayForge is control software - it cannot override the physical safety requirements of your laser hardware. + +## Essential Safety Principles + +### Never Leave Laser Unattended + +**Most important rule:** Never leave a running laser unattended, even for a few seconds. + +**Why:** Lasers can ignite materials instantly. A small flame can become a serious fire in seconds. + +**Always:** +- Stay within arm's reach of emergency stop +- Watch the cutting process continuously +- Keep fire extinguisher accessible + +### Fire Safety + +**Before every job:** +- Clear workspace of flammable materials +- Remove debris from cutting bed +- Have fire extinguisher ready (ABC or CO2 type) +- Know where emergency stop button is + +**If fire occurs:** +1. Press emergency stop immediately +2. Keep lid closed if fire is small (starves oxygen) +3. Use fire extinguisher if fire continues +4. Evacuate and call emergency services if fire spreads + +### Ventilation is Mandatory + +**All laser cutting produces toxic fumes.** Proper ventilation is not optional. + +**Requirements:** +- Exhaust system venting to outside (not recirculated) +- Sufficient airflow for your machine size +- Running during all laser operations +- Regular filter replacement (if using filtration) + +**Never operate without proper ventilation** - you risk serious health effects and will damage your laser's optics. + +### Prohibited Materials + +**Never cut or engrave these materials:** + +| Material | Danger | +|----------|--------| +| **PVC / Vinyl** | Produces chlorine gas (toxic, corrosive) | +| **ABS plastic** | Produces cyanide gas (deadly) | +| **Polycarbonate** | Toxic fumes, poor results | +| **Fiberglass** | Glass particles damage lungs and optics | +| **Any material containing chlorine** | Toxic and corrosive | + +**When in doubt:** Check material safety data sheet (MSDS) or test tiny sample with excellent ventilation. + +### Eye Protection + +Most enclosed laser systems don't require goggles during normal operation **if the enclosure is closed and has proper interlocks.** + +**Eye protection required when:** +- Opening enclosure during operation +- Performing maintenance or alignment +- Machine has viewing window without laser-safe filtering +- Manufacturer specifies it + +**Always check your manufacturer's requirements** - they vary by machine design and laser type. + +## RayForge Safety Features + +RayForge provides tools to help operate safely: + +- **[Simulation Mode](../features/simulation-mode.md)** - Preview jobs before running to identify issues +- **[Material Test Grid](../features/operations/material-test-grid.md)** - Find safe settings for new materials +- **Frame Job** - Verify positioning before cutting + +**These features help prevent errors but don't replace safe operating practices.** + +## Pre-Operation Checklist + +Before every job: + +- [ ] Read and understood job requirements +- [ ] Material is safe for laser cutting +- [ ] Workspace clear of flammable materials +- [ ] Ventilation system running +- [ ] Fire extinguisher accessible +- [ ] Emergency stop location confirmed +- [ ] Material secured flat on bed +- [ ] Job previewed in Simulation Mode + +## Emergency Procedures + +### Emergency Stop + +**When to use:** +- Fire visible +- Unusual sounds or smoke +- Material shifting dangerously +- Any emergency situation + +**How:** Press red emergency stop button on machine. All motion and laser power stop immediately. + +### Fire Response + +**Small fire (contained):** +1. Emergency stop +2. Keep lid closed if possible +3. Use fire extinguisher if needed + +**Large fire:** +1. Emergency stop +2. Evacuate immediately +3. Call emergency services +4. Do not attempt to fight large fires + +### Medical Emergencies + +**Eye exposure:** +- Seek immediate medical attention +- Do not rub eyes +- Bring laser specifications to doctor + +**Fume inhalation:** +- Move to fresh air +- Seek medical attention if symptoms persist +- Call poison control if severe + +## Training and Responsibility + +**Before operating:** +- Complete any required safety training +- Read manufacturer's manual completely +- Understand emergency procedures +- Know your specific laser's hazard class and requirements + +**Ongoing:** +- Review safety procedures periodically +- Maintain safety equipment +- Stay informed about new materials and hazards +- Never allow untrained users to operate equipment + +## Key Safety Rules + +!!! warning "Critical Safety Rules" + 1. **Never leave laser unattended during operation** + 2. **Never operate without proper ventilation** + 3. **Never cut prohibited materials (PVC, vinyl, ABS, etc.)** + 4. **Always have fire extinguisher within reach** + 5. **Always follow manufacturer's safety guidelines** + 6. **Know where emergency stop is** + 7. **Preview jobs in Simulation Mode before running** + +## Additional Resources + +**Your responsibilities:** +- Follow all manufacturer safety requirements +- Comply with local fire codes and regulations +- Maintain required safety equipment +- Ensure proper training for all operators +- Document and report safety incidents + +**Manufacturer resources:** +- Machine operating manual +- Safety data sheets +- Technical support contact +- Warranty and safety compliance documentation + +**Regulatory standards:** +- ANSI Z136 (North America) +- EN 60825 (Europe) +- Local workplace safety regulations + +## Related Pages + +- **[Simulation Mode](../features/simulation-mode.md)** - Preview jobs to identify safety issues +- **[Material Test Grid](../features/operations/material-test-grid.md)** - Find safe settings for materials +- **[Power vs Speed](power-vs-speed.md)** - Understanding safe power/speed settings + +--- + +**Remember:** Safe laser operation requires constant vigilance, proper equipment, and strict adherence to safety procedures. When in doubt, refer to your manufacturer's documentation and err on the side of caution. diff --git a/docs-site/concepts/power-vs-speed.md b/docs-site/concepts/power-vs-speed.md new file mode 100644 index 000000000..cda8e32de --- /dev/null +++ b/docs-site/concepts/power-vs-speed.md @@ -0,0 +1,561 @@ +# Power vs Speed + +Understanding the relationship between laser power, movement speed, and material interaction is crucial for achieving high-quality cuts and engravings. + +## The Fundamental Relationship + +**Energy delivered to material = Power x Time** + +When the laser moves more slowly, it delivers more energy per unit area. When it moves faster, less energy is delivered. + +**Key principle:** +``` +More power + slow speed = High energy (deep cuts, dark burns) +Less power + fast speed = Low energy (light marks, shallow cuts) +``` + +**Balance is key:** Different materials and operations require different combinations. + +--- + +## Understanding Power + +### What is Power? + +**Laser power** is the intensity of the laser beam, typically measured in watts (W). + +**Power control:** +- RayForge uses the S parameter (0-1000) to control power +- S0 = 0% power (off) +- S500 = 50% power +- S1000 = 100% power (maximum your laser can produce) + +**Example:** +```gcode +M4 S250 ; 25% power +M4 S750 ; 75% power +M4 S1000 ; 100% power +``` + +--- + +### Absolute Power vs Percentage + +**Your laser has a maximum power rating:** +- 5W diode laser +- 40W CO2 laser +- 80W CO2 laser + +**When you set 50% power:** +- 5W laser delivers: 2.5W +- 40W laser delivers: 20W +- 80W laser delivers: 40W + +**Implication:** Settings that work on one laser won't directly transfer to a different wattage laser. You must adjust for your specific laser power. + +--- + +## Understanding Speed + +### What is Speed? + +**Feed rate** (or cutting speed) is how fast the laser head moves across the material, measured in mm/min or inches/min. + +**Speed ranges:** +- Very slow: 50-300 mm/min (deep cuts, thick materials) +- Moderate: 500-1500 mm/min (general cutting, engraving) +- Fast: 2000-5000 mm/min (light engraving, travel moves) + +**Example:** +```gcode +G1 X100 F500 ; Move at 500 mm/min (slow cut) +G1 X200 F3000 ; Move at 3000 mm/min (fast travel) +``` + +--- + +### Speed Affects Energy Density + +**Slower movement** = More time at each point = More energy delivered + +**Example:** +- Laser power: 40W +- Speed 1: 100 mm/min +- Speed 2: 1000 mm/min + +At 100 mm/min, the laser spends **10x longer** at each point compared to 1000 mm/min, delivering 10x more energy. + +--- + +## The Power-Speed Matrix + +Different combinations of power and speed produce different results: + +| Power | Speed | Result | Use Case | +|-------|-------|--------|----------| +| **High** | Slow | Very deep cuts, charring | Cutting thick materials | +| **High** | Fast | Moderate cuts/engraving | Fast cutting, efficient production | +| **Low** | Slow | Deep engraving, controlled burns | Detailed engraving, dark marks | +| **Low** | Fast | Light engraving, surface marks | High-speed raster engraving | + +**Visualization:** + +``` +Power + ^ + | Charring/ | Through-cut + | Too deep | (ideal) + | | + |------------- +------------- + | Good | Too fast/ + | engraving | Not cutting + | | + +-----------------------------> Speed +``` + +--- + +## Material-Specific Considerations + +### Wood + +**Cutting:** +- Medium to high power +- Moderate speed +- Multiple passes for thick wood + +**Example (3mm plywood, 40W CO2):** +- Power: 70-80% +- Speed: 200-400 mm/min +- Passes: 1-2 + +**Engraving:** +- Low to medium power +- High speed for raster +- Lower speed for deeper marks + +**Example (wood engraving, 40W CO2):** +- Power: 20-30% +- Speed: 2000-3000 mm/min + +--- + +### Acrylic + +**Cutting:** +- High power +- Very slow speed +- Produces clean, flame-polished edges + +**Example (3mm cast acrylic, 40W CO2):** +- Power: 80-100% +- Speed: 100-200 mm/min +- Passes: 1 (through-cut) + +**Engraving:** +- Low power +- Fast speed +- Produces frosted appearance + +**Example (acrylic engraving, 40W CO2):** +- Power: 15-25% +- Speed: 2500-4000 mm/min + +--- + +### Cardboard / Paper + +**Cutting:** +- Very low power +- Fast speed +- **High fire risk** - monitor constantly + +**Example (cardboard, 40W CO2):** +- Power: 10-20% +- Speed: 1000-2000 mm/min + +**Engraving:** +- Extremely low power +- Very fast speed + +**Example (paper engraving, 40W CO2):** +- Power: 5-10% +- Speed: 3000-5000 mm/min + +--- + +### Leather + +**Cutting:** +- Medium power +- Moderate speed + +**Example (leather, 40W CO2):** +- Power: 40-60% +- Speed: 300-600 mm/min + +**Engraving:** +- Low power +- Fast to moderate speed +- Creates dark, detailed marks + +**Example (leather engraving, 40W CO2):** +- Power: 15-25% +- Speed: 2000-3000 mm/min + +--- + +## Multi-Pass Strategies + +### When to Use Multiple Passes + +**Reasons:** +1. Material too thick for single pass +2. Preventing excessive charring +3. Achieving cleaner cuts +4. Reducing heat buildup + +**How it works:** +Instead of one deep cut, make several shallower cuts: +- Pass 1: Cuts 30% through +- Pass 2: Cuts 60% through +- Pass 3: Cuts 90% through +- Pass 4: Cuts fully through + +--- + +### Benefits of Multi-Pass + +**Cleaner cuts:** +- Less charring on edges +- Less heat stress on material +- Better edge quality + +**Thicker materials:** +- Cut materials beyond single-pass capability +- Safer than maxing out power + +**Heat management:** +- Allows material to cool between passes +- Reduces warping and melting + +--- + +### Multi-Pass Settings + +**General approach:** + +1. **Determine total energy needed** to cut through +2. **Divide into multiple passes** (2-5 passes typical) +3. **Adjust speed or power** to deliver energy gradually + +**Example (6mm plywood, 40W CO2):** + +**Single pass (may fail or char heavily):** +- Power: 100% +- Speed: 100 mm/min +- Passes: 1 +- Result: Excessive charring, incomplete cut + +**Multi-pass (better):** +- Power: 80% +- Speed: 200 mm/min +- Passes: 3 +- Result: Clean cut, minimal charring + +--- + +### Configuring Multi-Pass in RayForge + +**In operation settings:** +1. Select Contour operation +2. Set **Passes** to desired number (e.g., 3) +3. Adjust power/speed as needed +4. RayForge will automatically repeat the cut path + +**G-code result:** +```gcode +; Pass 1 +G0 X10 Y10 +M4 S800 +G1 X50 Y10 F200 +; ...path... +M5 + +; Pass 2 (same path repeated) +G0 X10 Y10 +M4 S800 +G1 X50 Y10 F200 +; ...path... +M5 + +; Pass 3 +; ... +``` + +--- + +## Reading Burn Marks and Adjusting + +### Visual Feedback + +Material tells you if settings are correct: + +**Too much power or too slow:** +- Heavy charring (black edges) +- Excessive smoke +- Melted/deformed edges +- Material warping + +**Too little power or too fast:** +- Incomplete cuts +- Light surface marks only +- No visible change + +**Just right:** +- Clean cuts all the way through +- Minimal charring +- Smooth edges +- Consistent depth + +--- + +### Adjusting Based on Results + +**If cut doesn't go through:** +1. Increase power by 10-20% +2. OR decrease speed by 20-30% +3. OR add another pass + +**If too much charring:** +1. Decrease power by 10-20% +2. OR increase speed by 20-30% +3. OR switch to multi-pass with lower power + +**If engraving too light:** +1. Increase power by 10-15% +2. OR decrease speed by 15-25% + +**If engraving too dark/burned:** +1. Decrease power by 10-15% +2. OR increase speed by 15-25% + +--- + +## Diode Lasers vs CO2 Lasers + +### Diode Lasers (Typically 5-20W) + +**Characteristics:** +- Lower power output +- 445nm wavelength (blue light) +- Absorbed differently by materials + +**Power/speed considerations:** +- Slower speeds needed (lower power) +- Multiple passes often required +- Struggles with thick materials +- Excellent for wood engraving + +**Example (wood engraving, 5W diode):** +- Power: 60-80% +- Speed: 500-1500 mm/min + +--- + +### CO2 Lasers (Typically 40-150W) + +**Characteristics:** +- Higher power output +- 10,600nm wavelength (infrared) +- Efficiently absorbed by organic materials + +**Power/speed considerations:** +- Faster speeds possible +- Clean through-cuts on thicker materials +- Better for cutting acrylic, wood + +**Example (wood cutting, 40W CO2):** +- Power: 70-90% +- Speed: 200-500 mm/min + +--- + +## Material Testing Workflow + +### Using the Material Test Grid + +**RayForge's Material Test Grid** automates power/speed testing: + +1. **Create grid:** Features > Operations > Material Test Grid +2. **Set ranges:** + - Power: 20% to 80% (or appropriate range) + - Speed: 500 to 2000 mm/min (or appropriate range) +3. **Run grid** on scrap material +4. **Inspect results:** + - Find the cell with best cut quality + - Note the power/speed values +5. **Use those settings** in your actual job + +**Example grid result:** + +``` + 500mm/min 1000mm/min 1500mm/min 2000mm/min +20% Too light Too light Too light Too light +40% Good Too light Too light Too light +60% Too dark Good Light Too light +80% Charred Too dark Good Light +``` + +**Conclusion:** Use 60% power at 1500 mm/min for this material. + +See [Material Test Grid](../features/operations/material-test-grid.md) for details. + +--- + +## Advanced Topics + +### Kerf Compensation + +**Kerf** is the width of material removed by the laser beam. + +**Power/speed affect kerf:** +- Higher power = Wider kerf +- Slower speed = Wider kerf (more material burned away) + +**Adjust kerf compensation** if parts come out wrong size: +- Parts too small: Reduce kerf compensation +- Parts too large: Increase kerf compensation + +See [Overscan & Kerf](../features/overscan-kerf.md) for details. + +--- + +### Raster Speed Variation + +For raster engraving, RayForge varies speed to create different gray tones: + +**How it works:** +- Light areas: Fast speed, low power +- Dark areas: Slow speed, higher power (or just higher power at constant speed) + +**Bidirectional raster:** +- Laser engraves left-to-right, then right-to-left +- Must maintain consistent power at varying speeds +- M4 (laser mode) ensures constant power + +--- + +### Air Assist and Cooling + +**Air assist affects results:** +- Reduces charring +- Cools material +- Blows away smoke/debris + +**Settings interaction:** +- With air assist: May need slightly higher power +- Without air assist: More charring, may need lower power/faster speed + +--- + +## Common Mistakes + +### Mistake 1: Maxing Out Power + +**Problem:** Using 100% power for everything. + +**Why it's bad:** +- Excessive charring +- Accelerated wear on laser tube +- Less control and precision + +**Solution:** Use appropriate power (usually 60-80% for cuts). + +--- + +### Mistake 2: Ignoring Material Variation + +**Problem:** Using same settings for all "wood" without testing. + +**Why it's bad:** +- Different wood species vary significantly +- Plywood vs solid wood behaves differently +- Moisture content affects results + +**Solution:** Test each new material type with a Material Test Grid. + +--- + +### Mistake 3: Not Adjusting for Thickness + +**Problem:** Using same settings for 3mm and 6mm material. + +**Why it's bad:** +- 6mm needs much more energy (lower speed or more passes) +- 3mm settings won't cut through 6mm + +**Solution:** Adjust speed (slower) or passes (more) for thicker materials. + +--- + +### Mistake 4: Focusing on Power Only + +**Problem:** Only adjusting power, never speed. + +**Why it's bad:** +- Speed is equally important +- Sometimes speed adjustment is more effective + +**Solution:** Adjust both power AND speed to find optimal settings. + +--- + +## Quick Reference + +### Starting Points (40W CO2 Laser) + +| Material | Thickness | Power | Speed | Passes | +|----------|-----------|-------|-------|--------| +| **Plywood** | 3mm | 70% | 300 mm/min | 1-2 | +| **Plywood** | 6mm | 80% | 200 mm/min | 2-3 | +| **Acrylic** | 3mm | 90% | 150 mm/min | 1 | +| **Acrylic** | 6mm | 100% | 80 mm/min | 1-2 | +| **Cardboard** | 2mm | 15% | 1500 mm/min | 1 | +| **Leather** | 2mm | 50% | 400 mm/min | 1 | + +**Note:** These are starting points only. Always test on your specific machine and material. + +--- + +### Starting Points (5W Diode Laser) + +| Material | Thickness | Power | Speed | Passes | +|----------|-----------|-------|-------|--------| +| **Wood engrave** | - | 70% | 800 mm/min | 1 | +| **Wood cut** | 3mm | 90% | 100 mm/min | 3-5 | +| **Cardboard** | 2mm | 50% | 500 mm/min | 2 | +| **Leather engrave** | - | 60% | 600 mm/min | 1 | + +**Note:** Diode lasers struggle with thick materials. Multi-pass is often required. + +--- + +## Best Practices + +1. **Always test new materials** with Material Test Grid +2. **Start conservative** (lower power, moderate speed) and increase gradually +3. **Use multi-pass** for thick materials rather than maxing out power +4. **Adjust one parameter at a time** (power OR speed, not both) +5. **Document successful settings** for future reference +6. **Account for material variation** (different batches may need adjustment) +7. **Monitor first few cuts** of any job to catch issues early + +--- + +## Related Pages + +- [Material Test Grid](../features/operations/material-test-grid.md) - Automated power/speed testing +- [Understanding Operations](understanding-operations.md) - Operation types and settings +- [Overscan & Kerf](../features/overscan-kerf.md) - Compensation techniques +- [Laser Safety](laser-safety.md) - Safe power/speed practices diff --git a/docs-site/concepts/understanding-operations.md b/docs-site/concepts/understanding-operations.md new file mode 100644 index 000000000..9973a5289 --- /dev/null +++ b/docs-site/concepts/understanding-operations.md @@ -0,0 +1,420 @@ +# Understanding Operations + +Operations are the core of how RayForge converts your designs into laser instructions. This page explains what operations are, the different types available, and how to choose the right one for your project. + +## What is an Operation? + +An **operation** is a processing step that converts geometry (shapes, images, paths) into **toolpaths** - the actual instructions that tell the laser where to move and when to fire. + +**Think of it like this:** + +- Your **design** is what you want to create (a logo, a box, a photo) +- An **operation** is how you want to create it (engrave, cut, etc.) +- The **toolpath** is the specific commands that make it happen + +**Example:** + +``` +Design: A circle +Operation: Contour Cut +Result: Laser traces the circle outline and cuts it out + +Design: A circle +Operation: Raster Engrave +Result: Laser fills the circle area with back-and-forth scanning +``` + +--- + +## Operation Types + +RayForge provides several operation types, each suited for different tasks. + +### Contour (Vector Cutting) + +**What it does:** Follows the outline of vector paths. + +**How it works:** +- Traces the edges of shapes +- Laser follows the path continuously +- Can cut through material or just mark the surface + +**Best for:** +- Cutting out shapes +- Outlining designs +- Creating perimeters +- Precise vector work + +**Example uses:** +- Cutting box parts +- Creating stencils +- Outlining logos +- Cutting acrylic shapes + +**Settings:** +- **Power:** High for cutting, low for marking +- **Speed:** Slow for cutting, faster for marking +- **Passes:** Multiple for thick materials + +### Raster (Image Engraving) + +**What it does:** Scans back and forth to engrave images. + +**How it works:** +- Divides area into horizontal scan lines +- Laser moves left-to-right, then right-to-left +- Power varies to create shading +- Like a printer printing an image + +**Best for:** +- Photo engraving +- Grayscale images +- Filled areas +- Textures and patterns + +**Example uses:** +- Engraving photos on wood +- Creating gradients +- Filling shapes with texture +- Bitmap graphics + +**Settings:** +- **DPI:** Resolution (300-500 typical) +- **Speed:** Medium to fast +- **Power:** Varies with image darkness +- **Line spacing:** Controls density + +### Depth (3D Engraving) + +**What it does:** Varies engraving depth to create 3D relief. + +**How it works:** +- Similar to raster but controls depth +- Lighter areas = shallow engraving +- Darker areas = deeper engraving +- Creates raised or recessed surfaces + +**Best for:** +- 3D relief carving +- Topographic maps +- Embossed text +- Artistic depth effects + +**Example uses:** +- Carving landscapes in wood +- Creating textured surfaces +- Embossing designs +- Depth-based artwork + +**Settings:** +- **Depth map:** Grayscale image (black=deep, white=shallow) +- **Max depth:** Maximum engraving depth +- **Passes:** Multiple passes for depth +- **Power/Speed:** Control cutting per pass + +### Shrink Wrap + +**What it does:** Creates a tight boundary around selected objects. + +**How it works:** +- Calculates minimum outline containing all objects +- Useful for grouping or creating boundaries +- Can add offset/margin + +**Best for:** +- Creating cut boundaries around complex designs +- Grouping multiple objects +- Adding margins for cutting + +**Example uses:** +- Outlining scattered elements +- Creating packing boundaries +- Adding cut lines around designs + +### Material Test Grid + +**What it does:** Generates a power/speed test matrix. + +**How it works:** +- Creates grid of test squares +- Each square has different power/speed combination +- Helps find optimal settings + +**Best for:** +- Testing new materials +- Finding cut settings +- Optimizing engraving parameters + +**Example uses:** +- Testing wood power/speed combinations +- Finding acrylic cut settings +- Optimizing leather engraving + +See [Material Test Grid](../features/operations/material-test-grid.md) for details. + +--- + +## Choosing the Right Operation + +### Decision Tree + +``` +What do you want to do? + +Cut out a shape? + ├─ Vector design → Contour + └─ Raster design → Trace first, then Contour + +Engrave an image/photo? + ├─ Flat engraving → Raster + └─ 3D relief → Depth + +Mark/score surface? + → Contour (low power) + +Fill an area with texture? + → Raster + +Test material settings? + → Material Test Grid +``` + +### Operation Comparison + +| Goal | Operation | Why? | +|------|-----------|------| +| **Cut through material** | Contour | Follows edges precisely | +| **Engrave a photo** | Raster | Variable power for shading | +| **Create 3D effect** | Depth | Controls engraving depth | +| **Mark outline only** | Contour | Low power, just surface marking | +| **Fill shape with pattern** | Raster | Scans fill area | +| **Test settings** | Material Test Grid | Systematic testing | + +--- + +## How Operations Process Geometry + +Understanding how operations work helps you prepare files correctly. + +### Contour Processing + +**Input:** Vector paths (lines, curves, shapes) + +**Process:** +1. Extracts path outlines +2. Determines trace direction +3. Generates G-code to follow paths +4. Adds lead-in/out if configured + +**Requirements:** +- Vector geometry (not raster) +- Closed paths for cutting shapes +- Open paths for lines/curves + +### Raster Processing + +**Input:** Raster images (photos, bitmaps) or filled vectors + +**Process:** +1. Rasterizes geometry at specified DPI +2. Divides into scan lines +3. Converts pixel darkness to laser power +4. Generates back-and-forth scanning G-code +5. Applies overscan if enabled + +**Requirements:** +- Image data or shapes to fill +- Resolution (DPI) specified +- Power range configured + +### Depth Processing + +**Input:** Grayscale image (depth map) + +**Process:** +1. Reads depth map (black=deep, white=shallow) +2. Calculates multiple passes +3. Each pass engraves at different depth +4. Builds up 3D relief incrementally + +**Requirements:** +- Grayscale depth map +- Maximum depth specified +- Material capable of depth engraving + +--- + +## Multiple Operations on Same Geometry + +You can apply different operations to the same object: + +**Example: Logo** + +1. **Raster engrave** to fill the logo shape +2. **Contour cut** to outline and cut it out + +**Layer setup:** +``` +Layer 1: Logo Engrave (Raster) + └─ Logo shape + +Layer 2: Logo Cut (Contour) + └─ Logo outline +``` + +**Why separate layers?** +- Different operations need different settings +- Control execution order (engrave first, cut last) +- Easier to enable/disable independently + +See [Multi-Layer Workflow](../features/multi-layer.md) for details. + +--- + +## Common Operation Mistakes + +### Using Contour for Photos + +**Problem:** Trying to contour a raster image. + +**Why it fails:** Contour needs vector paths, not pixels. + +**Solution:** Use Raster operation, or trace the image first. + +### Using Raster for Cutting + +**Problem:** Using raster to cut out shapes. + +**Why it's inefficient:** Raster scans entire area, very slow for cutting. + +**Solution:** Use Contour operation for cutting outlines. + +### Wrong Power/Speed for Operation + +**Problem:** Using cutting settings for engraving (or vice versa). + +**Result:** Either doesn't work or damages material. + +**Solution:** +- **Contour (cutting):** High power, slow speed +- **Raster (engraving):** Medium power, medium-fast speed +- **Contour (marking):** Low power, fast speed + +### Forgetting Multi-Pass + +**Problem:** Trying to cut thick material in one pass. + +**Result:** Doesn't cut through, or excessive charring. + +**Solution:** Use multiple passes at lower power each. + +--- + +## Operation Settings Overview + +### Power + +**What it controls:** Laser intensity. + +**Range:** 0-100% (or 0-1000 in G-code) + +**Guidelines:** +- **Cutting:** 70-100% +- **Engraving:** 20-60% +- **Marking:** 10-30% + +### Speed + +**What it controls:** How fast the laser head moves. + +**Units:** mm/min (or mm/sec in some systems) + +**Guidelines:** +- **Cutting:** 100-500 mm/min (slow) +- **Engraving:** 500-3000 mm/min (medium) +- **Marking:** 1000-5000 mm/min (fast) + +### Passes + +**What it controls:** How many times to repeat the operation. + +**When to use:** +- Thick materials (can't cut in one pass) +- Deep engraving +- Better quality (multiple light passes vs one heavy) + +### DPI (Raster Only) + +**What it controls:** Resolution of raster engraving. + +**Guidelines:** +- **300 DPI:** Good for most photos +- **500 DPI:** High detail work +- **200 DPI:** Fast, lower quality + +**Trade-off:** Higher DPI = more detail but larger G-code files and slower execution. + +--- + +## Operation Execution Order + +Operations execute in a specific order: + +1. **Layer order** (top to bottom in layer list) +2. **Within a layer:** Defined by workflow +3. **Within operation:** Path ordering (can be optimized) + +**Important:** Layers execute sequentially, not in parallel. + +**Example execution:** +``` +Start Job + Layer 1: Engrave + Operation processes all workpieces in layer + Layer 2: Cut + Operation processes all workpieces in layer +End Job +``` + +**Why order matters:** +- Engrave before cutting (so parts don't move) +- Multiple passes in sequence +- Heat management (alternate areas) + +--- + +## Advanced: Operation Transformers + +Operations can have **transformers** that modify the toolpath: + +**Common transformers:** + +- **Overscan:** Extends raster lines for smooth acceleration +- **Tabs:** Adds holding tabs to contour cuts +- **Optimize:** Reorders paths for efficiency +- **Kerf:** Adjusts for material removal (planned feature) + +**Where to configure:** Layer workflow settings + +See individual feature pages for details. + +--- + +## Tips for Operation Selection + +1. **Start with the right operation** - It's easier than trying to fix wrong choice +2. **Test on scrap** - Try operation settings on waste material first +3. **Use Material Test Grid** - Find optimal settings systematically +4. **Check examples** - Look at similar projects for guidance +5. **Understand your goal** - Cut through? Mark surface? Engrave detail? + +--- + +## Related Pages + +- [Contour Operation](../features/operations/contour.md) - Detailed contour docs +- [Raster Operation](../features/operations/raster.md) - Detailed raster docs +- [Depth Operation](../features/operations/depth.md) - Detailed depth docs +- [Material Test Grid](../features/operations/material-test-grid.md) - Testing guide +- [Multi-Layer Workflow](../features/multi-layer.md) - Organizing operations +- [Power vs Speed](power-vs-speed.md) - Setting selection diff --git a/docs-site/contributing/index.md b/docs-site/contributing/index.md new file mode 100644 index 000000000..62757c819 --- /dev/null +++ b/docs-site/contributing/index.md @@ -0,0 +1,57 @@ +# Contributing to Rayforge + +We welcome contributions of all kinds! Whether you're fixing bugs, adding features, improving documentation, or helping with packaging, your contributions make Rayforge better for everyone. + +## Ways to Contribute + +### Report Bugs + +Found a bug? Help us fix it: + +1. Check [existing issues](https://github.com/barebaric/rayforge/issues) to avoid duplicates +2. Create a [new issue](https://github.com/barebaric/rayforge/issues/new) with: + - Clear description of the problem + - Steps to reproduce + - Expected vs. actual behavior + - System information (OS, Rayforge version) + - Screenshots or error messages if applicable + +### Suggest Features + +Have an idea for a new feature? + +1. Check [existing feature requests](https://github.com/barebaric/rayforge/issues?q=is%3Aissue+label%3Aenhancement) +2. Open a feature request issue with: + - Description of the feature + - Use case and benefits + - Possible implementation approach (optional) + +### Submit Code + +Contributing code improvements: + +1. **Fork the repository** on GitHub +2. **Set up your development environment**: See [Development Setup](development.md) +3. **Create a feature branch**: `git checkout -b feature/your-feature-name` +4. **Make your changes**: Follow coding conventions +5. **Test thoroughly**: Run tests and manual testing +6. **Submit a pull request**: Describe your changes and why they're needed + +!!! tip "Discuss First" + For major changes, open an issue first to discuss your approach before investing significant time. + +### Improve Documentation + +Documentation contributions are highly valued: + +- Fix typos or unclear explanations +- Add examples and screenshots +- Improve organization +- Translate to other languages + +Documentation source is in the `docs-site/` directory. + +You can click the "edit this page" button, then submit PRs the same way as +code contributions. + +s \ No newline at end of file diff --git a/docs-site/documentation-plan.md b/docs-site/documentation-plan.md new file mode 100644 index 000000000..e5d39592a --- /dev/null +++ b/docs-site/documentation-plan.md @@ -0,0 +1,875 @@ +# RayForge Documentation Improvement Plan + +**Date:** October 3, 2025 + +## Executive Summary + +This plan outlines strategic improvements to the RayForge documentation. The primary goal is to transform the current foundation (44 files, 25+ empty stubs) into comprehensive, user-friendly documentation that serves beginners through advanced users. + +### Current State + +**RayForge Documentation Status:** +- ✅ Well-structured navigation with MkDocs Material +- ✅ Strong foundation: Good index pages, getting-started journey +- ⚠️ **Critical gap**: 25+ stub files (0 lines) - empty placeholders +- ⚠️ Limited visual content (only 12 images) +- ⚠️ Missing conceptual/"Explainer" content +- ⚠️ No task-based "How-To" guides beyond quick-start + +### Documentation Goals + +**Target structure:** +- 100+ comprehensive documentation pages +- 4-tier organization (Getting Started, Guides, Concepts, Collections) +- Extensive visual library (150+ images/diagrams) +- Clear audience segmentation (beginners, intermediate, advanced) +- Strong thematic collections for deep-dive learning + +--- + +## Priority 1: Fill Critical Content Gaps (New Users) + +**Problem:** Empty files are linked throughout docs but contain no content, breaking user journeys. + +### Features Section (Core Functionality) + +**Empty files to complete:** +- `features/camera.md` - Camera integration walkthrough +- `features/holding-tabs.md` - Tab placement guide +- `features/multi-layer.md` - Multi-layer workflow +- `features/macros-hooks.md` - G-code automation +- `features/overscan-kerf.md` - Quality improvement techniques +- `features/operations/contour.md` - Contour cutting operation +- `features/operations/raster.md` - Raster engraving operation +- `features/operations/depth.md` - Depth engraving operation +- `features/operations/shrink-wrap.md` - Shrink wrap operation +- `features/operations/material-test-grid.md` - Material test grid generator +- `features/simulation-mode.md` - Execution simulation and visualization + +**Content requirements:** +- Step-by-step workflows with screenshots +- Use cases and when to use each feature +- Settings explanations with visual examples +- Common mistakes and troubleshooting tips + +### Machine Setup (Essential for First-Time Users) + +**Empty files to complete:** +- `machine/profiles.md` - Creating/managing machine profiles +- `machine/device-config.md` - Device configuration details +- `machine/grbl-settings.md` - GRBL parameter reference +- `machine/multi-laser.md` - Multiple laser setup + +**Content requirements:** +- Configuration wizards and dialogs +- Parameter tables with explanations +- Screenshots of every settings screen +- Example configurations for common machines + +### Troubleshooting (User Retention) + +**Empty files to complete:** +- `troubleshooting/connection.md` - Serial/network connection issues +- `troubleshooting/common.md` - FAQ-style problem/solution pairs +- `troubleshooting/performance.md` - Optimization tips +- `troubleshooting/snap-permissions.md` - Linux permissions guide + +**Content requirements:** +- Problem → Diagnosis → Solution format +- Step-by-step troubleshooting procedures +- Command examples with expected output +- Platform-specific solutions (Linux vs Windows) + +**Impact:** Prevents broken user journeys and dead-end links, establishes credibility + +--- + +## Priority 2: Add Conceptual "Explainer" Content (Understanding) + +**Create a new `concepts/` section with foundational knowledge:** + +### New Conceptual Articles + +1. **`concepts/index.md`** - Overview of conceptual learning resources + +2. **`concepts/understanding-operations.md`** + - What are operations and when to use each type + - Contour vs Raster vs Depth explained visually + - Decision tree for operation selection + - Real-world use case examples + +3. **`concepts/coordinates-and-origin.md`** + - How RayForge handles coordinate systems + - Job origin vs machine origin vs workpiece origin + - Common coordinate-related mistakes + - Visual diagrams showing different origin modes + +4. **`concepts/gcode-basics.md`** + - What is G-code and how RayForge generates it + - Understanding the generated code structure + - When and how to edit G-code manually + - Common G-code commands reference + +5. **`concepts/laser-safety.md`** + - Essential safety practices + - Material hazards (never cut PVC, acrylic fumes, etc.) + - Fire prevention and emergency procedures + - Proper ventilation and PPE requirements + - Emergency stop procedures + +6. **`concepts/power-vs-speed.md`** + - Relationship between power, speed, and material interaction + - Multi-pass strategies for thick materials + - Visual diagrams showing effects on different materials + - How to read burn marks and adjust settings + +**Impact:** Reduces support burden, empowers users to troubleshoot independently, builds deep understanding + +--- + +## Priority 3: Create Task-Based "How-To Guides" (Practical) + +**Create new `guides/` directory with specific, goal-oriented tutorials:** + +### Getting Work Done + +1. **`guides/index.md`** - Overview of available guides + +2. **`guides/calibrating-your-workspace.md`** + - Setting up accurate dimensions + - Testing dimensional accuracy + - Correcting steps-per-mm settings + +3. **`guides/using-camera-alignment.md`** + - Step-by-step camera workflow + - Camera calibration process + - Alignment techniques for precision work + +4. **`guides/creating-material-test-grid.md`** + - Using the built-in Material Test Grid generator + - Understanding speed/power matrices + - Configuring test parameters (speed range, power range, grid size) + - Using presets (Diode/CO2, Cut/Engrave) + - Interpreting test results and recording settings + - Risk-optimized execution order explained + +5. **`guides/batch-production-workflow.md`** + - Repeating jobs efficiently + - Using jigs and fixtures + - Production optimization tips + +### Quality & Precision + +6. **`guides/achieving-perfect-focus.md`** + - Laser focus techniques + - Focus testing procedures + - Variable focus for different materials + +7. **`guides/reducing-burn-marks.md`** + - Practical overscan/air-assist tips + - Speed and power optimization + - Material-specific techniques + +8. **`guides/cutting-thick-materials.md`** + - Multi-pass depth cutting strategies + - Power/speed/pass calculations + - Preventing charring + +### Advanced Workflows + +9. **`guides/using-simulation-mode.md`** + - Understanding the simulation overlay in 2D view + - Speed visualization with color heatmap (blue=slow, red=fast) + - Power visualization with transparency + - Laser head position tracking + - Playback controls and scrubbing + - Validating execution order before running jobs + - Using simulation for material test debugging + +10. **`guides/combining-raster-and-cut.md`** + - Engrave-then-cut workflow + - Layer organization best practices + - Avoiding workpiece movement + +11. **`guides/using-macros-for-automation.md`** + - Real-world macro examples + - Variable substitution + - Common automation patterns + +12. **`guides/rotary-attachment-setup.md`** (if supported) + - Rotary configuration + - Cylindrical object workflows + +**Impact:** Converts intermediate users to power users, showcases advanced features, demonstrates real-world value + +--- + +## Priority 4: Dramatically Expand Visual Content (Comprehension) + +**Current state:** 12 images +**Target:** 150+ images/diagrams + +### Establish Naming Convention + +Recommended naming convention: +- `Guide-[Topic]-[Element][Number].png` - Tutorial screenshots +- `Ref-[Feature]-[State].png` - Reference screenshots +- `Diag-[Concept].png` - Diagrams and illustrations +- `UI-[Window]-[Tab].png` - Interface documentation + +### Screenshot Strategy + +1. **Every Major UI State/Dialog:** + - Every settings panel mentioned in docs + - Every step in multi-step guides + - Before/after comparisons for operations + - Error states and troubleshooting scenarios + +2. **Create Custom Diagrams:** + - Workflow flowcharts (expand Mermaid usage) + - Technical diagrams for concepts (power vs speed, coordinates) + - Annotated screenshots highlighting specific UI elements + - Process diagrams showing data flow + +3. **Visual Examples:** + - Sample outputs showing different operations + - Common mistakes vs correct results + - Material test results with settings + - Quality comparison images + - Material test grid examples with different parameters + - Simulation mode screenshots showing speed heatmap and power visualization + - Annotated simulation screenshots explaining execution order + +### Screenshot Placeholder System + +To enable automated screenshot generation and maintain consistency, use standardized HTML comment placeholders in documentation files: + +**Simple placeholder:** +```markdown +```yaml +# +``` + +![Machine profile settings](../images/UI-Settings-MachineProfile.png) +``` + +**Detailed placeholder with automation steps:** +```markdown +```yaml +# +``` +``` + +See [SCREENSHOT_SPEC.md](SCREENSHOT_SPEC.md) for complete specification. + +### Image Guidelines + +- **Format:** PNG for screenshots, use mermaid markdown for diagrams where possible or svg as fallback +- **Resolution:** High-DPI screenshots (2x scale), then compress +- **Annotations:** Use consistent color scheme for callouts (#FF6B00 for highlights) +- **Alt text:** Descriptive alt text for accessibility +- **File size:** Optimize with compression tools +- **Placeholders:** Always include screenshot placeholders for automated regeneration + +**Impact:** dramatically improves comprehension and reduces support questions + +--- + +## Priority 5: Build Reference Section (Advanced Users) + +**Currently sparse - expand with detailed technical content:** + +### Complete Existing Empty Files + +1. **`reference/shortcuts.md`** + - Complete keyboard shortcut table + - Categorized by function (File, Edit, View, Machine, etc.) + - Searchable/filterable format + - Platform-specific variations (Linux vs Windows) + - Include F7 for Simulation Mode toggle + - Include shortcuts for material test grid operations + +2. **`reference/gcode-dialects.md`** + - Detailed comparison of GRBL vs Smoothieware G-code + - RayForge-specific commands and variables + - Dialect-specific limitations + - Compatibility matrix by firmware version + +3. **`reference/firmware.md`** + - Firmware compatibility matrix + - Version-specific features/bugs + - Upgrade recommendations + - Known issues by version + +### New Reference Content + +4. **`reference/command-reference.md`** + - All menu commands documented + - Keyboard shortcuts listed + - Command descriptions and use cases + - CLI arguments if applicable + +5. **`reference/file-format-spec.md`** + - RayForge project file format documentation + - Import/export capabilities by format + - Compatibility notes with other software + - Version differences + +6. **`reference/settings-reference.md`** + - Complete settings/preferences documentation + - Every option explained + - Default values and valid ranges + - Impact on performance and quality + +**Impact:** Power users and integrators need this; builds credibility, enables advanced usage + +--- + +## Priority 6: Enhance "Getting Started" Journey (Onboarding) + +**Current:** Good but can be broken into more granular, focused articles + +### Break Down Quick Start into Focused Articles + +Current state: `quick-start.md` (170 lines covering 7 steps) + +**Proposed breakdown:** + +1. **`getting-started/importing-your-first-file.md`** + - File format selection + - Import dialog walkthrough + - Common import issues + +2. **`getting-started/understanding-the-canvas.md`** + - Canvas navigation + - Zoom and pan controls + - Object manipulation basics + +3. **`getting-started/your-first-operation.md`** + - Choosing the right operation + - Basic operation settings + - Simple contour cut example + +4. **`getting-started/using-3d-preview.md`** + - Preview navigation + - What to look for in preview + - Common preview issues + +5. **`getting-started/simulating-your-job.md`** + - Activating simulation mode (F7) + - Understanding the speed heatmap (blue=slow, red=fast) + - Using playback controls and scrubbing + - Validating execution order before running + - What to check for in the simulation + +6. **`getting-started/framing-your-job.md`** + - Framing purpose and process + - Positioning material + - Adjusting job placement + +7. **`getting-started/running-your-first-job.md`** + - Pre-flight checklist + - Starting the job + - Monitoring progress + - Emergency stop + +8. **`getting-started/next-steps.md`** + - What to learn next + - Recommended learning path + - Links to guides and concepts + +### Add Progressive Complexity Indicators + +- **Level 1:** Absolute basics (getting-started) +- **Level 2:** Intermediate skills (guides) +- **Level 3:** Advanced techniques (advanced guides) + +**Impact:** Reduces overwhelm, increases completion rate for new users, improves retention + +--- + +## Priority 7: Add Collection/Topic Pages (Discovery) + +**Create thematic collections to organize related content:** + +### New Collections Section + +1. **`collections/index.md`** - Overview of available collections + +2. **`collections/new-user-essentials.md`** + - Curated links to must-read content for beginners + - Ordered learning path with checkboxes + - Estimated time to complete + - Prerequisites for each section + +3. **`collections/workflow-optimization.md`** + - All guides related to efficiency and quality + - Tips and tricks compilation + - Pro user techniques + - Time-saving shortcuts + +4. **`collections/troubleshooting-guide.md`** + - Problem-solution pairs by category + - Decision trees for diagnosis + - Common error messages explained + - When to seek help + +5. **`collections/material-library.md`** + - Community-contributed material settings + - Material safety information + - Best practices by material type + - Links to external resources + +**Impact:** Helps users discover related content, improves navigation, creates curated learning paths + +--- + +## Priority 8: File Formats Section (Currently Minimal) + +**Complete empty files with comprehensive content:** + +### Files to Complete + +1. **`files/importing.md`** + - Detailed import workflows for each format + - Format-specific settings and options + - Import dialog screenshots for each format + - Common import problems and solutions + +2. **`files/formats.md`** + - Format capabilities comparison table + - Supported features by format + - Recommended formats for different use cases + - Format conversion tips + +3. **`files/exporting.md`** + - Export options and settings + - G-code export customization + - Exporting for different firmware types + - Post-processing options + +### Additional Content + +- Format-specific import tips (SVG optimization, DXF units, PDF layer handling) +- File preparation in design tools (Inkscape, Illustrator, etc.) +- Troubleshooting malformed files +- Best practices for file organization + +**Impact:** Reduces import friction, helps users prepare better source files + +--- + +## Priority 9: Add Downloadable Resources + +**Provide downloadable resources for users:** + +### Create Downloads Directory + +**New directory:** `docs-site/assets/downloads/` + +### Sample Files + +1. **`sample-project.svg`** - Basic shapes for first test + - Simple square, circle, text + - Pre-sized for common laser beds + - Demonstration of different object types + +2. **`calibration-grid.svg`** - Dimensional accuracy test + - Measured grid pattern + - Reference dimensions + - Instructions in file metadata + +3. **`example-macro-library.txt`** - Common G-code macros + - Well-commented examples + - Usage instructions + - Variable substitution examples + +4. **`troubleshooting-checklist.pdf`** - Printable reference + - Quick diagnosis flowchart + - Common fixes + - When to seek help + +### Integration + +- Reference downloads in relevant guides +- Link from getting-started for immediate hands-on experience +- Include download counts/usage stats if possible + +**Impact:** Reduces friction, gets users producing results faster, demonstrates best practices + +--- + +## Implementation Strategy + +### Phase 1: Critical Path (Weeks 1-2) + +**Goal:** Remove all broken links and complete core user journeys + +- [x] Document Material Test Grid Generator (`features/operations/material-test-grid.md`) +- [x] Document Simulation Mode (`features/simulation-mode.md`) +- [x] Fill all empty operation files (contour, raster, depth, shrink-wrap) +- [x] Complete machine setup section (profiles, device-config, grbl-settings) +- [x] Finish core troubleshooting (connection, common problems, performance, snap-permissions) +- [x] Complete all empty feature files (camera, holding-tabs, macros-hooks, multi-layer, overscan-kerf) +- [ ] Screenshot every UI element mentioned in existing docs +- [ ] Screenshot Material Test Grid settings dialog and examples +- [ ] Screenshot Simulation Mode with speed heatmap and playback controls +- [x] Create `concepts/laser-safety.md` (critical safety content) + +**Deliverable:** All linked pages have content, no dead ends ✅ COMPLETE + +### Phase 2: Foundation (Weeks 3-4) + +**Goal:** Build conceptual understanding + +- [ ] Create `concepts/` section with index +- [ ] Write 5 key conceptual articles (operations, coordinates, power-speed, gcode, safety) +- [x] Expand reference section (shortcuts, g-code, firmware) +- [ ] Add 30+ screenshots for new content +- [ ] Create first set of diagrams (10+ custom illustrations) + +**Deliverable:** Users can understand "why" not just "how" - IN PROGRESS + +### Phase 3: Enrichment (Weeks 5-6) + +**Goal:** Provide practical, task-based guidance + +- [ ] Build `guides/` section with index +- [ ] Write `guides/creating-material-test-grid.md` +- [ ] Write `guides/using-simulation-mode.md` +- [ ] Write top 6-8 additional how-to articles (calibration, camera, etc.) +- [ ] Create downloadable sample files (3-4 essential files) +- [ ] Add 50+ workflow screenshots +- [ ] Complete file formats section + +**Deliverable:** Users can accomplish real tasks independently + +### Phase 4: Polish (Week 7+) + +**Goal:** Enhance discoverability and create learning paths + +- [ ] Create `collections/` section with curated content +- [ ] Add remaining how-to guides (advanced topics) +- [ ] Expand troubleshooting with more problem/solution articles +- [ ] Reach 150+ total images +- [ ] Gather user feedback and iterate + +**Deliverable:** Comprehensive, discoverable documentation + +### Phase 5: Advanced (Ongoing) + +**Optional enhancements:** + +- [ ] Video tutorials for complex workflows +- [ ] Interactive diagrams (if feasible with MkDocs) +- [ ] Community contributions section +- [ ] Translation improvements +- [ ] Search optimization + +--- + +## Proposed Navigation Structure + +**Reorganized `mkdocs.yml` nav section:** + +```yaml +nav: + - Home: index.md + + - Getting Started: + - getting-started/index.md + - Installation: getting-started/installation.md + - First Time Setup: getting-started/first-time-setup.md + - Importing Your First File: getting-started/importing-your-first-file.md + - Understanding the Canvas: getting-started/understanding-the-canvas.md + - Your First Operation: getting-started/your-first-operation.md + - Using 3D Preview: getting-started/using-3d-preview.md + - Simulating Your Job: getting-started/simulating-your-job.md + - Framing Your Job: getting-started/framing-your-job.md + - Running Your First Job: getting-started/running-your-first-job.md + - Next Steps: getting-started/next-steps.md + + - Concepts: + - concepts/index.md + - Understanding Operations: concepts/understanding-operations.md + - Coordinates & Origin: concepts/coordinates-and-origin.md + - Power vs Speed: concepts/power-vs-speed.md + - G-code Basics: concepts/gcode-basics.md + - Laser Safety: concepts/laser-safety.md + + - How-To Guides: + - guides/index.md + - Material Test Grid: guides/creating-material-test-grid.md + - Simulation Mode: guides/using-simulation-mode.md + - Calibrating Your Workspace: guides/calibrating-your-workspace.md + - Camera Alignment: guides/using-camera-alignment.md + - Batch Production: guides/batch-production-workflow.md + - Achieving Perfect Focus: guides/achieving-perfect-focus.md + - Reducing Burn Marks: guides/reducing-burn-marks.md + - Cutting Thick Materials: guides/cutting-thick-materials.md + - Combining Raster and Cut: guides/combining-raster-and-cut.md + - Using Macros: guides/using-macros-for-automation.md + + - User Interface: + - ui/index.md + - Main Window: ui/main-window.md + - Canvas Tools: ui/canvas-tools.md + - 3D Preview: ui/3d-preview.md + - Settings & Preferences: ui/settings.md + + - Features: + - features/index.md + - Simulation Mode: features/simulation-mode.md + - Operations: + - features/operations/index.md + - Material Test Grid: features/operations/material-test-grid.md + - Contour Cutting: features/operations/contour.md + - Raster Engraving: features/operations/raster.md + - Depth Engraving: features/operations/depth.md + - Shrink Wrap: features/operations/shrink-wrap.md + - Multi-Layer Workflow: features/multi-layer.md + - Camera Integration: features/camera.md + - Holding Tabs: features/holding-tabs.md + - G-code Macros & Hooks: features/macros-hooks.md + - Overscan & Kerf: features/overscan-kerf.md + + - Machine Setup: + - machine/index.md + - Machine Profiles: machine/profiles.md + - Device Configuration: machine/device-config.md + - GRBL Settings: machine/grbl-settings.md + - Multiple Lasers: machine/multi-laser.md + + - File Formats: + - files/index.md + - Importing Files: files/importing.md + - Supported Formats: files/formats.md + - Exporting G-code: files/exporting.md + + - Troubleshooting: + - troubleshooting/index.md + - Connection Issues: troubleshooting/connection.md + - Common Problems: troubleshooting/common.md + - Performance: troubleshooting/performance.md + - Permissions (Snap): troubleshooting/snap-permissions.md + + - Reference: + - reference/index.md + - Keyboard Shortcuts: reference/shortcuts.md + - Command Reference: reference/command-reference.md + - G-code Dialect Support: reference/gcode-dialects.md + - Firmware Compatibility: reference/firmware.md + - Settings Reference: reference/settings-reference.md + - File Format Specifications: reference/file-format-spec.md + + - Collections: + - collections/index.md + - New User Essentials: collections/new-user-essentials.md + - Workflow Optimization: collections/workflow-optimization.md + - Troubleshooting Guide: collections/troubleshooting-guide.md + - Material Library: collections/material-library.md + + - Contributing: + - contributing/index.md + - Development Setup: contributing/development.md + - Adding Device Drivers: contributing/drivers.md +``` + +--- + +## Success Metrics + +### Quantitative Goals + +- **Content volume:** 44 → 100+ substantive pages (from 25 empty stubs) +- **Visual aids:** 12 → 150+ images/diagrams +- **Complete user journeys:** 0 broken links or dead ends +- **Reference coverage:** 100% of features documented + +### Qualitative Goals + +- **New user success rate:** Significant improvement in onboarding completion +- **Support burden:** Reduced through self-service troubleshooting and concepts +- **User satisfaction:** Positive feedback on documentation completeness +- **Discoverability:** Users can find answers without external help + +### Tracking + +- Monitor GitHub issues related to documentation gaps +- Track common support questions that should be documented +- User feedback on documentation helpfulness +- Analytics on most-visited pages (identify gaps) + +--- + +## Content Creation Guidelines + +### Writing Style + +- **Audience:** End-users, not developers +- **Tone:** Friendly, clear, and concise +- **Voice:** Use second person ("you") and active voice +- **Examples:** Provide concrete examples and screenshots +- **Safety:** Always emphasize safety when relevant + +### Page Structure + +Each page should include: + +1. **Title:** Clear, descriptive H1 heading +2. **Introduction:** Brief overview (2-3 sentences) +3. **Prerequisites:** What users need before starting (if applicable) +4. **Body:** Detailed information with examples, organized with H2/H3 headings +5. **Tips/Warnings:** Callout boxes for important information +6. **Navigation:** "Next steps" or "Related pages" links at the end + +### Visual Content Standards + +- **Screenshots:** + - Use default theme for consistency + - Crop to relevant area, but include enough context + - Annotate with arrows/highlights if needed + - Include alt text describing what's shown + +- **Diagrams:** + - Use Mermaid for flowcharts when possible + - Create custom SVG diagrams for complex concepts + - Use consistent color scheme and style + - Include legends for symbols + +- **Code Examples:** + - Syntax highlighted + - Include comments explaining non-obvious parts + - Show expected output when relevant + - Test all examples before publishing + +--- + +## RayForge Documentation Focus + +The RayForge documentation should emphasize: + +1. **Open-source collaboration:** + - Contributing guide is prominent + - Community involvement encouraged + - Development transparency + - "Edit this page" links enabled for community contributions + +2. **Modern technology:** + - Highlight modern UI (Gtk4/Libadwaita) + - Cross-platform capabilities + - Integration possibilities + +3. **Target audience:** + - Hobbyists and makers (accessible pricing/free) + - Educational use + - Small businesses + +4. **Unique features:** + - Multi-laser support + - Advanced G-code preview + - Extensibility and customization + - Built-in Material Test Grid Generator (parametric, risk-optimized) + - Real-time Simulation Mode (speed heatmap, power visualization) + +--- + +## Resources Needed + +### Content Creation + +- **Technical writer:** 40-80 hours for Phase 1-2 +- **Subject matter expert:** Review and accuracy checking +- **Graphic designer:** Custom diagrams and illustrations (optional) + +### Tools + +- **Screenshot tools:** Built-in OS tools sufficient +- **Image editing:** GIMP or similar (annotations, cropping) +- **Diagram tools:** Mermaid (built-in), draw.io, or Inkscape for complex diagrams +- **Screen recording:** OBS Studio for video tutorials (Phase 5) + +### Review Process + +1. **Technical accuracy:** SME review of technical content +2. **User testing:** Beta testers validate guides with fresh eyes +3. **Editorial review:** Grammar, style, consistency +4. **Accessibility:** Alt text, screen reader compatibility +5. **Cross-linking:** Verify all internal links work + +--- + +## Maintenance Plan + +### Ongoing Updates + +- **Release notes:** Document new features in relevant sections +- **Deprecation notices:** Mark outdated content clearly +- **Version-specific content:** Use tabs for version differences +- **Link checking:** Automated link checking in CI/CD + +### Community Contributions + +**Enable "Edit this page" feature:** + +Already configured in `mkdocs.yml`: + +This allows users to click "Edit this page" on any documentation page and be taken directly to the GitHub editor for that file, making it easy to submit corrections and improvements via pull requests. + +**Workflow:** +- **Contribution guidelines:** Clear process for doc contributions +- **Recognition:** Credit contributors in changelog +- **Moderation:** Review process for community PRs +- **Easy access:** Users can click "Edit this page" to submit improvements directly + +### Feedback Loop + +- **Feedback widget:** "Was this helpful?" on each page +- **Issue tracking:** Document requests in GitHub issues +- **Analytics:** Monitor popular pages and search terms +- **User surveys:** Periodic documentation satisfaction surveys + +--- + +## Conclusion + +This plan transforms RayForge documentation from a solid foundation with gaps into comprehensive, user-friendly documentation that serves users from first install through advanced usage. By following LightBurn's proven structure while maintaining RayForge's unique voice and community focus, we can create documentation that: + +1. **Reduces support burden** through comprehensive self-service content +2. **Improves user success** with clear onboarding and task-based guides +3. **Builds user confidence** through conceptual understanding +4. **Serves all skill levels** from beginners to advanced users +5. **Enhances project credibility** with professional, complete documentation + +The phased approach ensures critical gaps are filled first, with progressive enhancement adding depth and discoverability over time. + +--- + +## Next Steps + +1. **Review and approve** this plan with stakeholders +2. **Prioritize** specific articles within each phase based on user feedback +3. **Assign resources** for content creation and review +4. **Set up tracking** for metrics and progress +5. **Begin Phase 1** with critical content gaps + +**Estimated timeline:** 7-10 weeks for Phases 1-4, with ongoing maintenance and enhancement. diff --git a/docs-site/features/camera.md b/docs-site/features/camera.md new file mode 100644 index 000000000..9ebdd6cb6 --- /dev/null +++ b/docs-site/features/camera.md @@ -0,0 +1,384 @@ +# Camera Integration + +RayForge supports USB camera integration for precise material alignment and positioning. The camera overlay feature allows you to see exactly where your laser will cut or engrave on the material, eliminating guesswork and reducing material waste. + +## Overview + +The camera integration provides: + +- **Live video overlay** on the canvas showing your material in real-time +- **Image alignment** to calibrate camera position relative to the laser +- **Visual positioning** to accurately place jobs on irregular or pre-marked materials +- **Material preview** before running jobs +- **Multiple camera support** for different machine setups + +!!! tip "Use Cases" + - Aligning cuts on pre-printed materials + - Working with irregularly shaped materials + - Precise placement of engravings on existing objects + - Reducing test cuts and material waste + +--- + +## Camera Setup + +### Hardware Requirements + +**Compatible cameras:** +- USB webcams (most common) +- Laptop built-in cameras (if running RayForge on laptop near machine) +- Any camera supported by Video4Linux2 (V4L2) on Linux or DirectShow on Windows + +**Recommended setup:** +- Camera mounted above the work area with clear view of material +- Consistent lighting conditions +- Camera positioned to capture the laser work area +- Secure mounting to prevent camera movement + +### Adding a Camera + +1. **Connect your camera** to your computer via USB + +2. **Open Camera Settings:** + - Navigate to **Settings Preferences Camera** + - Or use the camera toolbar button + +3. **Add a new camera:** + - Click the "+" button to add a camera + - Enter a descriptive name (e.g., "Top Camera", "Work Area Cam") + - Select the device from the dropdown + - On Linux: `/dev/video0`, `/dev/video1`, etc. + - On Windows: Camera 0, Camera 1, etc. + +4. **Enable the camera:** + - Toggle the camera enable switch + - The live feed should appear on your canvas + +5. **Adjust camera settings:** + - **Brightness:** Adjust if material is too dark/bright + - **Contrast:** Enhance edge visibility + - **Transparency:** Control overlay opacity (20-50% recommended) + - **White Balance:** Auto or manual Kelvin temperature + +--- + +## Camera Alignment + +Camera alignment calibrates the relationship between camera pixels and real-world coordinates, enabling accurate positioning. + +### Why Alignment is Necessary + +The camera sees the work area from above, but the image may be: +- Rotated relative to the machine axes +- Scaled differently in X and Y directions +- Distorted by lens perspective + +Alignment creates a transformation matrix that maps camera pixels to machine coordinates. + +### Alignment Procedure + +1. **Open the Alignment Dialog:** + - Click the camera alignment button in the toolbar + - Or go to **Camera Align Camera** + +2. **Place alignment markers:** + - You need at least 3 reference points (4 recommended for better accuracy) + - Alignment points should be spread across the work area + - Use known positions like: + - Machine home position + - Ruler markings + - Pre-cut alignment holes + - Calibration grid + +3. **Mark image points:** + - Click on the camera image to place a point at a known location + - The bubble widget appears showing point coordinates + - Repeat for each reference point + +4. **Enter world coordinates:** + - For each image point, enter the real-world X/Y coordinates in mm + - These are the actual machine coordinates where each point is located + - Measure accurately with a ruler or use known machine positions + +5. **Apply alignment:** + - Click "Apply" to calculate the transformation + - The camera overlay will now be properly aligned + +6. **Verify alignment:** + - Move the laser head to a known position + - Check that the laser dot aligns with the expected position in the camera view + - Fine-tune by re-aligning if needed + +### Alignment Tips + +!!! tip "Best Practices" + - Use points at the corners of your work area for maximum coverage + - Avoid clustering points in one area + - Measure world coordinates carefully - accuracy here determines overall alignment quality + - Re-align if you move the camera or change the focus distance + - Save your alignment - it persists across sessions + +**Example alignment workflow:** + +1. Move laser to home position (0, 0) and mark in camera +2. Move laser to (100, 0) and mark in camera +3. Move laser to (100, 100) and mark in camera +4. Move laser to (0, 100) and mark in camera +5. Enter exact coordinates for each point +6. Apply and verify + +--- + +## Using the Camera Overlay + +Once aligned, the camera overlay helps position jobs accurately. + +### Enabling/Disabling the Overlay + +- **Toggle camera:** Click the camera icon in the toolbar +- **Adjust transparency:** Use the slider in camera settings (20-50% works well) +- **Refresh image:** Camera updates continuously while enabled + +### Positioning Jobs with the Camera + +**Workflow for precise placement:** + +1. **Enable the camera overlay** to see your material + +2. **Import your design** (SVG, DXF, etc.) + +3. **Position the design** on the canvas: + - Drag the design to align with features visible in the camera + - Use zoom to see fine details + - Rotate/scale as needed + +4. **Preview the alignment:** + - Use the [Simulation Mode](simulation-mode.md) to visualize the toolpath + - Check that cuts/engravings will be where you expect + +5. **Frame the job** to verify positioning before running + +6. **Run the job** with confidence + +### Example: Engraving on a Pre-Printed Card + +1. Place the printed card on the laser bed +2. Enable camera overlay +3. Import your engraving design +4. Drag and position the design to align with printed features +5. Fine-tune position using arrow keys +6. Frame to verify +7. Run the job + +--- + +## Camera Settings Reference + +### Device Settings + +| Setting | Description | Values | +|---------|-------------|--------| +| **Name** | Descriptive name for the camera | Any text | +| **Device ID** | System device identifier | `/dev/video0` (Linux), `0` (Windows) | +| **Enabled** | Camera active state | On/Off | + +### Image Adjustment + +| Setting | Description | Range | +|---------|-------------|-------| +| **Brightness** | Overall image brightness | -100 to +100 | +| **Contrast** | Edge definition and contrast | 0 to 100 | +| **Transparency** | Overlay opacity on canvas | 0% (opaque) to 100% (transparent) | +| **White Balance** | Color temperature correction | Auto or 2000-10000K | + +### Alignment Data + +| Property | Description | +|----------|-------------| +| **Image Points** | Pixel coordinates in camera image | +| **World Points** | Real-world machine coordinates (mm) | +| **Transformation Matrix** | Calculated mapping (internal) | + +--- + +## Advanced Features + +### Camera Calibration (Lens Distortion Correction) + +For precise work, you can calibrate the camera to correct barrel/pincushion distortion: + +1. **Print a checkerboard pattern** (e.g., 86 grid with 25mm squares) +2. **Capture 10+ images** of the pattern from different angles/positions +3. **Use OpenCV calibration tools** to calculate camera matrix and distortion coefficients +4. **Apply calibration** in RayForge (advanced settings) + +!!! note "When to Calibrate" + Lens distortion correction is only necessary for: + - Wide-angle lenses with noticeable barrel distortion + - Precision work requiring <1mm accuracy + - Large work areas where distortion accumulates + + Most standard webcams work fine without calibration for typical laser work. + +### Multiple Cameras + +RayForge supports multiple cameras for different views or machines: + +- Add multiple cameras in preferences +- Each camera can have independent alignment +- Switch between cameras using the camera selector +- Use cases: + - Top view + side view for 3D objects + - Different cameras for different machines + - Wide angle + detail camera + +--- + +## Troubleshooting + +### Camera Not Detected + +**Problem:** Camera doesn't appear in device list. + +**Solutions:** + +=== "Linux" + Check if the camera is recognized by the system: + + ```bash + # List video devices + ls -l /dev/video* + + # Check camera with v4l2 + v4l2-ctl --list-devices + + # Test with another application + cheese # or VLC, etc. + ``` + + **For Snap users:** + ```bash + # Grant camera access + sudo snap connect rayforge:camera + ``` + +=== "Windows" + - Check Device Manager for camera under "Cameras" or "Imaging devices" + - Ensure no other application is using the camera (close Zoom, Skype, etc.) + - Try a different USB port + - Update camera drivers + +### Camera Shows Black Screen + +**Problem:** Camera detected but shows no image. + +**Possible causes:** + +1. **Camera in use by another application** - Close other video apps +2. **Incorrect device selected** - Try different device IDs +3. **Camera permissions** - On Linux Snap, ensure camera interface connected +4. **Hardware issue** - Test camera with another application + +**Solutions:** + +```bash +# Linux: Release camera device +sudo killall cheese # or other camera apps + +# Check which process is using the camera +sudo lsof /dev/video0 +``` + +### Alignment Not Accurate + +**Problem:** Camera overlay doesn't match real laser position. + +**Diagnosis:** + +1. **Insufficient alignment points** - Use at least 4 points +2. **Measurement errors** - Double-check world coordinates +3. **Camera moved** - Re-align if camera position changed +4. **Non-linear distortion** - May need lens calibration + +**Improve accuracy:** + +- Use more alignment points (6-8 for very large areas) +- Spread points across entire work area +- Measure world coordinates very carefully +- Use machine movement commands to precisely position laser at known coordinates +- Re-align after any camera adjustments + +### Poor Image Quality + +**Problem:** Camera image is blurry, dark, or washed out. + +**Solutions:** + +1. **Adjust brightness/contrast** in camera settings +2. **Improve lighting** - Add consistent work area lighting +3. **Clean camera lens** - Dust and debris reduce clarity +4. **Check focus** - Auto-focus may not work well; use manual if possible +5. **Reduce transparency** temporarily to see camera image more clearly +6. **Try different white balance** settings + +### Camera Lag or Stuttering + +**Problem:** Live camera feed is choppy or delayed. + +**Solutions:** + +- Lower camera resolution in device settings (if accessible) +- Close other applications using CPU/GPU +- Update graphics drivers +- On Linux, ensure using V4L2 backend (automatic in RayForge) +- Disable camera when not needed to save resources + +--- + +## Performance Considerations + +Camera overlay has minimal performance impact when configured correctly: + +- **Modern computers:** No noticeable slowdown +- **Lower-end systems:** Slight UI lag possible with high-resolution cameras +- **Disable when not needed:** Turn off camera during intensive operations + +**Optimize performance:** +- Use 720p or 1080p cameras (4K is overkill and slower) +- Close camera when doing complex G-code generation +- Enable camera only when actively positioning jobs + +--- + +## Best Practices + +### Lighting + +- Use consistent, diffuse lighting to avoid harsh shadows +- Avoid backlighting or glare on reflective materials +- LED work lights provide good, consistent illumination + +### Camera Mounting + +- Mount camera securely to prevent vibration +- Position camera parallel to work surface if possible +- Ensure camera covers entire work area +- Avoid mounting too high (reduces resolution) or too low (limited coverage) + +### Workflow Integration + +1. **Initial setup:** Configure and align camera once +2. **Material placement:** Use camera to position material on bed +3. **Job positioning:** Use camera overlay to precisely place design +4. **Verification:** Frame job to confirm position +5. **Execution:** Disable camera during job run (optional, saves resources) +6. **Next job:** Re-enable camera for next piece + +--- + +## Related Pages + +- [Simulation Mode](simulation-mode.md) - Preview execution with camera overlay +- [3D Preview](../ui/3d-preview.md) - Visualize jobs in 3D +- [Framing Jobs](../getting-started/framing-your-job.md) - Verify job position +- [Machine Setup](../machine/index.md) - Machine configuration diff --git a/docs-site/features/holding-tabs.md b/docs-site/features/holding-tabs.md new file mode 100644 index 0000000000000000000000000000000000000000..0f93041552abe0a375d1c156a4d7bd199f8fd956 GIT binary patch literal 9594 zcmbW7%X1q?lEx=|?3lwI_OQpYbr=#Okd$TZZpixxih5WPmc*s#(N0V_)_?uWX}i)!UA{Z*S~!(SbLxdUIewOjbI z47s~%ihLDXS2s>C51nsz`)K%-suKYZle>t?$;Y>(;(=*CA~A zyXjizyUs7xtlQPRW2L@n>b^2jHogl@;mad;xh`6_ZNg2cm}9FIVSyCOrrx+seIv>9 zzR@qO@@swd(A}M|FuR@oUn={2sq!~%Vo8l@S@1B>nb$JtXB(%P5>Z>wrT6eWG zXNlV8xvakTnZDw6$3qLw?f317mpt&AxjAxtY%S40st&A>Bf&*8mN*+x zD{tr<0B(y=Xd79 z+tM$>p;=%Ik<;8jcM5n4od@oJ`eJeIcx|2zn1vFEH+$a_MHZ99xjf_6gJ0O+=K#7= z2cHi%ecOQ!&dW`X7lMtx*`wTHrVyCT&Pr`F_-9wwrSK+(oBq1;Olp(`+PxbSMoq`E znId3VqmGl5a9AP+-CjC*nlv=GROkG58(10Ci&4JzRbDE;?H6%)DCia9tSINEFS`Oy z25=QR>CBrt#dq3Zw=I-5ckc20yQq*QM~E9){(A_}GDS~I4-j!aOKh2fa5j5Ud2rBX zN*PO60k^)4P#5fF?hd+owPIA#71&7v=?bLU`YM#@S62MV(u~xLCF9Z0>n%XpWEmJ3 z<&bfjx{R1Mn_U#EbvIwgFl?VRGTL0$P*z3EoTMS|f6`e-TWiY4=QBGKD^bA=`9r7fn7ls-T`(o1q`OAdi3LkFboL8!w) zP@#cAtY-fhsug&~dWP3`XcE>No#fm3lg$Qmndzf4PPf}~Cxs4)Obefn7LKOXvk$`a zEW57v=;wYK)>D^K6XxsRp!wDOzhFDLV+dk$~noG0^tvpHz&6%G)D5T+>+ zKGP3AG*H8qC94n>s>CWcGAQU8Gmi15AA-Lr1OZ~k!vwM9y*Sn+0$a-wRv_MuR0e%&?(5I5|2Y zH$6H!IgHaq8HXr^@(l|doNzFZu%VK9#7E*4=osL10=T59~) zvLPUgrm(!cNNa@{{>1>Tf-%v5I0xZK)G`VB};76{ndCvjvrogyK zhS@B_G;{6%b<;8UzO0M7ffZ|gh0Vr)EH?dSbRA_zqANgAlR^WF*4b1PYs`sAz-B(31{U&T@_-Es0$mD%zD9NfD-vrQ<$vAo{LT=#Q>zxG#g(MozfKXu<%i2sp`dS-%(<5TAXbV46VfIcag%G z+lvsQ@na$_ej2<#62x?(W9mV(l?pHNR!Gf^ut^vud&WxpK9>|CeUnJ(CHncs(Ysk( zU)3K`8d)#WbdBPzyD31CqAWU<<&mOtFd4_%C^(}$&$!?~#?h`QZYqI+T1agyi`hVH z4)k1hSQmM2(HV8-s~fKd$7RA*l^Ybbsdj}9rpAc`P-|y__n4?*L#xC$1w)cd(fC-4 znm1NDtTk54^T@m{CeTpcTf=M8ZIEi5EF@c|s{Xv#8bye)Awp@RPM1p+Q|XM8Y}3^A zw^}qXX=}}9$`=ui)C(Yr-FD3}P&f(Yv;M)rcC}WL}*h&Xc`37k*3DRIr-%)SZdl z8g*yla{oRVZ7mrY$AZ(xc8r$gly}Y%Eon`rOk!FNFf{lWm@XGNmy0AO)AUMb=9rL< z)5{lonO9w_ZAbIKP4crE|BbgF1Kqpb=|Fn=yL5E_uCY|S$$@~|197q z7EmwE*9JpYSc^%@!PFz6qQk3#Ss@}|m4TE%2|ja=xC?$SkBPpO*VUhBYAOjY#fEGg zqDYm4f5tj-5`)hax#x{1HVLGC)KPBkEcEE+;%(MzE8Xf2gQtc#hgiAy${?TIhnPG+ zk#hEx5z#^MGc9=bRnD~B8LAcydCi$J#$yUbf07>LivoZ%EAjMkAk` z%)dQJgX2?XjqQXu`bV`6H2A;9p{gZzjHD|1^RO`ICGcAn5eg+C_DfQ2QHEp4O>Z>7 zY7d$G&Ctq-b&6kxZf8^8Tdy?IXkTjR%Wyl?7x2(nU>H&Fw>HCcxe7Hzx!GyLnPKur z7m38a#;{r^l>^aYXgN|rBh~N4Cc|oHmZLn`v)p)|_cVv-VBf9&X@=0E!FQ15T}9GN zq}Tf4zr%2Esd}t$orlh&pZs`1t))K0*hW9?612oZ?j9qRgy%IeJ~lq0gi~TsSI`KR zLNp|=eCeUf!M`0sOYl}(G%x-#{OP7HQq z_eysut#5XzS9GBc`as=MFBmu#6zO0}^NC!ZH9(WQu8L()I|w3Rm}Sa-S@!LE4hEqF zYEGr*GavxMWo;9yFL?%9h)&&_pMftl0mp*Yb_fdn%mQ9>p7lbPxY zL@<5Q;aobu(2-Qc#AHUG3u3M)lbE2qEKfJ`7|RtsVztyqRPMNQ%|iL(3oCdB;bNQS zymZPv3MQ*X@6pF#ineZBLl_|U@Pjl$XQ$imQg}kD2j5a zQECM=Dxuh6NK6M2n@y%vn@cE(?iJq6cJCYuGd^!|rKp(1s9GblmR)hu%&$-Yw9Gw0}ke*uM-)<4`6Cxn!IWN6?Qa$p=O z)%S@+y|8p?)*G({)z-6KI`f4IZ8{R2Y+L|aHogV!j%h44{)RSx>?fM!496R36*8A) zfXlXyJ>~=P?h^$ug$M2%Sj$?{huIUw+(j5jdE%McedDjq(AKP3z|FZzLjatRMg!&I zc$1ZY#WKOOre@YlT@j^=FC5~Y@ob=g&+dk=j9Qo$bR7jM7A<$iW~4JNP-EW>&jOpG zKT{K?REsPlp0Gk{TiRGT($HaI8VAx~!-ZHc+bDx^>1~8^o&3v?t$VI?yU8HCbXJ*W zRUT%Ru|9XKxqDrypRC$%Fb_McO>YU&X2qDAG%)t!nAFy%7*gllCBM<-FlMGrq!M3Y zRx+?0b1Su{U4q9-MM}SChcOdKhd@YuRjmr^BQ@uAUIBZkJGImY?t z@FnWIzrwP+7>vsHy5y!6S%r^V=yS;Fit6Og3%{!9UPjQ0Mf0RoQ+DXc5q8f%^b)OE z>Ha(-Q|h*)*BtQmzFSFc9*G>Kzv7)cVe<`ThgM&6_>%gE{s<1(g!yhZRZG!LS4z)sgmgcg0>$SnlT_Wcqr`}B(h%A>2JaiBPIn_(snj%QIk+!+99xX4#V(96D@4D#wF%srp zVdM^)y0aRIF9L8JGN*Nm-`W9y`mqVhVdi$18}p=HT5zB-i3&r-1>#o#a5)Mb;R*30 z4dql$`ko2${EcG6u6luY+2QAdF@?3mHSp1fI|el(VL8oie<>X8C}fYI$!c$O<2wJ* z@8GQJP%Zho$uIT{X)OvoY8oQT+yzQSGuw^VwKh_U{oCW`19ABI;OOYMFODDQ z^TYzuQt?X*#c$(kL~R Dh)onp literal 0 HcmV?d00001 diff --git a/docs-site/features/index.md b/docs-site/features/index.md new file mode 100644 index 000000000..089169179 --- /dev/null +++ b/docs-site/features/index.md @@ -0,0 +1,93 @@ +# Features Overview + +Rayforge provides a comprehensive set of features for laser cutting and engraving. This section covers all the major capabilities and how to use them effectively. + +## Operations + +Operations define how Rayforge processes your designs. Each operation type is optimized for specific tasks: + +- **[Contour Cutting](operations/contour.md)**: Cut along the outline of shapes +- **[Raster Engraving](operations/raster.md)**: Fill shapes with engraving patterns +- **[Depth Engraving](operations/depth.md)**: Create 3D relief effects from images +- **[Shrink Wrap](operations/shrink-wrap.md)**: Create efficient cutting paths around multiple objects + +## Workflow Features + +- **[Multi-Layer Operations](multi-layer.md)**: Assign different operations to layers in your design for complex workflows +- **[Holding Tabs](holding-tabs.md)**: Add tabs to contour cuts to keep pieces in place during cutting +- **[G-code Macros & Hooks](macros-hooks.md)**: Automate tasks with custom G-code snippets + +## Quality Enhancement + +- **[Overscan & Kerf Compensation](overscan-kerf.md)**: Improve engraving quality and dimensional accuracy + +## Hardware Integration + +- **[Camera Integration](camera.md)**: Use a USB camera for workpiece alignment, positioning, and background tracing + +## Quick Feature Reference + +| Feature | Description | Learn More | +|:---------------------------|:----------------------------------------------------------------------------|:-----------| +| Multi-Layer Operations | Assign different operations (engrave, cut) to layers | [Guide](multi-layer.md) | +| 3D G-code Preview | Visualize toolpaths before sending to machine | [UI Guide](../ui/3d-preview.md) | +| Holding Tabs | Auto or manual tab placement for contour cuts | [Guide](holding-tabs.md) | +| Overscan | Reduce burn marks at raster engraving endpoints | [Guide](overscan-kerf.md) | +| Kerf Compensation | Adjust paths to compensate for material removed by laser | [Guide](overscan-kerf.md) | +| 2.5D Cutting | Multi-pass cuts with configurable step-down for thick materials | [Operations](operations/contour.md) | +| Camera Alignment | Position designs using live camera feed | [Camera Guide](camera.md) | +| Path Optimization | Minimize travel time and improve quality | [Operations](operations/index.md) | +| Variable Substitution | Use variables in macros and hooks | [Macros Guide](macros-hooks.md) | + +## Best Practices + +### Operation Selection + +- Use **Contour** for cutting out shapes and profiles +- Use **Raster** for filling areas with engraving (wood, leather, etc.) +- Use **Depth Engraving** for 3D effects on materials like acrylic or coated metals +- Use **Shrink Wrap** when you need to cut around multiple objects efficiently + +### Layer Organization + +Organize your designs by operation type: + +1. **Layer 1**: Engraving operations (run first) +2. **Layer 2**: Scoring or marking operations +3. **Layer 3**: Through-cutting operations (run last) + +```mermaid +flowchart TD + A[Design File] --> B{Select Objects} + B --> C[Layer 1: Raster/Depth
Engraving] + B --> D[Layer 2: Light Contour
Scoring] + B --> E[Layer 3: Full Power
Cutting] + + C --> F[Execute in Order] + D --> F + E --> F + + F --> G[Material stays in place
during engraving] + G --> H[Cut free at end] + + style C fill:#e3f2fd + style D fill:#fff3e0 + style E fill:#ffebee + style H fill:#e8f5e9 +``` + +!!! tip "Why this order?" + Engraving first prevents the material from moving if it's cut free. Cutting last ensures all other operations complete while the material is secured. + +### Power and Speed + +Start with conservative settings and gradually increase: + +- **Too fast/low power**: Incomplete cuts, light engraving +- **Too slow/high power**: Charring, melted edges, fire risk + +Always test on scrap material first! + +--- + +Explore each feature section to learn how to get the most out of Rayforge. diff --git a/docs-site/features/kerf.md b/docs-site/features/kerf.md new file mode 100644 index 000000000..1938bef1c --- /dev/null +++ b/docs-site/features/kerf.md @@ -0,0 +1,429 @@ +# Kerf Compensation + +Kerf is the material removed by the laser beam during cutting. Kerf compensation adjusts toolpaths to account for this, ensuring cut parts match their designed dimensions. + +## What is Kerf? + +**Kerf** = the width of material removed by the cutting process. + +When a laser cuts material, it vaporizes or melts a path through the material. This removed material creates a gap - the kerf. + +**Components of kerf:** +- Laser spot size (beam diameter at focal point) +- Heat-affected zone (material vaporized beyond spot) +- Material interaction (burning, melting expands the cut) + +**Example:** +- Laser spot size: 0.2mm +- Material interaction: adds ~0.1mm on each side +- **Total kerf:** ~0.4mm + +## The Problem Without Compensation + +Without kerf compensation, parts don't match their designed dimensions: + +**Outside cuts (cutting a part):** +``` +Designed: Actual cut: + + 50mm 49.6mm Part too small + (kerf removed from part) +``` + +**Inside cuts (cutting a hole):** +``` +Designed: Actual cut: + + 50mm 50.4mm Hole too big + (kerf removed into hole) +``` + +**Why this happens:** + +- Laser follows the design path exactly +- Material removal occurs on both sides of the path +- Half the kerf is removed from each side +- Final dimensions are off by the kerf width + +## When Kerf Matters + +**Critical for:** +- Precision assemblies (tight tolerances < 0.5mm) +- Snap-fit assemblies +- Interlocking designs (boxes, puzzles, gears) +- Mechanical parts with specific dimensions +- Parts that must fit together + +**Not critical for:** +- Decorative cutting (tolerance > 1mm acceptable) +- Single-piece projects with no assembly +- Artistic work where exact dimensions aren't important +- Engraving (no kerf in engraving) + +**Rule of thumb:** If parts need to fit together, compensate for kerf. + +## How Kerf Compensation Works + +Kerf compensation **offsets the toolpath** inward or outward to account for material removal: + +**For outside cuts (cutting a part):** +- Offset path **outward** by half the kerf width +- Laser cuts slightly outside the design +- After kerf is removed, part matches design size + +**For inside cuts (cutting a hole):** +- Offset path **inward** by half the kerf width +- Laser cuts slightly inside the design +- After kerf is removed, hole matches design size + +**Example with 0.4mm kerf:** + +``` +Original design: 50mm square (part) +Kerf measured: 0.4mm total width +Compensation: Offset outward by 0.2mm (half kerf) +Laser follows: 50.4mm square path +After cutting: Part measures 50.0mm (perfect!) +``` + +**Visual representation:** + +``` +Design path: [==========] 50mm +Kerf compensation: --[==========]-- offset 0.2mm out +Laser cuts here: [============] 50.4mm +Material removed: X X 0.2mm each side +Final part: [==========] 50.0mm +``` + +## Measuring Kerf + +Accurate kerf measurement is essential for proper compensation. + +**Test procedure:** + +1. **Create a test file:** + - Draw a 50mm x 50mm square (for outside cut test) + - Draw a 30mm diameter circle (for inside cut test) + - Export to RayForge + +2. **Cut the test:** + - Use your normal cutting settings (power/speed) + - Cut completely through material + - Let material cool completely + +3. **Measure with calipers:** + + **Outer square (part):** + - Measure actual width and height + - If part measures 49.6mm: kerf removed 0.4mm total (0.2mm per side) + - Kerf = (Designed - Measured) + - Example: 50 - 49.6 = 0.4mm kerf + + **Inner circle (hole):** + - Measure actual diameter + - If hole measures 30.4mm: kerf added 0.4mm total + - Kerf = (Measured - Designed) + - Example: 30.4 - 30 = 0.4mm kerf + +4. **Average the results:** + - Take multiple measurements (at least 3) + - Average them for accuracy + - Use this kerf value for compensation + +**Measurement tips:** +- Use digital calipers for accuracy (not a ruler) +- Measure at multiple points and average +- Ensure material has cooled (hot material may be slightly larger) +- Clean edges of test pieces before measuring + +## Typical Kerf Values + +Kerf varies by material, thickness, and cutting settings: + +| Material | Thickness | Typical Kerf | Notes | +|----------|-----------|--------------|-------| +| **Cardboard** | 1-3mm | 0.2-0.3mm | Thin, burns easily | +| **Plywood** | 3mm | 0.3-0.4mm | Standard cutting | +| **Plywood** | 6mm | 0.4-0.6mm | Thicker, wider kerf | +| **Acrylic** | 3mm | 0.2-0.3mm | Clean, narrow kerf | +| **Acrylic** | 6mm | 0.3-0.5mm | Thicker material | +| **MDF** | 3mm | 0.3-0.5mm | Dense, wider kerf | +| **Hardwood** | 3mm | 0.3-0.4mm | Varies by species | +| **Leather** | 2-3mm | 0.2-0.3mm | Soft material | + +**Factors affecting kerf:** +- **Laser power:** Higher power = wider kerf +- **Cutting speed:** Slower speed = wider kerf +- **Material density:** Denser materials = narrower kerf +- **Focus distance:** Optimal focus = narrower kerf +- **Air assist:** Strong air assist = slightly wider kerf + +**Important:** Always measure kerf for your specific material and settings. Don't rely on typical values. + +## Kerf Compensation in RayForge + +**Current implementation status:** + +RayForge may not have a dedicated built-in kerf compensation feature yet. Check your version for: + +- Workflow transformers labeled "Offset" or "Kerf" +- Operation settings with offset options +- Manual path offset tools + +**If available:** + +1. **Measure your kerf** (see above) +2. **Add kerf transformer** to workflow +3. **Enter offset value:** Half the measured kerf +4. **Select direction:** + - Outward for parts (outside cuts) + - Inward for holes (inside cuts) +5. **Apply to cutting operations** only (not engraving) + +**If not available:** Use manual compensation methods (see below). + +## Manual Kerf Compensation + +If automated kerf compensation isn't available in RayForge, compensate in your design software before import. + +### Inkscape + +**Offset path method:** + +1. **Select the path** you want to offset +2. **Path > Dynamic Offset** (or Ctrl+J) +3. **Drag the handle** to offset by half your kerf measurement + - Outward (larger) for parts + - Inward (smaller) for holes +4. **Click outside** to apply +5. **Path > Object to Path** to finalize the offset +6. **Delete original path**, keep offset path +7. **Export to SVG** for RayForge + +**Linked offset (advanced):** +- Dynamic Offset creates a live link +- You can adjust offset later by selecting and dragging handle +- Useful for testing different kerf values + +### Adobe Illustrator + +**Offset path method:** + +1. **Select the path** +2. **Object > Path > Offset Path** +3. **Enter offset value:** + - Positive value (e.g., +0.2mm) for outward offset (parts) + - Negative value (e.g., -0.2mm) for inward offset (holes) +4. **Click OK** +5. **Delete original path**, keep offset path +6. **Export to SVG** or other format + +**Tips:** +- Preview offset before applying +- Check units (mm vs inches) +- Offset creates new path, original remains (delete original) + +### Fusion 360 / CAD Software + +**Sketch offset:** + +1. **In your sketch:** Select entities to offset +2. **Use offset tool** in sketch toolbar +3. **Enter offset distance:** Half your kerf value +4. **Select direction:** Outward for parts, inward for holes +5. **Apply offset** +6. **Export DXF** with offset paths + +**Benefits of CAD offset:** +- Parametric (easy to change later) +- Precise dimensional control +- Can create offset as separate sketch for comparison + +### Manual Scaling (Simple but Inaccurate) + +**For simple rectangular parts only:** + +1. **Calculate scale factor:** + - For outside cuts: Scale up by kerf + - For inside cuts: Scale down by kerf +2. **Apply uniform scaling** to design +3. **Export** + +**Not recommended because:** +- Only works for simple shapes +- Non-uniform kerf compensation needed for complex shapes +- Corners don't offset correctly + +## Inside vs Outside Cuts + +**Determining direction:** + +**Outside cut (cutting a part):** +- Path defines the part outline +- Material outside the path is waste +- **Offset outward** (path gets larger) +- Examples: cutting a shape from a sheet, making a part + +**Inside cut (cutting a hole):** +- Path defines the hole outline +- Material inside the path is removed +- **Offset inward** (path gets smaller) +- Examples: cutting holes in a part, creating negative space + +**Complex parts with both:** +- Separate into different layers or paths +- Outside cuts: offset outward +- Inside cuts: offset inward +- Apply different compensation to each + +**Example (box with holes):** +``` +Box outline (outside): Offset +0.2mm outward +Ventilation holes (inside): Offset -0.2mm inward +``` + +## Testing Kerf Compensation + +**Verification procedure:** + +1. **Create a test assembly:** + - Part A: 50mm x 10mm tab + - Part B: 50mm x 10mm slot + - Designed to fit together snugly + +2. **Apply kerf compensation:** + - Tab (outside cut): offset outward by half kerf + - Slot (inside cut): offset inward by half kerf + +3. **Cut both parts** + +4. **Test fit:** + - Tab should fit into slot snugly + - Not too tight (can't insert) + - Not too loose (wobbles) + +5. **Adjust if needed:** + - Too tight: reduce compensation (use smaller kerf value) + - Too loose: increase compensation (use larger kerf value) + - Re-cut test parts with adjusted values + +**Iterative refinement:** +- First test gives you a baseline +- Adjust compensation based on fit +- Re-test until perfect fit achieved +- Document final kerf value for future projects + +## Advanced: Variable Kerf + +**Why kerf varies:** + +Different parts of the same design may have different effective kerf due to: + +- **Corner vs straight:** Corners may have wider kerf (laser dwells longer) +- **Power variation:** Different power settings = different kerf +- **Speed variation:** Different speeds = different kerf + +**Dealing with variable kerf:** + +1. **Test at actual settings:** Measure kerf using the exact power/speed you'll use +2. **Separate by settings:** Different layers for different power/speed combos +3. **Measure corners separately:** Some materials need different compensation at corners +4. **Iterate:** Test, measure, adjust, repeat + +**Advanced compensation:** +- Some CAD software allows variable offset along a path +- Useful for compensating corner differences +- Complex, usually not necessary for most work + +## Kerf and Multi-Pass Cutting + +**Multi-pass affects kerf:** + +- First pass: Normal kerf +- Second pass: May widen the kerf slightly (cuts into already-cut edges) +- Result: Multi-pass kerf is often slightly wider + +**Measuring multi-pass kerf:** +- Use the same number of passes you'll use in production +- Measure kerf after all passes complete +- Apply that compensation value + +## Best Practices + +1. **Always measure kerf for your setup:** + - Your machine, material, and settings are unique + - Don't rely on typical values or others' measurements + - Re-measure when changing materials or settings + +2. **Test before production:** + - Cut a test assembly to verify compensation + - Adjust based on actual fit + - Document final values for reuse + +3. **Use consistent settings:** + - Kerf changes if power/speed changes + - Keep cutting settings consistent for repeatable results + - Re-measure if you change settings + +4. **Consider material variation:** + - Different batches of same material may behave differently + - Test each new batch if precision is critical + - Keep sample test cuts for reference + +5. **When in doubt, test:** + - Cut a small test piece before committing to full job + - Verify dimensions before proceeding + - Better to waste one test piece than an entire sheet + +## Troubleshooting + +### Parts Still Wrong Size After Compensation + +**Problem:** Applied kerf compensation but parts are still incorrect dimensions. + +**Diagnosis:** +1. Measure the error: How much too big/too small? +2. Check if error matches kerf (forgot to apply?) or is different amount +3. Verify offset direction (should be outward for parts, inward for holes) + +**Solutions:** +- Re-measure kerf (may have measured incorrectly) +- Check offset direction (may be backwards) +- Verify compensation was actually applied (check paths in design software) +- Re-calculate offset (use half kerf, not full kerf) + +### Inconsistent Results + +**Problem:** Some parts fit perfectly, others don't, using same compensation. + +**Diagnosis:** +- Material thickness variation +- Laser power variation (dirty optics) +- Focus height inconsistent + +**Solutions:** +- Use more consistent material +- Clean optics before cutting +- Verify focus height is correct and consistent +- Check belt tension and mechanical components + +### Corners Don't Fit Right + +**Problem:** Straight edges fit well, but corners are too tight or loose. + +**Diagnosis:** +- Laser dwells at corners (more kerf) +- Sharp corners vs rounded corners behave differently + +**Solutions:** +- Add slight radius to sharp corners (e.g., 0.5mm fillet) +- Test corner fit specifically +- May need different compensation for corners (advanced) + +## Related Pages + +- [Overscan](overscan.md) - Related feature for raster quality +- [Contour Cutting](operations/contour.md) - Cutting operations that use kerf compensation +- [Calibrating Your Workspace](../guides/calibrating-your-workspace.md) - Dimensional accuracy +- [Power vs Speed](../concepts/power-vs-speed.md) - How settings affect kerf diff --git a/docs-site/features/macros-hooks.md b/docs-site/features/macros-hooks.md new file mode 100644 index 000000000..70e76eed3 --- /dev/null +++ b/docs-site/features/macros-hooks.md @@ -0,0 +1,459 @@ +# G-code Macros & Hooks + +RayForge provides two powerful automation features for customizing your workflow: **Macros** and **Hooks**. Both allow you to inject custom G-code into your jobs, but they serve different purposes. + +--- + +## Overview + +| Feature | Purpose | Trigger | Use Case | +|---------|---------|---------|----------| +| **Macros** | Reusable G-code snippets | Manual execution | Quick commands, test patterns, custom routines | +| **Hooks** | Automatic G-code injection | Job lifecycle events | Startup sequences, layer changes, cleanup | + +--- + +## Macros + +Macros are **named, reusable G-code scripts** that you can execute manually at any time. + +### What Are Macros For? + +Common macro use cases: + +- **Homing the machine** - Send `$H` quickly +- **Setting work offsets** - Store and recall G54/G55 positions +- **Air assist control** - Toggle air assist on/off +- **Focus testing** - Run a quick focus test pattern +- **Custom tool changes** - For multi-laser setups +- **Emergency routines** - Quick shutdown or alarm clear +- **Material probing** - Auto-focus or height measurement + +### Creating a Macro + +1. **Open Machine Settings:** + - Navigate to **Settings Machine Macros** + +2. **Add a new macro:** + - Click the **"+"** button + - Enter a descriptive name (e.g., "Home Machine", "Enable Air Assist") + +3. **Write your G-code:** + - Each line is a separate G-code command + - Comments start with `;` or `(` + - Variables can be used (see Variable Substitution below) + +4. **Save the macro** + +5. **Execute the macro:** + - From the macros list, click the macro + - Or assign a keyboard shortcut (if supported) + +### Example Macros + +#### Simple: Home the Machine + +**Name:** Home Machine +**Code:** +```gcode +$H +; Waits for homing to complete +``` + +**Use:** Quickly home the machine before starting work. + +--- + +#### Medium: Set Work Offset + +**Name:** Set G54 to Current Position +**Code:** +```gcode +G10 L20 P1 X0 Y0 +; Sets G54 work coordinate system origin to current position +``` + +**Use:** Mark the current laser position as the job origin. + +--- + +#### Advanced: Focus Test Grid + +**Name:** 9-Point Focus Test +**Code:** +```gcode +; 9-point grid for finding optimal focus +G21 ; Millimeters +G90 ; Absolute positioning +G0 X10 Y10 +M3 S1000 +G4 P0.1 +M5 +G0 X20 Y10 +M3 S1000 +G4 P0.1 +M5 +; ... (repeat for remaining points) +``` + +**Use:** Quickly test focus at different positions on the bed. + +--- + +### Macro Best Practices + +**Naming:** +- Use descriptive names: "Home Machine" not "Macro 1" +- Group related macros: "Air Assist ON", "Air Assist OFF" + +**Safety:** +- **Always** include safety checks (position limits, feedrate limits) +- Add comments explaining what each command does +- Test macros in simulation/air mode first + +**Organization:** +- Keep macros simple and focused on one task +- Create separate macros for on/off or start/stop operations +- Document required machine state (e.g., "Must be homed first") + +**Error Handling:** +- Macros don't have built-in error handling +- If a command fails, subsequent commands may still execute +- Use conservative settings to avoid crashes + +--- + +## Hooks + +Hooks are **automatic G-code injections** triggered by specific events during job execution. + +### Hook Triggers + +RayForge supports these hook triggers: + +| Trigger | When It Runs | Common Uses | +|---------|--------------|-------------| +| **Job Start** | Very beginning of the job | Homing, work offset, air assist on, preheat | +| **Job End** | Very end of the job | Return home, air assist off, beep, cooldown | +| **Layer Start** | Before processing each layer | Tool change, power adjust, comments | +| **Layer End** | After processing each layer | Progress notification, pause | +| **Workpiece Start** | Before processing each workpiece | Part numbering, alignment marks | +| **Workpiece End** | After processing each workpiece | Cooldown, inspection pause | + +### Creating a Hook + +1. **Open Machine Settings:** + - Navigate to **Settings Machine Hooks** + +2. **Select a trigger:** + - Choose the event when this hook should run + +3. **Write your G-code:** + - Hook code is injected at the trigger point + - Use variables for dynamic values (see below) + +4. **Enable/disable:** + - Toggle hooks on/off without deleting them + +### Example Hooks + +#### Job Start: Initialize Machine + +**Trigger:** Job Start +**Code:** +```gcode +G21 ; Millimeters +G90 ; Absolute positioning +$H ; Home the machine +G0 X0 Y0 ; Move to origin +M3 S0 ; Laser on but power 0 (some controllers need this) +M8 ; Air assist ON +``` + +**Purpose:** Ensures machine is in a known state before every job. + +--- + +#### Job End: Return Home and Beep + +**Trigger:** Job End +**Code:** +```gcode +M5 ; Laser OFF +M9 ; Air assist OFF +G0 X0 Y0 ; Return to origin +M300 S800 P200 ; Beep (if supported) +``` + +**Purpose:** Safely ends the job and signals completion. + +--- + +#### Layer Start: Add Comment + +**Trigger:** Layer Start +**Code:** +```gcode +; Starting layer: {layer_name} +; Layer index: {layer_index} +``` + +**Purpose:** Makes G-code more readable for debugging. + +--- + +#### Workpiece Start: Part Numbering + +**Trigger:** Workpiece Start +**Code:** +```gcode +; Part: {workpiece_name} +; Part {workpiece_index} of {total_workpieces} +``` + +**Purpose:** Track progress in multi-part jobs. + +--- + +### Hook Execution Order + +For a job with 2 layers, each with 2 workpieces: + +``` +[Job Start Hook] + [Layer Start Hook] (Layer 1) + [Workpiece Start Hook] (Workpiece 1) + ... workpiece 1 G-code ... + [Workpiece End Hook] (Workpiece 1) + [Workpiece Start Hook] (Workpiece 2) + ... workpiece 2 G-code ... + [Workpiece End Hook] (Workpiece 2) + [Layer End Hook] (Layer 1) + [Layer Start Hook] (Layer 2) + [Workpiece Start Hook] (Workpiece 3) + ... workpiece 3 G-code ... + [Workpiece End Hook] (Workpiece 3) + [Workpiece Start Hook] (Workpiece 4) + ... workpiece 4 G-code ... + [Workpiece End Hook] (Workpiece 4) + [Layer End Hook] (Layer 2) +[Job End Hook] +``` + +--- + +## Variable Substitution + +Both macros and hooks support **variable substitution** to inject dynamic values. + +### Available Variables + +Variables use `{variable_name}` syntax and are replaced during G-code generation. + +**Job-level variables:** + +| Variable | Description | Example Value | +|----------|-------------|---------------| +| `{job_name}` | Name of the current job/document | "test-job" | +| `{date}` | Current date | "2025-10-03" | +| `{time}` | Current time | "14:30:25" | + +**Layer-level variables:** + +| Variable | Description | Example Value | +|----------|-------------|---------------| +| `{layer_name}` | Name of the current layer | "Cut Layer" | +| `{layer_index}` | Zero-based index of current layer | 0, 1, 2... | +| `{total_layers}` | Total number of layers in job | 3 | + +**Workpiece-level variables:** + +| Variable | Description | Example Value | +|----------|-------------|---------------| +| `{workpiece_name}` | Name of the workpiece | "Circle 1" | +| `{workpiece_index}` | Zero-based index of current workpiece | 0, 1, 2... | +| `{total_workpieces}` | Total number of workpieces | 5 | + +**Machine variables:** + +| Variable | Description | Example Value | +|----------|-------------|---------------| +| `{machine_name}` | Name of the machine profile | "My K40" | +| `{max_speed}` | Maximum cutting speed (mm/min) | 1000 | +| `{work_width}` | Work area width (mm) | 300 | +| `{work_height}` | Work area height (mm) | 200 | + +### Example: Progress Notification + +**Hook:** Layer Start +**Code:** +```gcode +; ======================================== +; Layer {layer_index} of {total_layers}: {layer_name} +; Job: {job_name} +; Time: {time} +; ======================================== +``` + +**Result in G-code:** +```gcode +; ======================================== +; Layer 0 of 3: Cut Layer +; Job: test-project +; Time: 14:30:25 +; ======================================== +``` + +--- + +## Advanced Use Cases + +### Multi-Tool Setup + +For machines with multiple lasers or tools: + +**Hook:** Workpiece Start +**Code:** +```gcode +; Select tool for workpiece {workpiece_name} +T{tool_number} ; Tool change command (if supported) +G4 P1 ; Wait for tool change +``` + +### Conditional Pauses + +Add optional pauses for inspection: + +**Hook:** Layer End +**Code:** +```gcode +; M0 ; Uncomment to pause after each layer for inspection +``` + +### Air Assist Per Layer + +Control air assist on a per-layer basis: + +**Hook:** Layer Start (for cutting layers) +**Code:** +```gcode +M8 ; Air assist ON +``` + +**Hook:** Layer Start (for engraving layers) +**Code:** +```gcode +M9 ; Air assist OFF (prevents dust scattering for engraving) +``` + +!!! note "Layer-Specific Hooks" + RayForge doesn't currently support per-layer hook customization. To achieve this, use conditional G-code or separate machine profiles. + +--- + +## Troubleshooting + +### Macro Doesn't Execute + +**Problem:** Clicking a macro does nothing. + +**Solutions:** + +1. **Check connection** - Machine must be connected +2. **Check macro syntax** - Invalid G-code may be rejected +3. **Check machine state** - Some commands require specific states (not alarmed, homed, etc.) +4. **Check logs** - View debug logs for error messages + +### Hook Not Appearing in G-code + +**Problem:** Hook is enabled but doesn't show in generated G-code. + +**Solutions:** + +1. **Verify hook is enabled** - Check the toggle switch +2. **Regenerate G-code** - Make a small change to force regeneration +3. **Check trigger applies** - e.g., Workpiece Start requires at least one workpiece +4. **Look in the right place** - Search the G-code for hook content + +### Variables Not Substituting + +**Problem:** Variables appear as `{variable_name}` instead of values. + +**Causes:** + +1. **Typo in variable name** - Must match exactly (case-sensitive) +2. **Variable not available** - e.g., `{layer_name}` in Job Start hook (no layer yet) +3. **Escape characters** - Use `{{` to insert a literal `{` + +**Solution:** Double-check variable names against the table above. + +### G-code Syntax Errors + +**Problem:** Generated G-code has errors due to hooks/macros. + +**Diagnosis:** + +- Export G-code and review the hook injection points +- Look for: + - Missing newlines (each command should be on its own line) + - Invalid command syntax + - Commands not supported by your firmware + +**Solutions:** + +- Test hook G-code in a macro first +- Use comments liberally to identify problematic sections +- Validate against GRBL command reference + +--- + +## Safety Considerations + +!!! danger "Test Before Production" + Always test macros and hooks in **simulation mode** or with the laser **disabled** before running on real jobs. Incorrectly configured G-code can: + + - Crash the machine into limits + - Fire the laser unexpectedly + - Damage materials or equipment + +**Safety checklist:** + +- [ ] Macros include feedrate limits (`F` parameter) +- [ ] Macros check position bounds +- [ ] Job Start hooks include `M5` or laser off command +- [ ] Job End hooks turn off laser (`M5`) and air assist (`M9`) +- [ ] No destructive commands without confirmation +- [ ] Tested in simulation or with laser disabled + +--- + +## Best Practices Summary + +### Macros + +- **Keep simple** - One task per macro +- **Use comments** - Explain what each command does +- **Test thoroughly** - Verify on real hardware +- **Name clearly** - Descriptive names save time + +### Hooks + +- **Be conservative** - Hooks run on every job automatically +- **Add safety checks** - Ensure machine state is correct +- **Use variables** - Make hooks generic and reusable +- **Document triggers** - Note which hook runs when + +### Variables + +- **Verify availability** - Not all variables available at all triggers +- **Handle missing values** - Some variables may be empty +- **Test edge cases** - Single layer/workpiece jobs, empty names, etc. + +--- + +## Related Pages + +- [GRBL Settings](../machine/grbl-settings.md) - GRBL command reference +- [G-code Dialects](../reference/gcode-dialects.md) - G-code compatibility +- [Machine Setup](../machine/index.md) - Machine configuration +- [Multi-Layer Workflow](multi-layer.md) - Using hooks with layers diff --git a/docs-site/features/multi-layer.md b/docs-site/features/multi-layer.md new file mode 100644 index 000000000..b36de16df --- /dev/null +++ b/docs-site/features/multi-layer.md @@ -0,0 +1,399 @@ +# Multi-Layer Workflow + +RayForge's multi-layer system allows you to organize complex jobs into separate processing stages, each with its own operations and settings. This is essential for combining different processes like engraving and cutting, or working with multiple materials. + +## What Are Layers? + +A **layer** in RayForge is: + +- **A container** for workpieces (imported shapes, images, text) +- **A workflow** defining how those workpieces are processed +- **An execution unit** processed sequentially during jobs + +**Key concept:** Layers are processed in order, one after another, allowing you to control the sequence of operations. + +--- + +## Why Use Multiple Layers? + +### Common Use Cases + +**1. Engrave then Cut** + +The most common multi-layer workflow: + +- **Layer 1:** Raster engrave the design +- **Layer 2:** Contour cut the outline + +**Why separate layers?** +- Engraving first ensures the piece doesn't move during engraving +- Cutting last prevents pieces from falling before engraving completes +- Different power/speed settings for each operation + +**2. Multi-Pass Cutting** + +For thick materials: + +- **Layer 1:** First pass at moderate power +- **Layer 2:** Second pass at full power (same geometry) +- **Layer 3:** Optional third pass if needed + +**Benefits:** +- Reduces charring compared to single high-power pass +- Each layer can have different speed/power settings + +**3. Multi-Material Projects** + +Different materials in one job: + +- **Layer 1:** Cut acrylic parts +- **Layer 2:** Engrave wood parts +- **Layer 3:** Mark metal parts + +**Requirements:** +- Each layer targets different areas of the bed +- Different speed/power/focus for each material + +**4. Color Layer Mapping** + +Organize by color: + +- **Layer 1:** All red paths (cutting layer) +- **Layer 2:** All black paths (engraving layer) +- **Layer 3:** All blue paths (scoring layer) + +**Workflow:** +- Import SVG with color-coded paths +- RayForge can auto-assign paths to layers by color +- Each layer gets appropriate operation settings + +--- + +## Creating and Managing Layers + +### Adding a New Layer + +1. **Click the "+" button** in the Layers panel +2. **Name the layer** descriptively (e.g., "Engrave Layer", "Cut Layer") +3. **The layer appears** in the layer list + +**Default:** New documents start with one layer. + +### Layer Properties + +Each layer has: + +| Property | Description | +|----------|-------------| +| **Name** | User-facing label | +| **Visible** | Toggle visibility in canvas and preview | +| **Stock Item** | Optional material association | +| **Workflow** | The operation(s) applied to workpieces in this layer | +| **Workpieces** | The shapes/images contained in this layer | + +### Reordering Layers + +**Execution order = layer order in the list (top to bottom)** + +To reorder: + +1. **Drag and drop** layers in the Layers panel +2. **Order matters** - layers execute from top to bottom + +**Example:** +``` +Layers Panel: +1. Engrave Layer Executes first +2. Score Layer Executes second +3. Cut Layer Executes last (recommended) +``` + +### Deleting Layers + +1. **Select the layer** in the Layers panel +2. **Click the delete button** or press Delete +3. **Confirm deletion** (all workpieces in the layer are removed) + +!!! warning "Deletion is Permanent" + Deleting a layer removes all its workpieces and workflow settings. Use Undo if you delete accidentally. + +--- + +## Assigning Workpieces to Layers + +### Manual Assignment + +1. **Import or create** a workpiece +2. **Drag the workpiece** to the desired layer in the Layers panel +3. **Or use the properties panel** to change the workpiece's layer + +### Auto-Assignment by Color + +When importing SVG files: + +1. **Enable "Assign by Color"** in import settings +2. **RayForge creates layers** based on stroke/fill colors +3. **Each color** gets its own layer automatically + +**Example:** SVG with red, black, and blue paths: +- Red paths "Red Layer" +- Black paths "Black Layer" +- Blue paths "Blue Layer" + +### Moving Workpieces Between Layers + +**Drag and drop:** +- Select workpiece(s) in the canvas or Document panel +- Drag to target layer in Layers panel + +**Cut and paste:** +- Cut workpiece from current layer (Ctrl+X) +- Select target layer +- Paste (Ctrl+V) + +--- + +## Layer Workflows + +Each layer has a **Workflow** that defines how its workpieces are processed. + +### Workflow Structure + +A workflow consists of: + +1. **Producer** - Generates initial toolpaths from workpieces + - Contour, Raster, Depth Engraving, etc. + +2. **Transformers** (optional) - Modify toolpaths + - Overscan, Kerf adjustment, Tabs, etc. + +3. **Post-processing** - Final optimizations + - Path ordering, speed optimization + +### Common Layer Workflows + +**Engraving Layer:** +- Producer: Raster Engraving +- Settings: 300-500 DPI, moderate speed +- No transformers typically needed + +**Cutting Layer:** +- Producer: Contour Cutting +- Transformers: Tabs (for holding parts), Overscan (for clean edges) +- Settings: Slower speed, higher power + +**Scoring Layer:** +- Producer: Contour (without cutting through) +- Settings: Low power, fast speed +- Purpose: Fold lines, decorative lines + +--- + +## Layer Visibility + +Control which layers are shown in the canvas and previews: + +### Canvas Visibility + +- **Eye icon** in Layers panel toggles visibility +- **Hidden layers:** + - Not shown in 2D canvas + - Not shown in 3D preview + - **Still included in generated G-code** + +**Use cases:** +- Hide complex engraving layers while positioning cut layers +- Declutter the canvas when working on specific layers +- Focus on one layer at a time + +### Visibility vs. Enabled + +| State | Canvas | Preview | G-code | +|-------|--------|---------|--------| +| **Visible & Enabled** |  |  |  | +| **Hidden & Enabled** |  |  |  | +| **Visible & Disabled** |  |  |  | +| **Hidden & Disabled** |  |  |  | + +!!! note "Disabling Layers" + To temporarily exclude a layer from jobs without deleting it, disable the layer's workflow or remove its operation. + +--- + +## Layer Execution Order + +### How Layers are Processed + +During job execution: + +``` +FOR each layer (in order): + [Layer Start Hook] (if configured) + + FOR each workpiece in layer: + [Workpiece Start Hook] (if configured) + ... execute workpiece operations ... + [Workpiece End Hook] (if configured) + + [Layer End Hook] (if configured) +``` + +### Order Matters + +**Wrong order:** +``` +1. Cut Layer +2. Engrave Layer +``` +**Problem:** Cut parts may fall out or move before engraving! + +**Correct order:** +``` +1. Engrave Layer +2. Cut Layer +``` +**Why:** Engraving happens while part is still attached, then cutting frees it. + +### Multiple Passes + +For thick materials, create multiple cutting layers: + +``` +1. Engrave Layer +2. Cut Layer (Pass 1) - 50% power +3. Cut Layer (Pass 2) - 75% power +4. Cut Layer (Pass 3) - 100% power +``` + +**Tip:** Use the same geometry for all cutting passes (duplicate the layer). + +--- + +## Advanced Techniques + +### Layer Grouping by Material + +Use layers to organize by material when running mixed jobs: + +``` +Material 1 (3mm Acrylic): + - Acrylic Engrave Layer + - Acrylic Cut Layer + +Material 2 (3mm Plywood): + - Wood Engrave Layer + - Wood Cut Layer +``` + +**Workflow:** +1. Process all Material 1 layers +2. Swap materials +3. Process all Material 2 layers + +**Alternative:** Use separate documents for different materials. + +### Conditional Layer Processing + +**Using hooks for layer control:** + +Layer Start Hook: +```gcode +; Layer: {layer_name} +M0 (Pause for material change) +``` + +**Use case:** Pause between layers to inspect, adjust focus, or change materials. + +### Layer-Specific Settings + +Each layer's workflow can have unique settings: + +| Layer | Operation | Speed | Power | Passes | +|-------|-----------|-------|-------|--------| +| Engrave | Raster | 300 mm/min | 20% | 1 | +| Score | Contour | 500 mm/min | 10% | 1 | +| Cut | Contour | 100 mm/min | 90% | 2 | + +--- + +## Best Practices + +### Naming Conventions + +**Good layer names:** +- "Engrave - Logo" +- "Cut - Outer Contour" +- "Score - Fold Lines" +- "Pass 1 - Rough Cut" +- "Pass 2 - Final Cut" + +**Poor layer names:** +- "Layer 1", "Layer 2" (not descriptive) +- Long descriptions (keep concise) + +### Layer Organization + +1. **Top to bottom = execution order** +2. **Engraving before cutting** (general rule) +3. **Group related operations** (all cutting, all engraving) +4. **Use visibility** to focus on current work +5. **Delete unused layers** to keep projects clean + +### Performance + +**Many layers:** +- No significant performance impact +- 10-20 layers is common for complex jobs +- Organize logically, not to minimize layer count + +**Simplify if needed:** +- Combine similar operations into one layer when possible +- Use fewer raster engravings (most resource-intensive) + +--- + +## Troubleshooting + +### Layer Not Generating G-code + +**Problem:** Layer appears in document but not in generated G-code. + +**Solutions:** + +1. **Check layer has workpieces** - Empty layers are skipped +2. **Check workflow is configured** - Layer needs an operation +3. **Verify operation settings** - Power > 0, valid speed, etc. +4. **Check workpiece visibility** - Hidden workpieces may not process +5. **Regenerate G-code** - Make a small change to force regeneration + +### Wrong Layer Order + +**Problem:** Operations execute in unexpected order. + +**Solution:** Reorder layers in the Layers panel. Remember: top = first. + +### Layers Overlapping in Preview + +**Problem:** Multiple layers show overlapping content in preview. + +**Clarification:** This is normal if layers share the same XY area. + +**Solutions:** +- Use layer visibility to hide other layers temporarily +- Check 3D preview to see depth/order +- Verify this is intentional (e.g., engraving then cutting same shape) + +### Workpiece in Wrong Layer + +**Problem:** Workpiece was assigned to incorrect layer. + +**Solution:** Drag workpiece to correct layer in Layers panel or Document tree. + +--- + +## Related Pages + +- [Operations](operations/index.md) - Operation types for layer workflows +- [Simulation Mode](simulation-mode.md) - Preview multi-layer execution +- [Macros & Hooks](macros-hooks.md) - Layer-level hooks for automation +- [3D Preview](../ui/3d-preview.md) - Visualize layer stack diff --git a/docs-site/features/operations/contour.md b/docs-site/features/operations/contour.md new file mode 100644 index 000000000..40103a618 --- /dev/null +++ b/docs-site/features/operations/contour.md @@ -0,0 +1,336 @@ +# Contour Cutting + +Contour cutting traces the outline of vector shapes to cut them free from material. It's the most common laser operation for creating parts, signs, and decorative pieces. + +## Overview + +Contour operations: + +- Follow vector paths (lines, curves, shapes) +- Cut along the perimeter of objects +- Support single or multiple passes for thick materials +- Can use inside, outside, or on-line cutting paths +- Work with any closed or open vector shape + + + +![Contour cutting example](../../images/Ref-Contour-Example.png) + +## When to Use Contour + +Use contour cutting for: + +- Cutting parts free from stock material +- Creating outlines and borders +- Cutting shapes from wood, acrylic, cardboard +- Perforating or scoring (with reduced power) +- Creating stencils and templates + +**Don't use contour for:** +- L Filling areas (use [Raster](raster.md) instead) +- L Creating 3D depth effects (use [Depth Engraving](depth.md) instead) +- L Bitmap images (convert to vectors first) + +## Creating a Contour Operation + +### Step 1: Select Objects + +1. Import or draw vector shapes on the canvas +2. Select the objects you want to cut +3. Ensure shapes are closed paths for complete cuts + +### Step 2: Add Contour Operation + +- **Menu:** Operations Add Contour +- **Shortcut:** ++ctrl+shift+c++ +- **Right-click:** Context menu Add Operation Contour + +### Step 3: Configure Settings + + + +![Contour settings](../../images/UI-Contour-Settings.png) + +## Key Settings + +### Power & Speed + +**Power (%):** +- Laser intensity from 0-100% +- Higher power for thicker materials +- Lower power for scoring or marking + +**Speed (mm/min):** +- How fast the laser moves +- Slower = more energy = deeper cut +- Faster = less energy = lighter cut + +**Starting values (3mm plywood):** +- Power: 70-90% +- Speed: 300-600 mm/min +- Always test on scrap material first! + +### Multi-Pass Cutting + +For materials thicker than a single pass can cut: + +**Passes:** +- Number of times to repeat the cut +- Each pass cuts deeper +- Typical: 1-3 passes for 3mm material + +**Pass Depth (Z-step):** +- How much to lower Z-axis per pass (if supported) +- Requires Z-axis control on your machine +- Creates true 2.5D cutting +- Set to 0 for same-depth multiple passes + +**Example for 6mm plywood:** +- Passes: 3 +- Pass depth: 2mm per pass +- Result: Cuts 6mm total depth + +!!! warning "Z-Axis Required" + Pass depth only works if your machine has Z-axis control. For machines without Z-axis, use multiple passes at the same depth. + +### Path Offset + +Controls where the laser cuts relative to the vector path: + +| Offset | Description | Use For | +|--------|-------------|---------| +| **On Line** | Cuts directly on the path | Centerline cuts, scoring | +| **Inside** | Cuts inside the shape | Parts that must fit exact size | +| **Outside** | Cuts outside the shape | Holes that parts fit into | + +**Offset Distance:** +- How far inside/outside to offset (mm) +- Typically set to half your kerf width +- Kerf = width of material removed by laser +- Example: 0.15mm offset for 0.3mm kerf + + + +![Path offset diagram](../../images/Diag-Contour-PathOffset.png) + +### Cut Direction + +**Clockwise vs Counter-Clockwise:** +- Affects which side of the cut gets more heat +- Usually clockwise for right-hand rule +- Change if one side burns more than the other + +**Optimize Order:** +- Automatically sorts paths for minimum travel +- Reduces job time +- Prevents missed cuts + +## Advanced Features + +### Holding Tabs + +Tabs keep cut pieces attached to stock material during cutting: + +- Add tabs to prevent pieces from falling +- Tabs are small uncut sections +- Break tabs after job completes +- See [Holding Tabs](../holding-tabs.md) for details + + + +![Contour with holding tabs](../../images/Ref-Contour-HoldingTabs.png) + +### Kerf Compensation + +Kerf is the width of material removed by the laser beam: + +**Why it matters:** +- A circle cut "on line" will be slightly smaller than designed +- The laser removes ~0.2-0.4mm of material (depending on beam width) + +**How to compensate:** +1. Measure your kerf on test cuts +2. Use path offset = kerf/2 +3. For parts: offset **inside** by kerf/2 +4. For holes: offset **outside** by kerf/2 + +See [Overscan & Kerf](../overscan-kerf.md) for detailed guide. + +### Lead-In/Lead-Out + +Lead-ins and lead-outs control where cuts start and end: + +**Lead-in:** +- Gradual entry to the cut +- Prevents burn marks at start point +- Moves laser to full speed before hitting the material edge + +**Lead-out:** +- Gradual exit from the cut +- Prevents damage at end point +- Common for metals and acrylics + +**Configuration:** +- Length: How far the lead extends (mm) +- Angle: Direction of the lead path +- Type: Straight line, arc, or spiral + +## Tips & Best Practices + +### Material Testing + + **Always test first:** +1. Cut small test shapes on scrap +2. Start with conservative settings (lower power, slower speed) +3. Gradually increase power or decrease speed +4. Record successful settings + +### Cutting Order + + **Best practices:** +- Engrave before cutting (keeps material secured) +- Cut inside features before outside perimeter +- Use holding tabs for parts that might move +- Cut smallest parts first (less vibration) + +### Quality Cutting + + **For clean cuts:** +- Use air assist (blows debris away) +- Ensure proper focus (sharp beam = clean cut) +- Multiple faster passes often better than one slow pass +- Keep material flat and secured + +  **Avoid:** +- Cutting at maximum power (creates excessive charring) +- Single slow pass (more heat = more burning) +- Skipping material tests +- Cutting warped or unsecured material + +### Common Materials + +| Material | Thickness | Power | Speed | Passes | Notes | +|----------|-----------|-------|-------|--------|-------| +| Paper | 0.2mm | 10-20% | 3000+ mm/min | 1 | Very fast | +| Cardboard | 3mm | 40-60% | 1500-2500 mm/min | 1 | Test for char | +| Plywood | 3mm | 70-90% | 300-600 mm/min | 1-2 | Use air assist | +| Acrylic | 3mm | 80-95% | 200-400 mm/min | 1-2 | Slow for clean edges | +| MDF | 3mm | 70-85% | 400-700 mm/min | 1-2 | Very dusty | + +*Settings vary by laser type, power, and beam quality. Always test!* + +## Troubleshooting + +### Cuts not going through material + +- **Increase:** Power setting +- **Decrease:** Speed setting +- **Add:** More passes +- **Check:** Focus is correct +- **Check:** Beam is clean (dirty lens) + +### Excessive charring or burning + +- **Decrease:** Power setting +- **Increase:** Speed setting +- **Use:** Air assist +- **Try:** Multiple faster passes instead of one slow +- **Check:** Material is appropriate for laser cutting + +### Parts fall out during cutting + +- **Add:** [Holding tabs](../holding-tabs.md) +- **Use:** Cutting order optimization +- **Cut:** Inside features before outside +- **Ensure:** Material is flat and secured + +### Inconsistent cut depth + +- **Check:** Material thickness is uniform +- **Check:** Material is flat (not warped) +- **Check:** Focus distance is consistent +- **Verify:** Laser power is stable + +### Missed corners or curves + +- **Decrease:** Speed (especially on corners) +- **Check:** Machine acceleration settings +- **Verify:** Belts are tight +- **Reduce:** Path complexity (simplify curves) + +## Technical Details + +### Coordinate System + +Contour operations work in: +- **Units:** Millimeters (mm) +- **Origin:** Depends on machine and job setup +- **Coordinates:** X/Y plane (Z for multi-pass depth) + +### Path Generation + +RayForge converts vector shapes to G-code: + +1. Offset path (if inside/outside cutting) +2. Optimize path order (minimize travel) +3. Insert lead-in/lead-out (if configured) +4. Add holding tabs (if configured) +5. Generate G-code commands + +### G-code Commands + +Typical contour G-code: +```gcode +G0 X10 Y10 ; Rapid move to start +M3 S204 ; Laser on at 80% power +G1 X50 Y10 F500 ; Cut to point at 500 mm/min +G1 X50 Y50 F500 ; Cut to next point +G1 X10 Y50 F500 ; Continue cutting +G1 X10 Y10 F500 ; Complete the square +M5 ; Laser off +``` + +## Related Topics + +- **[Raster Engraving](raster.md)** - Filling areas with engraving patterns +- **[Depth Engraving](depth.md)** - Creating 3D relief effects +- **[Holding Tabs](../holding-tabs.md)** - Keeping parts secured during cutting +- **[Overscan & Kerf](../overscan-kerf.md)** - Improving cut quality and accuracy +- **[Material Test Grid](material-test-grid.md)** - Finding optimal power/speed settings diff --git a/docs-site/features/operations/depth.md b/docs-site/features/operations/depth.md new file mode 100644 index 000000000..19c9ba460 --- /dev/null +++ b/docs-site/features/operations/depth.md @@ -0,0 +1,410 @@ +# Depth Engraving + +Depth engraving creates 3D relief effects by varying laser power based on image brightness. It's used for creating dimensional artwork, terrain maps, lithophanes, and embossed designs. + +## Overview + +Depth engraving operations: + +- Vary laser power to create different engraving depths +- Work from grayscale images or height maps +- Create 3D relief effects on wood, acrylic, and coated materials +- Support multiple passes for deeper carving +- Produce tactile, three-dimensional results + + + +![Depth engraving example](../../images/Ref-Depth-Example.png) + +## When to Use Depth Engraving + +Use depth engraving for: + +- Creating 3D portraits and artwork +- Terrain and topographic maps +- Lithophanes (light-transmitting 3D images) +- Embossed logos and designs +- Textured surfaces and patterns +- Mold masters for casting + +**Don't use depth for:** +- L Simple flat engraving (use [Raster](raster.md) instead) +- L Cutting through material (use [Contour](contour.md)) +- L Text and line art (better with raster) + +## How Depth Engraving Works + +### Power-to-Depth Relationship + +The laser engraves deeper with higher power: + +- **Low power** (lighter pixels) Shallow engraving +- **Medium power** (medium pixels) Medium depth +- **High power** (dark pixels) Deep engraving + +**Image brightness to depth:** +``` +White pixel 0% power No engraving +Light gray 25% power Light engraving +Medium gray 50% power Medium depth +Dark gray 75% power Deep engraving +Black pixel 100% power Maximum depth +``` + +### Scanning Pattern + +Like raster engraving, depth uses scanning lines: +- Back-and-forth horizontal passes +- Power varies along each line based on image +- Creates smooth gradients and transitions + +## Creating a Depth Operation + +### Step 1: Prepare Image + +1. **Convert to grayscale** - Remove all color +2. **Adjust levels** - Increase contrast for more dramatic depth +3. **Invert if needed** - White=high, Black=low (or vice versa) +4. **Resize** - Match your desired output size + +**Image tips:** +- Higher contrast = more dramatic depth changes +- Smooth gradients = smooth 3D surfaces +- Sharp edges = steep depth transitions + +### Step 2: Import and Add Operation + +1. Import your grayscale image +2. Select the image +3. **Menu:** Operations Add Depth Engraving +4. **Shortcut:** ++ctrl+shift+d++ + +### Step 3: Configure Settings + + + +![Depth settings](../../images/UI-Depth-Settings.png) + +## Key Settings + +### Power Range + +**Minimum Power (%):** +- Laser power for lightest areas (white pixels) +- Usually 0-20% +- Set higher to avoid very shallow areas + +**Maximum Power (%):** +- Laser power for darkest areas (black pixels) +- Usually 40-80% depending on material +- Lower = subtle relief, higher = dramatic depth + +**Power Range Examples:** + +| Min | Max | Effect | +|-----|-----|--------| +| 0% | 40% | Subtle, light relief | +| 10% | 60% | Medium depth, safe | +| 20% | 80% | Deep, dramatic relief | + +**Start conservative:** +- Test with 10-50% range +- Increase max power for more depth +- Increase min power to avoid unengraved areas + +### Speed + +**Speed (mm/min):** +- How fast the laser scans +- Slower = deeper engraving at same power +- Typical: 1500-3000 mm/min + +**Speed vs Depth:** +- Half the speed = roughly double the depth +- Very slow speeds can char or burn +- Test to find optimal speed for material + +### Line Interval + +**Line Interval (mm):** +- Spacing between scan lines +- Smaller = smoother 3D surface +- Typical: 0.05-0.15mm + +**For depth engraving:** +- Use finer intervals than normal raster (0.05-0.08mm) +- Smooth 3D surfaces need close line spacing +- Visible lines create ribbed texture + +### Multiple Passes + +**Passes:** +- Number of times to repeat the engraving +- Each pass adds more depth +- Typical: 1-3 passes + +**Why multiple passes?** +- Safer (less risk of burning) +- Deeper total depth +- More consistent results +- Better for hard materials + +**Single pass vs multiple:** +- 1 pass at 80% power +- OR 2 passes at 50% power Usually better + +### Invert + +**Invert Image:** +- **Enabled:** White = deep, Black = shallow +- L **Disabled:** Black = deep, White = shallow (default) + +Use invert for: +- Lithophanes (light areas should be thin) +- Embossing (raised areas) +- Inverted height maps + +## Material Considerations + +### Best Materials + +**Excellent for depth:** +- **Wood** - Natural, forgiving, good depth range +- **Acrylic** - Clean results, good for lithophanes +- **Leather** - Creates beautiful embossed effects +- **Coated materials** - Removes coating in varying depths + +**Challenging:** +- **Metals** - Require marking compounds +- **Glass** - Difficult without special coatings +- **Very hard plastics** - May require high power + +### Material-Specific Tips + +**Wood:** +- Start with 10-50% power range +- Softwoods engrave deeper than hardwoods +- Watch for grain direction affecting depth +- Multiple light passes better than single heavy pass + +**Acrylic (for lithophanes):** +- Use 3-6mm thick clear acrylic +- Engrave from back, light shines through front +- Thinner = more light, thicker = darker +- Power controls remaining thickness +- Invert image (white = thin, black = thick) + +**Leather:** +- Very forgiving material +- 15-40% power range typical +- Creates beautiful embossed look +- Test on scrap (each leather type differs) + +## Tips & Best Practices + +### Image Preparation + + **For best results:** +- Use high-resolution images (300+ DPI) +- Increase contrast before engraving +- Blur sharp edges for smooth transitions +- Remove noise (creates unwanted texture) +- Test on small area first + + **Adjusting images:** +- **Too flat** Increase contrast +- **Too much depth** Decrease contrast +- **Rough surface** Apply slight blur +- **Missing detail** Sharpen slightly + +### Testing Strategy + +1. **Small test square** - 20mm 20mm area +2. **Power range test** - Try 10-40%, then adjust +3. **Speed test** - Try 2000-3000 mm/min +4. **Line interval test** - 0.05mm vs 0.1mm +5. **Scale up** - Use successful settings for full image + +### Quality Settings + + **For highest quality:** +- Line interval: 0.05-0.08mm +- Multiple passes (2-3) at lower power +- Slower speed (1500-2000 mm/min) +- Disable bidirectional scanning +- Material must be perfectly flat + + **For faster results:** +- Line interval: 0.1-0.15mm +- Single pass at higher power +- Faster speed (3000-4000 mm/min) +- Enable bidirectional scanning + +### Common Issues + +**Uneven depth:** +- Material not flat secure better +- Focus incorrect adjust focus +- Power unstable check laser + +**Too shallow:** +- Increase max power +- Decrease speed +- Add more passes +- Use softer material + +**Burning or charring:** +- Decrease max power +- Increase speed +- Use more passes at lower power +- Improve ventilation + +**Ribbed/lined surface:** +- Decrease line interval +- Check that material is flat +- Try different scan angle + +## Advanced Techniques + +### Lithophanes + +Lithophanes are 3D images viewed by backlighting: + +**Process:** +1. Use clear acrylic (3-6mm thick) +2. Engrave from **back** side +3. **Invert** the image (white = thin) +4. Power controls remaining thickness +5. View from front with backlight + +**Settings for lithophanes:** +- Power range: 20-70% +- Line interval: 0.05mm +- Multiple passes: 2-3 +- Very important: material must be flat + +### Terrain Maps + +Create 3D topographic maps: + +**Process:** +1. Get height map (white = high, black = low) +2. Increase contrast for dramatic relief +3. Use 10-60% power range +4. Fine line interval (0.05-0.08mm) + +### Combining with Contour + +Add depth engraving inside a contour cut: + +**Workflow:** +1. Depth engrave the image +2. Contour cut around the perimeter +3. Result: 3D relief plaque that's cut free + +See [Multi-Layer Workflow](../multi-layer.md) for details. + +## Troubleshooting + +### Image looks flat, no depth + +- **Increase:** Max power setting +- **Increase:** Contrast in source image +- **Try:** More passes +- **Check:** Material is suitable for depth + +### Surface is rough or textured + +- **Decrease:** Line interval (try 0.05mm) +- **Apply:** Blur to source image +- **Reduce:** Power (over-burning creates rough texture) +- **Try:** Different scan angle + +### Inconsistent depth across image + +- **Check:** Material is flat and secured +- **Check:** Focus is consistent across area +- **Verify:** Laser power is stable +- **Try:** Smaller area (check if issue persists) + +### Burning at dark areas + +- **Decrease:** Max power +- **Increase:** Speed +- **Use:** Multiple passes instead of one +- **Improve:** Ventilation/air assist + +### Image is backwards + +- **Flip:** Source image horizontally +- **Or:** Engrave from opposite side +- **Check:** If creating lithophane, engrave from back + +## Technical Details + +### Power Modulation + +Depth engraving uses PWM (Pulse Width Modulation): +- Laser power varies continuously along scan lines +- Each pixel gets proportional power +- Smooth gradients require many power levels + +### Grayscale to Power Mapping + +**Linear mapping:** +``` +power = min_power + (pixel_value / 255) (max_power - min_power) +``` + +**For inverted:** +``` +power = min_power + ((255 - pixel_value) / 255) (max_power - min_power) +``` + +### Resolution + +**Image resolution affects quality:** +- 254 DPI = 10 pixels/mm use d0.1mm line interval +- 508 DPI = 20 pixels/mm use d0.05mm line interval + +Higher resolution images can produce finer detail. + +## Related Topics + +- **[Raster Engraving](raster.md)** - Flat engraving with scanning lines +- **[Contour Cutting](contour.md)** - Cutting around depth-engraved pieces +- **[Multi-Layer Workflow](../multi-layer.md)** - Combining depth with other operations +- **[Material Test Grid](material-test-grid.md)** - Finding optimal power/speed settings +- **[Overscan & Kerf](../overscan-kerf.md)** - Improving engraving quality diff --git a/docs-site/features/operations/index.md b/docs-site/features/operations/index.md new file mode 100644 index 000000000..68a1eb81e --- /dev/null +++ b/docs-site/features/operations/index.md @@ -0,0 +1,206 @@ +# Operations + +Operations define how Rayforge processes your designs. Each operation type converts vector paths or raster images into toolpaths optimized for specific laser tasks. + +## Operation Workflow + +```mermaid +graph TB + A[Select Objects] --> B{Choose Operation} + B --> C[Contour] + B --> D[Raster] + B --> E[Depth] + B --> F[Shrink Wrap] + + C --> G[Configure Settings
Power, Speed, Passes] + D --> G + E --> G + F --> G + + G --> H[Preview 3D Toolpath] + H --> I{Looks Good?} + I -->|No| G + I -->|Yes| J[Generate G-code] + + style C fill:#e3f2fd + style D fill:#fff3e0 + style E fill:#f3e5f5 + style F fill:#e8f5e9 + style J fill:#c8e6c9 +``` + +## Operation Types + +Rayforge supports four main operation types: + +### [Contour Cutting](contour.md) + +Cut along the outline of shapes and paths. + +**Best For:** + +- Cutting out shapes and profiles +- Through-cutting materials +- Creating precise outlines +- Die-cutting and stencils + +**Key Features:** + +- Multi-pass cutting for thick materials +- Kerf compensation for dimensional accuracy +- Holding tabs to keep pieces in place +- Lead-in/lead-out for smooth starts and stops + +### [Raster Engraving](raster.md) + +Fill areas with back-and-forth engraving lines (bi-directional scanning). + +**Best For:** + +- Engraving photos and images +- Filling large areas +- Wood and leather engraving +- Creating textures and patterns + +**Key Features:** + +- Overscan to eliminate endpoint burn marks +- Cross-hatch fill for consistent coverage +- Variable power based on image brightness +- Line interval (spacing) control + +### [Depth Engraving](depth.md) + +Create 3D relief effects by varying power based on image brightness. + +**Best For:** + +- 3D effects on acrylic or coated metals +- Grayscale photo engraving with depth +- Embossing effects +- Relief sculptures + +**Key Features:** + +- Depth mapping from image brightness +- Configurable min/max depth +- Smooth gradients +- Compatible with grayscale images + +### [Shrink Wrap](shrink-wrap.md) + +Create efficient cutting paths around multiple objects. + +**Best For:** + +- Cutting around grouped objects +- Waste reduction +- Efficient material usage +- Quick outline cuts + +**Key Features:** + +- Automatic hull calculation +- Configurable offset distance +- Combines multiple objects into single path + +## Operation Workflow + +### 1. Select Objects + +Select one or more objects on the canvas that you want to apply the operation to. + +### 2. Add Operation + +- **Menu**: Operations → Add Operation +- **Keyboard**: ++ctrl+shift+a++ +- **Context menu**: Right-click → Add Operation + +### 3. Configure Settings + +Each operation type has specific settings: + +- **Power**: Laser power percentage (0-100%) +- **Speed**: Movement speed (mm/min) +- **Passes**: Number of times to repeat the operation +- **Advanced options**: Varies by operation type + +### 4. Preview + +Use the 3D preview (++ctrl+3++) to visualize the toolpath before sending to your machine. + +### 5. Generate G-code + +When ready, generate G-code (++ctrl+g++) to create machine instructions. + +## Operation Settings + +### Common Settings + +These settings are available for all operation types: + +| Setting | Description | Typical Range | +|:--------|:------------|:--------------| +| **Name** | Operation identifier | Any text | +| **Power** | Laser power percentage | 0-100% | +| **Speed** | Feed rate in mm/min | 100-6000 mm/min | +| **Passes** | Number of repetitions | 1-10 | +| **Enabled** | Enable/disable operation | On/Off | +| **Layer** | Assign to specific layer | Layer 1-10 | + +### Advanced Settings + +Additional settings vary by operation type: + +- **Contour**: Kerf, tabs, lead-in/lead-out +- **Raster**: Overscan, line interval, angle +- **Depth**: Min/max depth, smoothing +- **Shrink Wrap**: Offset distance, segments + +## Operation Order + +Operations execute in the order they appear in the layers panel. Reorder operations by dragging them up or down. + +**Best Practice Order:** + +1. **Engraving operations** (Raster, Depth) +2. **Scoring operations** (Light contour cuts) +3. **Through-cutting operations** (Contour with full power) + +!!! tip "Why this order?" + Engraving first ensures the material stays in place. Cutting last prevents pieces from moving during earlier operations. + +## Tips for Success + +### Power and Speed + +Start conservative and increase gradually: + +- **Too fast/low power**: Incomplete cuts, light engraving +- **Too slow/high power**: Charring, melted edges, fire risk + +### Multiple Passes + +Use multiple passes for: + +- Thick materials that won't cut in one pass +- Achieving deeper engraving +- Better edge quality on sensitive materials + +### Testing + +Always test on scrap material: + +1. Create a small test pattern +2. Try different power/speed combinations +3. Document successful settings for future jobs +4. Keep a material library with proven settings + +--- + +Explore each operation type for detailed information and examples: + +- **[Contour Cutting →](contour.md)** +- **[Raster Engraving →](raster.md)** +- **[Depth Engraving →](depth.md)** +- **[Shrink Wrap →](shrink-wrap.md)** diff --git a/docs-site/features/operations/material-test-grid.md b/docs-site/features/operations/material-test-grid.md new file mode 100644 index 000000000..8d319a550 --- /dev/null +++ b/docs-site/features/operations/material-test-grid.md @@ -0,0 +1,335 @@ +# Material Test Grid + +The Material Test Grid generator creates parametric test patterns to help you find optimal laser settings for different materials. Instead of manually creating test squares, RayForge automatically generates a grid with varying speed and power combinations. + +## Overview + +Material testing is essential for laser work - different materials require different power and speed settings. The Material Test Grid automates this process by: + +- Generating test grids with configurable speed/power ranges +- Providing presets for common laser types (Diode, CO2) +- Optimizing execution order for safety (fastest speeds first) +- Adding labels to identify each test cell's settings + + + +![Material test grid example](../../images/Ref-MaterialTestGrid-Example.png) + +## Creating a Material Test Grid + +### Step 1: Open the Generator + +Access the Material Test Grid generator: + +- Menu: **Tools → Material Test Grid** +- This creates a special workpiece that generates the test pattern + +### Step 2: Choose a Preset (Optional) + +RayForge includes presets for common scenarios: + +| Preset | Speed Range | Power Range | Use For | +|--------|-------------|-------------|---------| +| **Diode Engrave** | 1000-10000 mm/min | 10-100% | Diode laser engraving | +| **Diode Cut** | 100-5000 mm/min | 50-100% | Diode laser cutting | +| **CO2 Engrave** | 3000-20000 mm/min | 10-50% | CO2 laser engraving | +| **CO2 Cut** | 1000-20000 mm/min | 30-100% | CO2 laser cutting | + +Presets are starting points - you can adjust all parameters after selecting one. + + + +![Material test grid presets](../../images/UI-MaterialTestGrid-Presets.png) + +### Step 3: Configure Parameters + +Adjust the test grid parameters: + +#### Test Type +- **Engrave**: Fills squares with raster pattern +- **Cut**: Cuts outline of squares + +#### Speed Range +- **Min Speed**: Slowest speed to test (mm/min) +- **Max Speed**: Fastest speed to test (mm/min) +- Columns in grid represent different speeds + +#### Power Range +- **Min Power**: Lowest power to test (%) +- **Max Power**: Highest power to test (%) +- Rows in grid represent different power levels + +#### Grid Dimensions +- **Columns**: Number of speed variations (typically 3-7) +- **Rows**: Number of power variations (typically 3-7) + +#### Size & Spacing +- **Shape Size**: Size of each test square in mm (default: 20mm) +- **Spacing**: Gap between squares in mm (default: 5mm) + +#### Labels +- **Include Labels**: Enable/disable axis labels showing speed and power values +- Labels appear on left and top edges +- Labels are engraved at 10% power, 1000 mm/min + + + +![Material test grid settings](../../images/UI-MaterialTestGrid-SettingsDialog.png) + +### Step 4: Generate the Grid + +Click **Generate** to create the test pattern. The grid appears on your canvas as a special workpiece. + +## Understanding the Grid Layout + +### Grid Organization + +``` +Power (%) Speed (mm/min) → + ↓ 1000 2500 5000 7500 10000 + 100% [ ] [ ] [ ] [ ] [ ] + 75% [ ] [ ] [ ] [ ] [ ] + 50% [ ] [ ] [ ] [ ] [ ] + 25% [ ] [ ] [ ] [ ] [ ] + 10% [ ] [ ] [ ] [ ] [ ] +``` + +- **Columns**: Speed increases from left to right +- **Rows**: Power increases from bottom to top +- **Labels**: Show exact values for each row/column + +### Grid Size Calculation + +**Without labels:** +- Width = columns × (shape_size + spacing) - spacing +- Height = rows × (shape_size + spacing) - spacing + +**With labels:** +- Add 15mm margin to left and top for label space + +**Example:** 5×5 grid with 20mm squares and 5mm spacing: +- Without labels: 120mm × 120mm +- With labels: 135mm × 135mm + +## Execution Order (Risk Optimization) + +RayForge executes test cells in a **risk-optimized order** to prevent material damage: + +1. **Highest speed first**: Fast speeds are safer (less heat buildup) +2. **Lowest power within speed**: Minimizes risk at each speed level + +This prevents charring or fire from starting with slow, high-power combinations. + +**Example execution order for 3×3 grid:** +``` +Order: 1 2 3 + 4 5 6 ← Highest speed, power increasing + 7 8 9 + +(Fastest speed/lowest power executed first) +``` + +## Using Material Test Results + +### Step 1: Run the Test + +1. Load your material in the laser +2. Focus the laser properly +3. Run the material test grid job +4. Monitor the test - stop if any cell causes problems + +### Step 2: Evaluate Results + +After the test completes, examine each cell: + +- **Too light**: Increase power or decrease speed +- **Too dark/charred**: Decrease power or increase speed +- **Perfect**: Note the speed/power combination + +### Step 3: Record Settings + +Create a material settings reference: + +| Material | Thickness | Operation | Speed | Power | Notes | +|----------|-----------|-----------|-------|-------|-------| +| Birch Plywood | 3mm | Engrave | 5000 mm/min | 40% | Perfect contrast | +| Birch Plywood | 3mm | Cut | 500 mm/min | 80% | 2 passes | +| Acrylic (clear) | 3mm | Cut | 300 mm/min | 90% | Clean edge | + +!!! tip "Material Database" + Consider creating a material library in the [Collections](../../collections/material-library.md) section for quick reference. + +## Advanced Usage + +### Combining with Other Operations + +Material test grids are regular workpieces - you can combine them with other operations: + +**Example workflow:** +1. Create material test grid +2. Add contour cut around the entire grid +3. Run test, cut free, evaluate results + +This is useful for cutting the test piece free from stock material. + +### Custom Test Ranges + +For fine-tuning, create narrow-range tests: + +**Coarse test** (find ballpark): +- Speed: 1000-10000 mm/min (5 columns) +- Power: 10-100% (5 rows) + +**Fine test** (optimize): +- Speed: 4000-6000 mm/min (5 columns) +- Power: 35-45% (5 rows) + +### Different Materials, Same Grid + +Run the same grid configuration on different materials to build your material library faster. + +## Tips & Best Practices + +### Grid Design + +✅ **Start with presets** - Good starting points for common scenarios +✅ **Use 5×5 grids** - Good balance of detail and test time +✅ **Enable labels** - Essential for identifying results +✅ **Keep squares ≥20mm** - Easier to see and measure results + +### Testing Strategy + +✅ **Test scrap first** - Never test on final material +✅ **One variable at a time** - Test speed OR power range, not both extremes +✅ **Allow cooldown** - Wait between tests on same material +✅ **Consistent focus** - Same focus distance for all tests + +### Safety + +⚠️ **Monitor tests** - Never leave running tests unattended +⚠️ **Start conservative** - Begin with lower power ranges +⚠️ **Check ventilation** - Ensure proper fume extraction +⚠️ **Fire watch** - Have fire extinguisher ready + +## Troubleshooting + +### Grid doesn't appear on canvas + +- **Check**: Make sure you clicked "Generate" in the settings dialog +- **Check**: Zoom out - the grid might be outside the visible area +- **Try**: Use **View → Zoom to Fit** (++ctrl+0++) + +### Labels are missing + +- **Check**: "Include Labels" checkbox is enabled +- **Check**: Labels extend beyond the grid - zoom out to see them +- **Note**: Labels add 15mm margin to left and top + +### Test cells execute in wrong order + +- RayForge uses risk-optimized order (fastest speeds first) +- This is intentional and cannot be changed +- See [Execution Order](#execution-order-risk-optimization) above + +### Grid is too large for material + +- **Reduce**: Number of columns/rows +- **Reduce**: Shape size (try 15mm or 10mm) +- **Reduce**: Spacing (try 3mm or 2mm) +- **Calculate**: Use formula in [Grid Size Calculation](#grid-size-calculation) + +### Results are inconsistent + +- **Check**: Material is flat and properly secured +- **Check**: Focus is consistent across entire test area +- **Check**: Laser power is stable (check power supply) +- **Try**: Smaller grid to reduce test area + +## Technical Details + +### File Format + +Material test grids are stored as: +- **Import Source**: Virtual path `[material-test]` with JSON parameters +- **Workpiece**: References the import source +- **Layer**: Regular layer (can be mixed with other operations) + +### Serialization + +The test grid parameters are stored as JSON: + +```json +{ + "type": "MaterialTestGridProducer", + "params": { + "test_type": "Engrave", + "speed_range": [1000, 10000], + "power_range": [10, 100], + "grid_dimensions": [5, 5], + "shape_size": 20.0, + "spacing": 5.0, + "include_labels": true + } +} +``` + +## Related Topics + +- **[Simulation Mode](../../features/simulation-mode.md)** - Preview test execution before running +- **[Material Library](../../collections/material-library.md)** - Store and share material settings +- **[Creating Material Test Guide](../../guides/creating-material-test-grid.md)** - Step-by-step tutorial +- **[Raster Engraving](raster.md)** - Understanding engrave operations +- **[Contour Cutting](contour.md)** - Understanding cut operations diff --git a/docs-site/features/operations/raster.md b/docs-site/features/operations/raster.md new file mode 100644 index 000000000..3ad360a13 --- /dev/null +++ b/docs-site/features/operations/raster.md @@ -0,0 +1,373 @@ +# Raster Engraving + +Raster engraving fills areas with back-and-forth scanning lines, similar to how an inkjet printer works. It's ideal for creating images, text, and filled designs on materials like wood, leather, and anodized aluminum. + +## Overview + +Raster operations: + +- Fill closed shapes with scanning lines +- Support variable power for grayscale images +- Work with both vector shapes and bitmap images +- Use bidirectional scanning for speed +- Create permanent marks on many materials + + + +![Raster engraving example](../../images/Ref-Raster-Example.png) + +## When to Use Raster + +Use raster engraving for: + +- Engraving text and logos +- Creating images and photos on wood/leather +- Filling solid areas with texture +- Marking parts and products +- Creating grayscale artwork + +**Don't use raster for:** +- L Cutting through material (use [Contour](contour.md) instead) +- L Precise outlines (raster creates filled areas) +- L Fine line work (vectors are cleaner) + +## Creating a Raster Operation + +### Step 1: Prepare Content + +Raster works with: +- **Vector shapes** - Filled with scanning lines +- **Text** - Converted to filled paths +- **Images** - Converted to grayscale and engraved + +### Step 2: Add Raster Operation + +- **Menu:** Operations Add Raster +- **Shortcut:** ++ctrl+shift+r++ +- **Right-click:** Context menu Add Operation Raster + +### Step 3: Configure Settings + + + +![Raster settings](../../images/UI-Raster-Settings.png) + +## Key Settings + +### Power & Speed + +**Power (%):** +- Laser intensity for the engraving +- Lower power for lighter marking +- Higher power for deeper engraving +- Typical range: 20-60% for engraving + +**Speed (mm/min):** +- How fast the laser scans +- Faster = lighter, slower = darker +- Typical range: 2000-5000 mm/min + +**Starting values (wood engraving):** +- Power: 30-50% +- Speed: 2500-4000 mm/min +- Always test on scrap material! + +### Line Interval + +**Line Interval (mm):** +- Spacing between scan lines +- Smaller = higher quality, longer job time +- Larger = faster, visible lines + +| Interval | Quality | Speed | Use For | +|----------|---------|-------|---------| +| 0.05mm | Highest | Slowest | Photos, fine detail | +| 0.1mm | High | Medium | Text, logos, graphics | +| 0.2mm | Medium | Fast | Solid fills, textures | +| 0.3mm+ | Low | Fastest | Draft, testing | + +**Recommended:** 0.1mm for general use + +!!! tip "Resolution Match" + For images, line interval should match or exceed image resolution. If your image is 10 pixels/mm (254 DPI), use 0.1mm line interval or smaller. + +### Scan Direction + +**Scan Angle (degrees):** +- Direction of scan lines +- 0 = horizontal (left to right) +- 90 = vertical (top to bottom) +- 45 = diagonal + +**Why change angle?** +- Wood grain: Engrave perpendicular to grain for better results +- Pattern orientation: Match design aesthetics +- Reduce banding: Different angle can hide imperfections + +**Bidirectional Scanning:** +- **Enabled:** Laser engraves in both directions (faster) +- L **Disabled:** Laser only engraves left-to-right (slower, more consistent) + +For best quality, disable bidirectional. For speed, enable it. + +### Overscan + +**Overscan Distance (mm):** +- How far beyond the design the laser travels before turning around +- Allows laser to reach full speed before entering the design +- Prevents burn marks at line starts/ends + +**Typical values:** +- 2-5mm for most jobs +- Larger for high speeds +- See [Overscan & Kerf](../overscan-kerf.md) for details + + + +![Raster overscan diagram](../../images/Diag-Raster-Overscan.png) + +## Grayscale Images + +Raster operations can vary laser power based on image brightness: + +### Image Preparation + +1. **Convert to grayscale** - Color images are converted automatically +2. **Adjust contrast** - Increase contrast for better engraving +3. **Increase brightness** - Dark images may over-engrave +4. **Resize** - Match your desired output size + +### Power Mapping + +- **White pixels** Laser off (0% power) +- **Gray pixels** Proportional power (e.g., 50% gray = 50% of max power) +- **Black pixels** Maximum power setting + +**Example:** +- Max power setting: 60% +- 50% gray pixel 30% actual power +- 100% black pixel 60% actual power + +### Resolution + +**Image DPI vs Line Interval:** +- 254 DPI = 10 pixels/mm use 0.1mm line interval +- 508 DPI = 20 pixels/mm use 0.05mm line interval + +Higher resolution images require smaller line intervals for quality. + +## Tips & Best Practices + +### Material Selection + + **Best materials for raster:** +- Wood (natural variations create beautiful results) +- Leather (burns to dark brown/black) +- Anodized aluminum (removes coating, reveals metal) +- Coated metals (removes coating layer) +- Some plastics (test first!) + + **Challenging materials:** +- Clear acrylic (doesn't show engraving well) +- Metals without coating (requires special marking compounds) +- Glass (requires special settings/coatings) + +### Quality Settings + + **For best quality:** +- Use smaller line interval (0.05-0.1mm) +- Disable bidirectional scanning +- Increase overscan (3-5mm) +- Use lower power, multiple passes +- Ensure material is flat and secured + + **For faster engraving:** +- Use larger line interval (0.15-0.2mm) +- Enable bidirectional scanning +- Minimum overscan (1-2mm) +- Single pass at higher power + +### Common Issues + +**Burn marks at line ends:** +- Increase overscan distance +- Check acceleration settings +- Reduce power slightly + +**Visible scan lines:** +- Decrease line interval +- Reduce power (over-burning creates gaps) +- Check that material is flat + +**Uneven engraving:** +- Ensure material is flat +- Check focus consistency +- Verify laser power stability +- Clean laser lens + +**Banding (dark/light stripes):** +- Disable bidirectional scanning +- Check belt tension +- Reduce speed +- Try different scan angle + +### Material Settings + +| Material | Power | Speed | Line Interval | Notes | +|----------|-------|-------|--------------|-------| +| Birch plywood | 35-45% | 3000-4000 mm/min | 0.1mm | Nice contrast | +| Cherry wood | 30-40% | 3500-4500 mm/min | 0.1mm | Rich dark color | +| Leather | 25-35% | 3000-4000 mm/min | 0.1mm | Test on scrap | +| Anodized aluminum | 40-50% | 4000-5000 mm/min | 0.1mm | Removes coating | +| Cork | 20-30% | 3500-4500 mm/min | 0.15mm | Very forgiving | + +*Settings vary by laser type and material quality. Always test!* + +## Advanced Techniques + +### Crosshatch Engraving + +Run raster operation twice at different angles: + +1. First pass: 0 (horizontal) +2. Second pass: 90 (vertical) + +Creates deeper, more uniform engraving with crosshatch pattern. + +### Variable Line Interval + +For large areas: +- Use fine interval (0.05mm) for detailed areas +- Use coarse interval (0.2mm) for solid fills +- Combine multiple raster operations + +### Dithering + +For photo engraving: +- Convert images to dithered black & white +- Creates halftone-like effect +- Better detail than pure grayscale on some materials + +## Troubleshooting + +### Engraving too light + +- **Increase:** Power setting +- **Decrease:** Speed setting +- **Check:** Focus is correct +- **Try:** Multiple passes + +### Engraving too dark/burning + +- **Decrease:** Power setting +- **Increase:** Speed setting +- **Increase:** Line interval +- **Check:** Material is appropriate + +### Inconsistent darkness + +- **Check:** Material is flat +- **Check:** Focus distance is consistent +- **Verify:** Laser beam is clean +- **Test:** Different area of material (grain varies) + +### Image looks pixelated + +- **Decrease:** Line interval +- **Check:** Source image resolution +- **Try:** Smaller line interval (0.05mm) +- **Verify:** Image isn't being upscaled + +### Scan lines visible + +- **Decrease:** Line interval +- **Reduce:** Power (over-burning creates gaps) +- **Try:** Different scan angle +- **Ensure:** Material surface is smooth + +## Technical Details + +### Scan Pattern Generation + +RayForge converts filled shapes to scan lines: + +1. Determine bounding box +2. Calculate scan lines at specified angle and interval +3. Clip lines to shape boundaries +4. Add overscan extensions +5. Optimize scan order (reduce travel time) +6. Generate G-code + +### Bidirectional Scanning + +**Enabled (faster):** +``` + Scan line 1 + Scan line 2 + Scan line 3 +``` + +**Disabled (more consistent):** +``` + Scan line 1 + (return) + Scan line 2 + (return) + Scan line 3 +``` + +### G-code Example + +```gcode +G0 X-2 Y10 ; Move to overscan start +M3 S102 ; Laser on at 40% power +G1 X52 Y10 F3000 ; Scan line at 3000 mm/min +M5 ; Laser off +G0 X52 Y10.1 ; Move to next line +M3 S102 ; Laser on +G1 X-2 Y10.1 F3000 ; Scan back (bidirectional) +M5 ; Laser off +``` + +## Related Topics + +- **[Contour Cutting](contour.md)** - Cutting outlines and shapes +- **[Depth Engraving](depth.md)** - Creating 3D relief effects +- **[Overscan & Kerf](../overscan-kerf.md)** - Improving engraving quality +- **[Material Test Grid](material-test-grid.md)** - Finding optimal settings +- **[Multi-Layer Workflow](../multi-layer.md)** - Combining raster with other operations diff --git a/docs-site/features/operations/shrink-wrap.md b/docs-site/features/operations/shrink-wrap.md new file mode 100644 index 0000000000000000000000000000000000000000..e78975a505ddf94e53169739a3feb09a153d4743 GIT binary patch literal 9568 zcma)CU2ojR6*c^j2ckgx(1$)wEF_UPURk!|rd_lJY*~qoSeBrb;|C*fC~|g}G09>0 zA!&>LwW2?%f1&5xJ414Jl{AJ8dAY+ockaiz=ibqtnXl@s{Ak|QaTP_Q4<@N?+}g&( zrLl`emSnbUP13b(RxV8yw<{CZt}9bhba|Uqxi#+cC!4g5xm=s2Eo~jk(%4*bSzND8 zyNX+LuaO;_d*S_dWs3vzs{NudU1JwrZWgZYcj~2AaShpv+7%`?&C1%=TxZat$jYpU zb8{Uxtv!gMy*+b!W$UZVUT+@ARictBn^_c1&5@jMP>x5!Y4uD?{HPk^7U58M;e;Dy z|FounUFs}siEqwr+9kGExy=eoBP6c4#5>+x4HnM3s&aJ;xr+w+r&-g+WdbA1iE|s* z{D_6`T>Vjx7nea0%;`$1bOkHJLd`0!Y!gL)`*aG)N9V`KZ{{ygFJ@)|$91)xs-dsp z*{QvW3%DpsZIjelMM*Pr6qi?V13B)RO7@m+V9wl&_e$Us!(>Wfl}$IT7K}zmJ}{{* zVB*$$zqeHrUtyCbT4cE`E5UzTxSBH`W2mZo*)ZDThhoe%U(Djp7ys4z!9!ndrk8-4In2nn&?c2H=5 z@v9+yO4~?I_>9QlK1i8cNY`W;;!ZZ?w-Q_w)4CQh7c!7R7DbcE3s-*8GI4f}GnwG^ z*Jh4)N6ER*rSFei*}AU&VL#FT92Dt&lfi8^PVdWWXOeD`v89E_vog)Dvb2K=8`{4% zXSGc-2*nRX^Rmlh$zDVzQt_p`9vfZ)8{dpQ+XGDyyvA{O;FuXyb*%(G_FY<6*cLbv z=Sx>3_Y1h}(Seyv<}I|HOhT~YP*?WGtU83TPiRK8$EWDAydnXOcM!G1##wnC*C|Y` zKk!v}=?PzApz@V$xoUIhp zx$N%NYCe+J@A{wq!{*XY9Cc0)ntGC)mV4O+LfkXMfsemn!LO?maLKYH{-b`~>;BW+jB;&*%x+7YFjGi&Nq$L{K7&*DdNkfqm0-9Nl9# zOp(qfw(Mre=H5Gv*?tAMIhmXj8>UH~B_Fw*Kx=PWQ{Z)dp%(z)*OSugBh!6_%IwNT zwnPnw5ruH=miZ`4XQs=>MIMxb)uoAOj+sHFx3)xeZzGy&1{21)TW)fIe?`3-8ZaUF zU`CbZUxV3&Cd}}{6k&92>zVn>;b-!3UZF(H%+td|Qxp%u$mFRaU=MRM^Q0(rdEs2U zLNRP+Fie_tMTFhDN@d51(i8Bt@EmgdN3sJ2Uru@cg>h?%hVE!qK+4)GzO-T9LP#L!SxRqqa_-4QU)cZbK2n1$BW|!3^$B5`wd*nO$G3Bs*?^w{)V@fC z;gBWYPF*}J!dn;XDof&gX1+e0{`K%Pk%_o7RldGt$H^Ru{VY@_FY(-oI60LnJm94fk_ zSWzKV3`l;mamvw_1l@4fbTttK%-5GtwoYi^-agz4Z~wPD?Si;UaM1C6Mtje9`thJB%)6 zgC+&^-{*zIs|FCH7)&|>Z4AzXaV1oQ(uEA(%ndbvA1R>?e8*9Urr*{!(ya8^I2Pu+ z6@tmtC?A;wisDu6WTFGLzF`CpKHmo$5HF#u0=n>()QCOv#&@`v?8C)aX^q!+;VFFpTdSLmXtCK`<< z)B^i-OKQ>f=FRI zUHsnKb|a2J@pP7g)Im2ibTy2cMw1Vgw;1Eh;e+?mbWLB!Ys6Sc7oljvc&9nPkU0$# z)bHyX`As{XORlQ+GWMgtj>~0@G*6{pqJ2bNZ&`fe1Pcj=*KCk5HB>7Gb2WET3fa+q8IRybzGNW`0yK$Mku)C^mxHT^c1 z0^w>@T-Me ze+6U>w*(w90sws(+yOrF9zj010_PO(z?A-&edRTEhgjGzI045ih$HZNbpc0|W1N&* zfl=+{iH~=HlfuFbUw8w>Xwmm3Fh99VRf>+nrr5C8%nwp^8_gax!r~RQZKR9{WeIjY zIBGek&-AcNP)GG1+j(jiFKmm_1T#F#uj6&7Oe>pw)Bp+8z@*ML9QAVKmt#y6H25A# zvgm0lbEON8!0|Ag&&?ezLGHXOH1|I)QB?!3g^_XEFCvAxc> zv77TPX5(K;J6z-}8R!gtj1^FAT)m9TK-PMm!yUno+B&o7!qkN1ZLsX70mo{y*dx|r z?R@HB`P7(Y=Yh5Kl2!!{b?;4!Bi)occYo8fI48a81gT}x7fJ=y~0mE_5*+M7!7 zZ*xSwqo&f69ZG@%l4|E0m%P+TG!6P2?QN1QI?t;-6E^>fg9}LmB*Zw;MpRo7;K=vC zZTwLtR+w>M9H6oB!Va-9GUq;u4EufLGrhBYqA-Z!oiUAtg#!fZa^$p5OAsk10mWqi zvk416Z`GdC*m=0~l}Xj~hElM>ct{3sE0=q~G5Zba_)9#XyDqRmN+nm|!IW>XPO55v z6S_T^MY{xKBK0NLBAVd8a_Zx2wGIVT291Kz@Y-O{-p|;};Q@GSJdk1>V(|_@d(O?oVG2*LnD@jki2j`wGwzs7Y9I!c0!z|jv64j-Z0!1WEe zgM`dcFO<}pN?e@<}Dp>@ZsiE#iJ7u@#}d9y7B&C`h=F uYr<%KUJ3*L7A@2dXg~l-=tHNhrPC#zG5bXrno+?B2{eMP2gh*368#V2TWFa8 literal 0 HcmV?d00001 diff --git a/docs-site/features/overscan-kerf.md b/docs-site/features/overscan-kerf.md new file mode 100644 index 0000000000000000000000000000000000000000..a3d5768415c2f570a6e36bf0b847642c6e5ff863 GIT binary patch literal 10833 zcma)CTW=f36*ls?=tF?^p^sx5Xem~dWcdPANKz=0m8h{I!&2>sHi?(Jv*bp5VRo0I zXbAo7{l0T%W|xwTR1Y?}JC`%(@}2LT;Zt*dZJRcUEAtoggKaW%RF?}|wQ-l%RTN#$ z^VTflnKenxfu>v4CQh&8DzT}_Y}_py+nTIyOkOUU`Z}*>CRuhSu2N&GSrf~X-&ZD*UoP);0=?}_4uW9g1t#7VMj;$*!OMU%-Sik?0V2Zi`1 z)CrDe(q%)z!kM>?E%Gw2ph%V17Pb+sV)ZW1uwx79pF;9W2=KP4r-dyK%wdxBBhTXI zs*R!#c{i`2R51Z;wSE6Y?J~<~pRB1%=nwkoR|)%##|Kd~9)Fm}oteiA+WBBSjy`_; z7`>6>&25~TvZn3*fnvWGb%yD8WjTn3TFosCyP+l+wCP$iQcJsCI&93H#90^h3O-O+7=26DJcdYSbICNE z7CNlyreVo+WeaF=W{SF+*+!Q*t>{ZRq5$3$yvL+=(am>xWOynCj+3TtTSNbYRw}Em z^L@Pvj&DBH;w{1b$73G=ba9-dSj62NYfUWz7N>{v$C-p5S9MY1>`bSit%K9S_QpK& ze|N3ypFfJ!8)(Ku4XW1x2JlRrAsVT>ou8a+ap0Z5!CP-pghv8B(3a7&9a{?M zFuE4(g}6k_#%58sxw!CH4?5NWhSH4MINIkDA<}HWN^l5W3m!4EooU69onuhw=s6eA zgAHZ_46D|_?mhZp9Ryo|3t1_8!Py}!?k|vKvO;hrEHV~D4NgK}V=%w-PA)J4C(2=2 z^&QFsMe|73L+Vo+Im>5?Y~HN~_=?;R<0M@ZS1mlMv<=LWR}L@N zh?NywGDB!$(ee0_fEokldNW=CrIN0nfcYyr-Ce|1i=6|p!jh)7k_#9dBjlfY;qleK zaArD8(>_M-$eNj|2HY3G^>l3(Kn!S5?c>jGO^WDb!lUzz#}{r}ImE4TU(GFCyG@#W zA)a?@F4v1Z0SLX1i={QU(Jk_n{`H^uee)Z>N4Mfy)KiM1VWoODD{P2E_}6X?54knx zKbjFUuPSSco6xVEw1CEPOBNtVWN{-2O){bYNQ)KrCofG|Vxr`sqj`020O-;&439mPN7dF&6sc^I=ShTb#gimPKqv$Vg3nlb3O4 zx2Ro0P}u5gGtw~JHKTpguZmQ)6@dROI6)_BpDptg2^iq%>~t327)?mGgM5Wpy*2M_ zQkNwH3IP+2KD5|9E8R7kw=4|sd~a_LI^9L;H=~#Gv4v^O8))d(ICX!1*qKf9B`ji| zt6@Gr@_XbnjNA9)UJW;Xra}yMenwHmMLs()?EUI@hq}#Q=s?EyvV!M`u9<8#cXyq{ z`lh~1avA_}UKHj!Z*%y$y23~M?XXfq|ZO;0C;8~9Xht|6MTXCw(^cR))!h@CuB!a!&?%L-hgBHkby=)my4 zsOu{;tLxN^5H)Rl4FRB!EsfO=b3h@U{|jq-pCvjS7OQyOnk60s8hE;ic{{H$QgZ^s zd*lEEuTE$MumX^Pit0S9sO#B$lG-lLL7|kM6UMpvj{wUGqz+0AtG|b;079ObkC0@# zdO5)3mPF^hZPtb)Z74^`w&a^gCY7Cm@X;eU(#1%luf-D081Y{E=Q26tc(d5AOjUyH)0 zp?mvX4h(!0-^o6t;!v_pL7wfs>L-pc40RS2P1BK{wE#3Tubcc6wgTd=acXi9Rw!y` zVzizD(@6DD4j^urPyt3hd}vGI1rWnYP2GFaq&q62Gr82hK9rSPR)rJsx|1d@;bhAS zhzs*UOpMI4wHd@`^!V{(vx*yHgL!h!5++k)v`>WepJx3ANer)LwMoHw>YIf1gO{7t zRM&2sckvn-0~P6tzRShUx?b)8#nWXn2(*wnm?5n{o@A+C>*34nYK`av|Jj;|%ubku8C+X|zF^>UOC(>S?;LQ*qbn~(ndzm(<2%_+!qZUPMa z@Oa_3ADVdKqEG1}L%XR99$h3ogEE|{SZKpoD$S57%fL$^##&f`wSaaaPqRdm@lHA^ z6R;k4Aq%@d^W)r**o z&s9%T8<)Naci_6CD}t?r77ajxnT}S_@=ojlU35nAy3hqkY)h{rr`geM)?7b{k0rnm8UEbv(KKzrv*v4Ef)o5 z4S`duw|0Td(&nG+f!W*H7l=Ib+JR?-*-Hc*5EEPT-@Tn@z(+(xKt{pT%NoFFt{@-* z6{B8YC2WZ55#}$&knE!j6)15`rV08kDmZ}Oxj%=|IKx5o2VdcS>EDJYj~;y)ePLb- z?wc?CYd)a>_|9kF*Kj}>$xQQE^e4aApZ)0Yz($eUsUC~j+N%8PI8>59nQda_}V+Cqju&xNm z!)?>rw$)$B6uCVuJ0Y>E*>?kd^1e9Q+j$AQguS`-1-2~gWRas*COiBUP^;nYdzhoD z7S|e*4JHZ30}|;VBwZgyUJP9gSs#TPs#6VrAF+}p1csSzRin&*!yw*-inx$I9x;sQSM_@~gI#MoD4igX3Bw+)C- z!EriZycm1KFT64~7rK*fB?Qn_MaMyVi~wv{dva;EAg8iGg=K;j!>Z z+9HI10v><@ljDZ0oJf5ZS0DrI6=>O}6cGD@*!kRq!Ym`$Sl_*bh+y#uTgfS>*{*_* zSBmAzj-j2Y4Rkr4p06MWxE8VjI{hpO)re+fcV;`=4$bK=TRPIO!7%XT1^G%}itW&$ za4#kypKh65vmYtx15c4=8pEhZiy#WyRAQNdJ_!Tl>ujOvPOk}(ecU?lax<^lYjOu; zF9&fW!MW>EqO4Oij)mMEE*4NY)(_NF;99iuTDo*n)_O$gN9p>#+@-5{8Qg|)a}h4vI+&?~|>7oD0Nn<#8&sm?ikdN$X0 zZ_qgoxSfEWIn6sy3OnIWY)PYf2lUYGbjU&n91Fd~9MI8nZF(*$r>{f_+p5r2jPk?r zNQYs5sP|5Eqb5kAf=4MD@B1nz3gW85{$6Juxx@Zxj!F*_`t`8&H^IZf81?M~awydM zX45(&{^$1jKTC>c$HP0q2)Nh$8CVM;b86(~n>lGU} zXx_QE&+(RAkn{VuEciM11>VYMygf{sb&)57xxbO^KAt$p!aWRTRPP;$>Geq#nv)xlq6O8f_~c zbh}4c!r+6cL|D{mb%p!y#lx2p%tX+Tz{Fd8#s${8LN_pRbOBB}I_jF@Z~t_c4M3-v zpsJ9r0m~6A5$7C0p9UbpU+5pIab>;I@hjsiFj4MV@D>W!g&Ox#3J9DrP|2jxHw|Nj z!gH|1l8SsjC7Y#G{0^D$DI+an{(^6u76nR3kYsHbDgqB~W+;SLf?G>g3Yu4^-)62(VDL$ZXwM@6)z@i)b-^No^I4aij%PQw7#*Z z<`>IPpJ03G0D1x1t9+r+JScgjp7~rIgSf9(6I^<^@{CM_N4m@xu5`m^9yrUJwu1!_ zyV_nxGW5AwD<*gpFq+-Jpa+mn9Ai8N?eW*!K6lDeqFfeqxRBQrC-}3gSEQU7Pz4*&n5N=Yl;0Y}6 zrnxjR&&j9p6O1Tg?c)nYm4C{HP#{B6vO3lvK%;jI1l}UX-Kg5iQLT;N#mJ?e`^gMz zQ_r;oJ%;)b$;@?;49zg9m}sJ_Du-C5mLIOXasW zvRkOY97~lzWH;aq&uE?kyN8im zeE&fBJK&Rj(z{EuEr{~r&e}kT&#kQGo&zHYAUzFNo|#J!JEl+2YNozIX3;E=xmLB>Um-fYjjhC||{) zWf}HIiLd1gc&w8J#cE@(bGz~vy*NHDaHR8$ppolU@q)preSmY!1j_kMnp|A$K!Bn6vx_gYT4>vY7M}h^uMNpQW+L(=@9MVDH{s2iOVs_<^%Pe<<&_Ff`Yt4PVjHV7>>>>>>>>>>\___ + ^ ^ + Too light Too dark + (moving fast) (moving slow) +``` + +**Visual result:** +- **Light edges** where acceleration starts (laser moving too fast for power level) +- **Dark edges** where deceleration occurs (laser dwelling longer) +- **Inconsistent engraving depth/darkness** across each line +- Visible banding or streaking at line edges + +## How Overscan Works + +Overscan **extends the toolpath** before and after each raster line: + +``` +With overscan: + + Constant Speed + Accel Actual Engraving Decel +(Laser OFF) (Laser OFF) +``` + +**Process:** + +1. **Lead-in:** Laser moves to a position *before* the line starts +2. **Accelerate:** Laser accelerates to target speed (laser OFF) +3. **Engrave:** Laser turns on and engraves at constant speed +4. **Decelerate:** Laser turns off and decelerates *after* the line ends + +**Result:** The entire engraved area receives consistent power at constant velocity. + +**Benefits:** +- Even engraving depth across entire raster line +- No light/dark edges +- Higher quality photo engraving +- Professional-looking results + +## Configuring Overscan + +Overscan is a **transformer** in the RayForge workflow pipeline. + +**To enable:** + +1. **Select the layer** with raster engraving +2. **Open workflow settings** (or operation settings) +3. **Add Overscan transformer** if not already present +4. **Configure distance** + +**Settings:** + +| Setting | Description | Typical Value | +|---------|-------------|---------------| +| **Enabled** | Toggle overscan on/off | ON (for raster) | +| **Distance (mm)** | How far to extend lines | 2-5 mm | + +## Choosing Overscan Distance + +The overscan distance should allow the machine to **fully accelerate** to target speed. + +**Formula (approximate):** +``` +distance = (speed^2) / (2 * acceleration) +``` + +**Practical guidelines:** + +| Max Speed | Acceleration | Recommended Overscan | +|-----------|--------------|----------------------| +| 3000 mm/min (50 mm/s) | Low | 5 mm | +| 3000 mm/min (50 mm/s) | Medium | 3 mm | +| 3000 mm/min (50 mm/s) | High | 2 mm | +| 6000 mm/min (100 mm/s) | Low | 10 mm | +| 6000 mm/min (100 mm/s) | Medium | 6 mm | +| 6000 mm/min (100 mm/s) | High | 4 mm | + +**Factors affecting required distance:** + +- **Speed:** Higher speed = need more distance to accelerate +- **Acceleration:** Lower acceleration = need more distance +- **Machine mechanics:** Belt-driven vs direct-drive affects acceleration + +**Tuning:** + +- **Too little:** Acceleration marks still visible at edges +- **Too much:** Wastes time, may hit machine boundaries +- **Start with 3mm** and adjust based on results + +## Testing Overscan Settings + +**Test procedure:** + +1. **Create a test engraving:** + - Solid filled rectangle (50mm x 20mm) + - Use your typical engraving settings + - Enable overscan at 3mm + +2. **Engrave the test:** + - Run the job + - Allow to complete + +3. **Examine the edges:** + - Look at left and right edges of the rectangle + - Check for darkness variation at edges + - Compare edge darkness to center darkness + +4. **Adjust:** + - **If edges are lighter/darker:** Increase overscan + - **If edges match center:** Overscan is sufficient + - **If edges are perfect:** Try reducing overscan slightly to save time + +**Visual inspection guide:** + +``` +Too little overscan: Correct overscan: +|LIGHT|DARK|LIGHT| |EVEN|EVEN|EVEN| + edge center edge edge center edge +``` + +## When to Use Overscan + +**Always use for:** +- Photo engraving (raster) +- Fill patterns +- Any high-detail raster work +- Grayscale image engraving +- Text engraving (raster mode) + +**Not needed for:** +- Vector cutting (contour operations) +- Very slow engraving (acceleration is negligible) +- Machines with very high acceleration (rare) +- Single-line operations (no raster scanning) + +**Recommended by default:** Enable overscan for all raster operations unless you have a specific reason not to. + +## Overscan and Machine Boundaries + +**Important:** Overscan extends toolpaths beyond the visible content. + +**Example:** +- Content: 100mm x 100mm square +- Overscan: 3mm +- **Actual motion:** 106mm x 100mm (3mm added to each side horizontally) + +**Space requirements:** + +- Horizontal overscan: Added to left and right of content +- Vertical: No overscan added (raster lines run horizontally) +- Total width: Content width + (2 x overscan distance) + +**Ensure:** +- The extended paths fit within machine work area +- Content is positioned to allow for overscan extension +- Use Frame function to verify boundaries before running + +**Out of bounds warning:** + +If overscan causes paths to exceed machine limits, RayForge will warn you: + +``` +Warning: Overscan extends beyond machine boundaries. +Reduce overscan distance or reposition the job. +``` + +**Solutions:** +- Reduce overscan distance +- Move content further from edges +- Reduce content size +- Change work area settings if machine is actually larger + +## Technical Details + +**How RayForge implements overscan:** + +1. **Identifies raster sections** in the operation +2. **For each raster line:** + - Calculates line direction vector + - Extends start point backward by `distance_mm` + - Extends end point forward by `distance_mm` +3. **Wraps with power control:** + - Moves to extended start (laser OFF) + - Turns laser ON at actual start + - Engraves content at constant speed + - Turns laser OFF at actual end + - Continues to extended end (deceleration zone) + +**For variable power (photo engraving):** +- Pads the power data array with zeros at edges +- Ensures smooth power ramp at edges +- No abrupt power changes that could cause artifacts + +**G-code representation:** + +```gcode +; Without overscan +G0 X10 Y20 ; Move to start +M4 S500 ; Laser on +G1 X50 F3000 ; Engrave line +M5 ; Laser off + +; With overscan (3mm) +G0 X7 Y20 ; Move to overscan start (10-3=7) +G1 X10 F3000 ; Accelerate to speed (laser off) +M4 S500 ; Laser on at content start +G1 X50 ; Engrave content +M5 ; Laser off at content end +G1 X53 ; Continue to overscan end (50+3=53) +``` + +## Bidirectional vs Unidirectional Raster + +Overscan affects both scanning directions: + +**Bidirectional raster (default):** +- Raster lines alternate: left-to-right, right-to-left +- Overscan extends both directions +- Faster (no time wasted returning to left side) +- May show slight misalignment if machine backlash exists + +**Unidirectional raster:** +- All lines go left-to-right only +- Head returns to left side between lines (laser off) +- Slower but more consistent +- Overscan still used for acceleration/deceleration + +**Overscan is important for both modes** to ensure constant velocity during actual engraving. + +## Advanced: Variable Overscan + +Some advanced use cases may need different overscan distances: + +**Slow engraving:** +- Lower speeds need less overscan +- Can reduce to 1-2mm to save time/space + +**Fast engraving:** +- Higher speeds need more overscan +- May need 5-10mm for very fast raster work + +**Per-layer configuration:** +- Set different overscan for different layers +- Fast raster layer: 5mm overscan +- Slow detail layer: 2mm overscan + +## Troubleshooting + +### Acceleration Marks Still Visible + +**Problem:** Edges of engraving are lighter or darker than center despite overscan being enabled. + +**Diagnosis:** +- Overscan distance too small for current speed/acceleration +- Overscan not actually enabled +- Machine acceleration settings wrong + +**Solutions:** +1. Increase overscan distance (try doubling it) +2. Verify overscan is enabled in layer workflow +3. Reduce engraving speed (less acceleration needed) +4. Check machine acceleration settings in firmware + +### Overscan Causes Out-of-Bounds Error + +**Problem:** RayForge reports job exceeds machine boundaries when overscan is enabled. + +**Diagnosis:** +- Content positioned too close to edge +- Overscan distance too large +- Machine work area configured incorrectly + +**Solutions:** +1. Reduce overscan distance +2. Reposition content further from edges (at least overscan distance + 5mm margin) +3. Reduce content size slightly +4. Verify machine work area dimensions in settings + +### Inconsistent Results + +**Problem:** Some lines show artifacts, others don't. + +**Diagnosis:** +- Mechanical issues (belt tension, binding) +- Variable material (thickness changes) +- Firmware acceleration settings inconsistent + +**Solutions:** +1. Check belt tension and mechanical components +2. Use flat, consistent material for testing +3. Verify firmware acceleration settings ($120/$121 in GRBL) +4. Clean linear rails and ensure smooth motion + +### Engraving Takes Too Long + +**Problem:** Job time increased significantly with overscan. + +**Diagnosis:** +- Large overscan distance adds travel time +- Many short raster lines amplify time cost + +**Analysis:** +- Each line adds: 2 x overscan distance to travel +- 100 lines with 5mm overscan = 1000mm extra travel + +**Solutions:** +1. Reduce overscan to minimum needed (test to find smallest acceptable value) +2. Increase engraving speed if quality allows +3. Combine raster lines where possible +4. Accept the time cost for quality improvement + +## Best Practices + +1. **Enable by default for raster:** + - Always use overscan for photo engraving + - Enable for any raster operations + - Disable only if you have specific reasons + +2. **Start with 3mm:** + - Good baseline for most machines + - Test and adjust from there + - Document optimal value for your machine + +3. **Test on your machine:** + - Every machine is different + - Run test engraving to find ideal distance + - Re-test if you change acceleration settings + +4. **Account for boundaries:** + - Position content with overscan in mind + - Leave margin from work area edges + - Frame before running to verify + +5. **Balance quality vs time:** + - More overscan = better quality + - But also longer job time + - Find the sweet spot for your needs + +## Related Pages + +- [Raster Engraving](operations/raster.md) - Raster operations that use overscan +- [Multi-Layer Workflow](multi-layer.md) - Organizing layers with different overscan settings +- [Kerf Compensation](kerf.md) - Related feature for cutting accuracy +- [Power vs Speed](../concepts/power-vs-speed.md) - Understanding speed effects on quality diff --git a/docs-site/features/simulation-mode.md b/docs-site/features/simulation-mode.md new file mode 100644 index 000000000..0e6d899eb --- /dev/null +++ b/docs-site/features/simulation-mode.md @@ -0,0 +1,336 @@ +# Simulation Mode + +Simulation Mode provides real-time visualization of your laser job execution before you run it on the actual machine. It shows execution order, speed variations, and power levels through an interactive overlay in the 2D view. + +## Overview + +Simulation Mode helps you: + +- **Visualize execution order** - See the exact sequence operations will run +- **Identify speed variations** - Color heatmap shows slow (blue) to fast (red) movements +- **Check power levels** - Transparency indicates power (faint=low, bold=high) +- **Validate material tests** - Confirm test grid execution order +- **Catch errors early** - Spot issues before wasting material +- **Understand timing** - See how long different operations take + + + +![Simulation mode overview](../images/Ref-SimulationMode-Overview.png) + +## Activating Simulation Mode + +There are three ways to enter Simulation Mode: + +### Method 1: Keyboard Shortcut +Press ++f7++ to toggle simulation mode on/off. + +### Method 2: Menu +- Navigate to **View → Simulate Execution** +- Click to toggle on/off + +### Method 3: Toolbar (if available) +- Click the simulation mode button in the toolbar + +!!! note "2D View Only" + Simulation mode works in 2D view. If you're in 3D view (++f6++), switch to 2D view (++f5++) first. + +## Understanding the Visualization + +### Speed Heatmap + +Operations are colored based on their speed: + +| Color | Speed | Meaning | +|-------|-------|---------| +| 🔵 **Blue** | Slowest | Minimum speed in your job | +| 🔵 **Cyan** | Slow | Below average speed | +| 🟢 **Green** | Medium | Average speed | +| 🟡 **Yellow** | Fast | Above average speed | +| 🔴 **Red** | Fastest | Maximum speed in your job | + +The heatmap is **normalized** to your job's actual speed range: +- If your job runs 100-1000 mm/min, blue=100, red=1000 +- If your job runs 5000-10000 mm/min, blue=5000, red=10000 + + + +![Speed heatmap legend](../images/Ref-SimulationMode-HeatmapLegend.png) + +### Power Transparency + +Line opacity indicates laser power: + +- **Faint lines** (10% opacity) = Low power (0%) +- **Translucent** (50% opacity) = Medium power (50%) +- **Solid lines** (100% opacity) = Full power (100%) + +This helps identify: +- Travel moves (0% power) - Very faint +- Engraving operations - Moderate opacity +- Cutting operations - Solid, bold lines + +### Laser Head Indicator + +The laser position is shown with a crosshair: + +- 🔴 Red crosshair (6mm lines) +- Circle outline (3mm radius) +- Center dot (0.5mm) + +The indicator moves during playback, showing exactly where the laser is in the execution sequence. + +## Playback Controls + +When simulation mode is active, playback controls appear at the bottom of the canvas: + + + +![Simulation playback controls](../images/UI-SimulationMode-PlaybackControls.png) + +### Play/Pause Button + +- **▶️ Play**: Starts automatic playback +- **⏸️ Pause**: Stops at current position +- **Auto-play**: Playback starts automatically when you enable simulation mode + +### Progress Slider + +- **Drag** to scrub through the execution +- **Click** to jump to a specific point +- Shows current step / total steps +- Supports fractional positions for smooth scrubbing + +### Speed Range Display + +Shows the minimum and maximum speeds in your job: + +``` +Speed range: 100 - 5000 mm/min +``` + +This helps you understand the heatmap colors. + +## Using Simulation Mode + +### Validating Execution Order + +Simulation shows the exact order operations will execute: + +1. Enable simulation mode (++f7++) +2. Watch the playback +3. Verify operations run in the expected sequence +4. Check that cuts happen after engraving (if applicable) + +**Example:** Material test grid +- Observe risk-optimized order (fastest speeds first) +- Confirm low-power cells execute before high-power +- Validate test runs in safe sequence + +### Checking Speed Variations + +Use the heatmap to identify speed changes: + +- **Consistent color** = Uniform speed (good for engraving) +- **Color changes** = Speed variations (expected at corners) +- **Blue areas** = Slow movements (check if intentional) + +### Estimating Job Time + +Playback duration is scaled to 5 seconds for the full job: + +- Watch the playback speed +- Estimate actual time: If playback feels smooth, job will be quick +- If playback jumps rapidly, job has many small segments + +!!! tip "Actual Time" + For actual job time, check the G-code preview or status bar after generating G-code. + +### Debugging Material Tests + +For material test grids, simulation shows: + +1. **Execution order** - Verify cells run fastest→slowest +2. **Speed heatmap** - Each column should be a different color +3. **Power transparency** - Each row should have different opacity + +This helps confirm the test will run correctly before using material. + +## Editing While Simulating + +Unlike many CAM tools, RayForge lets you **edit workpieces during simulation**: + +- Move, scale, rotate objects ✅ +- Change operation settings ✅ +- Add/remove workpieces ✅ +- Zoom and pan ✅ + +**Auto-update:** Simulation automatically refreshes when you change settings. + +!!! note "No Context Switching" + You can stay in simulation mode while editing - no need to toggle back and forth. + +## Tips & Best Practices + +### When to Use Simulation + +✅ **Always simulate before:** +- Running expensive materials +- Long jobs (>30 minutes) +- Material test grids +- Jobs with complex execution orders + +✅ **Use simulation to:** +- Verify operation order +- Check for unexpected travel moves +- Validate speed/power settings +- Train new users + +### Reading the Visualization + +✅ **Look for:** +- Consistent colors within operations (good) +- Smooth transitions between segments (good) +- Unexpected blue areas (investigate - why so slow?) +- Faint lines in cutting areas (wrong - check power settings) + +⚠️ **Red flags:** +- Cutting before engraving (workpiece may move) +- Very long blue (slow) sections (inefficient) +- Power changes mid-operation (check settings) + +### Performance Tips + +- Simulation updates automatically on changes +- For very complex jobs (1000+ operations), simulation may slow down +- Disable simulation (++f7++) when not needed for better performance + +## Keyboard Shortcuts + +| Shortcut | Action | +|----------|--------| +| ++f7++ | Toggle simulation mode on/off | +| ++f5++ | Switch to 2D view (required for simulation) | +| ++space++ | Play/Pause playback | +| ++left++ | Step backward | +| ++right++ | Step forward | +| ++home++ | Jump to start | +| ++end++ | Jump to end | + +## Troubleshooting + +### Simulation doesn't activate + +- **Check**: Are you in 2D view? Press ++f5++ first +- **Check**: Do you have operations generated? No operations = nothing to simulate +- **Try**: Close and reopen the document + +### Playback controls not visible + +- **Check**: Zoom out - controls appear at bottom of canvas +- **Check**: Make sure simulation mode is active (++f7++) +- **Try**: Resize the window - controls may be off-screen + +### Colors don't match speed + +- **Remember**: Colors are normalized to YOUR job's speed range +- Blue = slowest in YOUR job (not universal slow) +- Red = fastest in YOUR job (not universal fast) +- **Check**: Speed range display shows your min/max speeds + +### Simulation is slow/laggy + +- **Reduce**: Number of operations (split complex jobs) +- **Disable**: Other canvas elements temporarily +- **Check**: System resources (close other applications) +- **Try**: Disable simulation when editing, re-enable to view + +### Lines appear in wrong order + +- This shows the **actual** execution order +- If it seems wrong, check your operation settings +- Remember: RayForge executes operations in layer order +- Material test grids use risk-optimized order (fastest first) + +## Technical Details + +### Playback Timing + +- **Target duration**: 5 seconds for full job +- **Frame rate**: 24 FPS +- **Step calculation**: Automatically scaled to job complexity + +### Color Mapping + +**Speed to heatmap:** +- Blue (H=240°) → Cyan (H=180°) → Green (H=120°) → Yellow (H=60°) → Red (H=0°) +- Normalized to actual speed range +- Linear interpolation between colors + +**Power to opacity:** +- Formula: `alpha = 0.1 + (power/100.0) * 0.9` +- Ensures even 0% power is visible (10% opacity) +- 100% power = fully opaque + +### Implementation + +- **Class**: `PreviewOverlay` (simulation visualization) +- **Controls**: `PreviewControls` (playback UI) +- **Data**: `OpsTimeline` (operation sequence with state) +- **Integration**: Canvas overlay in 2D view + +## Related Topics + +- **[3D Preview](../ui/3d-preview.md)** - 3D toolpath visualization +- **[Material Test Grid](operations/material-test-grid.md)** - Use simulation to validate tests +- **[Using Simulation Mode Guide](../guides/using-simulation-mode.md)** - Step-by-step tutorial +- **[Simulating Your Job](../getting-started/simulating-your-job.md)** - Getting started guide diff --git a/docs-site/files/exporting.md b/docs-site/files/exporting.md new file mode 100644 index 000000000..7a7545250 --- /dev/null +++ b/docs-site/files/exporting.md @@ -0,0 +1,482 @@ +# Exporting G-code + +This page explains how to export G-code from RayForge and customize export settings for your machine. + +## Quick Export + +**Generate G-code for your job:** + +1. **Design your job** with layers and operations +2. **Preview in 3D** to verify (optional) +3. **File Export G-code** (or Ctrl+E) +4. **Choose save location** and filename +5. **Click Save** + +Your G-code file is now ready to send to your machine! + +--- + +## Export Methods + +### Method 1: File Menu + +**File Export G-code** (Ctrl+E) + +- Opens file save dialog +- Choose location and filename +- G-code generated and saved + +### Method 2: Send to Machine + +**Machine Run Job** or click Run button + +- G-code generated in memory +- Sent directly to connected machine +- Optionally save to file as well + +### Method 3: Command Line + +```bash +# Export from command line (if supported) +rayforge --export output.gcode input.svg +``` + +--- + +## G-code Output + +### What's Included + +Generated G-code contains: + +**Header:** +- Comments with job information +- Setup commands (units, positioning mode) +- Job start hooks (if configured) + +**Body:** +- Toolpath commands for each layer +- Layer start/end hooks +- Workpiece start/end hooks +- Power control commands +- Feed rate specifications + +**Footer:** +- Job end hooks (if configured) +- Return to origin (if configured) +- Laser off, air assist off + +### Example G-code Structure + +```gcode +; ========================================== +; Generated by RayForge +; Job: my-project +; Date: 2025-10-03 14:30:00 +; ========================================== + +; Setup +G21 ; Millimeters +G90 ; Absolute positioning +M5 ; Laser off + +; Job Start Hook (if configured) +$H ; Home machine +M8 ; Air assist on + +; Layer 1: Engrave Layer +; Layer Start Hook +G0 X10.000 Y10.000 ; Rapid move to start +M3 S500 ; Laser on at power 500 +G1 X50.000 F3000 ; Cut to X50 at 3000mm/min +; ... (more engraving commands) +; Layer End Hook + +; Layer 2: Cut Layer +; Layer Start Hook +G0 X10.000 Y10.000 +M3 S900 ; Laser on at power 900 +G1 X50.000 F500 ; Cut at slower speed +; ... (more cutting commands) +; Layer End Hook + +; Job End Hook (if configured) +M5 ; Laser off +M9 ; Air assist off +G0 X0 Y0 ; Return to origin + +; End of job +``` + +--- + +## Export Settings + +### General Settings + +**Access:** Settings Machine G-code Settings + +| Setting | Description | Values | Default | +|---------|-------------|--------|---------| +| **Precision** | Decimal places for coordinates | 0-5 | 3 | +| **Dialect** | G-code flavor | GRBL, etc. | GRBL | +| **Max Speed** | Maximum travel speed (mm/min) | Positive number | 3000 | +| **Max Cut Speed** | Maximum cutting speed (mm/min) | Positive number | 1000 | + +### Coordinate Precision + +**Precision** determines how many decimal places are used for coordinates. + +**Examples:** + +| Precision | Example Output | Precision Level | +|-----------|----------------|-----------------| +| 0 | `G0 X50 Y100` | 1mm (very coarse) | +| 1 | `G0 X50.5 Y100.2` | 0.1mm | +| 2 | `G0 X50.53 Y100.27` | 0.01mm | +| 3 | `G0 X50.532 Y100.271` | 0.001mm (recommended) | +| 4 | `G0 X50.5320 Y100.2714` | 0.0001mm (usually unnecessary) | + +**Recommendations:** + +- **Precision 3 (default):** Best for most work (0.001mm = 1 micron) +- **Precision 2:** Faster processing, still very accurate +- **Precision 4+:** Unnecessary (laser spot size is typically 0.1-0.3mm) + +**Trade-offs:** + +- **Higher precision:** Larger file sizes, longer processing +- **Lower precision:** Faster, smaller files, but less smooth curves + +### G-code Dialect + +**Dialect** determines which G-code commands and syntax to use. + +**Supported dialects:** + +- **GRBL** (default) - For GRBL firmware controllers +- *Other dialects may be added in future versions* + +See [G-code Dialects](../reference/gcode-dialects.md) for details. + +--- + +## Customizing Output + +### Machine Configuration + +Machine settings affect G-code generation: + +**Settings Machine Profile** + +| Setting | Effect on G-code | +|---------|------------------| +| **Work Area Size** | Warns if job exceeds bounds | +| **Y-Axis Direction** | Inverts Y coordinates if needed | +| **Max Speeds** | Enforces speed limits | + +### Hooks and Macros + +Inject custom G-code at specific points: + +**Settings Machine Hooks** + +**Available hooks:** +- **Job Start** - Beginning of file +- **Job End** - End of file +- **Layer Start** - Before each layer +- **Layer End** - After each layer +- **Workpiece Start** - Before each workpiece +- **Workpiece End** - After each workpiece + +**Example Job Start Hook:** +```gcode +$H ; Home machine +G0 X0 Y0 ; Move to origin +M8 ; Air assist on +``` + +See [Macros & Hooks](../features/macros-hooks.md) for details. + +--- + +## File Naming + +### Recommended Naming Conventions + +**Good filenames:** +``` +project-name_material_date.gcode +box-3mm-ply_2025-10-03.gcode +logo-engrave_v2.nc +test-grid_CO2_50W.gcode +``` + +**Include:** +- Project or part name +- Material type/thickness (if relevant) +- Date or version number +- Machine or settings identifier + +**Avoid:** +- Spaces (use hyphens or underscores) +- Special characters (some controllers don't support) +- Very long names (>32 characters may be truncated) + +### Common Extensions + +| Extension | Usage | Compatibility | +|-----------|-------|---------------| +| `.gcode` | Most common | Widely recognized | +| `.nc` | Numerical Control | CNC standard | +| `.ngc` | NGC (Next Generation Controller) | LinuxCNC, some others | +| `.txt` | Plain text | Universal fallback | + +**Recommendation:** Use `.gcode` for clarity. + +--- + +## File Size Considerations + +### Typical File Sizes + +| Job Type | Complexity | File Size | +|----------|-----------|-----------| +| **Simple cut** | Square or circle | 1-10 KB | +| **Logo engrave** | Vector paths | 10-100 KB | +| **Photo engrave** | Raster, 300 DPI, 1010cm | 5-20 MB | +| **Detailed cut** | Many small paths | 100 KB - 5 MB | +| **Large photo** | Raster, 500 DPI, 2020cm | 50-100 MB | + +### Large Files + +**Problems with very large G-code files (>50 MB):** + +- Slow to load on controller +- May exceed controller memory +- Longer processing time +- Transfer delays over serial + +**Optimization strategies:** + +1. **Reduce raster DPI:** + - 300-400 DPI is usually sufficient + - Higher DPI doesn't improve quality beyond laser resolution + +2. **Simplify vector paths:** + - Reduce number of nodes + - Use path simplification tools + +3. **Lower precision:** + - Precision 2 instead of 3 significantly reduces size + - Quality difference is negligible + +4. **Split large jobs:** + - Break into multiple files + - Run sequentially + +5. **Reduce overscan:** + - Less overscan = fewer extra moves + - Balance quality vs file size + +--- + +## Verifying G-code + +### Preview Before Exporting + +**Always preview your job:** + +1. **3D Preview** - Check layer order and operations +2. **Simulation Mode** (F7) - Verify execution timing +3. **Frame Job** - Test boundaries on machine + +### Checking Exported G-code + +**Manual inspection:** + +1. **Open in text editor** to review +2. **Check header** - Verify setup commands +3. **Check footer** - Ensure laser turns off +4. **Scan for errors** - Look for unexpected values + +**G-code validators:** + +- **CAMotics** (free) - G-code simulator +- **NCViewer** (web-based) - Online G-code visualizer +- **Universal G-code Sender** - Has built-in visualizer + +**Common issues to check:** + +- Coordinates within machine bounds +- Feed rates reasonable (not 0, not excessive) +- Power values in valid range (0-1000 for GRBL S parameter) +- No missing laser-off commands +- Proper layer separation + +--- + +## Sending to Machine + +### Direct Send + +**From RayForge:** + +1. **Connect to machine** (Machine Connect) +2. **Click Run Job** or Machine Run +3. **G-code generated and streamed** to controller + +**Advantages:** +- No intermediate file needed +- Immediate execution +- Real-time monitoring + +### Via File + +**Export then load to controller:** + +1. **Export G-code** (File Export) +2. **Transfer to controller:** + - SD card (if controller supports) + - USB flash drive + - Serial upload via UGS or similar + +**Advantages:** +- Keep G-code for re-running jobs +- Use offline controllers +- Archive successful jobs + +### G-code Senders + +**Recommended senders for manual control:** + +- **Universal G-code Sender (UGS)** - Popular, cross-platform +- **LightBurn** - Full laser software (alternative to RayForge) +- **LaserGRBL** - Windows, GRBL-specific +- **bCNC** - Advanced, Linux-focused + +--- + +## Troubleshooting Export + +### Export Fails or Hangs + +**Problem:** Export process doesn't complete. + +**Solutions:** + +1. **Simplify the job** - Very complex jobs may time out +2. **Check for errors** - Review console/logs for error messages +3. **Reduce raster resolution** - Lower DPI +4. **Close other applications** - Free up system resources +5. **Save project first** - Ensure work isn't lost + +### G-code Has Errors + +**Problem:** Exported G-code contains invalid commands or values. + +**Diagnosis:** + +1. **Check operation settings** - Invalid power/speed values +2. **Review transformers** - Broken or misconfigured transformers +3. **Test simple job** - Export a basic square to isolate issue +4. **Check logs** - Look for warnings during generation + +**Solutions:** + +- Fix invalid settings +- Disable problematic transformers +- Report bug with sample project + +### File Won't Load on Controller + +**Problem:** Controller rejects or can't read the G-code file. + +**Possible causes:** + +1. **Wrong dialect** - GRBL vs other firmware +2. **Unsupported commands** - Custom commands not recognized +3. **File too large** - Exceeds controller memory +4. **Filename issues** - Spaces or special characters +5. **Line ending format** - Windows vs Unix line endings + +**Solutions:** + +- Verify correct dialect selected +- Simplify to reduce file size +- Rename file (no spaces, short name) +- Convert line endings if needed (dos2unix or unix2dos) + +### Coordinates Out of Bounds + +**Problem:** G-code tries to move outside machine limits. + +**Diagnosis:** + +Check the Frame feature or G-code for coordinates exceeding work area. + +**Solutions:** + +1. **Reposition job** within bounds +2. **Scale down** if too large +3. **Check machine dimensions** are correctly configured +4. **Account for overscan** - Reduces available area + +--- + +## Advanced Export Options + +### Custom Post-Processors + +For advanced users, custom G-code post-processing may be possible: + +**Potential customizations:** +- Add custom headers/footers +- Modify command syntax +- Insert pauses or prompts +- Translate to other dialects + +**Implementation:** Currently limited; consider scripting external post-processor. + +### Batch Export + +**Export multiple projects:** + +Currently requires manual export of each project. Scripting batch export may be possible via command-line interface (if available). + +--- + +## Best Practices + +### Before Export + +- [ ] Preview in 3D +- [ ] Run simulation mode +- [ ] Check all layers enabled/disabled as intended +- [ ] Verify operations have valid settings +- [ ] Test frame on machine (if possible) + +### After Export + +- [ ] Check file size is reasonable +- [ ] Open in text editor and spot-check +- [ ] Validate with G-code viewer +- [ ] Backup G-code for successful jobs +- [ ] Name file descriptively + +### For Production + +- **Archive successful G-code** - Keep files for repeat jobs +- **Version control** - Track changes to settings +- **Document settings** - Note material, power, speed in filename or comments +- **Test on scrap first** - Verify new exports before production runs + +--- + +## Related Pages + +- [Importing Files](importing.md) - Getting designs into RayForge +- [Supported Formats](formats.md) - File format details +- [G-code Dialects](../reference/gcode-dialects.md) - Dialect differences +- [Macros & Hooks](../features/macros-hooks.md) - Customizing output +- [Simulation Mode](../features/simulation-mode.md) - Preview before export diff --git a/docs-site/files/formats.md b/docs-site/files/formats.md new file mode 100644 index 000000000..81ff7ee9d --- /dev/null +++ b/docs-site/files/formats.md @@ -0,0 +1,304 @@ +# Supported File Formats + +This page provides detailed information about all file formats supported by RayForge, including capabilities, limitations, and recommendations. + +## Format Overview + +### Quick Reference + +| Format | Type | Import | Export | Recommended Use | +|--------|------|--------|--------|-----------------| +| **SVG** | Vector |  Direct |  | Primary design format | +| **DXF** | Vector |  Direct |  | CAD interchange | +| **PDF** | Mixed |  Trace |  | Document export (limited) | +| **PNG** | Raster |  Trace |  | Photos, images | +| **JPEG** | Raster |  Trace |  | Photos | +| **BMP** | Raster |  Trace |  | Simple graphics | +| **G-code** | Control |  |  | Machine output | +| **RayForge Project** | Project |  |  | Save/load projects | + +--- + +## Vector Formats + +### SVG (Scalable Vector Graphics) + +**Extension:** `.svg` +**MIME Type:** `image/svg+xml` +**Import:** Direct vector parsing or bitmap trace +**Export:** Not supported + +**What is SVG?** + +SVG is an XML-based vector image format. It's the **preferred format** for importing designs into RayForge. + +**Supported Features:** + +-  Paths (lines, curves, arcs) +-  Basic shapes (rectangles, circles, ellipses, polygons) +-  Groups and transformations +-  Stroke and fill colors +-  Multiple layers +-  Coordinate transformations (translate, rotate, scale) + +**Unsupported/Limited Features:** + +-  Text (must be converted to paths first) +-  Gradients (simplified or ignored) +-  Filters and effects (ignored) +-  Masks and clipping paths (may not work correctly) +-  Embedded raster images (imported separately if possible) +-  Complex stroke styles (dashes may be simplified) +-  Symbols and use elements (instances may not update) + +**Best Practices:** + +1. **Use Plain SVG format** (not Inkscape SVG or other tool-specific variants) +2. **Convert text to paths** before exporting +3. **Simplify complex paths** to reduce node count +4. **Flatten groups** when possible +5. **Remove unused elements** (guides, grids, hidden layers) +6. **Set document units** to mm (RayForge's native unit) + +**Software Recommendations:** + +- **Inkscape** (free) - Excellent SVG support, native format +- **Adobe Illustrator** - Professional tool, "Save As SVG" with simplified options +- **Affinity Designer** - Good SVG export capabilities +- **Figma** - Web-based, export as SVG + +--- + +### DXF (Drawing Exchange Format) + +**Extension:** `.dxf` +**MIME Type:** `application/dxf`, `image/vnd.dxf` +**Import:** Direct vector parsing +**Export:** Not supported + +**What is DXF?** + +DXF is an AutoCAD drawing format, widely used for CAD interchange. + +**Supported Versions:** + +-  **R12/LT2** (recommended - best compatibility) +-  R13, R14 +-  R2000 and later (usually works, but R12 is safer) + +**Supported Entities:** + +-  Lines (LINE) +-  Polylines (LWPOLYLINE, POLYLINE) +-  Arcs (ARC) +-  Circles (CIRCLE) +-  Splines (SPLINE) - converted to polylines +-  Ellipses (ELLIPSE) +-  Layers + +**Unsupported/Limited Features:** + +-  3D entities (use 2D projection) +-  Dimensions and annotations (ignored) +-  Blocks/inserts (may not instance correctly) +-  Complex line types (simplified to solid) +-  Text (ignored, convert to outlines first) +-  Hatches (may be simplified or ignored) + +**Common Issues:** + +**1. Wrong scale** + - **Cause:** DXF files don't always specify units clearly + - **Solution:** Verify units before export, scale manually if needed + +**2. Missing entities** + - **Cause:** Unsupported entity types or layers turned off + - **Solution:** Check layer visibility, convert complex entities to polylines + +**3. Segmented curves** + - **Cause:** Splines and ellipses converted to line segments + - **Solution:** Increase segment count in export settings + +**Best Practices:** + +1. **Export as R12/LT2 DXF** for maximum compatibility +2. **Use 2D geometry only** (no 3D) +3. **Simplify before export:** + - Convert splines to polylines + - Explode blocks if needed + - Remove dimensions and text +4. **Check units** (mm recommended) +5. **Test in viewer** before importing to RayForge + +**Software Recommendations:** + +- **LibreCAD** (free) - Good DXF support +- **QCAD** (free community edition) - DXF native format +- **AutoCAD** - Industry standard +- **FreeCAD** - Free parametric CAD with DXF export +- **Fusion 360** - Free for hobbyists, excellent DXF export + +--- + +### PDF (Portable Document Format) + +**Extension:** `.pdf` +**MIME Type:** `application/pdf` +**Import:** Rendered to bitmap, then traced +**Export:** Not supported + +**What is PDF Import?** + +RayForge can import PDF files by rasterizing them first, then tracing to vectors. + +**Process:** +1. PDF rendered to raster image (default 300 DPI) +2. Raster traced to create vector paths +3. Paths added to document + +**Limitations:** + +- **Not true vector import** - Even vector PDFs are rasterized +- **Quality loss** from rasterization +- **First page only** - Multi-page PDFs only import page 1 +- **Slow for complex PDFs** - Rendering and tracing takes time + +**When to Use:** + +- Last resort when SVG/DXF not available +- Quick import of simple designs +- Documents with mixed content + +**Better Alternatives:** + +- **Export SVG from source** instead of PDF +- **Use vector formats** (SVG, DXF) when possible +- **For text:** Export with text converted to outlines + +--- + +## Raster Formats + +All raster formats are **imported by tracing** - converted to vector paths automatically. + +### PNG (Portable Network Graphics) + +**Extension:** `.png` +**MIME Type:** `image/png` +**Import:** Trace to vectors +**Export:** Not supported + +**Characteristics:** + +- **Lossless compression** - No quality loss +- **Transparency support** - Alpha channel preserved +- **Good for:** Logos, line art, screenshots, anything needing transparency + +**Tracing Quality:**  (Excellent for high-contrast images) + +**Best Practices:** + +- Use PNG for logos and graphics with sharp edges +- Ensure high contrast between foreground and background +- Transparent background works better than white + +--- + +### JPEG (Joint Photographic Experts Group) + +**Extension:** `.jpg`, `.jpeg` +**MIME Type:** `image/jpeg` +**Import:** Trace to vectors +**Export:** Not supported + +**Characteristics:** + +- **Lossy compression** - Some quality loss +- **No transparency** - Always has background +- **Good for:** Photos, continuous-tone images + +**Tracing Quality:**  (Good for photos, but complex) + +**Best Practices:** + +- Use high-quality JPEG (low compression) +- Increase contrast before importing +- Consider pre-processing in image editor +- Better to convert to PNG first if possible + +--- + +### BMP (Bitmap) + +**Extension:** `.bmp` +**MIME Type:** `image/bmp` +**Import:** Trace to vectors +**Export:** Not supported + +**Characteristics:** + +- **Uncompressed** - Large file sizes +- **Simple format** - Widely compatible +- **Good for:** Simple graphics, old software output + +**Tracing Quality:**  (Good, but no better than PNG) + +**Best Practices:** + +- Convert to PNG for smaller file size (no quality difference) +- Only use if source software can't export PNG/SVG + +--- + +## Output Formats + +### G-code + +**Extension:** `.gcode`, `.nc`, `.ngc` +**MIME Type:** `text/plain` +**Import:** Not supported +**Export:**  Primary output format + +**What is G-code?** + +G-code is the **machine control language** used by laser controllers. + +**RayForge G-code Features:** + +- **Dialect support:** GRBL (primary) +- **Optimized toolpaths:** Efficient move ordering +- **Comments:** Human-readable annotations +- **Precision control:** Configurable decimal places +- **Macro insertion:** Custom G-code via hooks + +**Export Settings:** + +| Setting | Description | Typical Value | +|---------|-------------|---------------| +| **Precision** | Decimal places for coordinates | 3 (e.g., 12.345) | +| **Dialect** | G-code flavor | GRBL | +| **Line numbers** | Add N line numbers | Usually off | +| **Whitespace** | Add spaces for readability | Usually on | + +**File Size:** + +- Simple cuts: 1-50 KB +- Complex engraving: 1-50 MB (large jobs can be >100 MB) + +**Compatibility:** + +-  GRBL 1.1+ (primary target) +-  grblHAL +-  GRBL 0.9 (limited testing) +-  Marlin, Smoothieware (not officially supported) + +See [G-code Dialects](../reference/gcode-dialects.md) for details. + +--- + + +## Related Pages + +- [Importing Files](importing.md) - How to import each format +- [Exporting G-code](exporting.md) - G-code export options +- [File Format Specs](../reference/file-format-spec.md) - Technical specifications diff --git a/docs-site/files/importing.md b/docs-site/files/importing.md new file mode 100644 index 000000000..ca6801dd4 --- /dev/null +++ b/docs-site/files/importing.md @@ -0,0 +1,423 @@ +# Importing Files + +RayForge supports importing various file formats, both vector and raster. This page explains how to import files and optimize them for best results. + +## Supported File Formats + +### Vector Formats + +| Format | Extension | Import Method | Best For | +|--------|-----------|---------------|----------| +| **SVG** | `.svg` | Direct vectors or trace | Vector graphics, logos, designs | +| **DXF** | `.dxf` | Direct vectors | CAD drawings, technical designs | +| **PDF** | `.pdf` | Render and trace | Documents with vector content | + +### Raster Formats + +| Format | Extension | Import Method | Best For | +|--------|-----------|---------------|----------| +| **PNG** | `.png` | Trace to vectors | Photos, images with transparency | +| **JPEG** | `.jpg`, `.jpeg` | Trace to vectors | Photos, continuous-tone images | +| **BMP** | `.bmp` | Trace to vectors | Simple graphics, screenshots | + +!!! note "Raster Import" + All raster images are **traced** to create vector paths that can be used for laser operations. The quality depends on the tracing configuration. + +--- + +## Importing Files + +### Method 1: File Menu + +1. **File Import** (or Ctrl+I) +2. **Select your file** from the file picker +3. **For SVG:** Choose import method (see below) +4. **For rasters:** Files are automatically traced +5. **File appears** in the canvas and document tree + +### Method 2: Drag and Drop + +1. **Drag file** from your file manager +2. **Drop onto** the RayForge canvas +3. **Import proceeds** as above + +### Method 3: Command Line + +```bash +# Open RayForge with a file +rayforge myfile.svg + +# Multiple files +rayforge file1.svg file2.dxf +``` + +--- + +## SVG Import + +SVG (Scalable Vector Graphics) is the **recommended format** for vector designs. + +### Import Options + +When importing SVG, RayForge offers two methods: + +#### 1. Import Vectors Directly (Recommended) + +**How it works:** +- Parses SVG and converts paths directly to RayForge geometry +- High-fidelity preservation of curves and shapes +- Maintains exact vector data + +**Pros:** +- Best quality and precision +- Editable paths +- Small file size + +**Cons:** +- Some advanced SVG features not supported +- Complex SVGs may have issues + +**Use for:** +- Clean vector designs from Inkscape, Illustrator +- Simple to moderate complexity +- Designs without advanced SVG features + +#### 2. Trace Bitmap + +**How it works:** +- Renders SVG to a raster image first +- Traces the rendered image to create vectors +- More compatible but less precise + +**Pros:** +- Handles complex SVG features +- Robust fallback method +- Supports effects and filters + +**Cons:** +- Quality loss from rasterization +- Larger file sizes +- Not as precise + +**Use for:** +- SVGs that fail direct import +- SVGs with effects, filters, gradients +- When direct import produces errors + +### SVG Best Practices + +**Prepare your SVG for best results:** + +1. **Convert text to paths:** + - Inkscape: `Path Object to Path` + - Illustrator: `Type Create Outlines` + +2. **Simplify complex paths:** + - Inkscape: `Path Simplify` (Ctrl+L) + - Remove unnecessary nodes + +3. **Ungroup nested groups:** + - Flatten hierarchy where possible + - `Object Ungroup` (Ctrl+Shift+G) + +4. **Remove hidden elements:** + - Delete guides, grids, construction lines + - Remove invisible/transparent objects + +5. **Save as Plain SVG:** + - Inkscape: "Plain SVG" or "Optimized SVG" + - Not "Inkscape SVG" (has extra metadata) + +6. **Check document units:** + - Set to mm or inches as appropriate + - RayForge uses mm internally + +**Common SVG features that may not import:** + +- Gradients (convert to solid fills or raster) +- Filters and effects (flatten to paths) +- Masks and clipping paths (expand/flatten) +- Embedded raster images (export separately) +- Text (convert to paths first) + +--- + +## DXF Import + +DXF (Drawing Exchange Format) is common for CAD software. + +### DXF Versions + +RayForge supports standard DXF formats: + +- **R12/LT2** (recommended) - Best compatibility +- **R13, R14** - Good support +- **R2000+** - Generally works, but R12 is safer + +**Tip:** Export as R12/LT2 DXF for maximum compatibility. + +### DXF Import Tips + +**Before exporting from CAD:** + +1. **Simplify the drawing:** + - Remove unnecessary layers + - Delete dimensions and annotations + - Remove 3D objects (use 2D projection) + +2. **Check units:** + - Verify drawing units (mm vs inches) + - RayForge assumes mm by default + +3. **Flatten layers:** + - Consider exporting only relevant layers + - Hide or delete construction layers + +4. **Use appropriate precision:** + - Laser precision is typically 0.1mm + - Don't over-specify precision + +**After import:** + +- Check scale (DXF units may need adjustment) +- Verify all paths imported correctly +- Delete any unwanted construction elements + +--- + +## PDF Import + +PDF files can contain vector graphics, raster images, or both. + +### How PDF Import Works + +RayForge **renders the PDF** to an image, then **traces** it to create vectors. + +**Process:** +1. PDF rendered at specified DPI (default 300) +2. Rendered image traced using vectorization +3. Resulting paths added to document + +**Limitations:** +- Text is rasterized (not editable as paths) +- Vector quality depends on rendering DPI +- Multi-page PDFs: only first page imported + +### PDF Import Tips + +**Best results:** + +1. **Use vector PDFs:** + - PDFs created from vector software (Illustrator, Inkscape) + - Not scanned documents or embedded images + +2. **Export SVG instead if possible:** + - Most design software can export SVG directly + - SVG will have better quality than PDF import + +3. **For documents with text:** + - Export as SVG with fonts converted to paths + - Or render PDF at high DPI (600+) and trace + +--- + +## Raster Image Import (PNG, JPG, BMP) + +Raster images are **automatically traced** to create vector paths. + +### Tracing Process + +**How it works:** + +1. **Image loaded** into RayForge +2. **Tracing algorithm** detects edges and shapes +3. **Vector paths created** from the traced edges +4. **Paths added** to the document as workpieces + +### Tracing Configuration + +**Adjustable parameters:** + +| Parameter | Description | Effect | +|-----------|-------------|--------| +| **Threshold** | Black/white cutoff | Lower = more detail, higher = simpler | +| **Despeckle** | Remove noise | Higher = cleaner, removes small details | +| **Smoothing** | Curve smoothing | Higher = smoother but less accurate | +| **Corner Threshold** | Sharp vs smooth corners | Lower = more sharp corners | + +**Default settings** work well for most images. + +### Preparing Images for Tracing + +**For best results:** + +1. **High contrast:** + - Adjust brightness/contrast in image editor + - Clear distinction between foreground and background + +2. **Clean background:** + - Remove noise and artifacts + - Solid white or transparent background + +3. **Appropriate resolution:** + - 300-500 DPI for photos + - Too high = slow tracing, too low = poor quality + +4. **Crop to content:** + - Remove unnecessary borders + - Focus on the area to be engraved/cut + +5. **Convert to black and white:** + - For cutting: pure B&W + - For engraving: grayscale is fine + +**Image editing tools:** +- GIMP (free) +- Photoshop +- Krita (free) +- Paint.NET (free, Windows) + +### Trace Quality + +**Good trace candidates:** +- Logos with clear edges +- High-contrast images +- Line art and drawings +- Text (though better as vector) + +**Poor trace candidates:** +- Low-resolution images +- Photos with soft edges +- Images with gradients +- Very detailed or complex photos + +--- + +## Import Troubleshooting + +### File Won't Import + +**Problem:** RayForge doesn't recognize or can't open the file. + +**Solutions:** + +1. **Check file format** - Ensure it's a supported type +2. **Try different format** - Convert SVG DXF or vice versa +3. **Re-export from source** - Original software may have export issues +4. **Check file corruption** - Open in another application first +5. **Simplify the file** - Remove complex features and retry + +### Import is Empty + +**Problem:** File imports but nothing appears in canvas. + +**Diagnosis:** + +1. **Extremely large coordinates** - Objects far from origin +2. **Empty file** - No actual content +3. **Unsupported features only** - All elements filtered out + +**Solutions:** + +- **Zoom out significantly** or `View Zoom to Fit` +- **Check source file** in original application +- **Simplify and re-export** from design software +- **Check document tree** - objects may be there but not visible + +### Imported Shapes are Wrong + +**Problem:** Shapes are distorted, wrong size, or incorrect. + +**Common causes:** + +1. **Unit mismatch** - File in inches, interpreted as mm (or vice versa) +2. **Scale issue** - DPI or export settings wrong +3. **Transform matrix** - Complex transformations not handled +4. **Curved paths** - Arc/bezier conversion issues + +**Solutions:** + +- **Check source units** - Verify document units before export +- **Scale manually** - Measure and correct after import +- **Simplify paths** - Convert complex curves to simpler forms +- **Export as simpler format** - Try different export settings + +### Trace Quality Poor + +**Problem:** Raster images trace with jagged or incorrect paths. + +**Solutions:** + +1. **Increase image resolution** - Use higher quality source +2. **Adjust threshold** - Find right balance for your image +3. **Pre-process image** - Edit for contrast and cleanup +4. **Use smaller despeckle** - Preserve more detail +5. **Trace manually** - Redraw in vector software instead + +### Import Takes Forever + +**Problem:** Import process is extremely slow. + +**Causes:** + +- Very complex SVG (thousands of paths) +- High-resolution raster being traced +- Large file size + +**Solutions:** + +- **Simplify in design software** before importing +- **Reduce image resolution** for rasters +- **Split large files** into multiple smaller files +- **Remove unnecessary elements** (guides, hidden layers) + +--- + +## File Organization Tips + +### Naming Conventions + +**Good file names:** +- `logo-engrave.svg` +- `box-cuts-3mm-ply.dxf` +- `photo-portrait-150x200.png` + +**Include:** +- Project name +- Operation type (cut, engrave) +- Material/thickness if relevant +- Dimensions + +### File Preparation Checklist + +Before importing: + +- [ ] Text converted to paths +- [ ] Complex paths simplified +- [ ] Hidden elements removed +- [ ] Correct units set +- [ ] Appropriate file format selected +- [ ] File tested in original software +- [ ] Exported with compatible settings + +### Design Software Recommendations + +**Vector design:** +- **Inkscape** (free, excellent SVG support) +- **Adobe Illustrator** (professional, paid) +- **Affinity Designer** (affordable alternative) +- **LibreCAD** (free, for DXF/CAD work) + +**Raster editing:** +- **GIMP** (free, powerful) +- **Photoshop** (professional, paid) +- **Krita** (free, good for digital art) + +--- + +## Related Pages + +- [Supported Formats](formats.md) - Detailed format specifications +- [Exporting G-code](exporting.md) - Output options +- [File Format Specs](../reference/file-format-spec.md) - Technical details +- [Quick Start](../getting-started/quick-start.md) - First import tutorial diff --git a/docs-site/files/index.md b/docs-site/files/index.md new file mode 100644 index 000000000..05b289e8d --- /dev/null +++ b/docs-site/files/index.md @@ -0,0 +1,112 @@ +# File Formats + +Rayforge supports a wide variety of file formats for importing designs and exporting G-code. + +## Overview + +- **[Importing Files](importing.md)**: How to import designs into Rayforge +- **[Supported Formats](formats.md)**: Complete list of supported file types +- **[Exporting G-code](exporting.md)**: Generate and save G-code files + +## Supported Import Formats + +### Vector Formats + +Vector formats are ideal for cutting and engraving with sharp, precise paths: + +| Format | Extension | Best For | Notes | +|:-------|:----------|:---------|:------| +| **SVG** | `.svg` | General use, web graphics | Most common format, fully supported | +| **DXF** | `.dxf` | CAD drawings, technical designs | AutoCAD and CAD software output | +| **PDF** | `.pdf` | Documents, print-ready designs | Vector content extracted | + +### Raster Formats + +Raster (bitmap) images are best for engraving and photo reproduction: + +| Format | Extension | Best For | Notes | +|:-------|:----------|:---------|:------| +| **JPEG** | `.jpg`, `.jpeg` | Photos, complex images | Lossy compression | +| **PNG** | `.png` | Graphics with transparency | Lossless compression | +| **BMP** | `.bmp` | Simple graphics | Large file sizes | +| **TIFF** | `.tif`, `.tiff` | High-quality images | Support for multiple layers | + +### Specialized Formats + +| Format | Extension | Best For | Notes | +|:-------|:----------|:---------|:------| +| **Ruida** | `.rd` | Ruida laser controller files | Import existing Ruida jobs | + +## Working with Different File Types + +### Vector Files (SVG, DXF, PDF) + +**Best Practices:** + +- ✓ Use for contour cutting +- ✓ Scalable without quality loss +- ✓ Edit paths before import in design software +- ✓ Convert text to paths before import + +**Common Issues:** + +- Text not converted to paths: Convert in design software first +- Embedded raster images: Extract or trace to vectors +- Complex gradients: May not import correctly + +### Raster Images (JPEG, PNG, BMP) + +**Best Practices:** + +- ✓ Use for engraving photos and complex images +- ✓ Higher DPI = better detail (300+ DPI recommended) +- ✓ Convert to grayscale for single-color engraving +- ✓ High contrast improves results + +**Common Issues:** + +- Low resolution: Results in pixelated engraving +- Wrong DPI: Specify DPI in import settings +- Color images: Converted to grayscale automatically + +### Ruida Files (.rd) + +Import jobs created for Ruida controllers: + +- Operations converted to Rayforge operations +- Layer assignments preserved +- Power and speed settings imported +- May require adjustment for your specific machine + +## File Import Workflow + +1. **Prepare file**: Optimize in design software +2. **Import**: File → Open or drag-and-drop +3. **Review**: Check that all elements imported correctly +4. **Scale**: Verify dimensions are correct +5. **Assign operations**: Configure cutting/engraving operations +6. **Generate G-code**: Machine → Generate G-code + +## Export Formats + +### G-code + +Rayforge generates standard G-code for GRBL and Smoothieware: + +- **GRBL**: Standard GRBL commands (G0, G1, M3, M5, etc.) +- **Smoothieware**: Smoothieware-specific extensions +- **Custom**: Configure custom G-code dialect + +See [Exporting G-code](exporting.md) for details. + +### Project Files + +Save your work as Rayforge project files: + +- **Extension**: `.rayforge` (coming soon) +- **Contains**: All designs, operations, and settings +- **Portable**: Share with other Rayforge users + +--- + +**Next**: [Importing Files →](importing.md) | [Supported Formats →](formats.md) diff --git a/docs-site/getting-started/first-time-setup.md b/docs-site/getting-started/first-time-setup.md new file mode 100644 index 000000000..ee1793b61 --- /dev/null +++ b/docs-site/getting-started/first-time-setup.md @@ -0,0 +1,158 @@ +# First Time Setup + +After installing Rayforge, you'll need to configure your laser cutter or engraver. This guide will walk you through creating your first machine profile and establishing a connection. + +## Step 1: Launch Rayforge + +Start Rayforge from your application menu or by running `rayforge` in a terminal. You should see the main interface with an empty canvas. + +## Step 2: Open Machine Settings + +Navigate to **Settings → Machine Settings** or press ++ctrl+comma++ to open the machine configuration dialog. + +![Machine Settings](../images/machine-settings.png) + +## Step 3: Create a Machine Profile + +Rayforge supports multiple machine profiles, allowing you to switch between different laser cutters quickly. + +### General Settings + +1. **Machine Name**: Give your machine a descriptive name (e.g., "K40 Laser", "Ortur LM2") +2. **Working Area**: + - **Width**: Enter the maximum width of your working area in millimeters + - **Height**: Enter the maximum height of your working area in millimeters +3. **Origin Position**: Select where your machine's origin (0,0) is located: + - Bottom Left (most common for GRBL) + - Top Left + - Top Right + - Bottom Right + +### Laser Configuration + +4. **Power Settings**: + - **Min Power**: Minimum laser power percentage (typically 0-10%) + - **Max Power**: Maximum laser power percentage (typically 80-100%) + +!!! tip "Power Calibration" + Start with conservative power settings. You can always increase power later after testing. + +5. **Speed Settings**: + - **Default Speed**: Your typical engraving/cutting speed in mm/min + - **Max Speed**: Maximum speed your machine supports + +## Step 4: Configure Device Connection + +Switch to the **Device** tab to configure how Rayforge connects to your machine. + +![Device Settings](../images/machine-device.png) + +### Connection Types + +=== "Serial Port (USB)" + + The most common connection type for GRBL devices. + + 1. **Connection Type**: Select "Serial Port" + 2. **Port**: Choose your device from the dropdown (e.g., `/dev/ttyUSB0` on Linux, `COM3` on Windows) + 3. **Baud Rate**: Select `115200` (standard for most GRBL devices) + 4. **Flow Control**: Leave as "None" unless your device requires it + + !!! info + If your device doesn't appear in the list, check that it's connected and that you have the necessary permissions. On Linux, you may need to add your user to the `dialout` group. + +=== "Network (WiFi/Ethernet)" + + For GRBL devices with network connectivity. + + 1. **Connection Type**: Select "Network" + 2. **Host**: Enter the IP address of your device (e.g., `192.168.1.100`) + 3. **Port**: Enter the port number (typically `23` or `8080`) + +=== "Telnet (Smoothieware)" + + For Smoothieware-based devices. + + 1. **Connection Type**: Select "Telnet" + 2. **Host**: Enter the IP address of your Smoothieware device + 3. **Port**: Enter the Telnet port (typically `23`) + +### Firmware Settings + +1. **Firmware Type**: Select your device's firmware: + - **GRBL** (most common) + - **Smoothieware** + - **GRBL-compatible** + +## Step 5: Test Connection + +1. Click the **Connect** button in the device settings or use the connect button in the main toolbar +2. You should see a "Connected" status indicator +3. Try sending a simple command: + - Go to **Machine → Home** (or press ++ctrl+h++) + - Your machine should perform a homing cycle + +![Connection Status](../images/machine-device.png) + +!!! success "Connected!" + If your machine responds correctly, you're ready to start using Rayforge! + +## Step 6: Save Your Profile + +1. Click **Save** or **OK** to save your machine profile +2. Your settings will be remembered for future sessions + +## Optional: Advanced Configuration + +### Multiple Lasers + +If your machine has multiple laser modules (e.g., diode and CO2), you can configure them in the **Lasers** tab. + +![Laser Settings](../images/machine-laser.png) + +See [Multiple Lasers](../machine/multi-laser.md) for details. + +### Camera Setup + +If you have a USB camera for alignment and positioning, configure it in the **Camera** tab. + +![Camera Settings](../images/machine-camera.png) + +See [Camera Integration](../features/camera.md) for details. + +--- + +## Troubleshooting Connection Issues + +### Device Not Found + +- **Linux (Serial)**: Add your user to the `dialout` group: + ```bash + sudo usermod -a -G dialout $USER + ``` + Log out and back in for changes to take effect. + +- **Snap Package**: Ensure you've granted serial port permissions: + ```bash + sudo snap connect rayforge:serial-port + ``` + +- **Windows**: Check Device Manager to confirm the device is recognized and note the COM port number. + +### Connection Refused + +- Verify the IP address and port number are correct +- Ensure your machine is powered on and connected to the network +- Check firewall settings if using network connection + +### Machine Not Responding + +- Try a different baud rate (some devices use `9600` or `57600`) +- Check for loose cables or poor connections +- Power cycle your laser cutter and try again + +For more help, see [Connection Issues](../troubleshooting/connection.md). + +--- + +**Next:** [Quick Start Guide →](quick-start.md) diff --git a/docs-site/getting-started/index.md b/docs-site/getting-started/index.md new file mode 100644 index 000000000..cc6ec2b04 --- /dev/null +++ b/docs-site/getting-started/index.md @@ -0,0 +1,41 @@ +# Getting Started + +Welcome to Rayforge! This section will help you install, configure, and run your first laser job. + +## Prerequisites + +Before you begin, ensure you have: + +- A GRBL-based laser cutter or engraver +- A computer running Linux or Windows +- A USB cable or network connection to your machine +- Design files (SVG, DXF, PDF, or images) ready to laser + +## Installation Steps + +1. **[Install Rayforge](installation.md)** - Choose your platform and follow the installation guide +2. **[First Time Setup](first-time-setup.md)** - Configure your machine profile and test the connection +3. **[Quick Start Guide](quick-start.md)** - Run your first laser job + +## What You'll Learn + +By the end of this section, you'll be able to: + +- ✓ Install Rayforge on your system +- ✓ Connect to your laser cutter +- ✓ Create a machine profile +- ✓ Import a design file +- ✓ Configure operations +- ✓ Preview and send G-code to your machine + +## Need Help? + +If you encounter any issues during setup: + +- Check the [Troubleshooting](../troubleshooting/index.md) section +- Review [Connection Issues](../troubleshooting/connection.md) for connectivity problems +- Report bugs on [GitHub Issues](https://github.com/barebaric/rayforge/issues) + +--- + +**Next:** [Installation Guide →](installation.md) diff --git a/docs-site/getting-started/installation.md b/docs-site/getting-started/installation.md new file mode 100644 index 000000000..e718b7f1f --- /dev/null +++ b/docs-site/getting-started/installation.md @@ -0,0 +1,122 @@ +# Installation + +Rayforge is available for Linux and Windows. Choose your platform below and follow the installation instructions. + +## :fontawesome-brands-linux: Linux + +Rayforge offers several installation methods for Linux users. Choose the one that best fits your distribution. + +### Ubuntu & Derivatives (Recommended) + +For Ubuntu 24.04 LTS and newer, as well as derivatives like Linux Mint and Pop!_OS, we recommend using our official PPA. This method provides automatic updates through your system's package manager. + +```bash +sudo add-apt-repository ppa:knipknap/rayforge +sudo apt update +sudo apt install rayforge +``` + +Once installed, launch Rayforge from your application menu or by running `rayforge` in a terminal. + +### Snap Package (Cross-Distribution) + +The Snap package works on most Linux distributions and includes all dependencies in a sandboxed environment. + +[![Get it from the Snap Store](https://snapcraft.io/en/light/install.svg)](https://snapcraft.io/rayforge) + +Or install from the command line: + +```bash +sudo snap install rayforge +``` + +!!! warning "Permissions Required" + The Snap version runs in a sandbox and requires manual permission grants for hardware access. + +#### Granting Permissions + +**For Camera Access:** +```bash +sudo snap connect rayforge:camera +``` + +**For USB Serial Port Access:** +```bash +# Enable experimental hotplug support (one-time setup) +sudo snap set system experimental.hotplug=true + +# Connect your laser via USB, then grant access +sudo snap connect rayforge:serial-port +``` + +See [Snap Permissions Troubleshooting](../troubleshooting/snap-permissions.md) for more details. + +### From Source (Advanced) + +For developers and advanced users who want to run the latest development version or contribute to the project. + +**Requirements:** + +- Python 3.11 or newer +- System dependencies for GTK4 and GObject Introspection + +**Installation on Debian/Ubuntu:** + +```bash +# Install system dependencies +sudo apt update +sudo apt install python3-pip python3-gi gir1.2-gtk-3.0 gir1.2-adw-1 \ + gir1.2-gdkpixbuf-2.0 libgirepository-1.0-dev libgirepository-2.0-0 \ + libvips42t64 libadwaita-1-0 libopencv-dev + +# Install Rayforge from PyPI +pip3 install rayforge +``` + +!!! note + Package names may differ on other distributions. Refer to your distribution's documentation. + +--- + +## :fontawesome-brands-windows: Windows + +Download the latest installer from the **[Releases Page](https://github.com/barebaric/rayforge/releases/)**. + +1. Download `rayforge-x.x.x-installer.exe` +2. Run the installer and follow the on-screen instructions +3. Launch Rayforge from the Start Menu or Desktop shortcut + +--- + +## :fontawesome-brands-apple: macOS + +There are currently no official macOS builds. However, Rayforge may run from source using the pip installation method. Community contributions for macOS packaging are welcome! + +--- + +## Verifying Installation + +After installation, verify that Rayforge is working: + +1. Launch Rayforge from your application menu or terminal +2. You should see the main window with the canvas and toolbar +3. Check **Help → About** to confirm the installed version + +![Rayforge Main Window](../images/ss-main.png) + +--- + +## Next Steps + +Now that Rayforge is installed, proceed to [First Time Setup](first-time-setup.md) to configure your machine. + +## Troubleshooting + +If you encounter issues during installation: + +- **Linux PPA**: Ensure you're running Ubuntu 24.04 or newer +- **Snap permissions**: See [Snap Permissions Guide](../troubleshooting/snap-permissions.md) +- **Windows**: Run the installer as Administrator if you encounter permission errors +- **From source**: Ensure all system dependencies are installed + +For additional help, visit the [Troubleshooting](../troubleshooting/index.md) section or report an issue on [GitHub](https://github.com/barebaric/rayforge/issues). diff --git a/docs-site/getting-started/quick-start.md b/docs-site/getting-started/quick-start.md new file mode 100644 index 000000000..feb9f25e4 --- /dev/null +++ b/docs-site/getting-started/quick-start.md @@ -0,0 +1,169 @@ +# Quick Start Guide + +Now that Rayforge is installed and your machine is configured, let's run your first laser job! This guide will walk you through importing a design, configuring operations, and sending G-code to your machine. + +## Workflow Overview + +```mermaid +flowchart LR + A[Import Design] --> B[Position & Scale] + B --> C[Assign Operation] + C --> D[Preview G-code] + D --> E[Generate G-code] + E --> F[Frame Job] + F --> G[Start Job] + + style A fill:#e1f5ff + style C fill:#fff3e0 + style D fill:#f3e5f5 + style G fill:#e8f5e9 +``` + +## Step 1: Import a Design + +Rayforge supports various file formats including SVG, DXF, PDF, and raster images (JPEG, PNG, BMP). + +1. **Click** **File → Open** or press ++ctrl+o++ +2. Navigate to your design file and select it +3. The design will appear on the canvas + +![Canvas with imported design](../images/ss-main.png) + +!!! tip "Don't have a design yet?" + You can create simple shapes using the canvas tools or download free SVG files from sites like [Flaticon](https://www.flaticon.com/) or [SVG Repo](https://www.svgrepo.com/). + +## Step 2: Position Your Design + +Use the canvas tools to position and adjust your design: + +- **Pan**: Middle-click and drag, or hold ++space++ and drag +- **Zoom**: Scroll wheel, or ++ctrl+"+"++ / ++ctrl+"-"++ +- **Move**: Click and drag your design +- **Rotate**: Select the design and use the rotation handles +- **Scale**: Select the design and drag the corner handles + +## Step 3: Assign an Operation + +Operations define how Rayforge will process your design. Common operations include: + +- **Contour**: Cut along the outline of shapes +- **Raster Engrave**: Fill shapes with back-and-forth lines (for engraving) +- **Depth Engrave**: Create 3D depth effects from images + +### Adding an Operation + +1. Select your design on the canvas +2. Click **Operations → Add Operation** or press ++ctrl+shift+a++ +3. Choose the operation type (e.g., "Contour" for cutting) +4. Configure the operation settings: + - **Power**: Laser power percentage (start low and test!) + - **Speed**: Movement speed in mm/min + - **Passes**: Number of times to repeat the operation (useful for cutting thick materials) + +![Operation Settings](../images/contour-settings.png) + +!!! warning "Start with Low Power" + When working with new materials, always start with lower power settings and run test cuts. Gradually increase power until you achieve the desired result. + +### Material Testing Recommendations + +| Material | Power (%) | Speed (mm/min) | Passes | +|----------|-----------|----------------|--------| +| Paper | 10-20 | 3000-5000 | 1 | +| Cardboard| 30-50 | 1500-3000 | 1-2 | +| Plywood (3mm) | 60-80 | 300-600 | 1-3 | +| Acrylic (3mm) | 70-90 | 200-400 | 1-2 | + +*These are starting points only. Always test with your specific machine and materials.* + +## Step 4: Preview G-code + +Before sending to your machine, preview the toolpath in 3D: + +1. Click **View → 3D Preview** or press ++ctrl+3++ +2. The 3D preview window shows the complete toolpath +3. Use your mouse to rotate and zoom the preview +4. Verify that the path looks correct + +![3D Preview](../images/3d-preview.png) + +!!! tip "Catch Errors Early" + The 3D preview helps you spot issues like: + + - Missing paths + - Incorrect ordering + - Operations applied to the wrong objects + - Paths that exceed your working area + +## Step 5: Generate G-code + +1. Click **Machine → Generate G-code** or press ++ctrl+g++ +2. Rayforge will process your operations and generate the G-code +3. The generated code appears in the G-code viewer + +## Step 6: Send to Machine + +!!! danger "Safety First" + - Ensure the work area is clear + - Never leave the machine unattended during operation + - Have fire safety equipment nearby + - Wear appropriate eye protection + +### Preparing Your Material + +1. Place your material on the laser bed +2. Focus the laser according to your machine's instructions +3. If using the camera, align your design using the [camera overlay](../features/camera.md) + +### Starting the Job + +1. **Position the laser**: Use the jog controls to move the laser to the starting position + - Click **Machine → Jog Controls** or press ++ctrl+j++ + - Use the arrow buttons or keyboard arrows to move the laser + - Press ++home++ to home the machine + +2. **Frame the design**: Run the framing function to verify placement + - Click **Machine → Frame Job** or press ++ctrl+f++ + - The laser will trace the bounding box of your design at low/no power + - Verify it fits within your material + +3. **Start the job**: Click **Machine → Start Job** or press ++ctrl+r++ +4. Monitor the progress in the status bar + +### During the Job + +- The status bar shows the current progress and estimated time remaining +- You can pause the job with ++ctrl+p++ or click the Pause button +- Press ++esc++ or click Stop to cancel the job (emergency stop) + +## Step 7: Finishing Up + +Once the job completes: + +1. Wait for the exhaust fan to clear any fumes +2. Carefully remove your finished piece +3. Clean the laser bed if necessary + +!!! success "Congratulations!" + You've completed your first Rayforge job! Now you can explore more advanced features. + +## Next Steps + +Now that you've completed your first job, explore these features: + +- **[Multi-Layer Operations](../features/multi-layer.md)**: Assign different operations to layers +- **[Holding Tabs](../features/holding-tabs.md)**: Keep cut pieces in place during cutting +- **[Camera Integration](../features/camera.md)**: Use a camera for precise alignment +- **[G-code Macros](../features/macros-hooks.md)**: Automate repetitive tasks + +## Tips for Success + +1. **Save your work**: Use ++ctrl+s++ to save your project frequently +2. **Test cuts**: Always run a test cut on scrap material first +3. **Material database**: Keep notes on successful power/speed settings for different materials +4. **Maintenance**: Keep your laser lens clean and check belt tension regularly +5. **Air assist**: If your machine has air assist, use it to prevent charring and improve cut quality + +--- + +**Need Help?** Check the [Troubleshooting](../troubleshooting/index.md) section or visit the [GitHub Issues](https://github.com/barebaric/rayforge/issues) page. diff --git a/docs-site/guides/batch-production-workflow.md b/docs-site/guides/batch-production-workflow.md new file mode 100644 index 000000000..a53b015af --- /dev/null +++ b/docs-site/guides/batch-production-workflow.md @@ -0,0 +1,457 @@ +# Batch Production Workflow + +Efficiently produce multiple identical parts using RayForge's production features and best practices. + +## Goal + +Set up a repeatable workflow for cutting multiple identical parts, whether it's 10 coasters for a craft fair or 100 brackets for a product run. + +## Prerequisites + +- Design finalized and tested +- Material settings optimized (use Material Test Grid if needed) +- Sufficient material for production run +- Understanding of RayForge layers and operations + +## Production Workflow Overview + +**Efficient production requires:** + +1. Optimized design (nesting, spacing, minimal waste) +2. Consistent material positioning (jigs, fixtures, or reliable origin) +3. Streamlined job setup (save settings, templates) +4. Quality control (inspect first piece, monitor for drift) +5. Safety procedures (never leave unattended, fire watch) + +## Step 1: Optimize Your Design for Production + +Prepare your design for efficient batch cutting. + +### Part Layout and Nesting + +**Maximize material usage:** + +1. **Duplicate your part** to fill available material area +2. **Arrange in grid** with appropriate spacing +3. **Minimize waste** - pack parts efficiently +4. **Leave margin** for securing material (tape, clamps) + +**Spacing considerations:** + +- **Part-to-part spacing:** 3-5mm minimum + - Too close: Heat affects adjacent parts + - Too far: Wastes material +- **Edge spacing:** 10-15mm from material edges + - Room for securing material + - Avoids edge irregularities + +**Example layout (300mm x 400mm material, 50mm x 50mm parts):** + +``` +Margin -> [==========================] + [ Part Part Part Part ] + [ Part Part Part Part ] + [ Part Part Part Part ] + [ Part Part Part Part ] + [==========================] +``` + +Fits: 16 parts with 5mm spacing between parts, 10mm edge margin + +### Alignment Features + +**Add registration or alignment marks:** + +- Small crosses or circles at corners +- Help position material consistently +- Useful for multi-step processes (cut, then engrave) + +**Don't cut through alignment marks:** +- Use lower power or separate layer +- Keep marks visible for next sheet + +### Optimize Toolpaths + +**Reduce travel time:** + +- Use RayForge's path optimization (if available) +- Group adjacent parts together +- Minimize laser-off travel moves + +**Organize by operation:** + +- Layer 1: All engraving operations +- Layer 2: All cutting operations +- Runs all engraving first, then all cuts (prevents parts from falling out mid-job) + +## Step 2: Create Production Template + +Save your optimized design as a reusable template. + +**Save project file:** + +1. Design your full sheet layout (all parts arranged) +2. Configure all operation settings (power, speed, passes) +3. Save as: `ProductName-ProductionSheet.rf` (or similar) + +**Template benefits:** +- Quickly start new sheets +- Consistent settings every time +- No need to reconfigure for each run + +**Version control:** +- Save versions when changing settings +- Name files: `Coaster-v1.rf`, `Coaster-v2.rf` +- Document what changed in each version + +## Step 3: Set Up Material Positioning System + +Establish a reliable way to position material consistently. + +### Method 1: Absolute Positioning (Simplest) + +**Use job origin in absolute mode:** + +1. Set job origin to specific coordinates (e.g., X=10, Y=10) +2. Always place material in same position on bed +3. Use tape markers or physical stops to guide placement + +**Pros:** +- Simple, no fixtures needed +- Works for any material size + +**Cons:** +- Manual positioning, less precise +- Material must be placed carefully each time + +### Method 2: Physical Jigs + +**Create alignment jigs:** + +1. Cut a positioning jig from scrap material: + - Rectangle with cutout for your material sheet + - Place jig on laser bed, material fits inside + - Material is now positioned consistently + +**Example jig:** +``` +[================================] +[ ] +[ +-----------------+ ] +[ | Your material | ] +[ | fits here | ] +[ +-----------------+ ] +[ ] +[================================] +``` + +**Pros:** +- Fast, consistent positioning +- No measuring needed + +**Cons:** +- Requires creating jig +- Different jig for different material sizes + +### Method 3: Registration Pins + +**Use registration pins for repeatable positioning:** + +1. Cut small holes in corner of material sheet +2. Install pins on laser bed at matching positions +3. Drop material onto pins - perfect alignment every time + +**Pros:** +- Extremely precise +- Fast material changes + +**Cons:** +- Requires modifying material (cutting holes) +- Need to install pins on bed + +### Method 4: Laser-Bed Grid Markings + +**Mark laser bed with ruler markings:** + +1. Use tape or engraved marks to create reference grid +2. Align material edges to grid marks +3. Consistent positioning without jigs + +**Pros:** +- No jigs needed +- Works for various sizes + +**Cons:** +- Less precise than jigs +- Manual alignment each time + +## Step 4: First Article Inspection + +Always inspect the first piece before running full batch. + +**Why inspect first?** +- Verify settings are correct +- Catch design errors before wasting material +- Confirm dimensions are accurate + +**Run one part:** + +1. Run job to cut just the first part (or first few parts) +2. Pause job or run a single-part version of the design + +**Inspect thoroughly:** +- **Dimensions:** Measure with calipers - are parts correct size? +- **Quality:** Clean cuts, no excessive charring? +- **Fit/function:** If parts assemble, test fit now +- **Alignment:** Is positioning on material correct? + +**If issues found:** +- Stop production +- Adjust settings (power, speed, kerf compensation, etc.) +- Re-run first article test +- Don't proceed until first part is perfect + +**If first part is good:** +- Proceed with full production run +- Periodically inspect parts to catch any drift + +## Step 5: Run Production Batches + +Execute your production run efficiently and safely. + +### Safety for Long Runs + +**Never leave laser unattended:** +- Production runs can be long (hours) +- Stay near the machine at all times +- Watch for fires (more cuts = more fire risk) + +**Fire watch:** +- Keep fire extinguisher ready +- Clear debris between sheets (prevents accumulated debris from igniting) +- Monitor high-risk materials closely + +**Ventilation:** +- Ensure exhaust runs continuously +- Check airflow periodically +- Replace filters if using filtration system + +### Material Loading + +**Efficient material changes:** + +1. **Wait for completion** - let current sheet finish +2. **Remove cut parts** - clear bed completely +3. **Clean debris** - remove small pieces and dust (fire hazard) +4. **Load new sheet** - use jig or positioning method +5. **Verify position** - frame job to confirm alignment +6. **Restart job** + +**Material prep:** +- Pre-cut sheets to size (saves time between jobs) +- Stack sheets nearby for quick loading +- Keep sheets flat (warped material causes issues) + +### Monitoring Production + +**Watch for issues:** + +- **Quality drift:** Parts start charring more or cutting less deeply + - Cause: Lens/mirror getting dirty from smoke + - Solution: Pause and clean optics +- **Position drift:** Parts shifting on bed + - Cause: Material warping from heat or poor securing + - Solution: Re-secure material, use better hold-downs +- **Mechanical issues:** Strange sounds, skipped steps + - Cause: Belt slipping, motor overheating + - Solution: Stop, inspect mechanics, let cool + +**Periodic inspection:** +- Every 5-10 parts (or every sheet), inspect one part +- Measure critical dimensions +- Check for quality degradation +- Stop if issues arise + +## Step 6: Quality Control and Final Inspection + +Ensure all parts meet quality standards. + +### Sorting and Inspection + +**Inspect each part:** + +- **Visual inspection:** Check for burn marks, incomplete cuts, damage +- **Dimensional check:** Spot-check dimensions on random parts +- **Functional test:** If parts assemble or serve specific function, test a sample + +**Sort parts:** +- **Grade A:** Perfect, ready to use/sell +- **Grade B:** Minor flaws, usable for less critical applications +- **Scrap:** Defects, unusable + +### Record Keeping + +**Track production metrics:** + +- Number of parts produced +- Material used (sheets, area) +- Time taken +- Defect rate +- Settings used + +**Why track?** +- Improve future runs +- Calculate costs accurately +- Identify trends (quality degrading over time?) + +## Advanced Production Techniques + +### Multi-Material Projects + +**Different materials in same design:** + +**Challenge:** Each material needs different power/speed settings. + +**Solution:** + +1. **Separate layers by material:** + - Layer 1: Plywood parts (settings for plywood) + - Layer 2: Acrylic parts (settings for acrylic) +2. **Run each layer separately:** + - Load plywood, run Layer 1 + - Load acrylic, run Layer 2 +3. **Use consistent positioning** (jigs, registration marks) + +### Two-Step Production (Cut + Engrave) + +**Cut parts, then engrave details:** + +**Workflow:** + +1. **Step 1: Cut all parts** + - Batch cut 20 parts from sheets + - Remove parts from sheets +2. **Step 2: Engrave all parts** + - Load individual parts into jig + - Engrave details on each part + - Faster than cutting + engraving each part individually + +**Benefits:** +- Efficient material usage (cut from sheets) +- Precise engraving on individual parts +- Quality control between steps + +### Automated Part Numbering + +**Engrave unique numbers on each part:** + +**Use case:** Serialization, inventory tracking, kit assembly + +**Implementation:** + +1. Use RayForge's variable substitution (if supported) or macros +2. Increment part number for each piece +3. Engrave number automatically during production + +**Alternative:** Manually update part number between batches. + +## Troubleshooting Production Issues + +### Parts Not Cutting Through Consistently + +**Problem:** Some parts cut cleanly, others don't. + +**Causes:** +- Material thickness variation +- Dirty optics (power drops as lens gets dirty) +- Focus height wrong +- Warped material (parts of material closer/farther from laser) + +**Solutions:** +- Use higher quality, consistent material +- Clean optics between sheets +- Verify focus before each sheet +- Use multi-pass to compensate for variation + +### Material Warping During Cut + +**Problem:** Material curls or warps as laser cuts, causing later cuts to fail. + +**Causes:** +- Heat stress +- Thin material +- Large cuts release tension + +**Solutions:** +- Use hold-down pins or weights +- Cut in multiple passes (less heat per pass) +- Cut parts in smaller sections (less stress) +- Use thicker material if possible + +### Slow Production Speed + +**Problem:** Production taking longer than expected. + +**Causes:** +- Inefficient toolpaths (long travel moves) +- Conservative settings (low speed) +- Manual steps taking too long + +**Solutions:** +- Optimize part nesting and path order +- Increase speed (if quality allows) +- Streamline material loading process +- Use jigs for faster positioning + +### Defect Rate Too High + +**Problem:** Too many parts are scrap or Grade B. + +**Causes:** +- Settings not optimized +- Material quality issues +- Design flaws + +**Solutions:** +- Re-run Material Test Grid to optimize settings +- Source better quality material +- Refine design (add fillets to prevent cracking, adjust tolerances) + +## Best Practices Summary + +1. **Optimize before production:** + - Perfect your design on scrap material first + - Use Material Test Grid to dial in settings + - Run multiple test pieces until settings are perfect + +2. **Use templates and jigs:** + - Save production template files + - Create physical jigs for repeatable positioning + - Document settings for future runs + +3. **First article inspection:** + - Always inspect first part before full run + - Verify dimensions and quality + - Adjust if needed + +4. **Safety first:** + - Never leave laser unattended + - Watch for fires continuously + - Clear debris between sheets + +5. **Monitor and adapt:** + - Inspect periodically during run + - Clean optics when quality degrades + - Stop and fix issues immediately + +6. **Track and improve:** + - Record metrics (time, defects, material usage) + - Identify improvement opportunities + - Refine process over time + +## Related Pages + +- [Material Test Grid](creating-material-test-grid.md) - Optimize settings before production +- [Multi-Layer Workflow](../features/multi-layer.md) - Organize complex jobs +- [Calibrating Your Workspace](calibrating-your-workspace.md) - Ensure dimensional accuracy +- [Power vs Speed](../concepts/power-vs-speed.md) - Understand settings for consistency diff --git a/docs-site/guides/calibrating-your-workspace.md b/docs-site/guides/calibrating-your-workspace.md new file mode 100644 index 000000000..dc4d541ef --- /dev/null +++ b/docs-site/guides/calibrating-your-workspace.md @@ -0,0 +1,425 @@ +# Calibrating Your Workspace + +Ensure your laser cuts accurately to the dimensions you design. + +## Goal + +Verify and calibrate your laser's dimensional accuracy so that a 100mm square in RayForge cuts as a true 100mm square on your material. + +## Prerequisites + +- RayForge installed and connected to your laser +- Machine homed and ready +- Test material (cardboard, plywood, or acrylic scrap) +- Ruler or calipers (digital calipers preferred for accuracy) +- Basic understanding of machine settings + +## Why Calibration Matters + +Laser machines use stepper motors with a configured steps-per-millimeter setting. If this setting is incorrect: + +- Parts won't fit together properly +- Dimensions will be consistently off (e.g., 100mm design cuts as 98mm or 102mm) +- Assembly projects will fail + +**Calibration ensures:** 1mm in RayForge = 1mm on your material + +## Step 1: Check Current Machine Configuration + +First, verify your machine dimensions are configured correctly in RayForge. + +**Open machine settings:** + +1. Navigate to **Settings > Machine > Profile** +2. Check **Work Area** dimensions: + - Width: Should match your laser bed width (e.g., 300mm) + - Height: Should match your laser bed height (e.g., 400mm) +3. Check **Origin Position**: + - Top-left, bottom-left, or center (must match your actual machine) +4. Check **Y-axis Direction**: + - Does Y increase upward or downward? (must match your machine) + +**If dimensions are wrong:** Correct them now and save settings. + +## Step 2: Create a Test Pattern + +Create a simple test pattern with known dimensions. + +**Design the test:** + +1. Create a new project in RayForge +2. Add a **square** workpiece: + - Width: 100mm + - Height: 100mm +3. Add a second **rectangle** workpiece: + - Width: 50mm + - Height: 100mm +4. Position them with some spacing + +**Why these dimensions?** +- 100mm is easy to measure +- 50mm tests both axes independently +- Multiple shapes verify consistency + +## Step 3: Configure Cut Settings + +Set up appropriate cut settings for your test material. + +**For cardboard test (fast and cheap):** + +- **Operation:** Contour +- **Power:** 15-20% (just enough to cut through) +- **Speed:** 1500-2000 mm/min +- **Passes:** 1 + +**For plywood test (more accurate):** + +- **Operation:** Contour +- **Power:** 60-80% +- **Speed:** 300-500 mm/min +- **Passes:** 1-2 + +**For acrylic test (most accurate):** + +- **Operation:** Contour +- **Power:** 80-100% +- **Speed:** 150-200 mm/min +- **Passes:** 1 + +## Step 4: Preview and Frame + +Before cutting, verify the job will run in the correct location. + +**Frame the job:** + +1. In RayForge, click **Frame Job** (or use keyboard shortcut) +2. Laser head will trace the outline of the job boundary +3. Verify: + - Position is correct on your material + - Job fits within work area + - No collisions with clamps or obstacles + +**If position is wrong:** Adjust job origin or reposition material. + +## Step 5: Cut the Test Pattern + +Run the calibration test cut. + +**Safety first:** +- Ensure ventilation is running +- Have fire extinguisher ready +- Stay near the machine (never leave unattended) + +**Run the job:** + +1. Click **Start Job** in RayForge +2. Monitor the cut closely +3. Wait for completion +4. Allow material to cool before removing + +## Step 6: Measure the Results + +Carefully measure the cut pieces to determine accuracy. + +**What to measure:** + +1. **100mm square:** + - Measure width (X-axis): Should be 100.0mm + - Measure height (Y-axis): Should be 100.0mm +2. **50mm x 100mm rectangle:** + - Measure width: Should be 50.0mm + - Measure height: Should be 100.0mm + +**Measurement tips:** +- Measure from cut edge to cut edge (ignore kerf) +- Take 3 measurements and average them +- Use calipers for best accuracy (rulers are less precise) + +**Record your results:** + +``` +Target: 100mm x 100mm square +Actual: ___mm x ___mm + +Target: 50mm x 100mm rectangle +Actual: ___mm x ___mm +``` + +## Step 7: Calculate Calibration Error + +Determine how far off your machine is from true dimensions. + +**Calculate error percentage:** + +``` +Error (X-axis) = (Measured Width - Target Width) / Target Width * 100% +Error (Y-axis) = (Measured Height - Target Height) / Target Height * 100% +``` + +**Example:** + +Target: 100mm x 100mm +Actual: 98.5mm x 101.2mm + +``` +X error = (98.5 - 100) / 100 * 100% = -1.5% +Y error = (101.2 - 100) / 100 * 100% = +1.2% +``` + +**Interpretation:** +- X-axis is cutting 1.5% too small +- Y-axis is cutting 1.2% too large + +## Step 8: Determine if Calibration is Needed + +Decide if your accuracy is acceptable or needs correction. + +**Accuracy thresholds:** + +| Application | Acceptable Error | Action | +|-------------|------------------|--------| +| **Artistic/decorative** | +/- 2mm (2%) | Probably OK as-is | +| **General projects** | +/- 0.5mm (0.5%) | Calibrate if outside this | +| **Precision/assembly** | +/- 0.1mm (0.1%) | Calibrate, verify hardware | + +**If within tolerance:** You're done! No calibration needed. + +**If outside tolerance:** Proceed to Step 9. + +## Step 9: Adjust Firmware Settings (GRBL) + +Correct dimensional errors by adjusting steps-per-mm in firmware. + +### Understanding Steps-Per-Millimeter + +Your machine's controller needs to know how many motor steps equal one millimeter of movement. + +**Default GRBL settings:** +- $100: X-axis steps/mm (typical: 80-100) +- $101: Y-axis steps/mm (typical: 80-100) + +**If parts are too small:** Increase steps/mm +**If parts are too large:** Decrease steps/mm + +### Calculate New Settings + +**Formula:** + +``` +New steps/mm = Current steps/mm * (Target dimension / Measured dimension) +``` + +**Example:** + +Current X steps/mm: $100 = 80.00 +Target: 100mm +Measured: 98.5mm + +``` +New X steps/mm = 80.00 * (100 / 98.5) = 81.22 +``` + +Current Y steps/mm: $101 = 80.00 +Target: 100mm +Measured: 101.2mm + +``` +New Y steps/mm = 80.00 * (100 / 101.2) = 79.05 +``` + +### Read Current Settings + +**In RayForge console:** + +1. Open **Console** tab +2. Send command: `$$` (two dollar signs) +3. Firmware will respond with all settings +4. Note current values for $100 and $101 + +**Example output:** +``` +$100=80.000 +$101=80.000 +$102=80.000 +... +``` + +### Update Settings + +**Send new values:** + +In the RayForge console: + +``` +$100=81.22 +$101=79.05 +``` + +Wait for "ok" response from firmware. + +### Save Settings + +**GRBL automatically saves settings** to EEPROM, but verify: + +``` +$$ +``` + +Check that $100 and $101 now show the new values. + +## Step 10: Verify Calibration + +Cut another test pattern to confirm accuracy. + +**Repeat the test:** + +1. Use the same test pattern (100mm square, 50mm rectangle) +2. Cut on fresh material +3. Measure results again +4. Verify dimensions are now accurate + +**Expected results:** + +``` +Target: 100mm x 100mm +Actual: 100.0mm +/- 0.2mm x 100.0mm +/- 0.2mm +``` + +**If still off:** Repeat calibration process. Large errors may require multiple iterations. + +**If now accurate:** Calibration complete! + +## Advanced Calibration + +### Belt Tension and Mechanical Issues + +If calibration doesn't solve dimensional errors, check mechanical components: + +**Symptoms of mechanical issues:** +- Errors vary between tests (not consistent) +- One axis much worse than the other +- Dimensions change based on speed + +**Check:** + +1. **Belt tension:** + - Should be tight but not over-tensioned + - Loose belts cause backlash and dimensional errors +2. **Pulley set screws:** + - Ensure pulleys are tight on motor shafts + - Loose pulleys slip and cause errors +3. **Linear rails:** + - Should move smoothly without binding + - Clean and lubricate if needed +4. **Stepper drivers:** + - Verify current settings are correct + - Underpowered motors can skip steps + +### Kerf Compensation vs Calibration + +**Kerf** is the material removed by the laser beam (typically 0.1-0.3mm). + +**Kerf is NOT a calibration issue:** +- Kerf makes parts slightly smaller than designed +- Kerf is compensated in RayForge settings (see Overscan & Kerf) + +**Calibration corrects:** +- Systematic dimensional errors across the entire workspace +- Steps-per-mm configuration errors + +**If your 100mm square measures 99.8mm:** This might be kerf, not calibration error. + +### Testing at Different Scales + +For precision work, test calibration at multiple scales: + +**Create test patterns:** +- Small: 20mm x 20mm square +- Medium: 100mm x 100mm square +- Large: 200mm x 200mm square + +**Measure all three:** +- Errors should be proportional (e.g., 1% error at all scales) +- If errors vary by scale, there may be mechanical non-linearity + +## Troubleshooting + +### Dimensions Off by Large Amount (>5%) + +**Possible causes:** +- Wrong firmware settings +- Wrong machine profile in RayForge +- Mechanical issue (loose pulley, belt) + +**Solutions:** +- Verify machine work area dimensions in settings +- Check $100/$101 settings in firmware +- Inspect mechanical components + +### Dimensions Inconsistent Between Tests + +**Possible causes:** +- Loose belts or pulleys +- Stepper motors skipping steps +- Material warping or movement during cut + +**Solutions:** +- Tighten belts to proper tension +- Verify stepper driver current settings +- Secure material better, use flat material + +### One Axis Accurate, One Axis Wrong + +**Possible causes:** +- One axis has incorrect steps/mm +- Mechanical issue on one axis only + +**Solutions:** +- Calibrate the problem axis separately +- Inspect that axis's belt, pulley, rails + +### Still Inaccurate After Calibration + +**Possible causes:** +- Measurement error (using inaccurate ruler) +- Kerf not accounted for (measure outer edge to outer edge) +- Severe mechanical issues + +**Solutions:** +- Use digital calipers for accurate measurement +- Re-check calculation of new steps/mm +- Consult machine manufacturer documentation + +## Best Practices + +1. **Calibrate when:** + - Setting up a new machine + - After replacing belts or pulleys + - If dimensional errors are noticed + - Periodically (every 6-12 months) + +2. **Use good test materials:** + - Flat, stable materials (not warped) + - Acrylic or plywood preferred over cardboard + - Large enough to measure accurately + +3. **Measure carefully:** + - Use calipers, not rulers + - Take multiple measurements and average + - Measure edge to edge, not including kerf + +4. **Document your settings:** + - Record $100 and $101 values + - Note any mechanical adjustments + - Keep calibration test results for reference + +5. **Re-verify periodically:** + - Test dimensional accuracy on actual projects + - Re-calibrate if you notice consistent errors + +## Related Pages + +- [Machine Setup](../machine/device-config.md) - Configure machine dimensions +- [GRBL Settings](../machine/grbl-settings.md) - Firmware configuration reference +- [Overscan & Kerf](../features/overscan-kerf.md) - Kerf compensation techniques +- [Coordinates and Origin](../concepts/coordinates-and-origin.md) - Understanding coordinate systems diff --git a/docs-site/guides/creating-material-test-grid.md b/docs-site/guides/creating-material-test-grid.md new file mode 100644 index 000000000..2a9b11f36 --- /dev/null +++ b/docs-site/guides/creating-material-test-grid.md @@ -0,0 +1,432 @@ +# Creating Material Test Grid + +Find optimal laser settings for new materials using RayForge's built-in Material Test Grid generator. + +## Goal + +Quickly determine the best power and speed settings for cutting or engraving a material by running a systematic test that tries multiple combinations automatically. + +## Prerequisites + +- RayForge installed and connected to laser +- Test material (scrap piece of the material you want to test) +- Basic understanding of laser power and speed concepts +- Machine homed and ready + +## Why Use Material Test Grid? + +Every material responds differently to laser cutting: + +- Different woods burn at different rates +- Acrylic thickness affects required power +- Material batches vary (different moisture, density, etc.) + +**Manual testing is tedious:** +- Test at 50% power, 500mm/min - doesn't cut through +- Try 60% power - still not enough +- Try 70% power - works but too much charring +- Try different speeds... +- Hours of trial and error + +**Material Test Grid automates this:** +- Test 16-25 power/speed combinations in one job +- Organized grid makes results easy to compare +- Find optimal settings in 5-10 minutes + +## Step 1: Prepare Test Material + +Set up material for the test grid. + +**Material requirements:** + +- **Size:** At least 50mm x 50mm (larger is better, e.g., 100mm x 100mm) +- **Condition:** Representative of material you'll actually use + - Same thickness + - Same batch/supplier + - Similar moisture content +- **Placement:** Flat, secured on laser bed + +**Secure material:** +- Use tape, magnets, or hold-downs +- Ensure material won't shift during test +- Position within laser work area + +## Step 2: Access Material Test Grid Generator + +Open the Material Test Grid feature in RayForge. + +**Navigate to generator:** + +1. Open RayForge +2. Go to **Features > Operations > Material Test Grid** +3. Material Test Grid configuration dialog opens + +**Alternative access:** +- Some versions may have it in: **Tools > Material Test Grid** +- Or in operation selection dropdown + +## Step 3: Configure Test Parameters + +Set up the power and speed ranges to test. + +### Grid Size + +**Number of cells:** +- **4x4 grid:** 16 test cells (faster, less comprehensive) +- **5x5 grid:** 25 test cells (recommended, good coverage) + +**Choose based on:** +- Unknown material: 5x5 for wider range +- Similar to known material: 4x4 to refine settings + +### Cell Size + +**Default:** 10mm x 10mm per cell + +**Adjust if needed:** +- Smaller cells (8mm): Save material, harder to evaluate +- Larger cells (15mm): Easier to see results, uses more material + +### Power Range + +**What to test:** + +Define minimum and maximum power to test: + +- **Min Power:** Starting power (e.g., 20%) +- **Max Power:** Ending power (e.g., 80%) + +**Grid will test evenly spaced values between min and max.** + +**Example (5x5 grid, 20-80% power):** +- Row 1: 20% power +- Row 2: 35% power +- Row 3: 50% power +- Row 4: 65% power +- Row 5: 80% power + +**How to choose range:** + +| Material Type | Suggested Power Range | Notes | +|---------------|----------------------|-------| +| **Thin paper/cardboard** | 10% - 30% | Very low power needed | +| **3mm wood** | 40% - 80% | Medium power | +| **6mm wood** | 60% - 100% | Higher power for thick material | +| **3mm acrylic** | 70% - 100% | High power for clean cuts | +| **Engraving (any)** | 10% - 40% | Lower power for surface marking | + +**Tip:** If unsure, use wider range (e.g., 20% - 100%) to ensure you capture working settings. + +### Speed Range + +**What to test:** + +Define minimum and maximum speed to test: + +- **Min Speed:** Slowest speed (e.g., 100 mm/min) +- **Max Speed:** Fastest speed (e.g., 1000 mm/min) + +**Grid will test evenly spaced values between min and max.** + +**Example (5x5 grid, 100-1000 mm/min):** +- Column 1: 100 mm/min +- Column 2: 325 mm/min +- Column 3: 550 mm/min +- Column 4: 775 mm/min +- Column 5: 1000 mm/min + +**How to choose range:** + +| Material Type | Suggested Speed Range | Notes | +|---------------|----------------------|-------| +| **Thin paper/cardboard** | 1000 - 3000 mm/min | Fast speeds for thin material | +| **3mm wood** | 200 - 1000 mm/min | Moderate speeds | +| **6mm wood** | 100 - 500 mm/min | Slower for thick material | +| **3mm acrylic** | 100 - 400 mm/min | Very slow for clean cuts | +| **Engraving (any)** | 1000 - 4000 mm/min | Fast for surface engraving | + +### Test Type + +**Choose operation type:** + +- **Cut:** Tests through-cutting (Contour operation) +- **Engrave:** Tests surface engraving (Raster operation) + +**Select based on your goal:** +- Testing for cutting projects: Choose "Cut" +- Testing for engraving projects: Choose "Engrave" + +### Preset Selection (Optional) + +Some versions offer presets to auto-fill parameters: + +**Common presets:** +- **Diode Laser - Cut:** Low power range, moderate speeds +- **Diode Laser - Engrave:** Very low power, high speeds +- **CO2 Laser - Cut:** Medium/high power, moderate speeds +- **CO2 Laser - Engrave:** Low power, high speeds + +**Use presets to:** +- Get reasonable starting ranges +- Save time configuring +- Ensure you're in the right ballpark + +**You can still adjust preset values** to fine-tune ranges. + +## Step 4: Review and Generate Grid + +Check settings and generate the test grid. + +**Summary view:** + +RayForge shows: +- Grid dimensions (e.g., 5x5, 50mm x 50mm total) +- Power range (20% to 80%) +- Speed range (100 to 1000 mm/min) +- Number of test cells (25) +- Estimated time (varies by settings) + +**Click "Generate" or "Create Grid":** + +- Grid workpiece is added to canvas +- Grid appears as a series of small squares +- Each square represents one power/speed combination + +## Step 5: Position the Grid + +Place the grid on your canvas/material. + +**Position grid:** + +1. Grid appears on canvas in RayForge +2. Drag to position where your test material is located +3. Use job framing to verify position on actual laser bed + +**Framing:** + +1. Click **Frame Job** +2. Laser traces outline of grid boundary +3. Verify grid will fit on your test material +4. Adjust position if needed + +## Step 6: Run the Test Grid + +Execute the material test. + +**Safety check:** +- Ventilation running +- Fire extinguisher ready +- Test material secured +- Emergency stop accessible + +**Start job:** + +1. Click **Start Job** in RayForge +2. Laser begins cutting/engraving grid cells +3. Monitor the test closely (watch for fires on high-power cells) + +**Execution order:** + +RayForge uses **risk-optimized execution order:** +- Starts with lowest power/speed (safest) +- Gradually increases power +- Reduces fire risk by testing conservative settings first +- If material starts burning at high power, you can stop before completing all cells + +**During execution:** +- Watch each cell being cut +- Note which cells cut through (for cut tests) or produce desired darkness (for engrave tests) +- Emergency stop if fire occurs + +## Step 7: Inspect Results + +Examine the completed test grid to find optimal settings. + +**Cutting test results:** + +Check each cell: + +- **Didn't cut through:** Too little power or too fast speed +- **Cut through cleanly:** Good candidate settings +- **Excessive charring:** Too much power or too slow speed +- **Melted edges:** Too slow or too much power (material dependent) + +**Visual grid:** + +``` +Speed -> 100 325 550 775 1000 mm/min +Power + | + v +20% No cut No cut No cut No cut No cut +35% Char Light No cut No cut No cut +50% Char Good! Light No cut No cut +65% Burn Char Good! Light No cut +80% Burn Burn Char Good! Light +``` + +**Optimal settings:** Cells marked "Good!" - balance of cutting through without excessive charring. + +**Engraving test results:** + +Check each cell: + +- **No visible mark:** Too little power or too fast +- **Light mark:** Low energy, suitable for subtle engraving +- **Medium mark:** Good contrast, common target +- **Dark/burned mark:** High energy, may be too much + +**Choose based on desired darkness:** +- Light engraving: Low power + fast speed +- Medium engraving: Medium power + medium speed +- Dark engraving: High power + slow speed (watch for charring) + +## Step 8: Record and Use Settings + +Document the optimal settings and apply them to your project. + +**Record settings:** + +1. Identify the best cell in the grid +2. Note its row (power) and column (speed) +3. Write down exact values: + - Power: ___ % + - Speed: ___ mm/min + +**Example:** + +Best cell: Row 3, Column 2 +- Power: 50% +- Speed: 325 mm/min + +**Apply to your project:** + +1. Create your actual design in RayForge +2. Set operation power to: 50% +3. Set operation speed to: 325 mm/min +4. Run job with confidence + +**Tip:** Take a photo of the test grid with your phone and label the settings for future reference. + +## Advanced Testing + +### Multi-Pass Testing + +To test multi-pass cutting (multiple passes over same path): + +**Create multiple grids:** + +- Grid 1: Test 1 pass at various power/speed +- Grid 2: Test 2 passes at various power/speed +- Grid 3: Test 3 passes at various power/speed + +**Compare:** +- Which configuration gives cleanest cut? +- More passes at lower power often produces less charring + +### Variable Testing + +For more advanced testing, create custom grids: + +**Test additional variables:** +- Different pass counts +- Different focus heights +- With/without air assist +- Different layer heights (for depth engraving) + +**Method:** Create separate test grids for each variable, keep other settings constant. + +### Fine-Tuning + +After finding rough optimal settings, narrow the range: + +**Example:** + +Initial test showed 50% power at 325 mm/min works well. + +**Fine-tune test:** +- Power range: 45% to 55% (narrow range around 50%) +- Speed range: 250 to 400 mm/min (narrow range around 325) +- Run new 5x5 grid with tighter spacing +- Find even more precise optimal settings + +## Troubleshooting + +### All Cells Failed to Cut + +**Problem:** No cell in grid cut through material. + +**Cause:** Power range too low or speed range too fast. + +**Solution:** +- Increase max power (try up to 100%) +- Decrease min speed (try down to 50-100 mm/min) +- Re-run test with adjusted ranges + +### All Cells Over-Burned + +**Problem:** Every cell burned excessively or caught fire. + +**Cause:** Power range too high or speed range too slow. + +**Solution:** +- Decrease max power +- Increase min speed +- Test with lower energy settings + +### Results Inconsistent + +**Problem:** Same settings produce different results in different cells. + +**Cause:** Material inconsistency, focus issues, or mechanical problems. + +**Solution:** +- Use more uniform material for testing +- Verify laser focus is correct +- Check belt tension and mechanical components +- Ensure material is flat + +### Can't Tell Which Cell is Best + +**Problem:** Multiple cells look similar, hard to choose. + +**Cause:** Test range too narrow or cells too small. + +**Solution:** +- Use larger cell size (15mm instead of 10mm) +- Widen test range to see more variation +- Test on material with better visual contrast + +## Best Practices + +1. **Test on representative material:** + - Same thickness as production material + - Same batch/supplier if possible + - Similar condition (moisture, finish, etc.) + +2. **Use appropriate ranges:** + - Start wide if material is unknown + - Narrow range to fine-tune known settings + - Don't be afraid to test high power (monitor closely) + +3. **Monitor during test:** + - Watch for fires (high power cells) + - Note which cells look promising + - Stop test if all high-power cells burn + +4. **Label and save results:** + - Write settings on test material with marker + - Take photo for records + - Keep test samples for future reference + +5. **Re-test when needed:** + - Different material batches may need different settings + - Re-test after changing laser tube or optics + - Test again if results change unexpectedly + +## Related Pages + +- [Power vs Speed Concepts](../concepts/power-vs-speed.md) - Understanding power/speed relationship +- [Material Test Grid Feature](../features/operations/material-test-grid.md) - Detailed feature reference +- [Understanding Operations](../concepts/understanding-operations.md) - Operation types explained +- [Laser Safety](../concepts/laser-safety.md) - Safe material testing practices diff --git a/docs-site/guides/index.md b/docs-site/guides/index.md new file mode 100644 index 000000000..f20a5b1df --- /dev/null +++ b/docs-site/guides/index.md @@ -0,0 +1,45 @@ +# How-To Guides + +Task-based guides to help you accomplish specific goals with RayForge. + +## Getting Work Done + +Practical workflows for common laser cutting tasks: + +- **[Calibrating Your Workspace](calibrating-your-workspace.md)** - Set up accurate dimensions and test dimensional accuracy +- **[Using Camera Alignment](using-camera-alignment.md)** - Step-by-step camera workflow and alignment techniques +- **[Creating Material Test Grid](creating-material-test-grid.md)** - Find optimal power/speed settings for new materials +- **[Batch Production Workflow](batch-production-workflow.md)** - Efficiently repeat jobs for production runs + +## Quality & Precision + +Guides for achieving the best possible results: + +- **[Achieving Perfect Focus](achieving-perfect-focus.md)** - Laser focus techniques and testing procedures +- **[Reducing Burn Marks](reducing-burn-marks.md)** - Overscan, air assist, and optimization tips +- **[Cutting Thick Materials](cutting-thick-materials.md)** - Multi-pass strategies and power/speed calculations + +## Advanced Workflows + +Advanced techniques for complex projects: + +- **[Multi-Material Projects](multi-material-projects.md)** - Managing projects with different materials +- **[Custom G-code Automation](custom-gcode-automation.md)** - Advanced macro and hook workflows +- **[Optimizing Large Jobs](optimizing-large-jobs.md)** - Performance and efficiency for complex designs + +## About These Guides + +Each guide is focused on a specific task or goal, providing step-by-step instructions to achieve results quickly. For conceptual understanding, see the [Concepts](../concepts/index.md) section. + +**Guide format:** +- Clear goal statement +- Prerequisites listed +- Step-by-step procedures +- Expected results +- Troubleshooting tips + +## Related Resources + +- **[Concepts](../concepts/index.md)** - Foundational knowledge and theory +- **[Features](../features/index.md)** - Feature reference documentation +- **[Troubleshooting](../troubleshooting/common.md)** - Problem diagnosis and solutions diff --git a/docs-site/guides/using-camera-alignment.md b/docs-site/guides/using-camera-alignment.md new file mode 100644 index 000000000..b0fef925b --- /dev/null +++ b/docs-site/guides/using-camera-alignment.md @@ -0,0 +1,392 @@ +# Using Camera Alignment + +Align your laser work to existing material or previously cut pieces using RayForge's camera feature. + +## Goal + +Use a camera to precisely position your design on material, allowing you to: + +- Engrave on pre-cut or irregularly shaped objects +- Align work to existing features on material +- Precisely place designs on specific locations +- Resume work on previously cut pieces + +## Prerequisites + +- Camera installed and configured in RayForge +- Material placed on laser bed +- Basic understanding of RayForge workpiece operations +- Camera calibration completed (if required by your setup) + +## When to Use Camera Alignment + +**Good use cases:** +- Engraving on pre-made objects (coasters, boxes, etc.) +- Aligning to printed artwork or existing designs +- Cutting around irregularly shaped material +- Multi-step processes (cut, then engrave specific areas) +- Precise placement on small or expensive materials + +**Not ideal for:** +- Simple rectangular cuts on blank material (use job origin instead) +- Production runs of identical parts (use fixtures instead) +- Materials where camera view is blocked + +## Camera Alignment Workflow Overview + +**Process summary:** + +1. Configure camera in RayForge settings +2. Place material on laser bed +3. Capture camera image +4. Mark alignment points on image +5. Align design to alignment points +6. Run job with camera-aligned positioning + +## Step 1: Configure Camera + +Ensure your camera is set up correctly in RayForge. + +**Check camera settings:** + +1. Navigate to **Settings > Camera** +2. Verify camera is detected and selected +3. Test camera feed - you should see live video +4. Adjust camera settings if needed: + - **Resolution:** Higher is better (720p or 1080p) + - **Exposure:** Adjust for clear image of material + - **Focus:** Should be focused at laser bed height + +**Camera position:** +- Camera should be mounted to view the laser bed +- Typically mounted on laser head (moves with head) or fixed above bed +- Clear view of work area without obstructions + +## Step 2: Place Material on Laser Bed + +Position your material where you want to work. + +**Material placement tips:** + +- Secure material so it won't move during cutting +- Ensure material is flat (use tape, magnets, or hold-downs) +- Position material within camera's field of view +- Avoid reflective materials that cause glare + +**For pre-cut objects:** +- Identify features you want to align to +- Make sure those features are visible to camera +- Consider marking reference points with tape or marker + +## Step 3: Capture Camera Image + +Capture a reference image of your material. + +**Open camera view:** + +1. In RayForge, navigate to **Camera** menu or toolbar +2. Select **Capture Image** (or similar option) +3. Camera captures current view of laser bed + +**Move laser head if needed:** +- If camera is mounted on head, jog the head to position camera over your material +- Use manual jog controls or move to specific coordinates +- Ensure the area you want to align to is visible in camera view + +**Capture settings:** +- Use good lighting for clear image +- Avoid shadows or glare +- Capture at position where laser will start working + +## Step 4: Mark Alignment Points + +Define reference points that link camera image to real-world coordinates. + +**What are alignment points?** +- Points you mark on the camera image +- Correspond to known positions on your material +- RayForge uses these to calculate image-to-workspace transformation + +**How many points?** +- **Minimum 2 points:** Basic alignment (translation and rotation) +- **3+ points:** Better accuracy, compensates for camera distortion +- **4 points:** Recommended for best results + +**Marking alignment points:** + +1. **Identify features on material:** + - Corners of pre-cut object + - Edges or intersections + - Pre-marked reference dots + - Any clear, identifiable feature + +2. **Click on camera image** to place alignment point +3. **Enter real-world coordinates** for each point: + - Where is this point in machine coordinates? + - Example: Top-left corner at (50mm, 50mm) + +**Example alignment:** + +``` +Material: Pre-cut 100mm x 100mm coaster at position (50, 50) + +Point 1: Top-left corner of coaster + - Click on image at coaster's top-left corner + - Enter coordinates: (50, 50) + +Point 2: Top-right corner of coaster + - Click on image at coaster's top-right corner + - Enter coordinates: (150, 50) + +Point 3: Bottom-right corner of coaster + - Click on image at coaster's bottom-right corner + - Enter coordinates: (150, 150) + +Point 4: Bottom-left corner of coaster + - Click on image at coaster's bottom-left corner + - Enter coordinates: (50, 150) +``` + +**Accuracy tips:** +- Zoom in on camera image for precise clicking +- Use distinct features (sharp corners, intersections) +- Measure actual coordinates if possible (jog laser to feature) +- More points = better accuracy + +## Step 5: Align Your Design + +Import or create your design and position it relative to camera image. + +**Import design:** + +1. Import SVG, DXF, or other design file into RayForge +2. Design appears on canvas + +**Align to camera image:** + +1. Camera image is now visible on canvas as an overlay or reference +2. Move/rotate/scale your design to align with features in camera image +3. Use camera alignment tools to snap design to alignment points + +**Alignment methods:** + +**Visual alignment:** +- Drag design to match camera image +- Rotate to align angles +- Scale if needed + +**Point-to-point alignment:** +- Click design feature (e.g., corner) +- Click corresponding camera image feature +- RayForge aligns automatically + +**Example:** +- You want to engrave a logo in center of pre-cut coaster +- Camera image shows coaster position +- Drag logo to center of coaster in camera image +- Logo is now positioned correctly for engraving + +## Step 6: Verify Alignment + +Check that alignment is correct before cutting. + +**Frame the job:** + +1. Use **Frame Job** feature to trace job boundary with laser +2. Watch laser trace outline - does it match your material? +3. Verify position is correct + +**If alignment is off:** +- Re-check alignment points (did you mark them correctly?) +- Re-check real-world coordinates (did you enter correct values?) +- Re-align design to camera image + +**If alignment is good:** +- Proceed to cutting + +## Step 7: Run the Job + +Execute your aligned job. + +**Safety check:** +- Ensure material is still secured (hasn't moved) +- Ventilation running +- Fire extinguisher ready +- Emergency stop accessible + +**Run job:** + +1. Click **Start Job** +2. Monitor cutting closely +3. Verify first few cuts are landing in correct position +4. Emergency stop if alignment is wrong + +**If first cuts are misaligned:** +- Stop job immediately +- Re-check alignment points and coordinates +- Repeat alignment process + +## Advanced Camera Techniques + +### Using Registration Marks + +**What are registration marks?** +- Small reference marks (crosses, circles, etc.) cut or marked on material +- Used for precise multi-step alignment + +**Workflow:** + +1. **First pass:** Cut registration marks (small crosses at corners) +2. **Capture camera image** showing registration marks +3. **Mark alignment points** on registration marks +4. **Align second design** to registration marks +5. **Run second pass** - perfectly aligned to first pass + +**Use cases:** +- Multi-color engraving (engrave different layers aligned to each other) +- Cut, then engrave (cut outline, then engrave detail inside) +- Front/back alignment (flip material, align to registration marks) + +### Camera Calibration + +Some camera setups require calibration to compensate for lens distortion. + +**When to calibrate:** +- Wide-angle camera lenses (cause barrel distortion) +- Alignment accuracy is consistently off +- Different error at different positions in camera view + +**Calibration process:** + +1. Print or cut a calibration pattern (grid of points at known spacing) +2. Capture camera image of calibration pattern +3. Use RayForge's camera calibration tool to mark grid points +4. RayForge calculates distortion correction +5. Save calibration profile + +**After calibration:** Camera alignment should be more accurate across entire view. + +### Multiple Camera Positions + +For large work areas, capture multiple camera images: + +1. Capture image at position 1 (e.g., left side of bed) +2. Capture image at position 2 (e.g., right side of bed) +3. Mark alignment points on each image +4. Align design to stitched camera view + +**Benefits:** +- Cover larger work area than single camera view +- Better accuracy across large bed + +## Troubleshooting + +### Camera Not Detected + +**Problem:** RayForge doesn't see your camera. + +**Solutions:** + +1. Check camera is connected (USB or network) +2. Verify camera permissions (Linux: user in video group) +3. Check camera is not in use by another application +4. Restart RayForge +5. See [Camera Setup](../features/camera.md) for detailed troubleshooting + +### Image Blurry or Out of Focus + +**Problem:** Camera image is not clear enough to mark alignment points. + +**Solutions:** + +1. Adjust camera focus (physical focus ring or software setting) +2. Ensure camera is at correct height (focused at laser bed level) +3. Improve lighting in workspace +4. Clean camera lens + +### Alignment Consistently Off by Same Amount + +**Problem:** Alignment is wrong, but always off by same distance/direction. + +**Cause:** Camera offset not configured correctly. + +**Solutions:** + +1. Check camera offset settings in RayForge + - If camera is mounted on laser head, offset from laser focal point must be configured +2. Re-measure offset distance +3. Update settings and test again + +### Alignment Off in Different Directions + +**Problem:** Alignment error varies depending on position in camera view. + +**Cause:** Camera lens distortion not corrected. + +**Solutions:** + +1. Perform camera calibration (see Advanced Techniques above) +2. Use alignment points closer to center of camera view (less distortion) +3. Use narrower camera lens (less distortion) + +### Design Rotated Incorrectly + +**Problem:** Design angle doesn't match material angle. + +**Cause:** Not enough alignment points, or points not accurately marked. + +**Solutions:** + +1. Use at least 3 alignment points (4 recommended) +2. Spread alignment points far apart (better angle calculation) +3. Mark alignment points more precisely + +### Material Moved After Capture + +**Problem:** Material shifted after camera image was captured. + +**Cause:** Material not secured properly. + +**Solutions:** + +1. Secure material better (tape, magnets, hold-downs) +2. Re-capture camera image after material moves +3. Frame job before running to verify position + +## Tips for Best Results + +1. **Use distinct alignment features:** + - Sharp corners, not rounded edges + - High-contrast features (dark on light background) + - Pre-marked dots or crosses + +2. **Spread alignment points apart:** + - Use corners of work area + - Wide spacing improves rotation accuracy + - Avoid clustering points in one area + +3. **Measure real-world coordinates accurately:** + - Jog laser to feature to get exact coordinates + - Use calipers to measure from known origin + - Double-check coordinate entry + +4. **Secure material firmly:** + - Material must not move between capture and cutting + - Use tape, magnets, vacuum table, or fixtures + - Verify material is flat + +5. **Good lighting is crucial:** + - Even lighting across work area + - Avoid shadows and glare + - Consider adding supplemental lighting + +6. **Frame before running:** + - Always frame the job to verify alignment + - Stop immediately if frame doesn't match material + +## Related Pages + +- [Camera Feature](../features/camera.md) - Camera setup and configuration +- [Coordinates and Origin](../concepts/coordinates-and-origin.md) - Understanding coordinate systems +- [Machine Setup](../machine/device-config.md) - Configure camera offset +- [Multi-Layer Workflow](../features/multi-layer.md) - Organizing multi-step jobs diff --git a/docs/3d-preview.png b/docs-site/images/3d-preview.png similarity index 100% rename from docs/3d-preview.png rename to docs-site/images/3d-preview.png diff --git a/docs/camera-alignment.png b/docs-site/images/camera-alignment.png similarity index 100% rename from docs/camera-alignment.png rename to docs-site/images/camera-alignment.png diff --git a/docs/camera-image.png b/docs-site/images/camera-image.png similarity index 100% rename from docs/camera-image.png rename to docs-site/images/camera-image.png diff --git a/docs/camera-overlay.png b/docs-site/images/camera-overlay.png similarity index 100% rename from docs/camera-overlay.png rename to docs-site/images/camera-overlay.png diff --git a/docs/contour-settings.png b/docs-site/images/contour-settings.png similarity index 100% rename from docs/contour-settings.png rename to docs-site/images/contour-settings.png diff --git a/docs/machine-advanced.png b/docs-site/images/machine-advanced.png similarity index 100% rename from docs/machine-advanced.png rename to docs-site/images/machine-advanced.png diff --git a/docs/machine-camera.png b/docs-site/images/machine-camera.png similarity index 100% rename from docs/machine-camera.png rename to docs-site/images/machine-camera.png diff --git a/docs/machine-device.png b/docs-site/images/machine-device.png similarity index 100% rename from docs/machine-device.png rename to docs-site/images/machine-device.png diff --git a/docs/machine-laser.png b/docs-site/images/machine-laser.png similarity index 100% rename from docs/machine-laser.png rename to docs-site/images/machine-laser.png diff --git a/docs/machine-logs.png b/docs-site/images/machine-logs.png similarity index 100% rename from docs/machine-logs.png rename to docs-site/images/machine-logs.png diff --git a/docs/machine-settings.png b/docs-site/images/machine-settings.png similarity index 100% rename from docs/machine-settings.png rename to docs-site/images/machine-settings.png diff --git a/docs/ss-main.png b/docs-site/images/ss-main.png similarity index 100% rename from docs/ss-main.png rename to docs-site/images/ss-main.png diff --git a/docs-site/includes/abbreviations.md b/docs-site/includes/abbreviations.md new file mode 100644 index 000000000..32b97c05c --- /dev/null +++ b/docs-site/includes/abbreviations.md @@ -0,0 +1,8 @@ +*[GRBL]: An open-source, embedded, high performance g-code parser and CNC milling controller +*[G-code]: The programming language used to control CNC machines +*[DXF]: Drawing Exchange Format - a CAD data file format +*[SVG]: Scalable Vector Graphics - an XML-based vector image format +*[PPA]: Personal Package Archive - a special software repository for Ubuntu users +*[CNC]: Computer Numerical Control +*[UI]: User Interface +*[USB]: Universal Serial Bus diff --git a/docs-site/index.md b/docs-site/index.md new file mode 100644 index 000000000..e2f0d13f1 --- /dev/null +++ b/docs-site/index.md @@ -0,0 +1,95 @@ +# Welcome to Rayforge Documentation + +Rayforge is a modern, cross-platform G-code sender and control software for GRBL-based laser cutters and engravers. Built with Gtk4 and Libadwaita, it provides a clean, native interface for Linux and Windows, offering a full suite of tools for both hobbyists and professionals. + +![Rayforge Main Interface](images/ss-main.png) + +## What is Rayforge? + +Rayforge transforms your laser cutter or engraver into a powerful creative tool. Whether you're a hobbyist working on personal projects or a professional running a business, Rayforge provides the features and reliability you need. + +### Key Capabilities +## Key Features + +| Feature | Description | +| :--------------------------- | :------------------------------------------------------------------------------------------------- | +| **Modern UI** | Polished and modern UI built with Gtk4 and Libadwaita. Supports system, light, and dark themes. | +| **Multi-Layer Operations** | Assign different operations (e.g., engrave then cut) to layers in your design. | +| **Versatile Operations** | Supports Contour, Raster Engraving (with cross-hatch fill), Shrink Wrap, and Depth Engraving. | +| **Overscan & Kerf Comp.** | Improve engraving quality with overscan and ensure dimensional accuracy with kerf compensation. | +| **2.5D Cutting** | Perform multi-pass cuts with a configurable step-down between each pass for thick materials. | +| **3D G-code Preview** | Visualize G-code toolpaths in 3D to verify the job before sending it to the machine. | +| **Multi-Machine Profiles** | Configure and instantly switch between multiple machine profiles. | +| **GRBL Firmware Settings** | Read and write firmware parameters (`$$`) directly from the UI. | +| **Comprehensive 2D Canvas** | Full suite of tools: alignment, transformation, measurement, zoom, pan, and more. | +| **Advanced Path Generation** | High-quality image tracing, travel time optimization, path smoothing, and spot size interpolation. | +| **Holding Tabs** | Add tabs to contour cuts to hold pieces in place. Supports manual and automatic placement. | +| **G-code Macros & Hooks** | Run custom G-code snippets before/after jobs. Supports variable substitution. | +| **Broad File Support** | Import from SVG, DXF, PDF, JPEG, PNG, BMP, and even Ruida files (`.rd`). | +| **Multi-Laser Operations** | Choose different lasers for each operation in a job | +| **Camera Integration** | Use a USB camera for workpiece alignment, positioning, and background tracing. | +| **Cross-Platform** | Native builds for Linux and Windows. | +| **Extensible** | Open development model makes it easy to [add support for new devices](docs/driver.md). | +| **Multi-Language** | Available in English, Portuguese, Spanish, and German. | +| **G-code Dialects** | Supports GRBL, Smoothieware, and other GRBL-compatible firmwares. + +## Quick Links + +
+ +- :material-rocket-launch:{ .lg .middle } __[Getting Started](getting-started/index.md)__ + + --- + + New to Rayforge? Start here for installation instructions and your first project. + +- :material-view-dashboard:{ .lg .middle } __[User Interface](ui/index.md)__ + + --- + + Learn about the main window, canvas tools, and interface elements. + +- :material-feature-search:{ .lg .middle } __[Features](features/index.md)__ + + --- + + Explore all the operations and capabilities Rayforge offers. + +- :material-wrench:{ .lg .middle } __[Machine Setup](machine/index.md)__ + + --- + + Configure your laser cutter or engraver to work with Rayforge. + +
+ +## Platform Support + +Rayforge runs natively on: + +- **Linux** - Ubuntu 24.04+ (PPA), Snap package for all distributions, or install from source +- **Windows** - Native builds available + +See the [Installation Guide](getting-started/installation.md) for detailed instructions. + +## Device Compatibility + +| Device Type | Connection Method | Notes | +| :--------------- | :---------------------- | :------------------------------------------------------------- | +| **GRBL** | Serial Port | Supported since version 0.13. The most common connection type. | +| **GRBL** | Network (WiFi/Ethernet) | Connect to any GRBL device on your network. | +| **Smoothieware** | Telnet | Supported since version 0.15. | + +## Community & Support + +- **Report Issues**: [GitHub Issues](https://github.com/barebaric/rayforge/issues) +- **Source Code**: [GitHub Repository](https://github.com/barebaric/rayforge) +- **Contribute**: See our [Contributing Guide](contributing/index.md) + +## About This Documentation + +This documentation is designed for end-users of Rayforge. If you're looking for developer documentation, please see the [Development Setup](contributing/development.md) guide. + +--- + +Ready to get started? Head to the [Installation Guide](getting-started/installation.md) to install Rayforge on your system. diff --git a/docs-site/machine/device-config.md b/docs-site/machine/device-config.md new file mode 100644 index 000000000..b8d10e92e --- /dev/null +++ b/docs-site/machine/device-config.md @@ -0,0 +1,521 @@ +# Device Configuration + +Device configuration determines how RayForge communicates with your laser cutter hardware. Choosing the correct driver and connection settings is essential for reliable operation. + +## Overview + +Device configuration includes: + +- **Driver selection**: Communication protocol (Serial, Network, WiFi) +- **Connection parameters**: Port, baud rate, IP address, hostname +- **G-code dialect**: Command language variant (GRBL, Smoothie, Marlin) +- **Connection behavior**: Auto-homing, alarm clearing, retry logic + + + +![Device configuration dialog](../images/UI-Device-Config.png) + +## Available Drivers + +RayForge supports multiple communication methods to connect to different controller types. + +### GRBL (Serial) + +**Best for:** +- USB-connected laser cutters +- GRBL-based controllers (most common) +- Arduino/AVR-based systems +- Desktop and small format lasers + +**Connection method:** +- Direct USB serial connection +- Virtual COM port (Windows) or /dev/ttyUSB* (Linux) +- Standard baud rates: 115200 (most common), 230400, 57600 + +**Configuration parameters:** + + + +![GRBL Serial settings](../images/UI-GRBL-Serial-Settings.png) + +**Port:** +- Serial port device path +- **Linux:** `/dev/ttyUSB0`, `/dev/ttyACM0`, etc. +- **Windows:** `COM3`, `COM4`, etc. +- **macOS:** `/dev/tty.usbserial-*` + +!!! warning "Permission Issues on Linux" + On Linux, you may need permissions to access serial ports. See [Snap Permissions](../troubleshooting/snap-permissions.md) if running the snap package, or add your user to the `dialout` group for traditional installs: + ```bash + sudo usermod -a -G dialout $USER + ``` + Log out and back in for changes to take effect. + +**Baud Rate:** +- Communication speed in bits per second +- **115200**: Default for most GRBL controllers (recommended) +- **230400**: Faster, if controller supports it +- **57600**: Older boards or slow microcontrollers +- **9600**: Very old or specialized hardware + +**Finding your port:** + +=== "Linux" + ```bash + # List USB serial devices + ls /dev/ttyUSB* /dev/ttyACM* + + # Or use dmesg to see what was detected + dmesg | grep tty + ``` + +=== "Windows" + 1. Open Device Manager + 2. Expand "Ports (COM & LPT)" + 3. Look for "USB Serial Port (COMx)" + 4. Note the COM number + +=== "macOS" + ```bash + # List USB serial devices + ls /dev/tty.usbserial-* + ls /dev/cu.usbserial-* + ``` + +### GRBL (Network) + +**Best for:** +- WiFi-enabled GRBL controllers +- ESP32-based laser controllers +- Remote or wireless operation +- Controllers with WebUI (like Grbl_ESP32) + +**Connection method:** +- HTTP and WebSocket protocols +- Direct network connection to controller +- No USB cable required + +**Configuration parameters:** + +**Hostname/IP Address:** +- IP address of the controller (e.g., `192.168.1.100`) +- Or hostname (e.g., `laser.local`) +- Must be reachable on your network + +**Finding your controller's IP:** + +```bash +# If controller supports mDNS +ping laser.local + +# Or check your router's DHCP client list +# Or check controller's display/WebUI +``` + +**Network requirements:** +- Controller and computer on same network +- No firewall blocking ports 80, 81, or 8080 +- Controller must support HTTP API (Grbl_ESP32, etc.) + +**Advantages:** +- No USB cable required +- Can control from any computer on network +- Multiple clients can monitor status +- WebUI and RayForge can run simultaneously + +**Disadvantages:** +- Network latency may affect responsiveness +- Requires WiFi-capable controller +- More complex troubleshooting if connectivity issues + +### No Device (Simulator) + +**Best for:** +- Testing RayForge without hardware +- Designing jobs offline +- Training and demonstrations +- Developing G-code workflows + +**Behavior:** +- Simulates a connected laser +- Accepts all commands without error +- Reports simulated position and status +- Doesn't actually control any hardware + +**Use cases:** +- Preview G-code output +- Test operation sequences +- Learn RayForge interface +- Design projects away from machine + +!!! tip "Testing Without Risk" + Use "No Device" driver to safely test complex jobs before running on real hardware. You can generate G-code and review it, then switch to your real driver when ready to cut. + +## G-code Dialects + +Different controllers speak slightly different "dialects" of G-code. Select the one matching your hardware. + +### GRBL + +**Most common dialect** for hobby laser cutters. + +**Characteristics:** +- Uses `M3`/`M5` for laser on/off +- Power set with `S` parameter (S0-S1000) +- Supports `$` system commands +- Real-time status reporting (`?` command) + +**Typical controllers:** +- Arduino + GRBL firmware +- Grbl_ESP32 +- Most Chinese laser boards +- DIY laser builds + +**Example G-code:** +```gcode +G21 ; Millimeters +G90 ; Absolute positioning +M3 S800 ; Laser on at 80% power +G1 X10 Y10 F500 ; Move and cut +M5 ; Laser off +``` + +### Smoothie + +**Less common**, used on more advanced controllers. + +**Characteristics:** +- Similar to GRBL but different configuration system +- Uses `/dev/ttyACM*` typically +- Web-based configuration +- More sophisticated motion planning + +**Typical controllers:** +- Smoothieboard +- Cohesion3D boards (some) +- Higher-end laser retrofits + +**Example G-code:** +```gcode +G21 ; Millimeters +G90 ; Absolute positioning +M3 ; Laser on +S0.8 ; Power (0.0-1.0 range) +G1 X10 Y10 F500 ; Move and cut +M5 ; Laser off +``` + +### Marlin + +**Primarily for 3D printers**, occasionally used for lasers. + +**Characteristics:** +- 3D printer origins +- Laser support added via M3/M4 commands +- Complex configuration through firmware +- May require recompilation for laser mode + +**Typical controllers:** +- RepRap boards (RAMPS, SKR, etc.) with laser module +- 3D printer + laser upgrade +- CNC routers with laser attachment + +!!! info "Dialect Mismatch Symptoms" + If commands are rejected or laser doesn't respond correctly, verify your dialect selection matches your controller's firmware. Check controller documentation or manufacturer website. + +## Connection Settings + +### Home on Start + +**Enabled:** +- Machine runs homing cycle immediately after connection +- Finds physical home switches (X, Y origins) +- Establishes absolute coordinate system +- Required for accurate positioning + +**Disabled:** +- No automatic homing +- Uses current position as origin +- Must home manually if needed + +**When to enable:** +- Your machine has home/limit switches +- You want absolute positioning +- Production workflows requiring repeatability + +**When to disable:** +- L Machine lacks home switches +- L Home switches are broken/disconnected +- L You prefer manual homing control + +!!! warning "Homing Without Switches" + Enabling "Home on Start" on a machine without home switches will cause the machine to drive into physical limits, potentially damaging belts or losing position. Only enable if hardware supports it. + +### Clear Alarm on Connect + +**Enabled:** +- Automatically sends `$X` (unlock) command on connection +- Clears GRBL alarm state +- Allows movement immediately + +**Disabled:** +- Alarm state must be cleared manually +- User must diagnose alarm cause +- Safer, prevents ignoring real issues + +**When to enable:** +- Machine frequently enters alarm state on connection +- You understand the alarm cause (e.g., power cycle alarm) +- Convenience over safety checking + +**When to disable:** +- **Recommended default** +- You want to diagnose alarm causes +- Safety-critical applications +- Unknown alarm conditions + +**GRBL alarms:** +- Hard limit triggered +- Soft limit exceeded +- Abort during cycle +- Probe fail +- Homing fail + +See [GRBL documentation](https://github.com/gnea/grbl/wiki/Grbl-v1.1-Alarms) for alarm details. + +## Testing Your Configuration + +### Connection Test + +After configuring driver settings: + +1. Click "Test Connection" button +2. RayForge attempts to connect to device +3. Success: Green indicator, "Connected" status +4. Failure: Error message with diagnostic info + + + +![Connection test success](../images/UI-Connection-Test-Success.png) + +### Verifying Communication + +Once connected: + +**Check console log:** +- Should show connection handshake +- GRBL welcome message +- Status reports + +**Test movement:** +- Use jog controls to move laser head +- Verify movement direction matches commands +- Check homing if enabled + +**Test framing:** +- Load a simple design +- Run frame operation (low power outline) +- Verify dimensions and position + +## Common Connection Issues + +### Port not found + +**Symptoms:** +- Port doesn't appear in dropdown +- "Port not found" error + +**Solutions:** +- Check USB cable is connected +- Try different USB port +- Check device power +- Linux: Verify permissions (see [Snap Permissions](../troubleshooting/snap-permissions.md)) +- Windows: Install CH340/CP2102 drivers if needed + +### Connection timeout + +**Symptoms:** +- "Connection timeout" error +- Port opens but no response + +**Solutions:** +- Verify baud rate (try 115200 first) +- Check if another program is using the port +- Restart controller (power cycle) +- Try different USB cable +- Check for hardware issues + +### Commands rejected + +**Symptoms:** +- "Unknown command" errors +- G-code not executing + +**Solutions:** +- Verify G-code dialect matches controller +- Check for firmware compatibility +- Update GRBL firmware if outdated +- Review controller documentation + +### Intermittent connection + +**Symptoms:** +- Random disconnections +- Dropped commands +- "Connection lost" errors + +**Solutions:** +- Replace USB cable (most common cause) +- Check for electrical interference +- Reduce baud rate (115200 57600) +- Verify adequate power supply to controller +- Check for loose connections + +See [Connection Troubleshooting](../troubleshooting/connection.md) for detailed diagnostics. + +## Advanced Configuration + +### Multiple Controller Support + +If you have multiple lasers: + +1. Create separate machine profiles +2. Each profile has its own driver configuration +3. Switch between machines using machine selector + +See [Machine Profiles](profiles.md) for details. + +### Custom Baud Rates + +Some controllers use non-standard baud rates: + +- 256000 bps +- 921600 bps (high-speed controllers) +- Custom firmware rates + +Check controller documentation or try standard rates first. + +### Network Driver Advanced + +**Custom ports:** +- Default: HTTP on 80, WebSocket on 81 +- Some controllers use 8080 for HTTP +- Check controller's WebUI documentation + +**Static IP vs. DHCP:** +- Static IP: Reliable, consistent connection +- DHCP: Convenient but IP may change +- Consider setting static IP on controller + +**Firewall issues:** +- Ensure ports 80 and 81 are open +- Disable firewall temporarily to test +- Add firewall exception for RayForge + +## G-code Precision + +**Setting:** Number of decimal places for coordinates + +**Values:** +- **1**: `X12.3` - Very small files, lower precision +- **2**: `X12.34` - Compact, adequate for most work +- **3**: `X12.345` - **Recommended default** - Good balance +- **4**: `X12.3456` - High precision, larger files +- **5**: `X12.34567` - Extreme precision, rarely needed + +**When to adjust:** +- **Lower (1-2)**: Large engraving files, storage-limited controllers +- **Higher (4-5)**: Precision mechanical parts, fine detail work + +**Impact:** +- Precision: More decimals = finer positioning resolution +- File size: More decimals = larger G-code files +- Performance: Larger files = longer transfer time + +Most machines have 0.01mm resolution, making precision=3 optimal. + +## Driver Development + +RayForge's driver system is extensible. If your controller isn't supported: + +**Options:** +1. Use generic GRBL driver (often works for GRBL-based controllers) +2. Request driver support (GitHub issues) +3. Contribute a driver (see developer docs) + +**Driver interface:** +- Python-based +- Async I/O for responsiveness +- Signal-based event system +- VarSet for configuration UI + +## Related Topics + +- **[Machine Profiles](profiles.md)** - Complete machine configuration +- **[GRBL Settings](grbl-settings.md)** - Controller parameters ($$ settings) +- **[Connection Troubleshooting](../troubleshooting/connection.md)** - Fixing connection problems +- **[Snap Permissions](../troubleshooting/snap-permissions.md)** - Linux serial port access diff --git a/docs-site/machine/grbl-settings.md b/docs-site/machine/grbl-settings.md new file mode 100644 index 000000000..bb9f26788 --- /dev/null +++ b/docs-site/machine/grbl-settings.md @@ -0,0 +1,625 @@ +# GRBL Settings + +GRBL settings (also called "dollar settings" or `$$` settings) are parameters stored in your controller's EEPROM that control how your laser behaves. Understanding these settings is essential for proper machine configuration and troubleshooting. + +!!! warning "Caution When Changing Settings" + Incorrect GRBL settings can cause your machine to behave unpredictably, lose position, or even damage hardware. Always record original values before making changes, and modify one setting at a time. + +## Overview + +GRBL settings control: + +- **Motion parameters**: Speed limits, acceleration, calibration +- **Limit switches**: Homing behavior, soft/hard limits +- **Laser control**: Power range, laser mode enable +- **Electrical configuration**: Pin inversions, pullups +- **Reporting**: Status message format and frequency + +These settings are stored on your controller (not in RayForge) and persist across power cycles. + + + +![GRBL settings panel](../images/UI-GRBL-Settings.png) + +## Accessing GRBL Settings + +### From RayForge + +1. **Menu:** Preferences Machine GRBL Settings +2. RayForge reads settings from device automatically +3. Edit values in the interface +4. Click "Apply" to write changes to controller + +### From Console + +You can also view/modify settings via G-code console: + +**View all settings:** +``` +$$ +``` + +**View single setting:** +``` +$100 +``` + +**Modify setting:** +``` +$100=80.0 +``` + +**Restore defaults:** +``` +$RST=$ +``` + +!!! danger "Restore Defaults Erases All Settings" + The `$RST=$` command resets all GRBL settings to factory defaults. You'll lose any calibration and tuning. Back up your settings first! + +## Critical Settings for Lasers + +These settings are most important for laser operation: + +### $32 - Laser Mode + +**Value:** 0 = Disabled, 1 = Enabled + +**Purpose:** Enables laser-specific features in GRBL + +**When enabled (1):** +- Laser automatically turns off during G0 (rapid) moves +- Power dynamically adjusts during acceleration/deceleration +- Prevents accidental burns during positioning + +**When disabled (0):** +- Laser behaves like a spindle (CNC mode) +- Doesn't turn off during rapids +- **Dangerous for laser use!** + +!!! warning "Always Enable Laser Mode" + $32 should **always** be set to 1 for laser cutters. Disabled laser mode can cause unintended burns and fire hazards. + +**Setting laser mode:** +```gcode +$32=1 +``` + +### $30 & $31 - Laser Power Range + +**$30 - Maximum Laser Power (RPM)** +**$31 - Minimum Laser Power (RPM)** + +**Purpose:** Defines the power range for S commands + +**Typical values:** +- $30=1000, $31=0 (S0-S1000 range, most common) +- $30=255, $31=0 (S0-S255 range, some controllers) +- $30=1000, $31=10 (prevents laser from dropping below 1%) + +**How it works:** +- `S1000` $30 value 100% laser power +- `S500` 50% of $30 50% laser power +- `S0` $31 value Minimum power (typically 0%) + +**Example:** +```gcode +$30=1000.0 ; Maximum S value = 100% power +$31=0.0 ; Minimum S value = 0% power +``` + +!!! tip "Matching RayForge Configuration" + The "Max Power" setting in your [Machine Profile](profiles.md) should match your $30 value. If $30=1000, set max power to 1000 in RayForge. + +### $130 & $131 - Maximum Travel + +**$130 - X Maximum Travel (mm)** +**$131 - Y Maximum Travel (mm)** + +**Purpose:** Defines your machine's working area + +**Typical values:** +- $130=300, $131=200 (300mm 200mm bed) +- $130=400, $131=400 (400mm 400mm bed) +- $130=1000, $131=600 (large format laser) + +**Why it matters:** +- Soft limits ($20) use these values to prevent crashes +- Defines the coordinate system bounds +- Must match your physical machine size + +**Measuring your bed:** +1. Manually jog to maximum X position +2. Note X position from status (`?` command) +3. Set $130 to that value +4. Repeat for Y axis ($131) + +**Example:** +```gcode +$130=400.0 ; X-axis can travel 400mm +$131=300.0 ; Y-axis can travel 300mm +``` + +## Settings by Category + +### Stepper Configuration ($0-$6) + +Controls stepper motor electrical signals and timing. + +| Setting | Description | Typical Value | Notes | +|---------|-------------|---------------|-------| +| $0 | Step pulse time ( s) | 10 | How long step signal lasts | +| $1 | Step idle delay (ms) | 25 | Delay before disabling steppers | +| $2 | Step pulse invert (mask) | 0 | Invert step signal (rare) | +| $3 | Step direction invert (mask) | 0 | Reverse motor direction | +| $4 | Invert step enable pin | 0 | Invert stepper enable signal | +| $5 | Invert limit pins | 0 | Invert limit switch logic | +| $6 | Invert probe pin | 0 | Invert probe signal (not used for lasers) | + +**When to change:** +- Motors run backwards: Adjust $3 +- Stepper driver compatibility: Adjust $0 or $4 +- Limit switches trigger incorrectly: Adjust $5 + +**Example - Inverting Y direction:** +```gcode +$3=2 ; Bit 1 set (binary 10 = Y-axis inverted) +``` + +### Control & Reporting ($10-$13) + +Controls motion planning and status report format. + +| Setting | Description | Typical Value | Notes | +|---------|-------------|---------------|-------| +| $10 | Status report options (mask) | 1 | WPos=1, MPos=0 | +| $11 | Junction deviation (mm) | 0.010 | Cornering speed (lower = sharper) | +| $12 | Arc tolerance (mm) | 0.002 | Accuracy of curved paths | +| $13 | Report in inches | 0 | 0=mm, 1=inches | + +**$11 - Junction Deviation:** +- **Lower (0.005-0.010)**: Sharp corners, slower on curves, better accuracy +- **Higher (0.020-0.050)**: Smoother motion, faster on curves, slightly rounded corners +- **Laser typical**: 0.010mm works well for most jobs + +**$12 - Arc Tolerance:** +- Defines how finely arcs are approximated +- Lower = smoother circles, more G-code commands +- 0.002mm is good for most work + +**Example:** +```gcode +$10=1 ; Report work position (WPos) +$11=0.010 ; 0.010mm junction deviation +$12=0.002 ; 0.002mm arc tolerance +$13=0 ; Report in millimeters +``` + +### Limits & Homing ($20-$27) + +Controls limit switches and homing behavior. + +| Setting | Description | Typical Value | Notes | +|---------|-------------|---------------|-------| +| $20 | Soft limits enable | 0 or 1 | Prevents moves beyond $130/$131 | +| $21 | Hard limits enable | 0 | Physical limit switch protection | +| $22 | Homing cycle enable | 0 or 1 | Enable $H homing command | +| $23 | Homing direction invert (mask) | 0 | Which direction to home | +| $24 | Homing locate feed rate (mm/min) | 25 | Slow approach speed | +| $25 | Homing search seek rate (mm/min) | 500 | Fast search speed | +| $26 | Homing debounce delay (ms) | 250 | Switch debounce time | +| $27 | Homing pull-off distance (mm) | 1.0 | Distance to back off switch | + +**$20 - Soft Limits:** +- **Enabled (1)**: Controller prevents moves beyond $130/$131 +- **Disabled (0)**: No software travel limits +- Requires homing to work (must know position) +- Recommended if you have home switches + +**$21 - Hard Limits:** +- **Enabled (1)**: Triggers alarm if limit switch activated +- **Disabled (0)**: Limit switches ignored (except during homing) +- Can cause nuisance alarms if switches are sensitive +- Often left disabled on lasers + +**$22 - Homing Enable:** +- **Enabled (1)**: `$H` command performs homing cycle +- **Disabled (0)**: Homing not available +- Only enable if you have home switches installed + +**Homing cycle process:** +1. Rapid search ($25 speed) until switch triggers +2. Back off pull-off distance ($27) +3. Slow approach ($24 speed) for precise location +4. Back off to pull-off distance +5. Set position to (0,0) + +**Example - Machine with home switches:** +```gcode +$20=1 ; Enable soft limits +$21=0 ; Disable hard limits (optional) +$22=1 ; Enable homing +$23=0 ; Home to min (default) +$24=50.0 ; Slow approach at 50mm/min +$25=1000.0 ; Fast search at 1000mm/min +$26=250 ; 250ms debounce +$27=2.0 ; Pull off 2mm from switch +``` + +### Spindle & Laser ($30-$32) + +**See "Critical Settings" section above** for detailed explanation of $30, $31, and $32. + +| Setting | Description | Laser Value | Notes | +|---------|-------------|-------------|-------| +| $30 | Maximum spindle speed | 1000.0 | Max S value (100% power) | +| $31 | Minimum spindle speed | 0.0 | Min S value (0% power) | +| $32 | Laser mode enable | 1 | **MUST be 1 for lasers** | + +**Example:** +```gcode +$30=1000.0 +$31=0.0 +$32=1 ; Laser mode ON +``` + +### Axis Calibration ($100-$102) + +Defines how many stepper motor steps equal one millimeter of movement. + +| Setting | Description | Notes | +|---------|-------------|-------| +| $100 | X steps/mm | Depends on pulley/belt/gear ratio | +| $101 | Y steps/mm | Usually same as X for typical lasers | +| $102 | Z steps/mm | Not used on most lasers | + +**Calculating steps/mm:** + +``` +steps/mm = (motor_steps_per_rev microstepping) / (pulley_teeth belt_pitch) +``` + +**Example calculation:** +- Motor: 200 steps/rev (1.8 stepper) +- Microstepping: 16 (typical) +- Pulley: 20 teeth +- Belt: GT2 (2mm pitch) + +``` +steps/mm = (200 16) / (20 2) = 3200 / 40 = 80 +``` + +**Calibration procedure:** +1. Mark starting position on bed +2. Command 100mm move: `G0 X100` +3. Measure actual distance traveled +4. Calculate: `new_value = current_value (100 / actual_distance)` +5. Set new value: `$100=new_value` + +**Example:** +```gcode +$100=80.0 ; X-axis: 80 steps/mm +$101=80.0 ; Y-axis: 80 steps/mm +$102=80.0 ; Z-axis: 80 steps/mm (unused) +``` + +!!! tip "Calibration Test" + Cut a 100mm 100mm square and measure the result. If it's 102mm 98mm, adjust $100 and $101 accordingly using the formula above. + +### Axis Kinematics ($110-$122) + +Controls maximum speed and acceleration for each axis. + +| Setting | Description | Typical Value | Notes | +|---------|-------------|---------------|-------| +| $110 | X max rate (mm/min) | 5000.0 | Max X speed | +| $111 | Y max rate (mm/min) | 5000.0 | Max Y speed | +| $112 | Z max rate (mm/min) | 500.0 | Max Z speed (unused) | +| $120 | X acceleration (mm/sec ) | 500.0 | How fast X accelerates | +| $121 | Y acceleration (mm/sec ) | 500.0 | How fast Y accelerates | +| $122 | Z acceleration (mm/sec ) | 100.0 | How fast Z accelerates | + +**Max rate ($110-$112):** +- Absolute speed limit for each axis +- Controller won't exceed these values +- Should match or exceed your machine profile's max speeds +- Typical: 3000-6000 mm/min for lasers + +**Acceleration ($120-$122):** +- How quickly machine reaches target speed +- **Lower (100-300)**: Smooth, slow acceleration, gentler on mechanics +- **Higher (500-1000)**: Snappy, fast start/stop, may cause vibration +- Typical: 300-500 mm/sec for lasers + +**Finding safe values:** +1. Start conservative (max rate: 3000, accel: 300) +2. Gradually increase while testing +3. Listen for motor skipping, belt slipping +4. Watch for excessive vibration or ringing + +**Example:** +```gcode +$110=4000.0 ; X max 4000 mm/min +$111=4000.0 ; Y max 4000 mm/min +$112=500.0 ; Z max 500 mm/min +$120=400.0 ; X accel 400 mm/sec +$121=400.0 ; Y accel 400 mm/sec +$122=100.0 ; Z accel 100 mm/sec +``` + +### Axis Travel ($130-$132) + +**See "Critical Settings" section** for detailed explanation of $130 and $131. + +| Setting | Description | Notes | +|---------|-------------|-------| +| $130 | X max travel (mm) | Working area width | +| $131 | Y max travel (mm) | Working area depth | +| $132 | Z max travel (mm) | Z travel (if applicable) | + +**Example:** +```gcode +$130=400.0 ; 400mm X travel +$131=400.0 ; 400mm Y travel +$132=50.0 ; 50mm Z travel (if you have Z-axis) +``` + +## Common Configuration Examples + +### Typical Small Diode Laser (300 400mm) + +```gcode +$0=10 ; Step pulse 10 s +$1=255 ; Step idle delay 255ms +$2=0 ; No step invert +$3=0 ; No direction invert +$4=0 ; No enable invert +$5=0 ; No limit invert +$10=1 ; Report WPos +$11=0.010 ; Junction deviation 0.01mm +$12=0.002 ; Arc tolerance 0.002mm +$13=0 ; Report mm +$20=1 ; Soft limits enabled +$21=0 ; Hard limits disabled +$22=1 ; Homing enabled +$23=0 ; Home to min +$24=50.0 ; Homing feed 50mm/min +$25=1000.0 ; Homing seek 1000mm/min +$26=250 ; Homing debounce 250ms +$27=2.0 ; Homing pull-off 2mm +$30=1000.0 ; Max power S1000 +$31=0.0 ; Min power S0 +$32=1 ; Laser mode ON +$100=80.0 ; X steps/mm +$101=80.0 ; Y steps/mm +$102=80.0 ; Z steps/mm +$110=5000.0 ; X max rate +$111=5000.0 ; Y max rate +$112=500.0 ; Z max rate +$120=500.0 ; X accel +$121=500.0 ; Y accel +$122=100.0 ; Z accel +$130=400.0 ; X max travel +$131=300.0 ; Y max travel +$132=0.0 ; Z max travel +``` + +### CO Laser Without Home Switches + +```gcode +$0=10 +$1=25 +$2=0 +$3=0 +$4=0 +$5=0 +$10=1 +$11=0.010 +$12=0.002 +$13=0 +$20=0 ; Soft limits OFF (no homing) +$21=0 ; Hard limits OFF +$22=0 ; Homing disabled +$30=1000.0 +$31=0.0 +$32=1 ; Laser mode ON +$100=157.48 ; Example calibration value +$101=157.48 +$102=157.48 +$110=3000.0 +$111=3000.0 +$112=500.0 +$120=300.0 +$121=300.0 +$122=100.0 +$130=600.0 ; 600 400mm bed +$131=400.0 +$132=0.0 +``` + +## Backing Up and Restoring Settings + +### Backup Procedure + +1. **Via RayForge:** + - Open GRBL Settings panel + - Click "Export Settings" + - Save file as `grbl-backup-YYYY-MM-DD.txt` + +2. **Via console:** + - Send `$$` command + - Copy all output to text file + - Save with date + +### Restore Procedure + +1. **From backup file:** + - Open file + - Send each line (`$100=80.0`, etc.) via console + - Verify with `$$` command + +2. **Via RayForge:** + - Open GRBL Settings panel + - Click "Import Settings" + - Select backup file + - Review changes and apply + +!!! tip "Regular Backups" + Back up your GRBL settings after any calibration or tuning. Store backups in a safe location (cloud storage, USB drive). This makes recovery quick if settings are lost or corrupted. + +## Troubleshooting GRBL Settings + +### Can't write settings + +**Error:** `error:7` (Read-only setting) + +**Cause:** Setting is locked or doesn't exist + +**Fix:** +- Check setting number is valid for your GRBL version +- Some settings require specific GRBL compile options + +--- + +**Error:** `error:3` (Invalid statement) + +**Cause:** Incorrect syntax + +**Fix:** +- Use format: `$100=80.0` (no spaces around =) +- Ensure value is appropriate type (number vs. boolean) + +### Settings won't apply + +**Symptom:** Changes don't take effect + +**Fix:** +- Send soft reset after changes: `Ctrl+X` or `$X` +- Power cycle controller +- Verify setting was written: Send `$$` and check value + +### Machine behavior incorrect + +**Symptom:** Motors run backwards + +**Fix:** +- Adjust $3 (direction invert) for affected axis +- X-axis: $3=1, Y-axis: $3=2, Both: $3=3 + +--- + +**Symptom:** Jobs go out of bounds + +**Fix:** +- Check $130/$131 match your machine size +- Enable soft limits ($20=1) with homing ($22=1) +- Verify origin position before starting job + +--- + +**Symptom:** Laser doesn't turn off during rapids + +**Fix:** +- **CRITICAL**: Set $32=1 (laser mode) +- Verify with `$$` that $32 shows value 1 +- Power cycle controller if necessary + +### Lost all settings + +**Cause:** EEPROM cleared, firmware update, or `$RST=$` command + +**Fix:** +1. Restore from backup file (see "Backing Up" above) +2. Or recalibrate from scratch: + - Start with example config for your machine type + - Adjust $100/$101 calibration + - Set $130/$131 to bed size + - Enable laser mode ($32=1) + - Set power range ($30/$31) + - Tune speeds and acceleration + +## Advanced Topics + +### GRBL Versions + +Different GRBL versions support different settings: + +- **GRBL 0.9:** Older, fewer settings +- **GRBL 1.1:** Standard, most common +- **Grbl_ESP32:** Extended settings for ESP32 features +- **GRBL-Mega:** More axes (A, B, C) + +Check your version: +```gcode +$I +``` + +Output example: +``` +[VER:1.1h.20190825:] +[OPT:V,15,128] +``` + +### Bitmask Settings + +Some settings use bitmasks (multiple flags in one number): + +**$3 - Direction Invert Mask:** +- Bit 0 (value 1) = X-axis +- Bit 1 (value 2) = Y-axis +- Bit 2 (value 4) = Z-axis + +**Examples:** +- $3=0: No inversion +- $3=1: X inverted +- $3=2: Y inverted +- $3=3: X and Y inverted (1+2=3) +- $3=7: All axes inverted (1+2+4=7) + +**$10 - Status Report Mask:** +- Bit 0 (value 1) = Report work position (WPos) +- Bit 1 (value 2) = Report buffer data + +**Examples:** +- $10=0: MPos only +- $10=1: WPos only (recommended) +- $10=3: WPos + buffer (1+2=3) + +## Related Topics + +- **[Machine Profiles](profiles.md)** - Higher-level machine configuration +- **[Device Configuration](device-config.md)** - Driver and connection setup +- **[Connection Troubleshooting](../troubleshooting/connection.md)** - Fixing connection issues +- **[Common Problems](../troubleshooting/common.md)** - General troubleshooting + +## External Resources + +- [GRBL v1.1 Configuration](https://github.com/gnea/grbl/wiki/Grbl-v1.1-Configuration) +- [GRBL v1.1 Commands](https://github.com/gnea/grbl/wiki/Grbl-v1.1-Commands) +- [Grbl_ESP32 Documentation](https://github.com/bdring/Grbl_Esp32/wiki) diff --git a/docs-site/machine/index.md b/docs-site/machine/index.md new file mode 100644 index 000000000..97fecc13e --- /dev/null +++ b/docs-site/machine/index.md @@ -0,0 +1,163 @@ +# Machine Setup + +Configure your laser cutter or engraver to work with Rayforge. This section covers machine profiles, device connections, and hardware configuration. + +## Quick Start + +1. **[Machine Profiles](profiles.md)**: Create profiles for different machines +2. **[Device Configuration](device-config.md)**: Connect via serial, network, or telnet +3. **[GRBL Settings](grbl-settings.md)**: Configure firmware parameters +4. **[Multiple Lasers](multi-laser.md)**: Set up machines with multiple laser modules + +## Supported Devices + +Rayforge supports a wide range of GRBL and Smoothieware-based laser cutters: + +### GRBL Devices + +- **Connection**: Serial (USB) or Network (WiFi/Ethernet) +- **Versions**: GRBL 1.1 and later +- **Common Brands**: + - Ortur + - Atomstack + - Xtool + - Generic K40 with GRBL board + - DIY GRBL builds + +### Smoothieware Devices + +- **Connection**: Telnet over network +- **Versions**: Smoothieware v1 and v2 +- **Common Brands**: + - Cohesion3D boards + - Custom CNC controllers + +## Machine Profiles + +Machine profiles store all configuration for a specific laser cutter: + +- Working area dimensions +- Power and speed ranges +- Origin position +- Laser module configuration +- Device connection settings +- GRBL/firmware parameters + +**Benefits of Profiles:** + +- Switch between multiple machines instantly +- Share configurations with others +- Backup and restore settings +- Test different configurations safely + +See [Machine Profiles](profiles.md) for details. + +## Connection Types + +### Serial Port (USB) + +Most common connection method for GRBL devices. + +**Pros:** + +- ✓ Reliable and fast +- ✓ No network configuration required +- ✓ Works with any GRBL device + +**Cons:** + +- ✗ Requires USB cable +- ✗ Limited by cable length + +### Network (WiFi/Ethernet) + +Connect to GRBL devices over your local network. + +**Pros:** + +- ✓ Wireless operation +- ✓ No cable length limitations +- ✓ Multiple users can access (not simultaneously) + +**Cons:** + +- ✗ Requires network-capable GRBL board +- ✗ Potential latency issues on congested networks + +### Telnet (Smoothieware) + +Standard connection for Smoothieware controllers. + +**Pros:** + +- ✓ Full Smoothieware feature support +- ✓ Network-based (no cables) + +**Cons:** + +- ✗ Only for Smoothieware devices +- ✗ Requires network configuration + +## Configuration Workflow + +Follow this workflow to set up a new machine: + +```mermaid +stateDiagram-v2 + [*] --> Disconnected + Disconnected --> Connecting: Connect + Connecting --> Connected: Success + Connecting --> Error: Failed + Error --> Disconnected: Reset + + Connected --> Idle: Ready + Idle --> Homing: Home Command + Homing --> Idle: Complete + + Idle --> Running: Start Job + Running --> Paused: Pause + Paused --> Running: Resume + Running --> Idle: Complete/Stop + + Connected --> Disconnected: Disconnect + Running --> Error: Alarm/Error + Error --> Idle: Reset + + note right of Disconnected + Configure profile + Select connection type + end note + + note right of Connected + Test communication + Read GRBL settings + end note + + note right of Idle + Ready for commands + Can jog/frame/start + end note +``` + +**Setup Steps:** + +1. **Create Profile**: Define basic machine parameters +2. **Configure Device**: Set up connection (serial/network/telnet) +3. **Test Connection**: Verify communication with machine +4. **Read GRBL Settings**: Import firmware parameters +5. **Configure Lasers**: Set up laser modules (if multiple) +6. **Test Movement**: Jog controls and homing +7. **Calibrate**: Run test cuts to verify power and speed settings + +## Troubleshooting + +Common machine setup issues: + +- **[Connection Issues](../troubleshooting/connection.md)**: Can't connect to device +- **[Permissions](../troubleshooting/snap-permissions.md)**: Linux/Snap permission problems +- **Homing Fails**: Check limit switches and GRBL settings +- **Incorrect Origin**: Verify origin position in machine profile + +--- + +**Next**: [Machine Profiles →](profiles.md) | [Device Configuration →](device-config.md) diff --git a/docs-site/machine/multi-laser.md b/docs-site/machine/multi-laser.md new file mode 100644 index 000000000..d0e0517d0 --- /dev/null +++ b/docs-site/machine/multi-laser.md @@ -0,0 +1,546 @@ +# Multi-Laser Setup + +Some laser machines have multiple laser modules (e.g., a diode laser and a CO tube, or multiple diodes at different wavelengths). RayForge supports multi-laser setups through tool selection and head configuration. + +## Overview + +Multi-laser systems allow: + +- **Multiple laser types**: Combine different laser technologies on one machine +- **Different wavelengths**: Blue diode for marking, IR for cutting +- **Varied power levels**: Low-power engraving head + high-power cutting head +- **Specialized applications**: UV for special materials, fiber for metals + +RayForge handles multi-laser machines through: + +- **Laser head configuration**: Define each laser's properties +- **Tool selection**: Switch between lasers via G-code commands +- **Per-operation assignment**: Choose which laser executes each operation + + + +![Multi-laser configuration](../images/UI-Multi-Laser-Config.png) + +## Common Multi-Laser Configurations + +### Diode + CO + +**Use case:** Versatility - marking with diode, cutting with CO + +**Example setup:** +- **Head 1 (T0):** 10W blue diode laser + - Engraving on metals, anodized aluminum + - Low-power marking + - Visible beam for alignment +- **Head 2 (T1):** 40W CO laser tube + - Cutting wood, acrylic, leather + - Deep engraving + - High power for thick materials + +**Advantages:** +- Best of both worlds +- One machine for multiple materials +- No tool changes required + +**Challenges:** +- Different focal lengths (may need Z adjustment) +- Different power characteristics +- More complex calibration + +### Dual Diodes + +**Use case:** Different wavelengths or power levels + +**Example setup:** +- **Head 1 (T0):** 20W 450nm blue diode + - General cutting and engraving + - Wood, leather, cardboard +- **Head 2 (T1):** 5W 1064nm infrared diode + - Metal marking + - Anodized aluminum engraving + - Specialized materials + +**Advantages:** +- Similar focal characteristics +- Easier mechanical alignment +- Compatible power supplies + +### High Power + Low Power + +**Use case:** Precision engraving and heavy cutting on one machine + +**Example setup:** +- **Head 1 (T0):** 5W diode for fine detail + - Intricate engraving + - Small text + - Delicate work +- **Head 2 (T1):** 80W CO for cutting + - Thick material cutting + - Fast production work + - Heavy-duty operations + +## Configuring Laser Heads + +Each laser head needs individual configuration in your machine profile. + +### Adding a Laser Head + +1. **Open Preferences** Machine Laser Heads +2. Click "Add Head" +3. Configure head properties (see below) +4. Assign tool number +5. Save profile + +### Laser Head Properties + + + +![Single head configuration](../images/UI-Single-Head-Config.png) + +**Head Name:** +- Descriptive label for this laser +- Examples: "Blue Diode 20W", "CO Tube", "IR Fiber Laser" +- Helps identify which laser to use for each operation + +**Tool Number:** +- G-code tool identifier (T0, T1, T2, etc.) +- T0 typically the default/primary laser +- Must match your controller's tool configuration +- Sequential numbering (0, 1, 2...) + +**Max Power (0-1000):** +- Maximum S value for this laser +- Defines 100% power for this head +- Typically 1000 for GRBL (S1000 = 100%) +- See [GRBL Settings](grbl-settings.md) $30/$31 + +**Frame Power:** +- Low-power setting for framing (outline preview) +- Should be barely visible, not cutting +- Typical: 5-20 for diodes, 5-10 for CO +- Set to 0 to disable framing for this head + +**Spot Size (mm):** +- Physical diameter of focused laser beam +- X and Y dimensions (usually circular) +- Affects fill patterns and kerf calculations +- Measure by test cutting and comparing to design + +### Example Configuration + +**Diode + CO Setup:** + +**Head 1 - Blue Diode:** +```yaml +name: "20W Blue Diode" +tool_number: 0 +max_power: 1000 +frame_power: 20 +spot_size_mm: [0.15, 0.15] +``` + +**Head 2 - CO Tube:** +```yaml +name: "50W CO Tube" +tool_number: 1 +max_power: 1000 +frame_power: 8 +spot_size_mm: [0.08, 0.08] +``` + +## Tool Selection in G-code + +RayForge automatically generates tool change commands when switching between laser heads. + +### Tool Change Command + +**G-code:** +```gcode +T ; Select tool +``` + +**Examples:** +```gcode +T0 ; Select first laser (tool 0) +T1 ; Select second laser (tool 1) +``` + +### Automatic Tool Selection + +When you assign operations to different laser heads, RayForge: + +1. Groups operations by tool number +2. Inserts tool change commands between groups +3. Optimizes order to minimize tool changes + +**Example workflow:** +```gcode +; Job with diode engraving and CO cutting + +T0 ; Select diode laser +M3 S300 ; Diode on at 30% +G1 X10 Y10 F3000 ; Engrave logo +M5 ; Diode off + +T1 ; Select CO laser +M3 S800 ; CO on at 80% +G1 X0 Y0 F500 ; Cut outline +M5 ; CO off +``` + +## Assigning Operations to Laser Heads + +When creating operations, choose which laser should execute it. + +### In Operation Settings + +Each operation has a "Laser Head" selector: + + + +![Operation head selector](../images/UI-Operation-Head-Selector.png) + +**Choosing the right head:** + +**For engraving text/logos (low power):** +- Use diode laser if available +- Visible beam helps with alignment +- Lower power for surface marking + +**For cutting thick materials:** +- Use CO if available +- Higher power for deep cutting +- Faster cutting speeds + +**For metal marking:** +- Use IR/fiber laser if available +- Or diode for anodized aluminum +- Specific wavelengths for different metals + +### Default Head Assignment + +When adding operations: +- RayForge uses primary head (T0) by default +- Change in operation settings if needed +- Settings persist for similar operations + +## Controller Requirements + +Not all controllers support multiple laser heads. Check your controller's capabilities. + +### GRBL Support + +**Standard GRBL (v1.1):** +- Limited multi-tool support +- T0/T1 commands accepted but may not switch hardware +- Requires custom firmware or external relay + +**Grbl_ESP32:** +- Better multi-tool support +- Can control multiple PWM outputs +- Configure via `config.h` + +**Custom GRBL builds:** +- May support tool changing via custom macros +- Check your firmware documentation + +### Hardware Switching + +**Methods for physical tool selection:** + +**1. PWM Output Switching:** +- Controller routes S command to different PWM pins +- T0 PWM1, T1 PWM2 +- Requires firmware support + +**2. External Relay:** +- G-code triggers relay (M3/M5 or custom M-code) +- Relay switches power to different lasers +- Works with standard GRBL + +**3. Manual Switching:** +- Software tracks active tool +- User manually switches laser modules +- Useful for testing or simple setups + +### Configuration Example (Grbl_ESP32) + +In `config.h`: + +```cpp +#define SPINDLE_TYPE SpindleType::PWM +#define SPINDLE_OUTPUT_PIN GPIO_NUM_25 // Tool 0 +#define SPINDLE2_OUTPUT_PIN GPIO_NUM_26 // Tool 1 +``` + +Consult your controller documentation for specific configuration. + +## Calibration for Multi-Laser + +### Alignment + +Different lasers may not be perfectly co-located: + +**Physical offset:** +- Measure distance between laser focal points +- Account for X/Y offset in designs +- Or use RayForge's future "head offset" feature + +**Z-axis (focus) offset:** +- Different lasers may have different focal lengths +- Adjust Z height when changing tools +- Consider motorized Z-axis for automatic adjustment + +### Testing Alignment + +1. Create test pattern (crosshairs + small squares) +2. Engrave with Tool 0 (first laser) +3. Engrave same pattern with Tool 1 (second laser) +4. Measure offset between patterns +5. Adjust design placement or configure head offset + + + +![Alignment test pattern](../images/Ref-Multi-Laser-Alignment.png) + +### Power Calibration + +Each laser needs individual power/speed testing: + +1. Run [Material Test Grid](../features/operations/material-test-grid.md) for Tool 0 +2. Record optimal settings +3. Run separate test grid for Tool 1 +4. Record settings +5. Use appropriate settings for each laser in operations + +Power levels are **not** interchangeable between lasers! + +**Example:** +- Diode at S300 (30%) for engraving +- CO at S800 (80%) for same visual result +- Different materials respond differently to each wavelength + +## Workflow Examples + +### Example 1: Logo Engraving + Part Cutting + +**Scenario:** Engrave logo with diode, cut outline with CO + +**Steps:** +1. Import design with logo and outline +2. Create raster operation for logo Assign to Tool 0 (diode) +3. Create contour operation for outline Assign to Tool 1 (CO) +4. RayForge generates: + ```gcode + T0 ; Select diode + ; ... raster engraving commands + T1 ; Select CO + ; ... contour cutting commands + ``` + +**Order:** +- Engrave first (while part secured to bed) +- Cut second (part comes free) + +### Example 2: Multi-Material Job + +**Scenario:** Mark anodized aluminum and cut acrylic in same job + +**Steps:** +1. Design includes aluminum tags and acrylic frame +2. Engraving on aluminum Tool 0 (diode for anodized) +3. Cutting on acrylic Tool 1 (CO for cutting) +4. Position materials correctly on bed +5. Run job with automatic tool switching + +### Example 3: Detail + Production + +**Scenario:** Fine engraving with low-power laser, heavy cutting with high-power laser + +**Steps:** +1. Intricate design elements Tool 0 (5W for detail) +2. Structural cuts Tool 1 (80W for speed) +3. Same material, different laser strengths +4. Automatic switching based on operation requirements + +## Troubleshooting Multi-Laser Setups + +### Wrong laser activates + +**Symptoms:** +- T0 command triggers T1 laser +- Both lasers fire simultaneously + +**Fix:** +- Check controller firmware tool support +- Verify PWM output pin configuration +- Test with manual T0/T1 commands +- Check relay wiring if using external switching + +### Tool changes don't work + +**Symptoms:** +- T1 command ignored +- No physical switching occurs + +**Fix:** +- Verify controller supports multi-tool (check firmware) +- Check tool number assignments in head config +- Test tool commands manually in console +- May need firmware modification or external relay + +### Power levels incorrect after tool change + +**Symptoms:** +- S500 on Tool 1 gives different power than Tool 0 + +**Fix:** +- Verify each laser's max power setting ($30) +- Calibrate each laser separately +- Ensure power values in operations match laser characteristics +- Check $30/$31 haven't been changed + +### Alignment offset between lasers + +**Symptoms:** +- Tool 0 and Tool 1 engrave in different positions +- Designs don't line up + +**Fix:** +- Run alignment test pattern +- Measure X/Y offset +- Account for offset in design placement +- Consider adding head offset configuration (future feature) + +### Focus changes between tools + +**Symptoms:** +- Tool 1 is out of focus when Tool 0 was focused + +**Fix:** +- Different lasers may have different focal lengths +- Manually adjust Z-axis when changing tools +- Or install motorized Z-axis +- Or add Z-offset in tool change macro + +## Advanced: Tool Change Macros + +For advanced users with controller support, tool change macros can automate switching. + +### Example Macro (Grbl_ESP32) + +**Tool 0 Tool 1:** +```gcode +; Macro for T1 +G0 Z5 ; Raise Z-axis (clearance) +M5 ; Ensure laser off +; Custom M-code to switch relay +M62 P1 ; Example: Enable relay for Tool 1 +G0 Z0 ; Return to work height (Tool 1 focus) +``` + +**Tool 1 Tool 0:** +```gcode +; Macro for T0 +G0 Z5 +M5 +M63 P1 ; Disable relay (back to Tool 0) +G0 Z2.5 ; Return to work height (Tool 0 focus, different focal length) +``` + +Check your controller documentation for macro support and syntax. + +## Future Enhancements + +RayForge may add in future versions: + +- **Head offset configuration**: Define X/Y offset between laser focal points +- **Auto Z-adjustment**: Automatic Z movement for different focal lengths +- **Tool-specific speed limits**: Different max speeds per laser +- **Visual tool indicators**: Show which laser is active in simulation +- **Per-head kerf settings**: Different kerf compensation for each laser + +## Related Topics + +- **[Machine Profiles](profiles.md)** - Configuring your machine +- **[GRBL Settings](grbl-settings.md)** - Controller-level parameters +- **[Material Test Grid](../features/operations/material-test-grid.md)** - Calibrating power/speed for each laser +- **[Simulation Mode](../features/simulation-mode.md)** - Previewing multi-tool jobs diff --git a/docs-site/machine/profiles.md b/docs-site/machine/profiles.md new file mode 100644 index 000000000..4904ce665 --- /dev/null +++ b/docs-site/machine/profiles.md @@ -0,0 +1,470 @@ +# Machine Profiles + +Machine profiles are pre-configured templates that contain all the settings needed to connect to and operate your laser cutter. They make setup quick and easy by providing default values for your specific hardware. + +## Overview + +Machine profiles contain: + +- **Device driver**: The communication method (Serial, Network, WiFi) +- **Machine dimensions**: Working area size (width height) +- **Speeds**: Maximum travel and cutting speeds +- **G-code dialect**: Command format (GRBL, Smoothie, etc.) +- **Laser head configuration**: Power ranges, spot size, framing settings +- **Motion settings**: Coordinate system orientation +- **Optional features**: Home-on-start, alarm clearing, hook scripts + + + +![Machine profile selection](../images/UI-Machine-Profile-Selection.png) + +## Using Built-in Profiles + +RayForge includes profiles for common laser machines. These provide tested default settings to get you running quickly. + +### Available Profiles + +**Sculpfun iCube:** +- Small desktop laser engraver +- Working area: 120mm 120mm +- GRBL-based control +- Serial connection +- Includes homing support + +**Sculpfun S30:** +- Medium-format laser cutter +- Working area: 400mm 400mm +- GRBL-based control +- Serial connection +- Higher power capabilities + +**Other Device:** +- Generic GRBL-compatible machine +- Customizable dimensions +- Use this as a starting point for unlisted machines +- Requires manual configuration + +### Selecting a Profile + +When you first launch RayForge: + +1. Profile selection dialog appears automatically +2. Choose your machine from the list +3. RayForge applies all settings from the profile +4. Connection to device begins automatically + +**To change profiles later:** + +- **Menu:** Preferences Machine Change Profile +- Or create a new machine instance for different hardware + + + +![First launch profile selection](../images/UI-First-Launch-Profile.png) + +## Creating Custom Profiles + +For machines not in the built-in list, create a custom profile with your specific settings. + +### Step 1: Start with a Base Profile + +1. Select "Other Device" as your starting point +2. This provides a generic GRBL configuration +3. You'll customize it to match your hardware + +### Step 2: Configure Basic Settings + + + +![Machine basic settings](../images/UI-Machine-Basic-Settings.png) + +**Machine Name:** +- Descriptive name for this profile +- Examples: "Workshop K40", "Garage Diode Laser" + +**Driver Selection:** +- Choose how RayForge communicates with your machine +- See [Device Configuration](device-config.md) for driver details + +**Dimensions (width height):** +- Your machine's working area in millimeters +- Example: 400 300 for a 400mm wide, 300mm deep bed +- Measure actual cutting area, not machine exterior + +**Y-Axis Orientation:** +- Unchecked: Y increases upward (most common) +- Checked: Y increases downward (some CNC-style machines) +- Test by moving Y+ and observing direction + +### Step 3: Set Speed Limits + +**Max Travel Speed:** +- Fastest non-cutting movement speed +- Used for rapid positioning moves +- Typical range: 2000-5000 mm/min +- Check your machine's specifications + +**Max Cutting Speed:** +- Maximum speed while laser is firing +- Used to limit cutting operations +- Typical range: 500-2000 mm/min +- Lower than travel speed for accuracy + +!!! tip "Finding Safe Speeds" + Start conservative (travel: 3000, cut: 1000) and increase gradually. Observe your machine for: + - Belt skipping or motor stalling + - Excessive vibration + - Loss of positioning accuracy + +### Step 4: Configure Laser Head(s) + +Each laser head in your system needs configuration: + + + +![Laser head configuration](../images/UI-Laser-Head-Config.png) + +**Head Name:** +- Descriptive label (e.g., "10W Diode", "CO Tube") +- Useful for multi-laser machines + +**Tool Number:** +- For multi-head machines, the tool index (T0, T1, etc.) +- Single-head machines use 0 +- Must match your controller's tool mapping + +**Max Power (0-1000):** +- Maximum laser power value in your G-code +- GRBL typically uses 0-1000 range (S1000 = 100%) +- Some controllers use 0-255 +- Check your controller documentation + +**Frame Power:** +- Power level for framing (outlining without cutting) +- Set to 0 to disable framing +- Typical values: 5-20 (just visible, won't mark) +- Higher values for diode lasers (blue is dimmer) + +**Spot Size (mm):** +- Physical size of focused laser beam +- X and Y dimensions (usually circular: 0.1 0.1) +- Affects fill pattern spacing and kerf calculations +- Measure: Test cut a circle, measure diameter difference + +!!! info "Multiple Laser Heads" + Some machines have multiple laser types (e.g., diode + CO). Configure each head separately and use tool selection commands to switch between them. See [Multi-Laser Setup](multi-laser.md). + +### Step 5: Additional Settings + +**G-code Dialect:** +- Command format your controller understands +- Options: GRBL (most common), Smoothie, Marlin +- Mismatched dialect causes command errors +- See [Device Configuration](device-config.md) + +**G-code Precision:** +- Decimal places for coordinates +- Default: 3 (e.g., X12.345) +- Lower values (1-2) produce smaller files +- Higher values (4-5) increase precision +- 3 is optimal for most machines + +**Home on Start:** +- Enable: Machine homes (finds origin) on connection +- Disable: No automatic homing +- Only enable if your machine has home switches +- Recommended if hardware supports it + +**Clear Alarm on Connect:** +- Enable: Automatically clears GRBL alarm state on connection +- Useful if machine frequently enters alarm state +- May hide important safety alerts +- Generally leave disabled unless needed + +## Saving and Managing Profiles + +### Profile Storage + +RayForge automatically saves profile changes to: + +``` +~/.config/rayforge/machines/.yaml +``` + +Each machine instance is saved separately, allowing multiple profiles. + +### Exporting Profiles + +To share a profile with others: + +1. Locate your machine YAML file in the config directory +2. Copy the file +3. Share via email, forum, or repository +4. Others can import by placing in their config directory + +### Creating Multiple Machine Instances + +For different machines or configurations: + +1. **Menu:** File New Machine +2. Configure settings for the new machine +3. Switch between machines using the machine selector + + + +![Machine selector](../images/UI-Machine-Selector.png) + +**Use cases for multiple profiles:** +- Different physical machines +- Same machine with different laser heads +- Test vs. production configurations +- Different material-specific speed limits + +## Troubleshooting Profiles + +### Machine won't connect + +**Check:** +- Driver is correct for your connection type +- Driver arguments match your setup (port, baud rate, IP address) +- Physical connection is secure +- See [Connection Troubleshooting](../troubleshooting/connection.md) + +### Wrong coordinate system + +**Symptoms:** +- Jobs run mirrored or inverted +- Origin in wrong corner + +**Fix:** +- Toggle "Y-Axis Down" setting +- Verify origin location matches your machine +- Test with a small square in corner + +### Speeds too fast/slow + +**Symptoms:** +- Motors skipping steps +- Excessive vibration +- Jobs take too long + +**Fix:** +- Reduce max speeds in profile +- Test with [Material Test Grid](../features/operations/material-test-grid.md) +- Check belt tension and mechanical condition + +### Power levels incorrect + +**Symptoms:** +- Laser too weak at 100% +- Laser too strong at low percentages + +**Check:** +- Max power setting matches controller range +- Some controllers use 0-255, others 0-1000 +- Frame power should be barely visible, not cutting +- See [GRBL Settings](grbl-settings.md) for $30 and $31 + +### G-code commands rejected + +**Symptoms:** +- "Unknown command" errors in log +- Commands not executing + +**Fix:** +- Verify G-code dialect matches your controller +- Check GRBL vs. Smoothie vs. Marlin +- See [Device Configuration](device-config.md) + +## Profile Best Practices + +### Before Creating a Profile + + **Document your machine:** +- Take photos of controller and labeling +- Record working area dimensions +- Note any special features (auto-focus, air assist, rotary) +- Check manufacturer specifications + + **Test connection manually:** +- Verify you can connect with other software +- Confirm baud rate and port +- Test basic G-code commands + +### Safe Testing Procedure + +When testing a new profile: + +1. **Start conservative:** + - Lower speeds (50% of max) + - Lower power (20-30%) + - Small test jobs + +2. **Test systematically:** + - Verify connection first + - Test framing (no cutting) + - Run a small engraving (low power) + - Progress to cutting slowly + +3. **Use simulation:** + - Preview in [Simulation Mode](../features/simulation-mode.md) first + - Verify speeds look reasonable + - Check path is correct + +### Documentation + +For complex or unusual machines: + +- Keep notes on settings that work +- Document any quirks or special requirements +- Record material test results +- Share profiles with community (forums, wiki) + +## Common Profile Examples + +### Typical K40 Laser + +```yaml +name: "K40 CO Laser" +driver: GrblSerialDriver +dimensions: [300, 200] +y_axis_down: false +max_travel_speed: 3000 +max_cut_speed: 1000 +dialect: GRBL +heads: + - frame_power: 10 + max_power: 1000 + spot_size_mm: [0.1, 0.1] +``` + +### Diode Engraver + +```yaml +name: "20W Diode Engraver" +driver: GrblSerialDriver +dimensions: [400, 400] +y_axis_down: false +max_travel_speed: 5000 +max_cut_speed: 2000 +dialect: GRBL +heads: + - frame_power: 20 + max_power: 1000 + spot_size_mm: [0.15, 0.15] +``` + +### Large Format CO + +```yaml +name: "1000600 CO Laser" +driver: GrblNetworkDriver +dimensions: [1000, 600] +y_axis_down: false +max_travel_speed: 4000 +max_cut_speed: 1500 +dialect: GRBL +heads: + - frame_power: 8 + max_power: 1000 + spot_size_mm: [0.08, 0.08] +``` + +## Related Topics + +- **[Device Configuration](device-config.md)** - Driver setup and connection details +- **[GRBL Settings](grbl-settings.md)** - Controller-level parameters +- **[Multi-Laser Setup](multi-laser.md)** - Configuring machines with multiple laser heads +- **[Connection Troubleshooting](../troubleshooting/connection.md)** - Fixing connection issues diff --git a/docs-site/reference/firmware.md b/docs-site/reference/firmware.md new file mode 100644 index 000000000..3236411f8 --- /dev/null +++ b/docs-site/reference/firmware.md @@ -0,0 +1,463 @@ +# Firmware Compatibility + +This page documents firmware compatibility for laser controllers used with RayForge. + +## Overview + +RayForge is designed primarily for **GRBL-based controllers** but has experimental support for other firmware types. + +### Compatibility Matrix + +| Firmware | Version | Status | Driver | Notes | +|----------|---------|--------|--------|-------| +| **GRBL** | 1.1+ |  Fully supported | GRBL Serial | Recommended | +| **grblHAL** | 2023+ |  Compatible | GRBL Serial | Modern GRBL fork | +| **GRBL** | 0.9 |  Limited | GRBL Serial | Older, may have issues | +| **Smoothieware** | All |  Experimental | None (use GRBL driver) | Untested | +| **Marlin** | 2.0+ |  Experimental | None (use GRBL driver) | Laser mode required | +| **Other** | - |  Not supported | - | Request support | + +--- + +## GRBL Firmware + +**Status:**  Fully Supported +**Versions:** 1.1+ +**Driver:** GRBL Serial + +### GRBL 1.1 (Recommended) + +**What is GRBL 1.1?** + +GRBL 1.1 is the most common firmware for hobby CNC and laser machines. Released in 2017, it's stable, well-documented, and widely supported. + +**Features supported by RayForge:** + +-  Serial communication (USB) +-  Real-time status reporting +-  Laser mode (M4 constant power) +-  Settings read/write ($$, $X=value) +-  Homing cycles ($H) +-  Work coordinate systems (G54) +-  Jogging commands ($J=) +-  Feed rate override +-  Soft limits +-  Hard limits (endstops) + +**Known limitations:** + +- Power range: 0-1000 (S parameter) +- No network connectivity (USB only) +- Limited onboard memory (small G-code buffer) + +### Checking GRBL Version + +**Query version:** + +Connect to your controller and send: +``` +$I +``` + +**Response examples:** +``` +[VER:1.1h.20190825:] +[OPT:V,15,128] +``` + +- `1.1h` = GRBL version 1.1h +- Date indicates build + +### GRBL 0.9 (Older) + +**Status:**  Limited Support + +GRBL 0.9 is an older version with some compatibility issues: + +**Differences:** + +- Different status report format +- No laser mode (M4) - uses M3 only +- Fewer settings +- Different jogging syntax + +**If you have GRBL 0.9:** + +1. **Upgrade to GRBL 1.1** if possible (recommended) +2. **Use M3 instead of M4** (less predictable power) +3. **Test thoroughly** - some features may not work + +**Upgrade instructions:** See [GRBL Wiki](https://github.com/gnea/grbl/wiki) + +--- + +## grblHAL + +**Status:**  Compatible +**Versions:** 2023+ +**Driver:** GRBL Serial + +### What is grblHAL? + +grblHAL is a modern fork of GRBL with enhanced features: + +- Multiple controller hardware support (STM32, ESP32, etc.) +- Ethernet/WiFi networking +- SD card support +- More I/O pins +- Enhanced laser support + +**Compatibility with RayForge:** + +-  **Fully compatible** - grblHAL maintains GRBL 1.1 protocol +-  All GRBL features work +-  Additional features (networking, SD) not yet supported by RayForge +-  Status reporting identical to GRBL + +**Using grblHAL:** + +1. Select "GRBL Serial" driver in RayForge +2. Connect via USB serial (just like GRBL) +3. All features work as documented for GRBL + +**Future:** RayForge may add support for grblHAL-specific features (networking, etc.) + +--- + +## Smoothieware + +**Status:**  Experimental +**Versions:** All +**Driver:** GRBL Serial (compatibility mode) + +### Compatibility Notes + +Smoothieware uses different G-code syntax: + +**Key differences:** + +| Feature | GRBL | Smoothieware | +|---------|------|--------------| +| **Laser On** | M4 S{power} | M3 S{power} | +| **Power Range** | 0-1000 | 0.0-1.0 (float) | +| **Status** | `<...>` format | Different format | + +**Using Smoothieware with RayForge:** + +1. **Select Smoothieware dialect** in machine settings +2. **Test with low power** first +3. **Verify power range** matches your config +4. **No real-time status** - limited feedback + +**Limitations:** + +- Status reporting not fully compatible +- Power scaling may differ +- Settings ($$ commands) not supported +- Untested on real hardware + +**Recommendation:** If possible, use GRBL-compatible firmware instead. + +--- + +## Marlin + +**Status:**  Experimental +**Versions:** 2.0+ with laser support +**Driver:** GRBL Serial (limited compatibility) + +### Marlin for Laser + +Marlin 2.0+ can control lasers when properly configured. + +**Requirements:** + +1. **Marlin 2.0 or later** firmware +2. **Laser features enabled:** + ```cpp + #define LASER_FEATURE + #define LASER_POWER_INLINE + ``` +3. **Correct power range** configured: + ```cpp + #define SPEED_POWER_MAX 1000 + ``` + +**Compatibility:** + +-  M4 laser mode supported +-  Basic G-code (G0, G1, G2, G3) +-  Status reporting differs +-  Settings commands different +-  Air assist (M8/M9) may not work + +**Using Marlin with RayForge:** + +1. **Select Marlin dialect** in machine settings +2. **Configure Marlin** for laser use +3. **Test power range** matches (0-1000 or 0-255) +4. **Limited testing** - use with caution + +**Better alternative:** Use GRBL firmware on laser machines. + +--- + +## Firmware Upgrade Guide + +### Upgrading to GRBL 1.1 + +**Why upgrade?** + +- Laser mode (M4) for constant power +- Better status reporting +- More reliable +- Better RayForge support + +**How to upgrade:** + +1. **Identify your controller board:** + - Arduino Nano/Uno (ATmega328P) + - Arduino Mega (ATmega2560) + - Custom board + +2. **Download GRBL 1.1:** + - [GRBL Releases](https://github.com/gnea/grbl/releases) + - Get latest 1.1 version (1.1h recommended) + +3. **Flash firmware:** + + **Using Arduino IDE:** + ``` + 1. Install Arduino IDE + 2. Open GRBL sketch (grbl.ino) + 3. Select correct board and port + 4. Upload + ``` + + **Using avrdude:** + ```bash + avrdude -c arduino -p m328p -P /dev/ttyUSB0 \ + -U flash:w:grbl.hex:i + ``` + +4. **Configure GRBL:** + - Connect via serial + - Send `$$` to view settings + - Configure for your machine + +### Backup Before Upgrade + +**Save your settings:** + +1. Connect to controller +2. Send `$$` command +3. Copy all settings output +4. Save to file + +**After upgrade:** + +- Restore settings one-by-one: `$0=10`, `$1=25`, etc. +- Or use defaults and reconfigure + +--- + +## Controller Hardware + +### Common Controllers + +| Board | Typical Firmware | RayForge Support | +|-------|------------------|------------------| +| **Arduino CNC Shield** | GRBL 1.1 |  Excellent | +| **MKS DLC32** | grblHAL |  Excellent | +| **Cohesion3D** | Smoothieware |  Limited | +| **SKR boards** | Marlin/grblHAL |  Varies | +| **Ruida** | Proprietary |  Not supported | +| **Trocen** | Proprietary |  Not supported | +| **TopWisdom** | Proprietary |  Not supported | + +### Recommended Controllers + +For best RayForge compatibility: + +1. **Arduino Nano + CNC Shield** (GRBL 1.1) + - Cheap (~$10-20) + - Easy to flash + - Well documented + +2. **MKS DLC32** (grblHAL) + - Modern (ESP32-based) + - WiFi capable + - Active development + +3. **Custom GRBL boards** + - Many available on marketplaces + - Check for GRBL 1.1+ support + +--- + +## Firmware Configuration + +### GRBL Settings for Laser + +**Essential settings:** + +``` +$30=1000 ; Max spindle/laser power (1000 = 100%) +$31=0 ; Min spindle/laser power +$32=1 ; Laser mode enabled (1 = on) +``` + +**Machine settings:** + +``` +$100=80 ; X steps/mm (calibrate for your machine) +$101=80 ; Y steps/mm +$110=3000 ; X max rate (mm/min) +$111=3000 ; Y max rate +$120=100 ; X acceleration (mm/sec) +$121=100 ; Y acceleration +$130=300 ; X max travel (mm) +$131=200 ; Y max travel (mm) +``` + +**Safety settings:** + +``` +$20=1 ; Soft limits enabled +$21=1 ; Hard limits enabled (if you have endstops) +$22=1 ; Homing enabled +``` + +### Testing Firmware + +**Basic test sequence:** + +1. **Connection test:** + ``` + Send: ? + Expect: + ``` + +2. **Version check:** + ``` + Send: $I + Expect: [VER:1.1...] + ``` + +3. **Settings check:** + ``` + Send: $$ + Expect: $0=..., $1=..., etc. + ``` + +4. **Movement test:** + ``` + Send: G91 G0 X10 + Expect: Machine moves 10mm in X + ``` + +5. **Laser test (very low power):** + ``` + Send: M4 S10 + Expect: Laser turns on (dim) + Send: M5 + Expect: Laser turns off + ``` + +--- + +## Troubleshooting Firmware Issues + +### Firmware Not Responding + +**Symptoms:** +- No response to commands +- Connection fails +- Status not reported + +**Diagnosis:** + +1. **Check baud rate:** + - GRBL 1.1 default: 115200 + - GRBL 0.9: 9600 + - Try both + +2. **Check USB cable:** + - Data cable, not charge-only + - Replace with known-good cable + +3. **Check port:** + - Linux: `/dev/ttyUSB0` or `/dev/ttyACM0` + - Windows: COM3, COM4, etc. + - Correct port selected in RayForge + +4. **Test with terminal:** + - Use screen, minicom, or PuTTY + - Send `?` and see if you get response + +### Firmware Crashes + +**Symptoms:** +- Controller locks up during job +- Random disconnections +- Inconsistent behavior + +**Possible causes:** + +1. **Buffer overflow** - G-code file too complex +2. **Electrical noise** - Poor grounding or EMI +3. **Firmware bug** - Upgrade to latest version +4. **Hardware issue** - Faulty controller + +**Solutions:** + +- Upgrade firmware to latest stable version +- Simplify G-code (reduce precision, fewer segments) +- Add ferrite beads to USB cable +- Improve grounding and cable routing + +### Wrong Firmware + +**Symptoms:** +- Commands rejected +- Unexpected behavior +- Error messages + +**Solution:** + +1. Query firmware version: `$I` +2. Compare with RayForge expectations +3. Upgrade or select correct dialect + +--- + +## Future Firmware Support + +### Requested Features + +Users have requested support for: + +- **Ruida controllers** - Chinese laser controllers +- **Trocen/AWC** - Commercial laser controllers +- **ESP32 WiFi** - Network connectivity for grblHAL +- **Laser API** - Direct machine API (no G-code) + +**Status:** Not currently supported. Feature requests welcome on GitHub. + +### Contributing + +To add firmware support: + +1. Implement driver in `rayforge/machine/driver/` +2. Define G-code dialect in `rayforge/machine/models/dialect.py` +3. Test thoroughly on real hardware +4. Submit pull request with documentation + +--- + +## Related Pages + +- [G-code Dialects](gcode-dialects.md) - Dialect details +- [GRBL Settings](../machine/grbl-settings.md) - GRBL configuration +- [Connection Issues](../troubleshooting/connection.md) - Connection troubleshooting +- [Device Configuration](../machine/device-config.md) - Machine setup diff --git a/docs-site/reference/gcode-dialects.md b/docs-site/reference/gcode-dialects.md new file mode 100644 index 000000000..c5af52566 --- /dev/null +++ b/docs-site/reference/gcode-dialects.md @@ -0,0 +1,26 @@ +# G-code Dialect Support + +RayForge supports multiple G-code dialects to work with different controller firmware. + +## Supported Dialects + +RayForge currently supports these G-code dialects: + +| Dialect | Firmware | Common Use | Status | +|---------|----------|------------|--------| +| **GRBL (universal)** | GRBL 1.1+ | Diode lasers, hobby CNC |  Primary, fully supported | +| **GRBL (no Z axis)** | GRBL 1.1+ | 2D laser cutters without Z |  Optimized variant | +| **Smoothieware** | Smoothieware | Laser cutters, CNC |  Experimental | +| **Marlin** | Marlin 2.0+ | 3D printers with laser |  Experimental | + +!!! note "Recommended Dialect" + **GRBL (universal)** is the most tested and recommended dialect for laser applications. + +--- + +## Related Pages + +- [Exporting G-code](../files/exporting.md) - Export settings +- [Firmware Compatibility](firmware.md) - Firmware versions +- [GRBL Settings](../machine/grbl-settings.md) - GRBL configuration +- [Macros & Hooks](../features/macros-hooks.md) - Custom G-code injection diff --git a/docs-site/reference/index.md b/docs-site/reference/index.md new file mode 100644 index 000000000..e06efe580 --- /dev/null +++ b/docs-site/reference/index.md @@ -0,0 +1,108 @@ +# Reference + +Technical reference documentation for Rayforge. + +## Quick Reference + +- **[Keyboard Shortcuts](shortcuts.md)**: Complete list of keyboard shortcuts +- **[G-code Dialects](gcode-dialects.md)**: Supported G-code flavors and their differences +- **[Firmware Compatibility](firmware.md)**: Compatible firmware versions and features + +## Keyboard Shortcuts + +Master Rayforge with keyboard shortcuts for faster workflow. See the complete [Keyboard Shortcuts](shortcuts.md) reference. + +**Most Common:** + +- ++ctrl+o++: Open file +- ++ctrl+s++: Save project +- ++ctrl+g++: Generate G-code +- ++ctrl+3++: 3D preview +- ++ctrl+r++: Start job +- ++ctrl+p++: Pause job +- ++esc++: Stop job + +## G-code Dialects + +Rayforge supports multiple G-code dialects: + +- **GRBL**: Standard GRBL 1.1+ +- **Smoothieware**: Smoothieware v1 and v2 +- **GRBL-compatible**: Generic GRBL-compatible controllers + +See [G-code Dialects](gcode-dialects.md) for command differences and compatibility notes. + +## Firmware Compatibility + +### GRBL + +- **Minimum Version**: GRBL 1.1 +- **Recommended**: GRBL 1.1h or later +- **Tested Versions**: 1.1f, 1.1h, 1.1i + +### Smoothieware + +- **Supported**: v1 and v2-dev +- **Connection**: Telnet over network +- **Tested Versions**: v1.1, v2-dev + +See [Firmware Compatibility](firmware.md) for detailed version information and features. + +## Technical Specifications + +### Supported File Import Formats + +| Format | Extension | Type | Notes | +|:-------|:----------|:-----|:------| +| SVG | .svg | Vector | Full support | +| DXF | .dxf | Vector | AutoCAD R12-R2018 | +| PDF | .pdf | Vector | Vector content only | +| JPEG | .jpg, .jpeg | Raster | Lossy compression | +| PNG | .png | Raster | Lossless, transparency | +| BMP | .bmp | Raster | Uncompressed | +| TIFF | .tif, .tiff | Raster | High quality | +| Ruida | .rd | Proprietary | Import from Ruida controllers | + +### G-code Output + +- **Format**: Plain text G-code +- **Encoding**: UTF-8 or ASCII +- **Line endings**: LF (Linux/Mac) or CRLF (Windows) +- **Commands**: Standard GRBL/Smoothieware command set + +### Coordinate System + +- **Units**: Millimeters (mm) or inches +- **Origin**: Configurable (bottom-left, top-left, etc.) +- **Coordinate Mode**: Absolute (G90) or relative (G91) + +### Performance Limits + +| Metric | Recommended | Maximum | +|:-------|:------------|:--------| +| Canvas Objects | < 1000 | 10000 | +| Path Points | < 100K | 1M | +| Raster Resolution | 300 DPI | 600 DPI | +| G-code Lines | < 1M | 10M | + +## System Requirements + +### Minimum Requirements + +- **OS**: Ubuntu 24.04+, Windows 10+ +- **CPU**: Dual-core 2.0 GHz +- **RAM**: 4 GB +- **GPU**: OpenGL 3.3 compatible +- **Disk**: 500 MB free space + +### Recommended Requirements + +- **OS**: Ubuntu 24.04 LTS, Windows 11 +- **CPU**: Quad-core 3.0 GHz or better +- **RAM**: 8 GB or more +- **GPU**: Dedicated graphics with OpenGL 4.5+ +- **Disk**: 1 GB free space (SSD recommended) + +--- + +**Explore:** [Keyboard Shortcuts →](shortcuts.md) | [G-code Dialects →](gcode-dialects.md) | [Firmware →](firmware.md) diff --git a/docs-site/reference/shortcuts.md b/docs-site/reference/shortcuts.md new file mode 100644 index 000000000..faad6c365 --- /dev/null +++ b/docs-site/reference/shortcuts.md @@ -0,0 +1,362 @@ +# Keyboard Shortcuts + +Complete reference of keyboard shortcuts in RayForge. + +!!! note "Platform Conventions" + - **Linux/Windows:** `Ctrl` key + - **macOS:** ` (Command)` key + - Documentation uses `Ctrl` - macOS users substitute with `` + +--- + +## File Operations + +| Shortcut | Action | Description | +|----------|--------|-------------| +| `Ctrl+I` | Import | Open file import dialog | +| `Ctrl+E` | Export | Export G-code | +| `Ctrl+Q` | Quit | Exit RayForge | +| `Ctrl+,` | Preferences | Open preferences dialog | + +--- + +## Edit & Clipboard + +| Shortcut | Action | Description | +|----------|--------|-------------| +| `Ctrl+Z` | Undo | Undo last action | +| `Ctrl+Y` | Redo | Redo last undone action | +| `Ctrl+Shift+Z` | Redo (alternate) | Alternative redo shortcut | +| `Ctrl+X` | Cut | Cut selection to clipboard | +| `Ctrl+C` | Copy | Copy selection to clipboard | +| `Ctrl+V` | Paste | Paste from clipboard | +| `Ctrl+A` | Select All | Select all items in active layer | +| `Ctrl+D` | Duplicate | Duplicate selected items | +| `Delete` | Remove | Delete selected items | +| `Ctrl+Shift+Delete` | Clear | Clear all items from document | + +--- + +## View & Display + +| Shortcut | Action | Description | +|----------|--------|-------------| +| `H` | Toggle Workpieces | Show/hide workpiece visibility | +| `T` | Toggle Tabs | Show/hide holding tabs | +| `Alt+C` | Toggle Camera | Show/hide camera overlay | +| `F12` | 3D View | Toggle 3D preview window | +| `Ctrl+Shift+S` | Simulation Mode | Toggle simulation mode | + +### 3D View Controls + +| Shortcut | Action | Description | +|----------|--------|-------------| +| `1` | Top View | Switch to top-down view | +| `2` | Front View | Switch to front view | +| `7` | Isometric View | Switch to isometric view | +| `P` | Toggle Perspective | Switch between perspective and orthographic | + +--- + +## Layer & Organization + +| Shortcut | Action | Description | +|----------|--------|-------------| +| `Ctrl+G` | Group | Group selected items | +| `Ctrl+U` | Ungroup | Ungroup selected group | +| `Ctrl+Page Up` | Move Layer Up | Move layer up in stack | +| `Ctrl+Page Down` | Move Layer Down | Move layer down in stack | +| `Alt+S` | Add Stock | Add stock/material item | + +--- + +## Tabs (Holding Tabs) + +| Shortcut | Action | Description | +|----------|--------|-------------| +| `Alt+T` | Add Tabs (Equidistant) | Add evenly-spaced tabs | +| `T` | Toggle Tab Visibility | Show/hide tabs overlay | + +--- + +## Alignment & Distribution + +### Alignment + +| Shortcut | Action | Description | +|----------|--------|-------------| +| `Shift+Left` | Align Left | Align selected items to left | +| `Shift+Right` | Align Right | Align selected items to right | +| `Shift+Up` | Align Top | Align selected items to top | +| `Shift+Down` | Align Bottom | Align selected items to bottom | +| `Shift+Home` | Align H-Center | Align selected items horizontally to center | +| `Shift+End` | Align V-Center | Align selected items vertically to center | + +### Distribution + +| Shortcut | Action | Description | +|----------|--------|-------------| +| `Ctrl+Shift+H` | Spread Horizontally | Distribute items evenly horizontally | +| `Ctrl+Shift+V` | Spread Vertically | Distribute items evenly vertically | + +### Layout + +| Shortcut | Action | Description | +|----------|--------|-------------| +| `Alt+A` | Pixel Perfect | Snap to pixel grid | + +--- + +## Transform + +| Shortcut | Action | Description | +|----------|--------|-------------| +| `Shift+H` | Flip Horizontal | Mirror selected items horizontally | +| `Shift+V` | Flip Vertical | Mirror selected items vertically | + +--- + +## Machine Control + +| Shortcut | Action | Description | +|----------|--------|-------------| +| `Ctrl+<` | Machine Settings | Open machine settings dialog | +| `F1` | About | Show about dialog | + +!!! note "Machine Operations" + Machine control operations (Home, Frame, Send, etc.) currently don't have default shortcuts but can be accessed via toolbar buttons or menus. + +--- + +## Canvas Navigation + +### Mouse Controls + +| Input | Action | Description | +|-------|--------|-------------| +| **Left Click** | Select | Select item | +| **Left Drag** | Move | Move selected items | +| **Ctrl+Left Drag** | Box Select | Select multiple items | +| **Middle Click Drag** | Pan | Pan the canvas | +| **Scroll Wheel** | Zoom | Zoom in/out | +| **Ctrl+Scroll** | Precision Zoom | Finer zoom control | + +### Arrow Keys + +| Shortcut | Action | Description | +|----------|--------|-------------| +| `` `` `` `` | Nudge | Move selected items by 1 unit | +| `Shift+Arrow` | Large Nudge | Move selected items by 10 units | + +--- + +## Text Editor (G-code Editor) + +When editing G-code or text fields: + +| Shortcut | Action | Description | +|----------|--------|-------------| +| `Ctrl+Z` | Undo | Undo text edit | +| `Ctrl+Y` | Redo | Redo text edit | +| `Ctrl+A` | Select All | Select all text | +| `Ctrl+X` | Cut | Cut selected text | +| `Ctrl+C` | Copy | Copy selected text | +| `Ctrl+V` | Paste | Paste text | +| `Ctrl+F` | Find | Find text (if supported) | + +--- + +## Quick Reference by Category + +### Most Used (Top 10) + +1. `Ctrl+Z` / `Ctrl+Y` - Undo/Redo +2. `Ctrl+C` / `Ctrl+V` - Copy/Paste +3. `Ctrl+D` - Duplicate +4. `Delete` - Remove +5. `Ctrl+A` - Select All +6. `Ctrl+I` - Import +7. `Ctrl+E` - Export +8. `H` - Toggle Workpieces +9. `F12` - 3D View +10. `Ctrl+Shift+S` - Simulation Mode + +### View & Visualization + +- `H` - Hide/show workpieces +- `T` - Hide/show tabs +- `Alt+C` - Toggle camera +- `F12` - 3D view +- `Ctrl+Shift+S` - Simulation mode +- `1`, `2`, `7` - 3D view presets +- `P` - Perspective toggle + +### Edit & Transform + +- `Ctrl+Z` / `Ctrl+Y` - Undo/Redo +- `Ctrl+X` / `Ctrl+C` / `Ctrl+V` - Cut/Copy/Paste +- `Ctrl+D` - Duplicate +- `Delete` - Remove +- `Shift+H` / `Shift+V` - Flip H/V +- `Ctrl+G` / `Ctrl+U` - Group/Ungroup + +### Alignment + +- `Shift+Arrow Keys` - Align to edges +- `Shift+Home` / `Shift+End` - Center align +- `Ctrl+Shift+H` / `Ctrl+Shift+V` - Distribute +- `Alt+A` - Pixel perfect + +--- + +## Customizing Shortcuts + +!!! note "Custom Shortcuts" + Keyboard shortcuts are currently hardcoded. Custom shortcut configuration may be added in future versions. + +**Current limitations:** +- Shortcuts cannot be changed without modifying source code +- No GUI for shortcut customization +- Some actions may not have shortcuts assigned + +**Feature request:** If you need custom shortcuts, please open an issue on GitHub. + +--- + +## Tips & Tricks + +### Efficiency Tips + +1. **Learn the edit shortcuts first** - `Ctrl+Z/Y/C/V/D` are used constantly +2. **Use single-key toggles** - `H`, `T`, `P` for quick view changes +3. **3D view shortcuts** - `1`, `2`, `7` for instant view switching +4. **Alignment shortcuts** - `Shift+Arrow` faster than clicking alignment buttons +5. **Simulation mode** - `Ctrl+Shift+S` to quickly check execution + +### Workflow Shortcuts + +**Quick edit cycle:** +``` +1. Import (Ctrl+I) +2. Arrange items (arrow keys, Shift+Arrow for alignment) +3. Duplicate parts (Ctrl+D) +4. Check in 3D (F12) +5. Simulate (Ctrl+Shift+S) +6. Export (Ctrl+E) +``` + +**Precision positioning:** +``` +1. Select item +2. Arrow keys for 1mm nudges +3. Shift+Arrow for 10mm jumps +4. Shift+Home/End for centering +``` + +### Hidden Shortcuts + +Some lesser-known shortcuts: + +- `Ctrl+,` - Quick access to preferences (standard on macOS, works here too) +- `Ctrl+Shift+Z` - Alternative redo (for users who prefer this over Ctrl+Y) +- `Alt+A` - Pixel-perfect snapping for precise placement +- `Alt+T` - Quick equidistant tab placement + +--- + +## Platform Differences + +### Linux + +- Uses standard `Ctrl` modifier +- All shortcuts work as documented +- GTK standard shortcuts apply in text fields + +### Windows + +- Uses standard `Ctrl` modifier +- Identical to Linux shortcuts +- Windows-specific keys (Win key) not used + +### macOS + +- `Ctrl` maps to ` (Command)` +- `Alt` maps to `% (Option)` +- Standard macOS conventions apply +- `Cmd+Q` to quit (instead of Ctrl+Q) + +--- + +## Troubleshooting Shortcuts + +### Shortcut Not Working + +**Common issues:** + +1. **Focus on wrong element** - Ensure canvas or main window has focus, not a text field +2. **Conflicting application** - Another app may be intercepting the shortcut +3. **Desktop environment shortcut** - System shortcuts may override (e.g., Alt+F4) +4. **Numpad vs number row** - Use number row for 3D view shortcuts, not numpad + +**Solutions:** + +- Click on the canvas to ensure it has focus +- Check system keyboard shortcuts for conflicts +- Try the menu action instead to verify functionality + +### Modifier Keys + +**If Ctrl doesn't work:** + +- Verify Caps Lock is off (can interfere on some systems) +- Try Ctrl on both sides of keyboard +- Check keyboard layout settings + +**If Alt doesn't work:** + +- Some window managers capture Alt for window dragging +- Try disabling window manager Alt shortcuts +- Use menu items as alternative + +--- + +## Shortcut Cheat Sheet + +**Print this quick reference:** + +``` +  + RayForge Keyboard Shortcuts  +$ + FILE  EDIT  + Ctrl+I Import  Ctrl+Z Undo  + Ctrl+E Export  Ctrl+Y Redo  + Ctrl+Q Quit  Ctrl+C Copy  + Ctrl+, Preferences  Ctrl+V Paste  +  Ctrl+D Duplicate  +  Delete Remove  +$ + VIEW  ALIGN  + H Workpieces  Shift+ Left  + T Tabs  Shift+ Right  + Alt+C Camera  Shift+ Top  + F12 3D View  Shift+ Bottom  + 1/2/7 View Presets  Shift+Home H-Center  + P Perspective  Shift+End V-Center  +$ + SIMULATE  TRANSFORM  + Ctrl+Shift+S Mode  Shift+H Flip H  +  Shift+V Flip V  +  Ctrl+G Group  +  Ctrl+U Ungroup  + +``` + +--- + +## Related Pages + +- [Main Window](../ui/main-window.md) - UI overview +- [Canvas Tools](../ui/canvas-tools.md) - Canvas interaction +- [3D Preview](../ui/3d-preview.md) - 3D view controls +- [Simulation Mode](../features/simulation-mode.md) - Simulation features diff --git a/docs-site/stylesheets/extra.css b/docs-site/stylesheets/extra.css new file mode 100644 index 000000000..880e8c360 --- /dev/null +++ b/docs-site/stylesheets/extra.css @@ -0,0 +1,84 @@ +/* Custom styles for Rayforge documentation */ + +/* Image styling for screenshots */ +.md-content img { + border-radius: 8px; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + margin: 1.5em 0; +} + +/* Cards styling */ +.grid.cards { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 1rem; + margin: 1.5em 0; +} + +.grid.cards > * { + border: 1px solid var(--md-default-fg-color--lightest); + border-radius: 8px; + padding: 1.5rem; + transition: all 0.2s ease; +} + +.grid.cards > *:hover { + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + transform: translateY(-2px); +} + +/* Feature list styling */ +.feature-list { + list-style: none; + padding-left: 0; +} + +.feature-list li { + padding: 0.5em 0 0.5em 2em; + position: relative; +} + +.feature-list li:before { + content: "✓"; + color: var(--md-accent-fg-color); + font-weight: bold; + position: absolute; + left: 0; +} + +/* Admonition customization for tips */ +.md-typeset .admonition.tip, +.md-typeset details.tip { + border-left-color: #00e676; +} + +/* Table styling */ +.md-typeset table:not([class]) { + border-radius: 8px; + overflow: hidden; +} + +/* Version badge */ +.version-badge { + display: inline-block; + padding: 0.2em 0.6em; + font-size: 0.85em; + font-weight: 600; + line-height: 1; + color: #fff; + background-color: var(--md-accent-fg-color); + border-radius: 4px; + margin-left: 0.5em; +} + +/* Keyboard shortcut styling */ +kbd { + background-color: var(--md-code-bg-color); + border: 1px solid var(--md-default-fg-color--lightest); + border-radius: 4px; + box-shadow: 0 2px 0 var(--md-default-fg-color--lightest); + font-family: var(--md-code-font-family); + font-size: 0.85em; + padding: 0.1em 0.4em; + vertical-align: middle; +} diff --git a/docs-site/troubleshooting/common.md b/docs-site/troubleshooting/common.md new file mode 100644 index 000000000..56a04d2fc --- /dev/null +++ b/docs-site/troubleshooting/common.md @@ -0,0 +1,382 @@ +# Common Problems + +This page provides quick solutions to frequently encountered issues in RayForge. + +## File Import Issues + +### SVG Import Problems + +**Problem:** SVG file imports with missing or incorrect elements. + +**Common causes:** + +1. **Unsupported SVG features** - Some advanced SVG features may not import correctly +2. **Embedded raster images** - Images inside SVG files need special handling +3. **Text not converted to paths** - Text must be converted to paths in your design software +4. **Grouped or nested elements** - Deep nesting can sometimes cause issues + +**Solutions:** + +- In Inkscape: Select all text and use `Path Object to Path` +- Simplify complex paths: `Path Simplify` +- Ungroup nested groups: `Object Ungroup` (multiple times if needed) +- Save as "Plain SVG" or "Optimized SVG" rather than "Inkscape SVG" +- Ensure document units match your intended units (mm, inches) + +### DXF Import Problems + +**Problem:** DXF file imports with wrong scale or missing elements. + +**Solutions:** + +1. **Check units** - Ensure the DXF file uses the correct units (mm vs inches) +2. **Verify layer visibility** - Some layers may be hidden or on non-printing layers +3. **Simplify the file** - Remove unnecessary layers and objects in your CAD software +4. **Save as R12/LT2 DXF** - This older format has better compatibility + +### PDF Import Issues + +**Problem:** PDF imports as raster image instead of vector paths. + +**Solution:** + +PDFs containing raster images will import as images. To get vector paths: + +1. Ensure the PDF contains actual vector graphics, not embedded images +2. Use vector design software (Inkscape, Illustrator) to open and re-export as SVG +3. Flatten layers and convert text to paths before exporting + +--- + +## Job Execution Problems + +### Job Runs in Wrong Location + +**Problem:** The laser cuts/engraves in the wrong position on the material. + +**Diagnosis:** + +This is usually an origin or positioning issue. + +**Solutions:** + +1. **Frame the job first** - Use the Frame command to preview where the job will run +2. **Check job origin settings** - Verify the origin is set correctly (typically top-left or center) +3. **Home the machine** - Some machines require homing before accurate positioning +4. **Check work offset** - Ensure G54 work coordinate system is set correctly +5. **Verify machine position** - Move the laser to the desired start position manually first + +### Cuts Don't Go Through Material + +**Problem:** The laser doesn't cut all the way through the material. + +**Common causes:** + +1. **Insufficient power** - Power setting too low for material thickness +2. **Speed too fast** - Not enough time for the laser to cut through +3. **Poor focus** - Laser beam not focused at material surface +4. **Multiple passes needed** - Material too thick for single pass +5. **Air assist off** - Removes debris and improves cutting efficiency + +**Solutions:** + +- Use [Material Test Grid](../features/operations/material-test-grid.md) to find optimal settings +- Reduce speed or increase power incrementally +- Ensure proper focus distance (usually 2-5mm depending on lens) +- Enable multiple passes for thick materials +- Enable air assist if available +- Clean laser lens and mirrors + +### Engraving Too Light or Too Dark + +**Problem:** Raster engraving output is too faint or too dark. + +**Solutions:** + +**Too light:** +- Increase power +- Reduce speed +- Ensure proper focus +- Clean optics +- Check if material surface is reflective (some metals/plastics won't mark well) + +**Too dark/charred:** +- Reduce power +- Increase speed +- Enable overscan to reduce acceleration marks +- Adjust DPI/line spacing +- Consider multiple light passes instead of one heavy pass + +### Disconnection During Job + +**Problem:** Machine disconnects in the middle of a job. + +**Possible causes:** + +1. **USB cable issues** - Loose connection or faulty cable +2. **Power supply problems** - Voltage drops under load +3. **EMI interference** - Motor cables too close to USB +4. **Firmware crash** - Controller firmware hung +5. **Computer sleep/power saving** - OS suspending USB + +**Solutions:** + +- Use a high-quality, short (<2m) USB cable +- Secure USB connections (tape if necessary) +- Route USB cables away from stepper motor wires +- Disable USB selective suspend in power settings (Windows) +- Disable computer sleep mode while running jobs +- Update controller firmware + +--- + +## Preview and Simulation Issues + +### 3D Preview Looks Wrong + +**Problem:** The 3D preview doesn't match expected output. + +**Common issues:** + +1. **Operation order** - Operations execute in a specific order +2. **Overlapping operations** - Multiple operations affect the same area +3. **Material height incorrect** - Set material thickness in settings + +**Solutions:** + +- Check operation order in the layers panel +- Use [Simulation Mode](../features/simulation-mode.md) to see execution order and timing +- Adjust Z-height and material thickness settings +- Review operation settings for each layer + +### Simulation Mode Not Starting + +**Problem:** Simulation mode (F7) doesn't activate or shows nothing. + +**Solutions:** + +1. Ensure you have at least one operation in your document +2. Check that operations have valid G-code (preview them first) +3. Try regenerating the G-code (make a small change to force regeneration) +4. Check for errors in the console/logs + +--- + +## Performance Issues + +### Slow UI Response + +**Problem:** RayForge feels sluggish or unresponsive. + +**Solutions:** + +1. **Reduce preview quality** - Lower 3D preview resolution in settings +2. **Simplify paths** - Use fewer nodes in complex paths +3. **Limit operations** - Reduce number of active operations/layers +4. **Close unused documents** - Multiple open documents consume memory +5. **Update graphics drivers** - Especially on Linux + +See [Performance Troubleshooting](performance.md) for detailed optimization tips. + +### Long Import Times + +**Problem:** Importing large files takes a very long time. + +**Solutions:** + +- Simplify paths in your design software before importing +- Remove unnecessary detail (nodes, guides, hidden layers) +- Split very large jobs into multiple smaller files +- For raster images, reduce resolution to what's actually needed (typically 300-500 DPI) + +--- + +## Material and Quality Issues + +### Burn Marks on Cuts + +**Problem:** Visible char marks or discoloration along cut edges. + +**Solutions:** + +1. **Enable overscan** - Allows laser to reach full speed before cutting +2. **Use air assist** - Blows away smoke and debris +3. **Mask the material** - Apply masking tape to protect surface +4. **Reduce power slightly** - Find minimum power that still cuts through +5. **Increase speed** - Faster cutting = less heat buildup +6. **Multiple light passes** - Instead of one heavy pass + +See [Reducing Burn Marks](../guides/reducing-burn-marks.md) guide. + +### Inconsistent Engraving Depth + +**Problem:** Raster engraving has uneven depth across the work area. + +**Possible causes:** + +1. **Uneven material surface** - Material not flat +2. **Bed not level** - Cutting bed tilted +3. **Variable focus** - Focal point changes across work area +4. **Inconsistent material** - Material density varies + +**Solutions:** + +- Use a flat, rigid material surface +- Check bed levelness with a straightedge +- Ensure material is secured flat (not warped) +- Use consistent, high-quality materials +- Test with a known-good material to isolate hardware vs material issues + +### Jobs Look Distorted or Skewed + +**Problem:** Circles appear oval, squares are parallelograms. + +**Causes:** + +1. **Mechanical issues** - Loose belts, worn wheels +2. **Step calibration wrong** - Steps-per-mm incorrectly configured +3. **Acceleration too high** - Motors skipping steps + +**Solutions:** + +- Tighten belts and check for mechanical play +- Calibrate steps-per-mm: [Calibrating Your Workspace](../guides/calibrating-your-workspace.md) +- Reduce acceleration settings in GRBL config +- Check for binding or friction in axes +- Verify pulleys are secure on motor shafts + +--- + +## G-code Issues + +### Warning: Out of Bounds + +**Problem:** RayForge warns that the job exceeds machine boundaries. + +**Solutions:** + +1. **Scale down your design** - Reduce size to fit work area +2. **Reposition the job** - Move it within bounds +3. **Check machine dimensions** - Verify work area size in machine settings +4. **Adjust job origin** - Change origin point (e.g., from center to corner) + +### G-code Contains Errors + +**Problem:** Generated G-code has warnings or errors. + +**Solutions:** + +1. Check operation settings for invalid values (negative speeds, zero power) +2. Ensure all paths are valid (no unclosed paths for cutting operations) +3. Review operations in the correct order +4. Check for extremely small or degenerate geometry +5. Try removing and re-adding problematic operations + +--- + +## Layer and Organization Issues + +### Can't See My Objects + +**Problem:** Imported objects aren't visible in the canvas. + +**Possible causes:** + +1. **Outside viewport** - Objects imported at large coordinates +2. **Layer hidden** - Layer visibility toggled off +3. **Extremely small** - Object too small to see at current zoom +4. **Behind other objects** - Obscured by other elements + +**Solutions:** + +- Use `View Zoom to Fit` or zoom out significantly +- Check layer panel for hidden layers (eye icon) +- Select all (`Ctrl+A`) and zoom to selection +- Check the layer stack order + +### Operations Not Generating G-code + +**Problem:** Operation exists but produces no G-code output. + +**Diagnosis:** + +1. **No objects assigned** - Operation has no geometry to process +2. **Empty layer** - Layer contains no paths +3. **Invalid operation settings** - Settings that produce no output + +**Solutions:** + +- Ensure the operation's layer contains visible paths +- Check that paths are assigned to the correct layer +- Verify operation settings (especially power > 0) +- Review operation type matches geometry (e.g., Contour needs closed paths for cutting) + +--- + +## Installation and Startup Issues + +### Application Won't Start + +=== "Linux (Snap)" + ```bash + # Check snap installation + snap list | grep rayforge + + # View logs + snap logs rayforge + + # Reinstall if needed + sudo snap refresh rayforge + ``` + +=== "Linux (From Source)" + ```bash + # Check Python version + python --version # Should be 3.10+ + + # Install dependencies + pixi install + + # Run with verbose logging + RAYFORGE_LOG_LEVEL=DEBUG pixi run rayforge + ``` + +=== "Windows" + - Ensure you have the latest Visual C++ Redistributable + - Check that antivirus isn't blocking the executable + - Try running as administrator + - Check Windows Event Viewer for error details + +### Missing Icons or UI Elements + +**Problem:** UI shows missing icons or broken layout. + +**Solutions:** + +- Ensure GTK libraries are properly installed +- On Linux, install `libadwaita-1-0` package +- Check theme compatibility (try default system theme) +- For Snap users, ensure you have `gtk-common-themes` connected + +--- + +## When to File a Bug Report + +If you've tried the solutions above and still have issues, please file a bug report on GitHub with: + +1. **RayForge version** and installation method (Snap, source, AppImage, etc.) +2. **Operating system** and version +3. **Steps to reproduce** the issue +4. **Expected vs actual behavior** +5. **Logs** (run with `RAYFORGE_LOG_LEVEL=DEBUG`) +6. **Sample files** if relevant (SVG, project files) +7. **Screenshots** showing the problem + +--- + +## Related Pages + +- [Connection Issues](connection.md) - Serial connection troubleshooting +- [Performance](performance.md) - Optimization and performance tuning +- [Snap Permissions](snap-permissions.md) - Linux Snap-specific issues +- [Machine Setup](../machine/index.md) - Machine configuration guide diff --git a/docs-site/troubleshooting/connection.md b/docs-site/troubleshooting/connection.md new file mode 100644 index 000000000..7c4dfc982 --- /dev/null +++ b/docs-site/troubleshooting/connection.md @@ -0,0 +1,306 @@ +# Connection Issues + +This page helps you diagnose and resolve problems connecting RayForge to your laser machine via serial connection. + +## Quick Diagnosis + +### Symptoms + +Common connection problems include: + +- "Port must be configured" error when trying to connect +- Connection repeatedly failing and reconnecting +- Serial port not appearing in the port list +- "Permission denied" errors when trying to open serial port +- Device appears to connect but doesn't respond to commands + +--- + +## Common Problems and Solutions + +### No Serial Ports Detected + +**Problem:** The serial port dropdown is empty or doesn't show your device. + +**Diagnosis:** + +1. Check if your device is powered on and connected via USB +2. Try unplugging and re-plugging the USB cable +3. Test the USB cable with another device (cables can fail) +4. Try a different USB port on your computer + +**Solutions:** + +=== "Linux" + If you're using the Snap version, you need to grant serial port permissions: + + ```bash + sudo snap connect rayforge:serial-port + ``` + + See [Snap Permissions](snap-permissions.md) for detailed Linux setup. + + For non-Snap installations, add your user to the `dialout` group: + + ```bash + sudo usermod -a -G dialout $USER + ``` + + Then log out and log back in for the change to take effect. + +=== "Windows" + 1. Open Device Manager (Win+X, then select Device Manager) + 2. Look under "Ports (COM & LPT)" for your device + 3. If you see a yellow warning icon, update or reinstall the driver + 4. Note the COM port number (e.g., COM3) + 5. If the device isn't listed at all, the USB cable or driver may be faulty + +=== "macOS" + 1. Check System Information USB to verify the device is recognized + 2. Install CH340/CH341 drivers if your controller uses this chipset + 3. Check for `/dev/tty.usbserial*` or `/dev/cu.usbserial*` devices + +### Permission Denied Errors + +**Problem:** You get "Permission denied" or similar errors when trying to connect. + +**On Linux (non-Snap):** + +Your user needs to be in the `dialout` group (or `uucp` on some distributions): + +```bash +# Add yourself to the dialout group +sudo usermod -a -G dialout $USER + +# Verify you're in the group (after logging out/in) +groups | grep dialout +``` + +**Important:** You must log out and log back in (or reboot) for group changes to take effect. + +**On Linux (Snap):** + +Grant serial port access to the snap: + +```bash +sudo snap connect rayforge:serial-port +``` + +See the [Snap Permissions](snap-permissions.md) guide for more details. + +**On Windows:** + +Close any other applications that might be using the serial port (including: +- Previous instances of RayForge +- Serial monitor tools +- Other laser software +- Arduino IDE or similar tools + +### Wrong Serial Port Selected + +**Problem:** RayForge connects but the machine doesn't respond. + +**Diagnosis:** + +You might have selected the wrong port, especially if you have multiple USB devices connected. + +**Solution:** + +1. Disconnect all other USB serial devices +2. Note which ports are available in RayForge +3. Plug in your laser controller +4. Refresh the port list - the new port is your laser +5. On Linux, laser controllers typically appear as: + - `/dev/ttyUSB0` (common for CH340 chipsets) + - `/dev/ttyACM0` (common for native USB controllers) +6. On Windows, note the COM port from Device Manager +7. Avoid ports named `/dev/ttyS*` on Linux - these are hardware serial ports, not USB + +!!! warning "Hardware Serial Ports" + RayForge will warn you if you select `/dev/ttyS*` ports on Linux, as these are typically not USB-based GRBL devices. USB serial ports use `/dev/ttyUSB*` or `/dev/ttyACM*`. + +### Incorrect Baud Rate + +**Problem:** Connection establishes but commands don't work or produce garbled responses. + +**Solution:** + +GRBL controllers typically use one of these baud rates: + +- **115200** (most common, GRBL 1.1+) +- **9600** (older GRBL versions) +- **250000** (less common, some custom firmware) + +Try different baud rates in RayForge's device settings. The most common is **115200**. + +### Connection Keeps Dropping + +**Problem:** RayForge connects successfully but keeps disconnecting and reconnecting. + +**Possible Causes:** + +1. **Flaky USB cable** - Replace with a known-good cable (preferably short, <2m) +2. **USB power issues** - Try a different USB port, preferably on the computer itself rather than a hub +3. **EMI/Interference** - Keep USB cables away from motor wires and high-voltage power supplies +4. **Firmware issues** - Update your GRBL firmware if possible +5. **USB port conflicts** - On Windows, try different USB ports + +**Troubleshooting Steps:** + +```bash +# On Linux, monitor system logs while connecting: +sudo dmesg -w +``` + +Look for messages like: +- "USB disconnect" - indicates physical/cable issues +- "device descriptor read error" - often a power or cable problem + +### Device Not Responding After Connection + +**Problem:** Connection status shows "Connected" but the machine doesn't respond to commands. + +**Diagnosis:** + +1. Check that the correct firmware type is selected (GRBL vs other) +2. Verify the machine is powered on (controller and power supply) +3. Check if the machine is in an alarm state (requires homing or alarm clear) + +**Solution:** + +Try sending a manual command in the debug console (if available): + +- `?` - Request status report +- `$X` - Clear alarm +- `$H` - Home the machine + +If there's no response, double-check baud rate and port selection. + +--- + +## Connection Status Messages + +RayForge shows different connection states: + +| Status | Meaning | Action | +|--------|---------|--------| +| **Disconnected** | Not connected to any device | Configure port and connect | +| **Connecting** | Attempting to establish connection | Wait, or check configuration if stuck | +| **Connected** | Successfully connected and receiving status | Ready to use | +| **Error** | Connection failed with an error | Check error message for details | +| **Sleeping** | Waiting before reconnection attempt | Previous connection failed, retrying in 5s | + +--- + +## Testing Your Connection + +### Step-by-Step Connection Test + +1. **Configure the machine:** + - Open Settings Machine + - Select or create a machine profile + - Choose the correct driver (GRBL Serial) + - Select the serial port + - Set baud rate (typically 115200) + +2. **Attempt connection:** + - Click "Connect" in the machine control panel + - Watch the connection status indicator + +3. **Verify communication:** + - If connected, try sending a status query + - The machine should report its position and state + +4. **Test basic commands:** + - Try homing (`$H`) if your machine has limit switches + - Or clear alarms (`$X`) if needed + +### Using Debug Logs + +RayForge includes detailed debug logging for connection issues. + +To enable verbose logging: + +```bash +# Run RayForge from terminal with debug logging +RAYFORGE_LOG_LEVEL=DEBUG rayforge +``` + +Check the logs for: +- Connection attempts and failures +- Serial data transmitted (TX) and received (RX) +- Error messages with stack traces + +--- + +## Advanced Troubleshooting + +### Checking Port Availability Manually + +=== "Linux" + ```bash + # List all USB serial devices + ls -l /dev/ttyUSB* /dev/ttyACM* + + # Check permissions + ls -l /dev/ttyUSB0 # Replace with your port + + # Should show: crw-rw---- 1 root dialout + # You need to be in the 'dialout' group + + # Test port manually + sudo minicom -D /dev/ttyUSB0 -b 115200 + ``` + +=== "Windows" + ```powershell + # List COM ports in PowerShell + [System.IO.Ports.SerialPort]::getportnames() + + # Or use Device Manager: + # Win + X Device Manager Ports (COM & LPT) + ``` + +### Firmware Compatibility + +RayForge is designed for GRBL-compatible firmware. Ensure your controller runs: + +- **GRBL 1.1** (most common, recommended) +- **GRBL 0.9** (older, may have limited features) +- **grblHAL** (modern GRBL fork, supported) + +Other firmware types (Marlin, Smoothieware) are not currently supported via the GRBL driver. + +### USB-to-Serial Chipsets + +Common chipsets and their drivers: + +| Chipset | Linux | Windows | macOS | +|---------|-------|---------|-------| +| **CH340/CH341** | Built-in kernel driver | [CH341SER driver](http://www.wch.cn/downloads/) | Requires driver | +| **FTDI FT232** | Built-in kernel driver | Built-in (Windows 10+) | Built-in | +| **CP2102 (SiLabs)** | Built-in kernel driver | Built-in (Windows 10+) | Built-in | + +--- + +## Still Having Issues? + +If you've tried everything above and still can't connect: + +1. **Check the GitHub issues** - Someone may have reported the same problem +2. **Create a detailed issue report** with: + - Operating system and version + - RayForge version (Snap/Flatpak/AppImage/source) + - Controller board model and firmware version + - USB chipset (check Device Manager on Windows or `lsusb` on Linux) + - Full error messages and debug logs +3. **Test with another application** - Try connecting with a serial terminal (minicom, PuTTY, Arduino Serial Monitor) to verify the hardware works + +--- + +## Related Pages + +- [Snap Permissions](snap-permissions.md) - Detailed Linux Snap permission setup +- [Common Problems](common.md) - Other common issues and solutions +- [Device Configuration](../machine/device-config.md) - Machine setup guide +- [GRBL Settings](../machine/grbl-settings.md) - GRBL configuration reference diff --git a/docs-site/troubleshooting/index.md b/docs-site/troubleshooting/index.md new file mode 100644 index 000000000..e88c59dc0 --- /dev/null +++ b/docs-site/troubleshooting/index.md @@ -0,0 +1,97 @@ +# Troubleshooting + +Having issues with Rayforge? This section covers common problems and their solutions. + +## Quick Fixes + +Before diving into specific issues, try these general troubleshooting steps: + +1. **Restart Rayforge**: Close and reopen the application +2. **Check connections**: Ensure cables are firmly connected +3. **Power cycle**: Turn your laser cutter off and on +4. **Update software**: Check for the latest Rayforge version +5. **Check permissions**: Verify you have the necessary hardware access permissions + +## Common Issues + +### Connection Problems + +Can't connect to your laser cutter? See the [Connection Issues](connection.md) guide. + +**Quick checklist:** + +- [ ] Device is powered on +- [ ] USB cable is connected (or network is accessible) +- [ ] Correct port/IP address is selected +- [ ] Baud rate matches device settings (usually 115200) +- [ ] User has permission to access serial ports (Linux) + +### Snap Package Permissions + +Using the Snap version? You may need to grant hardware permissions. See [Snap Permissions](snap-permissions.md). + +### Performance Issues + +Experiencing slow performance? Check the [Performance](performance.md) guide. + +**Common causes:** + +- Large or complex files +- Insufficient system resources +- Too many operations or layers +- High-resolution raster images + +### Common Problems + +See [Common Problems](common.md) for solutions to frequently reported issues including: + +- G-code generation errors +- Interface glitches +- File import problems +- Unexpected behavior + +## Getting Help + +If you can't find a solution here: + +1. **Search existing issues**: Check [GitHub Issues](https://github.com/barebaric/rayforge/issues) to see if others have reported the same problem +2. **Report a new issue**: If your problem is not listed, [create a new issue](https://github.com/barebaric/rayforge/issues/new) with: + - Detailed description of the problem + - Steps to reproduce + - Your system information (OS, Rayforge version) + - Any error messages + - Screenshots if applicable + +## Diagnostic Information + +When reporting issues, include this information: + +### System Information + +- **Operating System**: (e.g., Ubuntu 24.04, Windows 11) +- **Rayforge Version**: Check Help → About +- **Installation Method**: (PPA, Snap, pip, Windows installer) + +### Machine Information + +- **Device Type**: (GRBL, Smoothieware) +- **Connection Method**: (Serial, Network, Telnet) +- **Firmware Version**: Check Machine → GRBL Settings + +### Log Files + +Rayforge logs can help diagnose issues: + +- **Linux**: `~/.local/share/rayforge/logs/` +- **Windows**: `%APPDATA%\rayforge\logs\` + +Include relevant log entries when reporting issues. + +--- + +## Issue Categories + +- **[Connection Issues](connection.md)**: Can't connect to your machine +- **[Snap Permissions](snap-permissions.md)**: Permission problems with Snap package +- **[Performance](performance.md)**: Slow operation or lag +- **[Common Problems](common.md)**: Frequently reported issues and solutions diff --git a/docs-site/troubleshooting/performance.md b/docs-site/troubleshooting/performance.md new file mode 100644 index 000000000..d308cea42 --- /dev/null +++ b/docs-site/troubleshooting/performance.md @@ -0,0 +1,411 @@ +# Performance Optimization + +This page helps you diagnose and resolve performance issues in RayForge, including slow UI, sluggish rendering, and long processing times. + +## Common Performance Issues + +### Slow Canvas Response + +**Symptoms:** +- Panning and zooming feels laggy +- Selecting objects takes time +- Moving objects stutters + +**Solutions:** + +#### Simplify Complex Paths + +Complex vector paths with thousands of nodes can slow down rendering: + +1. **In Inkscape before import:** + - Select path + - `Path Simplify` (or Ctrl+L) + - Adjust smoothing threshold to reduce nodes while preserving shape + +2. **Check node count:** + - Very detailed paths (>5000 nodes) should be simplified + - For engraving, detail beyond what the laser can resolve is wasted + +3. **Remove hidden objects:** + - Delete guides, construction lines, and hidden layers + - Only import what needs to be cut/engraved + +#### Reduce Active Operations + +Each operation adds processing overhead: + +- Combine similar operations when possible +- Disable or delete unused operations +- Break very large jobs into multiple smaller files + +#### Optimize Raster Images + +Large raster images impact performance: + +- Reduce resolution to what's actually needed (300-500 DPI is typical) +- Crop images to remove unnecessary areas +- Convert to grayscale if color isn't needed +- Avoid extremely large image files (>10MB) + +--- + +### Slow 3D Preview + +**Symptoms:** +- Long delay when opening 3D preview +- Choppy rotation and navigation +- High CPU/GPU usage + +**Solutions:** + +#### Reduce Preview Quality + +RayForge may allow adjusting preview quality in preferences: + +1. Open Settings/Preferences +2. Look for 3D Preview or Rendering settings +3. Reduce: + - Mesh resolution/quality + - Anti-aliasing + - Texture detail + +#### Simplify Operations + +The 3D preview must render all operations: + +- Reduce operation count +- Lower raster DPI for preview (doesn't affect output) +- Disable preview auto-update if available + +#### Update Graphics Drivers + +Especially on Linux: + +```bash +# Check current driver +glxinfo | grep "OpenGL renderer" + +# Ubuntu/Debian: Update Mesa drivers +sudo apt update && sudo apt upgrade + +# For NVIDIA cards, use proprietary drivers +sudo ubuntu-drivers autoinstall +``` + +--- + +### Long G-code Generation Time + +**Symptoms:** +- Significant delay before job starts +- "Generating G-code..." takes minutes +- Application becomes unresponsive during generation + +**Causes:** + +1. **Complex raster engraving** - High DPI on large areas +2. **Many small operations** - Hundreds of small paths +3. **Inefficient path ordering** - Optimization calculations + +**Solutions:** + +#### Optimize Raster Settings + +For engraving operations: + +- **Reduce DPI** - 300-500 DPI is usually sufficient, not 1200+ +- **Crop images** - Only engrave the necessary area +- **Increase line spacing** - Slightly wider spacing significantly reduces G-code +- **Use appropriate operation type** - Depth engraving for 3D effects, raster for photos + +#### Simplify Vector Operations + +For cutting/contour operations: + +- **Merge adjacent paths** - Combine small segments +- **Remove tiny details** - Features smaller than laser spot size won't show +- **Use appropriate tolerance** - Don't over-optimize path ordering for simple jobs + +#### Example: Large Photo Engraving + +Before (slow): +- Image: 3000x2000 pixels (6MP) +- DPI: 1000 +- Result: 10+ minutes generation, 500MB G-code + +After (optimized): +- Image: Scaled to 1500x1000 pixels +- DPI: 500 +- Cropped to subject area only +- Result: <1 minute generation, 50MB G-code +- **Visual quality: Nearly identical** + +--- + +### Application Startup Slow + +**Symptoms:** +- RayForge takes a long time to launch +- Splash screen visible for extended period + +**Solutions:** + +=== "Linux (Snap)" + Snaps have some startup overhead due to sandboxing: + + ```bash + # Ensure snap is updated + sudo snap refresh rayforge + + # Check for disk space issues + df -h + + # Clear snap cache if needed + sudo snap set system refresh.retain=2 + ``` + +=== "Linux (From Source)" + ```bash + # Precompile Python files + python -m compileall rayforge/ + + # Use faster Python interpreter (if available) + python3.11 # or latest version + ``` + +=== "General" + - Close unused documents before quitting (they reopen on startup) + - Clear recent file history if very long + - Check for large log files that may slow startup + +--- + +### Import Takes Too Long + +**Symptoms:** +- Importing SVG/DXF/PDF files is very slow +- Application freezes during import + +**Solutions:** + +#### Prepare Files in Design Software + +**Before exporting to RayForge:** + +1. **Simplify paths:** + - Inkscape: `Path Simplify` + - Illustrator: `Object Path Simplify` + +2. **Remove unnecessary elements:** + - Delete guides, grids, construction geometry + - Remove hidden layers + - Flatten nested groups + +3. **Convert text to paths:** + - Select all text + - `Path Object to Path` + +4. **Optimize SVG export:** + - Use "Optimized SVG" or "Plain SVG" + - Don't include metadata, editor data + +#### File Size Guidelines + +For smooth import: + +- **SVG files:** <5MB ideal, <20MB acceptable +- **Raster images:** <10MB, reduce resolution if larger +- **DXF files:** <1000 entities for fast import + +#### Split Large Jobs + +Instead of one massive file: + +- Break into multiple smaller sections +- Import and process separately +- Combine if needed after optimization + +--- + +## System Requirements + +### Recommended Hardware + +For smooth performance: + +- **CPU:** Modern multi-core processor (4+ cores) +- **RAM:** 8GB minimum, 16GB+ recommended for large files +- **GPU:** Dedicated graphics recommended for 3D preview +- **Storage:** SSD preferred (faster file I/O) + +### Operating System + +#### Linux + +**Best performance:** +- Recent kernel (5.15+) +- Up-to-date Mesa graphics drivers +- Wayland or X11 (both supported) + +**For GTK4/Libadwaita:** +```bash +# Ensure required libraries installed +sudo apt install libadwaita-1-0 libgtk-4-1 +``` + +#### Windows + +- Windows 10/11 recommended +- Latest Visual C++ Redistributable +- Updated graphics drivers + +--- + +## Monitoring Performance + +### Check Resource Usage + +=== "Linux" + ```bash + # Monitor CPU and memory while running RayForge + htop + + # Check GPU usage (if NVIDIA) + nvidia-smi + + # Monitor disk I/O + iotop + ``` + +=== "Windows" + - Open Task Manager (Ctrl+Shift+Esc) + - Check "Performance" tab + - Look for high CPU, Memory, or Disk usage + +### Enable Debug Logging + +To identify bottlenecks: + +```bash +# Run with debug logging +RAYFORGE_LOG_LEVEL=DEBUG rayforge 2>&1 | tee rayforge.log + +# Look for slow operations in the log +grep -i "slow\|delay\|timeout" rayforge.log +``` + +--- + +## Optimization Checklist + +Before reporting performance issues, try: + +- [ ] Simplify paths (reduce node count) +- [ ] Reduce raster image resolution +- [ ] Lower 3D preview quality +- [ ] Remove unused operations/layers +- [ ] Update graphics drivers +- [ ] Close other applications +- [ ] Ensure adequate free disk space (>10GB) +- [ ] Ensure adequate free RAM (>2GB available) +- [ ] Check for system updates +- [ ] Try a known-simple file (single square) to isolate issue + +--- + +## Known Performance Limitations + +### Large Raster Engravings + +Very large photo engravings (>100cm at high DPI) will inherently take time to process: + +- **This is normal** - Millions of G-code commands must be generated +- **Mitigation:** Use appropriate DPI, don't over-sample + +### Complex Path Optimization + +Optimization algorithms for ordering thousands of paths: + +- **This is normal** - Traveling salesman problem is computationally expensive +- **Mitigation:** Reduce path count, disable optimization if speed isn't critical + +### First Operation After Import + +Initial processing of a new file may be slower: + +- **This is normal** - Caching and initial calculations +- **Subsequent operations should be faster** + +--- + +## Platform-Specific Issues + +### Linux: Snap Performance + +Snap sandboxing adds some overhead: + +**If performance is critical:** + +1. Consider building from source instead: + ```bash + git clone https://github.com/kylemartin57/rayforge + cd rayforge + pixi install + pixi run rayforge + ``` + +2. Or use Flatpak (if available) - often faster than Snap + +### Linux: Wayland vs X11 + +Some users report better performance on X11: + +```bash +# Force X11 session +# (Configure in your display manager before login) +``` + +### Windows: Anti-virus Scanning + +Real-time scanning can slow file operations: + +- Add RayForge installation directory to antivirus exclusions +- Add temporary directory to exclusions +- Don't disable antivirus entirely - use targeted exclusions + +--- + +## Reporting Performance Issues + +If performance is still poor after optimization: + +1. **Provide system specs:** + - CPU model and speed + - RAM amount + - GPU model + - OS and version + +2. **Describe the specific operation:** + - File import? G-code generation? UI interaction? + - How long does it take? + - With what file (provide sample if possible) + +3. **Include benchmarks:** + ```bash + # Example timing information + time rayforge --import test.svg --export test.gcode + ``` + +4. **Attach debug log:** + ```bash + RAYFORGE_LOG_LEVEL=DEBUG rayforge 2>&1 | tee performance-issue.log + ``` + +--- + +## Related Pages + +- [Common Problems](common.md) - General troubleshooting +- [Connection Issues](connection.md) - Serial connection performance +- [3D Preview](../ui/3d-preview.md) - Preview settings +- [Operations](../features/operations/index.md) - Operation optimization diff --git a/docs-site/troubleshooting/snap-permissions.md b/docs-site/troubleshooting/snap-permissions.md new file mode 100644 index 000000000..fc24cad12 --- /dev/null +++ b/docs-site/troubleshooting/snap-permissions.md @@ -0,0 +1,366 @@ +# Snap Permissions (Linux) + +This page explains how to configure permissions for RayForge when installed as a Snap package on Linux. + +## What are Snap Permissions? + +Snaps are containerized applications that run in a sandbox for security. By default, they have limited access to system resources. To use certain features (like serial ports for laser controllers), you must explicitly grant permissions. + +## Required Permissions + +RayForge needs these Snap interfaces connected for full functionality: + +| Interface | Purpose | Required? | +|-----------|---------|-----------| +| `serial-port` | Access to USB serial devices (laser controllers) | **Yes** (for machine control) | +| `home` | Read/write files in your home directory | Auto-connected | +| `removable-media` | Access external drives and USB storage | Optional | +| `network` | Network connectivity (for updates, etc.) | Auto-connected | + +--- + +## Granting Serial Port Access + +**This is the most important permission for RayForge.** + +### Check Current Permissions + +```bash +# View all connections for RayForge +snap connections rayforge +``` + +Look for the `serial-port` interface. If it shows "disconnected" or "-", you need to connect it. + +### Connect Serial Port Interface + +```bash +# Grant serial port access +sudo snap connect rayforge:serial-port +``` + +**You only need to do this once.** The permission persists across app updates and reboots. + +### Verify Connection + +```bash +# Check if serial-port is now connected +snap connections rayforge | grep serial-port +``` + +Expected output: +``` +serial-port rayforge:serial-port :serial-port - +``` + +If you see a plug/slot indicator, the connection is active. + +--- + +## Granting Removable Media Access + +If you want to import/export files from USB drives or external storage: + +```bash +# Grant access to removable media +sudo snap connect rayforge:removable-media +``` + +Now you can access files in `/media` and `/mnt`. + +--- + +## Troubleshooting Snap Permissions + +### Serial Port Still Not Working + +**After connecting the interface:** + +1. **Replug the USB device:** + - Unplug your laser controller + - Wait 5 seconds + - Plug it back in + +2. **Restart RayForge:** + - Close RayForge completely + - Relaunch from the application menu or: + ```bash + snap run rayforge + ``` + +3. **Check that the port appears:** + - Open RayForge Settings Machine + - Look for serial ports in the dropdown + - Should see `/dev/ttyUSB0`, `/dev/ttyACM0`, or similar + +4. **Verify the device exists:** + ```bash + # List USB serial devices + ls -l /dev/ttyUSB* /dev/ttyACM* + ``` + +### "Permission Denied" Despite Connected Interface + +This is rare but can happen if: + +1. **The Snap installation is broken:** + ```bash + # Reinstall the snap + sudo snap refresh rayforge --devmode + # Or if that fails: + sudo snap remove rayforge + sudo snap install rayforge + # Re-connect interfaces + sudo snap connect rayforge:serial-port + ``` + +2. **Conflicting udev rules:** + - Check `/etc/udev/rules.d/` for custom serial port rules + - They might conflict with Snap's device access + +3. **AppArmor denials:** + ```bash + # Check for AppArmor denials + sudo journalctl -xe | grep DENIED | grep rayforge + ``` + + If you see denials for serial ports, there may be an AppArmor profile conflict. + +### Can't Access Files Outside Home Directory + +**By design**, Snaps can't access files outside your home directory unless you grant `removable-media`. + +**Workaround options:** + +1. **Move files to your home directory:** + ```bash + # Copy SVG files to ~/Documents + cp /some/other/location/*.svg ~/Documents/ + ``` + +2. **Grant removable-media access:** + ```bash + sudo snap connect rayforge:removable-media + ``` + +3. **Use Snap's file picker:** + - The built-in file chooser has broader access + - Open files through File Open rather than command-line arguments + +--- + +## Manual Interface Management + +### List All Available Interfaces + +```bash +# See all Snap interfaces on your system +snap interface +``` + +### Disconnect an Interface + +```bash +# Disconnect serial-port (if needed) +sudo snap disconnect rayforge:serial-port +``` + +### Reconnect After Disconnect + +```bash +sudo snap connect rayforge:serial-port +``` + +--- + +## Alternative: Install from Source + +If Snap permissions are too restrictive for your workflow: + +**Option 1: Build from source** + +```bash +# Clone the repository +git clone https://github.com/kylemartin57/rayforge.git +cd rayforge + +# Install dependencies using pixi +pixi install + +# Run RayForge +pixi run rayforge +``` + +**Benefits:** +- No permission restrictions +- Full system access +- Easier debugging +- Latest development version + +**Drawbacks:** +- Manual updates (git pull) +- More dependencies to manage +- No automatic updates + +**Option 2: Use Flatpak (if available)** + +Flatpak has similar sandboxing but sometimes with different permission models. Check if RayForge offers a Flatpak package. + +--- + +## Snap Permission Best Practices + +### Only Connect What You Need + +Don't connect interfaces you don't use: + +-  Connect `serial-port` if you use a laser controller +-  Connect `removable-media` if you import from USB drives +- L Don't connect everything "just in case" - defeats security purpose + +### Verify Snap Source + +Always install from the official Snap Store: + +```bash +# Check publisher +snap info rayforge +``` + +Look for: +- Verified publisher +- Official repository source +- Regular updates + +--- + +## Understanding Snap Sandbox + +### What Can Snaps Access by Default? + +**Allowed:** +- Files in your home directory +- Network connections +- Display/audio + +**Not allowed without explicit permission:** +- Serial ports (USB devices) +- Removable media +- System files +- Other users' home directories + +### Why This Matters for RayForge + +RayForge needs: + +1. **Home directory access** (auto-granted) + - To save project files + - To read imported SVG/DXF files + - To store preferences + +2. **Serial port access** (must be granted) + - To communicate with laser controllers + - **This is the critical permission** + +3. **Removable media** (optional) + - To import files from USB drives + - To export G-code to external storage + +--- + +## Debugging Snap Issues + +### Enable Verbose Snap Logging + +```bash +# Run Snap with debug output +snap run --shell rayforge +# Inside the snap shell: +export RAYFORGE_LOG_LEVEL=DEBUG +exec rayforge +``` + +### Check Snap Logs + +```bash +# View RayForge logs +snap logs rayforge + +# Follow logs in real-time +snap logs -f rayforge +``` + +### Check System Journal for Denials + +```bash +# Look for AppArmor denials +sudo journalctl -xe | grep DENIED | grep rayforge + +# Look for USB device events +sudo journalctl -f -u snapd +# Then plug in your laser controller +``` + +--- + +## Getting Help + +If you're still having Snap-related issues: + +1. **Check permissions first:** + ```bash + snap connections rayforge + ``` + +2. **Try a serial port test:** + ```bash + # If you have screen or minicom installed + sudo snap connect rayforge:serial-port + # Then test in RayForge + ``` + +3. **Report the issue with:** + - Output of `snap connections rayforge` + - Output of `snap version` + - Output of `snap info rayforge` + - Your Ubuntu/Linux distribution version + - Exact error messages + +4. **Consider alternatives:** + - Install from source (see above) + - Use a different package format (AppImage, Flatpak) + +--- + +## Quick Reference Commands + +```bash +# Grant serial port access (most important) +sudo snap connect rayforge:serial-port + +# Grant removable media access +sudo snap connect rayforge:removable-media + +# Check current connections +snap connections rayforge + +# View RayForge logs +snap logs rayforge + +# Refresh/update RayForge +sudo snap refresh rayforge + +# Remove and reinstall (last resort) +sudo snap remove rayforge +sudo snap install rayforge +sudo snap connect rayforge:serial-port +``` + +--- + +## Related Pages + +- [Connection Issues](connection.md) - Serial connection troubleshooting +- [Common Problems](common.md) - General troubleshooting +- [Installation](../getting-started/installation.md) - Installation guide +- [Device Configuration](../machine/device-config.md) - Machine setup diff --git a/docs-site/ui/3d-preview.md b/docs-site/ui/3d-preview.md new file mode 100644 index 000000000..fee2af2bd --- /dev/null +++ b/docs-site/ui/3d-preview.md @@ -0,0 +1,151 @@ +# 3D Preview + +The 3D preview window lets you visualize your G-code toolpaths before sending them to your machine. This powerful feature helps you catch errors and verify your job setup. + +![3D Preview](../images/3d-preview.png) + +## Opening 3D Preview + +Access the 3D preview: + +- **Menu**: View → 3D Preview +- **Keyboard**: ++ctrl+3++ +- **After G-code generation**: Automatically opens (configurable) + +## Navigation + +### Mouse Controls + +- **Rotate**: Left-click and drag +- **Pan**: Right-click and drag, or middle-click and drag +- **Zoom**: Scroll wheel, or ++ctrl++ + left-click and drag + +### Keyboard Controls + +- ++r++: Reset camera to default view +- ++home++: Reset zoom and position +- ++f++: Fit view to toolpath +- Arrow keys: Rotate camera + +### View Presets + +Quick camera angles: + +- **Top** (++1++): Bird's eye view +- **Front** (++2++): Front elevation +- **Right** (++3++): Right side elevation +- **Isometric** (++4++): 3D isometric view + +## Display Options + +### Toolpath Visualization + +Customize what you see: + +- **Show Rapid Moves**: Display travel moves (dotted lines) +- **Show Work Moves**: Display cutting/engraving moves (solid lines) +- **Color by Operation**: Different colors for each operation +- **Color by Power**: Gradient based on laser power +- **Color by Speed**: Gradient based on feed rate + +### Machine Visualization + +- **Show Origin**: Display (0,0) reference point +- **Show Work Area**: Display machine boundaries +- **Show Laser Head**: Display current position indicator + +### Quality Settings + +- **Line Width**: Thickness of toolpath lines +- **Anti-aliasing**: Smooth line rendering (may impact performance) +- **Background**: Light, dark, or custom color + +## Playback Controls + +Simulate job execution: + +- **Play/Pause** (++space++): Animate toolpath execution +- **Speed**: Adjust playback speed (0.5x - 10x) +- **Step Forward/Back**: Advance by individual G-code commands +- **Jump to Position**: Click timeline to jump to specific point + +### Timeline + +The timeline shows: + +- Current position in job +- Operation boundaries (colored segments) +- Estimated time at any point + +## Analysis Tools + +### Distance Measurement + +Measure distances in 3D: + +1. Enable measurement tool +2. Click two points on toolpath +3. View distance in current units + +### Statistics Panel + +View job statistics: + +- **Total Distance**: Sum of all moves +- **Work Distance**: Cutting/engraving distance only +- **Rapid Distance**: Travel moves only +- **Estimated Time**: Job duration estimate +- **Bounding Box**: Overall dimensions + +### Layer Visibility + +Toggle visibility of operations: + +- Click operation name to show/hide +- Focus on specific operations for inspection +- Isolate problems without regenerating G-code + +## Verification Checklist + +Before sending to machine, verify: + +- [ ] **Toolpath is complete**: No missing segments +- [ ] **Within work area**: Stays inside machine boundaries +- [ ] **Correct operation order**: Engrave before cut +- [ ] **No collisions**: Head doesn't hit clamps/fixtures +- [ ] **Proper origin**: Starts at expected position +- [ ] **Tab positions**: Holding tabs in correct locations (if used) + +## Performance Tips + +For large or complex jobs: + +1. **Reduce line detail**: Lower display quality for faster rendering +2. **Hide rapid moves**: Focus on work moves only +3. **Disable anti-aliasing**: Improves framerate +4. **Close other applications**: Free up GPU resources + +## Troubleshooting + +### Preview is blank or black + +- Regenerate G-code (++ctrl+g++) +- Check that operations are enabled +- Verify objects have operations assigned + +### Slow or laggy preview + +- Reduce line width +- Disable anti-aliasing +- Hide rapid moves +- Update graphics drivers + +### Colors not showing correctly + +- Check color by setting (operation/power/speed) +- Ensure operations have different colors assigned +- Reset view settings to defaults + +--- + +**Next**: [Settings & Preferences →](settings.md) diff --git a/docs-site/ui/canvas-tools.md b/docs-site/ui/canvas-tools.md new file mode 100644 index 000000000..048c4806c --- /dev/null +++ b/docs-site/ui/canvas-tools.md @@ -0,0 +1,149 @@ +# Canvas Tools + +The canvas provides a comprehensive set of tools for manipulating designs, measuring, and preparing your laser jobs. + +## Selection Tool + +Select, move, and transform objects on the canvas. + +**Usage:** + +- Click to select single object +- ++ctrl++ + click to select multiple objects +- Drag to create selection box +- Click and drag selected objects to move + +**Transform Handles:** + +- **Corner handles**: Scale proportionally (hold ++shift++ to scale non-proportionally) +- **Edge handles**: Scale in one direction +- **Rotation handle**: Rotate around center point + +**Keyboard Shortcuts:** + +- ++arrow-keys++: Move selected objects by 1 unit +- ++shift+arrow-keys++: Move by 10 units +- ++ctrl+d++: Duplicate selection + +## Pan Tool + +Navigate around the canvas without accidentally moving objects. + +**Usage:** + +- Click and drag to pan +- Alternatively, hold ++space++ with any tool active and drag + +## Zoom Tool + +Zoom in on specific areas of your design. + +**Usage:** + +- Click to zoom in at point +- ++alt++ + click to zoom out +- Click and drag to zoom to specific area + +**Shortcuts:** + +- ++ctrl+"+"++: Zoom in +- ++ctrl+"-"++: Zoom out +- ++ctrl+0++: Reset zoom (fit to window) +- Mouse wheel: Zoom in/out at cursor position + +## Measurement Tool + +Measure distances and angles on the canvas. + +**Usage:** + +- Click starting point +- Click ending point to complete measurement +- Measurement displays in current units (mm or inches) + +**Features:** + +- Distance between two points +- Angle relative to horizontal +- Real-time preview while measuring + +## Alignment Tools + +Align and distribute multiple objects. + +**Alignment Options:** + +- Align left edges +- Align right edges +- Align top edges +- Align bottom edges +- Align horizontal centers +- Align vertical centers + +**Distribution Options:** + +- Distribute horizontally +- Distribute vertically +- Equal spacing + +**Usage:** + +1. Select multiple objects +2. Choose alignment/distribution option from toolbar or Edit menu +3. Objects align/distribute immediately + +## Grid and Snapping + +Assist precise positioning with grid and snapping. + +**Grid:** + +- Toggle: View → Show Grid (++ctrl+g++) +- Configure spacing in Preferences +- Visual guide only (optional snapping) + +**Snapping:** + +- **Snap to Grid**: Align objects to grid points +- **Snap to Objects**: Align to edges of other objects +- **Snap to Origin**: Align to machine origin (0,0) + +Toggle snapping: View → Snap (++ctrl+shift+g++) + +## Object Transformation + +Transform objects numerically for precision. + +**Accessible via Properties Panel:** + +- **Position (X, Y)**: Exact coordinates +- **Size (W, H)**: Exact dimensions +- **Rotation**: Degrees from horizontal +- **Scale**: Percentage of original size + +## Boolean Operations + +Combine or subtract shapes: + +- **Union**: Merge overlapping shapes +- **Difference**: Subtract one shape from another +- **Intersection**: Keep only overlapping areas +- **Exclusion**: Remove overlapping areas + +**Usage:** + +1. Select two or more vector objects +2. Choose boolean operation from Edit menu +3. Result replaces selected objects + +## Tips for Efficient Canvas Use + +1. **Use keyboard shortcuts**: Much faster than toolbar clicks +2. **Master pan and zoom**: Essential for large or detailed designs +3. **Snap to grid**: Speeds up alignment for rectangular layouts +4. **Measure first**: Verify dimensions before generating G-code +5. **Group related objects**: Easier to move and organize (++ctrl+g++ to group) + +--- + +**Next**: [3D Preview →](3d-preview.md) diff --git a/docs-site/ui/index.md b/docs-site/ui/index.md new file mode 100644 index 000000000..823eea494 --- /dev/null +++ b/docs-site/ui/index.md @@ -0,0 +1,45 @@ +# User Interface + +Rayforge features a modern, intuitive interface built with GTK4 and Libadwaita. This section covers all the UI elements and how to use them effectively. + +## Interface Overview + +![Main Window](../images/ss-main.png) + +The Rayforge interface consists of several key areas: + +1. **Menu Bar & Toolbar**: Access common functions and tools +2. **Canvas**: The main work area where you arrange and edit designs +3. **Layers Panel**: Manage operations and layer assignments +4. **Properties Panel**: Configure operation settings +5. **Status Bar**: Monitor job progress and machine status + +## Sections + +- **[Main Window](main-window.md)**: Overview of the main interface elements +- **[Canvas Tools](canvas-tools.md)**: Tools for manipulating designs on the canvas +- **[3D Preview](3d-preview.md)**: Visualize G-code toolpaths in 3D +- **[Settings & Preferences](settings.md)**: Customize Rayforge to your workflow + +## Theme Support + +Rayforge supports system, light, and dark themes: + +- **System**: Follow your operating system's theme preference +- **Light**: Bright interface for well-lit environments +- **Dark**: Reduced eye strain for extended use + +Change themes in **Settings → Appearance**. + +## Keyboard Navigation + +Rayforge supports extensive keyboard shortcuts for efficient workflow. See the [Keyboard Shortcuts](../reference/shortcuts.md) reference for a complete list. + +## Accessibility + +Rayforge is built with accessibility in mind, following GTK4 and Libadwaita best practices for: + +- Screen reader support +- Keyboard navigation +- High contrast themes +- Scalable interface elements diff --git a/docs-site/ui/main-window.md b/docs-site/ui/main-window.md new file mode 100644 index 000000000..69a684d9a --- /dev/null +++ b/docs-site/ui/main-window.md @@ -0,0 +1,103 @@ +# Main Window + +The Rayforge main window is your primary workspace for creating and managing laser jobs. + +## Window Layout + +![Main Window](../images/ss-main.png) + +### 1. Menu Bar + +Access all Rayforge functions through organized menus: + +- **File**: Open, save, import, export, and recent files +- **Edit**: Undo, redo, copy, paste, preferences +- **View**: Zoom, grid, rulers, panels, and view modes +- **Operations**: Add, edit, and manage operations +- **Machine**: Connect, jog, home, start/stop jobs +- **Help**: Documentation, about, and support + +### 2. Toolbar + +Quick access to frequently used tools: + +- **Selection tool**: Select and move objects +- **Pan tool**: Navigate the canvas +- **Zoom tool**: Zoom in/out on specific areas +- **Measurement tool**: Measure distances and angles +- **Alignment tools**: Align and distribute objects + +### 3. Canvas + +The main workspace where you: + +- Import and arrange designs +- Preview toolpaths +- Position objects relative to machine origin +- Test frame boundaries + +**Canvas Controls:** + +- **Pan**: Middle-click drag or ++space++ + drag +- **Zoom**: Mouse wheel or ++ctrl+"+"++ / ++ctrl+"-"++ +- **Reset View**: ++ctrl+0++ or View → Reset Zoom + +### 4. Layers Panel + +Manage operations and layer assignments: + +- View all operations in your project +- Assign operations to design elements +- Reorder operation execution +- Enable/disable individual operations +- Configure operation parameters + +### 5. Properties Panel + +Configure settings for selected objects or operations: + +- Operation type (Contour, Raster, etc.) +- Power and speed settings +- Number of passes +- Advanced options (overscan, kerf, tabs) + +### 6. Status Bar + +Monitor real-time information: + +- **Connection Status**: Shows if connected to machine +- **Job Progress**: Current operation and completion percentage +- **Coordinates**: Current laser position +- **Estimated Time**: Remaining time for current job + +## Window Management + +### Panels + +Show/hide panels as needed: + +- **Layers Panel**: View → Layers Panel (++ctrl+l++) +- **Properties Panel**: View → Properties Panel (++ctrl+i++) + +### Full Screen Mode + +Focus on your work with full screen: + +- Enter: ++f11++ or View → Full Screen +- Exit: ++f11++ or ++esc++ + + + +## Customization + +Customize the interface in **Edit → Preferences**: + +- **Theme**: Light, dark, or system +- **Units**: Millimeters or inches +- **Grid**: Show/hide and configure grid spacing +- **Rulers**: Show/hide rulers on canvas +- **Toolbar**: Customize visible buttons + +--- + +**Next**: [Canvas Tools →](canvas-tools.md) diff --git a/docs-site/ui/settings.md b/docs-site/ui/settings.md new file mode 100644 index 000000000..bc37b20ae --- /dev/null +++ b/docs-site/ui/settings.md @@ -0,0 +1,147 @@ +# Settings & Preferences + +Customize Rayforge to match your workflow and preferences. + +## Accessing Settings + +- **Menu**: Edit → Preferences +- **Keyboard**: ++ctrl+comma++ + +## General Settings + +### Interface + +- **Theme**: Choose between System, Light, or Dark theme +- **Language**: Select interface language (English, Portuguese, Spanish, German) +- **Window Behavior**: Restore window size and position on startup + +### Units + +- **Measurement Units**: Millimeters or Inches +- **Speed Units**: mm/min, mm/sec, or inches/min +- **Display Precision**: Number of decimal places + +### Canvas + +- **Grid**: + - Show/hide grid + - Grid spacing + - Grid color and opacity + +- **Rulers**: + - Show/hide rulers + - Ruler units (inherit from general units) + +- **Background Color**: Canvas background color + +### Snapping + +- **Snap to Grid**: Enable/disable grid snapping +- **Snap Distance**: Distance threshold for snapping (pixels) +- **Snap to Objects**: Enable edge and center point snapping + +## Machine Settings + +Configure machine profiles and hardware. See [Machine Setup](../machine/index.md) for detailed information. + +- **Machine Profiles**: Create and manage multiple machine configurations +- **Default Profile**: Select which profile loads on startup + +## Performance + +### Rendering + +- **Hardware Acceleration**: Enable/disable GPU acceleration +- **Anti-aliasing**: Smooth line rendering (may impact performance) +- **Maximum Path Points**: Limit for complex path rendering + +### G-code Generation + +- **Arc Interpolation**: Enable arc (G2/G3) commands vs. line segments +- **Decimal Places**: Precision for coordinates in G-code +- **Optimize Path Order**: Reduce travel time by reordering paths + +### Preview + +- **3D Preview Quality**: Low, Medium, High +- **Auto-open Preview**: Automatically show 3D preview after G-code generation +- **Preview Update Frequency**: Real-time vs. manual update + +## File Handling + +### Import + +- **Default DPI**: For raster images without embedded DPI information +- **SVG Import**: + - Flatten layers + - Convert text to paths + - Import hidden layers + +### Export + +- **G-code File Encoding**: UTF-8, ASCII +- **Line Endings**: LF (Linux/Mac) or CRLF (Windows) +- **Add Comments**: Include operation information in G-code + +### Autosave + +- **Enable Autosave**: Automatically save project at intervals +- **Autosave Interval**: Time between autosaves (minutes) +- **Autosave Location**: Directory for autosave files + +## Keyboard Shortcuts + +Customize keyboard shortcuts for common actions. See [Keyboard Shortcuts](../reference/shortcuts.md) for the complete list. + +- **Reset to Defaults**: Restore all shortcuts to default bindings +- **Import/Export**: Share shortcut configurations + +## Advanced + +### Logging + +- **Log Level**: Debug, Info, Warning, Error +- **Log Location**: View and change log file directory +- **Enable Crash Reports**: Help improve Rayforge by sending anonymous crash reports + +### Experimental Features + +Enable features in development: + +- **New Feature Flags**: Access cutting-edge features +- **Beta Testing**: Opt-in to test new functionality + +!!! warning "Experimental Features" + Experimental features may be unstable or change without notice. Use with caution in production environments. + +### Developer Tools + +- **Show Developer Menu**: Access debugging and profiling tools +- **Enable Debug Output**: Verbose console logging +- **Performance Metrics**: Display FPS and memory usage + +## Resetting Settings + +### Reset to Defaults + +Restore all settings to default values: + +1. Open Preferences +2. Click "Reset All Settings" +3. Confirm the action +4. Restart Rayforge + +!!! caution + This will reset all preferences, including machine profiles. Export your machine profiles first if you want to keep them. + +### Reset Specific Sections + +Reset only certain settings: + +- **Reset Window Layout**: Restore default panel positions +- **Reset Keyboard Shortcuts**: Restore default key bindings +- **Reset Theme**: Return to system theme + +--- + +**Next**: [Features Overview →](../features/index.md) diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..6b314e184 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,183 @@ + +## Contributing + +We welcome contributions of all kinds! Whether you're fixing a bug, adding +a feature, or improving documentation, your help is appreciated. + +- **Report a Bug:** Open an [issue](https://github.com/barebaric/rayforge/issues) + with a clear description and steps to reproduce. +- **Suggest a Feature:** Start a discussion or open a feature request issue. +- **Submit a Pull Request:** Please discuss major changes in an issue first. +- **Add a Driver:** See the [driver development guide](docs/driver.md) to add + support for your hardware. + +### Packaging Help Wanted + +We are actively seeking help to create and maintain a **[Flatpak](flatpak/)** package. +If you have experience with Flatpak, your contribution would be highly valuable! + +## Development + +This project uses [**Pixi**](https://pixi.sh/) to manage dependencies and +development environments for a reproducible setup. + +### Prerequisites + +First, install Pixi by following the instructions on the +[official website](https://pixi.sh/latest/installation/). + +### 1. Setup Environment + +Clone the repository and install dependencies. + +```bash +# Install Gtk/Adwaita system dependency (Debian/Ubuntu) +sudo apt install gir1.2-adw-1 + +# Let Pixi handle the rest +pixi install +``` + +This command reads `pixi.toml` and installs all conda and pip dependencies into a local +`.pixi` virtual environment. + +### 2. Run the Application + +```bash +pixi run rayforge +``` + +### 3. Run Tests and Lint + +```bash +pixi run test +pixi run lint +``` + +### 4. Activate the Development Shell + +For an interactive workflow, you can activate a shell within the project's environment. + +```bash +pixi shell +``` + +Inside this shell, you can run commands directly without the `pixi run` prefix +(e.g., `rayforge`, `pytest`). Type `exit` to leave the shell. + +### 5. Manage Dependencies + +Always use Pixi to manage dependencies to ensure the `pixi.lock` file is updated. + +```bash +# Add a conda package +pixi add numpy + +# Add a PyPI package +pixi add --pypi requests +``` + +### 6. Translation Workflow + +The following tasks are available for managing language translations: + +#### Update `.po` files from source code + +```bash +pixi run update-translations +``` + +#### Compile `.po` files to binary `.mo` files + +```bash +pixi run compile-translations +``` + + + +### Add Device Drivers + +Expand hardware support by adding drivers for new devices. See the [Adding Device Drivers](drivers.md) guide for details. + +### Help with Packaging + +We need help maintaining packages for different platforms: + +- **Flatpak**: We're actively seeking help with Flatpak packaging +- **Other distributions**: Arch, Fedora, etc. +- **macOS**: Help bring Rayforge to Mac users + +## Contribution Guidelines + +### Code Style + +- Follow PEP 8 for Python code +- Use descriptive variable and function names +- Add docstrings to functions and classes +- Keep functions focused and single-purpose + +### Testing + +- Add tests for new features +- Ensure existing tests pass: `pixi run test` +- Test manually on your system +- Test with real hardware if possible + +### Commit Messages + +Write clear, descriptive commit messages: + +``` +Add overscan support for raster engraving + +- Implement overscan calculation for raster operations +- Add UI controls for overscan settings +- Update G-code generator to handle overscan moves +- Add tests for overscan calculation + +Fixes #123 +``` + +### Pull Request Process + +1. **Update documentation** if your changes affect user-facing features +2. **Run linter**: `pixi run lint` +3. **Run tests**: `pixi run test` +4. **Update CHANGELOG** (if applicable) +5. **Request review** from maintainers + +## Development Resources + +- **[Development Setup](development.md)**: Set up your development environment +- **[Adding Device Drivers](drivers.md)**: Create drivers for new hardware +- **Architecture Overview**: (Coming soon) +- **API Reference**: (Coming soon) + +## Community + +- **GitHub Discussions**: Ask questions and share ideas +- **Issues**: Track bugs and feature requests +- **Pull Requests**: Review and contribute code + +## Code of Conduct + +We are committed to providing a welcoming and inclusive environment. Please: + +- Be respectful and considerate +- Welcome newcomers +- Focus on what is best for the community +- Show empathy towards others + +## Recognition + +Contributors are recognized in: + +- GitHub contributor list +- Release notes for significant contributions +- About dialog in the application + +Thank you for contributing to Rayforge! + +--- + +**Next**: [Development Setup →](development.md) | [Adding Device Drivers →](drivers.md) diff --git a/docs/user-docs-site.md b/docs/user-docs-site.md new file mode 100644 index 000000000..1c04076ac --- /dev/null +++ b/docs/user-docs-site.md @@ -0,0 +1,224 @@ +# Rayforge Documentation Setup + +This document describes the mkdocs-material documentation setup for Rayforge with versioning support. + +## Overview + +The documentation system is built using: + +- **[MkDocs Material](https://squidfunk.github.io/mkdocs-material/)**: Modern documentation theme +- **[Mike](https://github.com/jimporter/mike)**: Documentation versioning +- **GitHub Actions**: Automated deployment + +## Features + +✅ **Versioned documentation** - Users can switch between versions (dev, latest, specific releases) +✅ **Rich content** - Support for screenshots, code blocks, admonitions, tabs, and more +✅ **Search** - Full-text search across all documentation +✅ **Responsive** - Works on desktop, tablet, and mobile +✅ **Dark mode** - Automatic light/dark theme switching +✅ **Navigation** - Multi-level navigation with breadcrumbs +✅ **Extensible** - Easy to add new pages and sections + +## Directory Structure + +``` +rayforge/ +├── mkdocs.yml # MkDocs configuration +├── docs-site/ # Documentation source files +│ ├── index.md # Homepage +│ ├── getting-started/ # Installation and setup +│ ├── ui/ # User interface documentation +│ ├── features/ # Feature guides +│ ├── machine/ # Machine setup +│ ├── files/ # File format documentation +│ ├── troubleshooting/ # Problem solving +│ ├── reference/ # Technical reference +│ ├── contributing/ # Contribution guide +│ ├── assets/ # Logos, icons, etc. +│ ├── stylesheets/ # Custom CSS +│ └── includes/ # Reusable snippets +├── docs/ # Screenshots (shared with README) +└── .github/workflows/ + └── docs.yml # Documentation deployment workflow +``` + +## Quick Start +This guide shows the simplified commands for working with Rayforge documentation. + +## ✅ Simplified Commands (New!) + +The documentation tasks have been simplified so you don't need to specify the environment: + +### Serve Documentation Locally + +Start a local development server with live reload: + +```bash +pixi run docs-serve +``` + +- Opens http://127.0.0.1:8000/ +- Auto-reloads when you edit files +- Perfect for writing and previewing documentation + +### Build Documentation + +Build the static site to the `site/` directory: + +```bash +pixi run docs-build +``` + +- Creates production-ready HTML in `site/` +- Validates all links and references +- Use this to test before deploying + +### Deploy Documentation + +Deploy documentation with versioning: + +```bash +# Deploy development version +VERSION=dev pixi run docs-deploy + +# Deploy release version +VERSION=1.0.0 pixi run docs-deploy +``` + +- Pushes to `gh-pages` branch +- Updates version selector +- Requires push access to repository + + +## Versioning Workflow + +### Development Documentation + +Updated automatically when pushing to `main` branch: + +```bash +git checkout main +# Make documentation changes in docs-site/ +git add docs-site/ +git commit -m "docs: update feature guide" +git push origin main +``` + +The GitHub Action will deploy to the `dev` version. + +### Release Documentation + +Tagged releases automatically create versioned documentation: + +```bash +# Create and push a version tag +git tag v1.0.0 +git push origin v1.0.0 +``` + +The GitHub Action will: +1. Deploy documentation for version `1.0.0` +2. Update the `latest` alias to point to `1.0.0` +3. Make `latest` the default version + +### Manual Deployment + +If needed, deploy manually using mike: + +```bash +# Deploy development version +mike deploy dev development --update-aliases + +# Deploy release version +mike deploy 1.0.0 latest --update-aliases + +# Set default version +mike set-default latest + +# List all versions +mike list + +# Delete a version +mike delete old-version +``` + +## Adding New Pages + +1. Create a new `.md` file in the appropriate directory +2. Add to navigation in `mkdocs.yml`: + +```yaml +nav: + - Section: + - section/index.md + - New Page: section/new-page.md +``` + +3. Write content following the structure guidelines +4. Add internal links to related pages +5. Test locally before committing + +## Customization + +### Theme Colors + +Edit `mkdocs.yml` to change colors: + +```yaml +theme: + palette: + primary: indigo # Change to blue, red, green, etc. + accent: indigo # Accent color for buttons, links +``` + + +## GitHub Pages Setup + +The documentation is deployed to GitHub Pages via the `gh-pages` branch. + +### Initial Setup + +1. Enable GitHub Pages in repository settings +2. Set source to `gh-pages` branch +3. Wait for first deployment from workflow + +### Custom Domain (Optional) + +To use a custom domain: + +1. Add `CNAME` file to `docs-site/` with your domain +2. Configure DNS with your domain provider +3. Update `site_url` in `mkdocs.yml` + +## Automated Deployment + +The `.github/workflows/docs.yml` workflow handles automatic deployment: + +- **Pull Requests**: Build docs to verify no errors (doesn't deploy) +- **Push to main**: Deploy to `dev` version +- **Version tags**: Deploy to version number and update `latest` + +### Workflow Configuration + +Key environment variables in the workflow: + +- `version`: Extracted from git tag or defaults to `dev` +- `alias`: Set to `latest` for releases, `dev` for development + +## Maintenance + +### Updating Dependencies + +```bash +# Update pixi dependencies +pixi update -e docs + +# Or update pip packages +pip install --upgrade mkdocs-material mike +``` + +### Checking Build Status + +Visit the [Actions tab](https://github.com/barebaric/rayforge/actions) on GitHub to monitor deployment status. + diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 000000000..3a3c8917c --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,191 @@ +site_name: Rayforge Documentation +site_url: https://barebaric.github.io/rayforge/ +site_description: Modern G-code sender and control software for GRBL-based laser cutters and engravers +site_author: Rayforge Contributors +repo_url: https://github.com/barebaric/rayforge +repo_name: barebaric/rayforge +edit_uri: edit/main/docs-site/ +docs_dir: docs-site + +theme: + name: material + language: en + logo: assets/logo.svg + favicon: assets/favicon.png + palette: + # Light mode + - media: "(prefers-color-scheme: light)" + scheme: default + primary: indigo + accent: indigo + toggle: + icon: material/brightness-7 + name: Switch to dark mode + # Dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + primary: indigo + accent: indigo + toggle: + icon: material/brightness-4 + name: Switch to light mode + features: + - announce.dismiss + - content.action.edit + - content.action.view + - content.code.annotate + - content.code.copy + - content.tooltips + - navigation.expand + - navigation.footer + - navigation.indexes + - navigation.instant + - navigation.instant.prefetch + - navigation.instant.progress + - navigation.path + - navigation.sections + - navigation.tabs + - navigation.tabs.sticky + - navigation.top + - navigation.tracking + - search.highlight + - search.share + - search.suggest + - toc.follow + +plugins: + - search: + separator: '[\s\u200b\-_,:!=\[\]()"`/]+|\.(?!\d)|&[lg]t;|(?!\b)(?=[A-Z][a-z])' + - glightbox: + touchNavigation: true + loop: false + effect: zoom + slide_effect: slide + width: 100% + height: auto + zoomable: true + draggable: true + skip_classes: + - custom-skip-class-name + auto_caption: false + caption_position: bottom + +markdown_extensions: + - abbr + - admonition + - attr_list + - def_list + - footnotes + - md_in_html + - toc: + permalink: true + - pymdownx.arithmatex: + generic: true + - pymdownx.betterem: + smart_enable: all + - pymdownx.caret + - pymdownx.details + - pymdownx.emoji: + emoji_generator: !!python/name:material.extensions.emoji.to_svg + emoji_index: !!python/name:material.extensions.emoji.twemoji + - pymdownx.highlight: + anchor_linenums: true + line_spans: __span + pygments_lang_class: true + - pymdownx.inlinehilite + - pymdownx.keys + - pymdownx.magiclink: + normalize_issue_symbols: true + repo_url_shorthand: true + user: barebaric + repo: rayforge + - pymdownx.mark + - pymdownx.smartsymbols + - pymdownx.snippets: + auto_append: + - includes/abbreviations.md + - pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format + - pymdownx.tabbed: + alternate_style: true + combine_header_slug: true + slugify: !!python/object/apply:pymdownx.slugs.slugify + kwds: + case: lower + - pymdownx.tasklist: + custom_checkbox: true + - pymdownx.tilde + +extra: + version: + provider: mike + default: latest + social: + - icon: fontawesome/brands/github + link: https://github.com/barebaric/rayforge + - icon: fontawesome/brands/python + link: https://pypi.org/project/rayforge/ + analytics: + provider: google + property: !ENV GOOGLE_ANALYTICS_KEY + +extra_css: + - stylesheets/extra.css + +nav: + - Home: index.md + - Getting Started: + - getting-started/index.md + - Installation: getting-started/installation.md + - First Time Setup: getting-started/first-time-setup.md + - Quick Start Guide: getting-started/quick-start.md + - User Interface: + - ui/index.md + - Main Window: ui/main-window.md + - Canvas Tools: ui/canvas-tools.md + - 3D Preview: ui/3d-preview.md + - Settings & Preferences: ui/settings.md + - Features: + - features/index.md + - Operations: + - features/operations/index.md + - Contour Cutting: features/operations/contour.md + - Raster Engraving: features/operations/raster.md + - Depth Engraving: features/operations/depth.md + - Shrink Wrap: features/operations/shrink-wrap.md + - Multi-Layer Workflow: features/multi-layer.md + - Camera Integration: features/camera.md + - Holding Tabs: features/holding-tabs.md + - G-code Macros & Hooks: features/macros-hooks.md + - Overscan & Kerf: features/overscan-kerf.md + - Machine Setup: + - machine/index.md + - Machine Profiles: machine/profiles.md + - Device Configuration: machine/device-config.md + - GRBL Settings: machine/grbl-settings.md + - Multiple Lasers: machine/multi-laser.md + - File Formats: + - files/index.md + - Importing Files: files/importing.md + - Supported Formats: files/formats.md + - Exporting G-code: files/exporting.md + - Troubleshooting: + - troubleshooting/index.md + - Connection Issues: troubleshooting/connection.md + - Common Problems: troubleshooting/common.md + - Performance: troubleshooting/performance.md + - Permissions (Snap): troubleshooting/snap-permissions.md + - Reference: + - reference/index.md + - Keyboard Shortcuts: reference/shortcuts.md + - G-code Dialect Support: reference/gcode-dialects.md + - Firmware Compatibility: reference/firmware.md + - Contributing: + - contributing/index.md + - Development Setup: contributing/development.md + - Adding Device Drivers: contributing/drivers.md + +copyright: Copyright © 2024-2025 Rayforge Contributors diff --git a/pixi.lock b/pixi.lock index 7a30049b7..e7613c72f 100644 --- a/pixi.lock +++ b/pixi.lock @@ -38,7 +38,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/freetype-2.14.1-ha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/fribidi-1.0.16-hb03c661_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/g-ir-build-tools-1.84.0-py313hff75e6e_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/g-ir-build-tools-1.84.0-py312h510a0e2_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/g-ir-host-tools-1.84.0-h5654c37_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gdk-pixbuf-2.44.2-h2b0a6b4_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gettext-0.25.1-h3f43e3d_1.conda @@ -47,7 +47,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/giflib-5.2.2-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-2.86.0-he175458_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-tools-2.86.0-hf516916_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/gobject-introspection-1.84.0-py313h07c7e49_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gobject-introspection-1.84.0-py312h74c86ee_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/graphviz-13.1.2-h87b6fe6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gtk3-3.24.43-h0c6a113_5.conda @@ -113,8 +113,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-devel-5.8.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libmatio-1.5.28-h3671a80_3.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.67.0-had1ee68_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpciaccess-0.18-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.50-h421ea60_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/librsvg-2.58.4-he92a37e_3.conda @@ -128,6 +128,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-1.6.0-h9635ea4_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libxkbcommon-1.11.0-he8b52b9_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.13.8-h04c0eec_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda @@ -150,15 +151,576 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.4.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.7-h2b335a9_100_cp313.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.11-h9e4cc4f_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rav1e-0.7.1-h8fae777_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8c095d6_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/svgelements-1.9.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/svt-av1-3.1.2-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_hd72426e_102.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.2.1-pyhe01879c_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/wayland-1.24.0-h3e06ad9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/x265-3.5-h924138e_3.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/xkeyboard-config-2.45-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-compositeproto-0.4.2-hb9d3cd8_1002.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-damageproto-1.2.1-hb9d3cd8_1003.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-glproto-1.4.17-hb9d3cd8_1003.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-inputproto-2.3.2-hb9d3cd8_1003.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-kbproto-1.0.7-hb9d3cd8_1003.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-he73a12e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.12-h4f16b4b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxcomposite-0.4.6-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxcursor-1.2.3-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdamage-1.1.6-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.6-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxfixes-6.0.1-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxi-1.8.2-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxinerama-1.1.5-h5888daf_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrandr-1.5.4-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrender-0.9.12-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxt-1.3.1-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxtst-1.2.5-hb9d3cd8_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxxf86vm-1.1.6-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-presentproto-1.1-hb9d3cd8_1002.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-renderproto-0.11.1-hb9d3cd8_1003.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-xextproto-7.3.0-hb9d3cd8_1004.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-xf86vidmodeproto-2.3.1-hb9d3cd8_1005.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-xineramaproto-1.2.1-hb9d3cd8_1002.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-xorgproto-2024.1-hb9d3cd8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-xproto-7.0.31-hb9d3cd8_1008.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb8e6e7a_2.conda + - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/73/12/2530fb2b08773f717ab2d249ca7a982ac66e32187c62d49e2c86c9bba9b4/aiohttp-3.12.14-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/8c/2b30c12155ad8de0cf641d76a8b396a16d2c36bc6d50b621a62b7c4567c1/build-1.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/a6/90/a64aaacab3b37a17aaedd83e8000142561a29eb262cede42d94a67f7556b/coverage-7.10.7-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/4d/c1/ed30f798587199a64db82ea2867fa01ab3260287ceeb762f5108902061fd/ezdxf-1.3.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/9f/56/13ab06b4f93ca7cac71078fbe37fcea175d3216f31f85c3168a6bbd0bb9a/flake8-7.3.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c0/ca/4bb48a26ed95a1e7eba175535fe5805887682140ee0a0d10a88e1de84208/fonttools-4.60.1-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/8d/db/48421f62a6f77c553575201e89048e97198046b793f4a089c79a6e3268bd/frozenlist-1.7.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/af/65/753a2d8b05daf496f4a9c367fe844e90a1b2cac78e2be2c844200d10cc4c/multidict-6.6.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/39/04/78d2e7402fb479d893953fb78fa7045f7deb635ec095b6b4f0260223091a/numpy-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/68/1f/795e7f4aa2eacc59afa4fb61a2e35e510d06414dd5a802b51a012d691b37/opencv_python-4.12.0.88-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/37/7c/54fd5301ef38505ab235d98827207176a5c9b2aa61939b10a460ca53e123/propcache-0.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/07/4a/42b26390181a7517718600fa7d98b951da20be982a50cd4afb3d46c2e603/pycairo-1.27.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/76/65/cb014acc41cd5bf6bbfa4671c7faffffb9cee01706642c2dec70c5209ac8/pyclipper-1.3.0.post6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/2f/81d580a0fb83baeb066698975cb14a618bdbed7720678566f1b046a95fe8/pyflakes-3.4.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/58/d34e67a79631177e3c08e7d02b5165147f590171f2cae6769502af5f7f7e/pygobject-3.50.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/d1/3f/d9a43ab76ad7a2d6d3a2968513b76760100c33128c6a0d3ac996dfb37c77/pygobject_stubs-2.13.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/92/44/8634af40b0db528b5b37e901c0dc67321354880d251bf8965901d57693a5/PyOpenGL-3.1.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/42/ae/67ddc9674d07c1900b0f094a16d2fa996492ffb25ad974e5af4e53dcad22/PyOpenGL_accelerate-3.1.9-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/10/5e/1aa9a93198c6b64513c9d7752de7422c06402de6600a8767da1524f9570b/pyparsing-3.2.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/83/2cacc506eb322bb31b747bc06ccb82cc9aa03e19ee9c1245e538e49d52be/pypdf-6.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/07/bc/587a445451b253b285629263eb51c2d8e9bcea4fc97826266d186f96f558/pyserial-3.5-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/27/24/c820cf15f87f7b164e83710c1852d4f900d9793961579e5ef64189bc0c10/pyserial_asyncio-0.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/93/2fa34714b7a4ae72f2f8dad66ba17dd9a2c793220719e736dda28b7aec27/pytest_asyncio-1.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5a/cc/06253936f4a7fa2e0f48dfe6d851d9c56df896a9ab09ac019d70b760619c/pytest_mock-3.15.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4c/a2/d8ecd2f7ffa084870ba071a584aac44800a89f3c77b305999be7dc8b7bb3/pyvips-3.0.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/c0/53/eaada1a414c026673eb983f8b4a55fe5eb172725d33d62c1b21f63ff6ca4/scipy-1.15.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/96/24/07a0a4d12d31c49513823a15deea3c735580819eb67af914676df5cb9c8e/vtracer-0.6.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/81/da/72f7caabd94652e6eb7e92ed2d3da818626e70b4f2b15a854ef60bf501ec/websockets-14.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/98/28/3ab7acc5b51f4434b181b0cee8f1f4b77a65919700a355fb3617f9488874/yarl-1.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: ./ + osx-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/adwaita-icon-theme-49.0-unix_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aom-3.9.1-hf036a51_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/atk-1.0-2.38.0-h4bec284_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h500dc9f_8.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.34.5-hf13058a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.8.3-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cairo-1.18.4-h950ec3b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cfitsio-4.6.2-ha7f915d_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/dav1d-1.2.1-h0dc2134_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/epoxy-1.5.10-h8616949_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/expat-2.7.1-h21dd04a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/fftw-3.3.10-nompi_h292e606_110.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/fontconfig-2.15.0-h37eeddb_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/freetype-2.14.1-h694c41f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/fribidi-1.0.16-h8616949_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/g-ir-build-tools-1.84.0-py312hf291c09_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/g-ir-host-tools-1.84.0-h4690c84_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/gdk-pixbuf-2.44.2-h07555a4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/gettext-0.25.1-he52a196_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/gettext-tools-0.25.1-h3184127_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ghostscript-10.06.0-heffb93a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/giflib-5.2.2-h10d778d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/glib-2.86.0-h7f22f8f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/glib-tools-2.86.0-h8650975_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/gobject-introspection-1.84.0-py312h4be7b1d_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/graphite2-1.3.14-h21dd04a_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/graphviz-13.1.2-h42bfd48_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/gtk3-3.24.43-h70b172e_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/gtk4-4.14.1-hb3e4d51_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/gts-0.7.6-h53e17e3_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/harfbuzz-11.5.1-hc5d3ef4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/hdf5-1.14.6-nompi_hc8237f9_103.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/hicolor-icon-theme-0.17-h694c41f_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-75.1-h120a0e1_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/imagemagick-7.1.2_3-gpl_hd161fd0_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/jbig-2.1-h0d85af4_2003.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.3-h37d8d59_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/lcms2-2.17-h72f5680_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/lerc-4.0.0-hcca01a6_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libaec-1.1.4-ha6bc127_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarchive-3.8.1-gpl_h9912a37_100.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libasprintf-0.25.1-h3184127_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libasprintf-devel-0.25.1-h3184127_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libavif16-1.3.0-h1c10324_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlicommon-1.1.0-h1c43f85_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlidec-1.1.0-h1c43f85_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlienc-1.1.0-h1c43f85_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.14.1-h5dec5d8_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-21.1.2-h3d58e20_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libde265-1.0.15-h7728843_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libdeflate-1.24-hcc1b750_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libdicom-1.2.0-h1c43f85_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20250104-pl5321ha958ccf_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-h10d778d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libexif-0.6.21-h0d85af4_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.7.1-h21dd04a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.4.6-h281671d_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libfreetype-2.14.1-h694c41f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libfreetype6-2.14.1-h6912278_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgd-2.3.3-h8555400_11.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgettextpo-0.25.1-h3184127_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgettextpo-devel-0.25.1-h3184127_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran-15.1.0-h5f6db21_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran5-15.1.0-hfa3c126_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgirepository-1.84.0-h40d85bd_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libglib-2.86.0-h7cafd41_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgraphene-1.10.8-h43f7b35_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libheif-1.19.7-gpl_h95ec88c_100.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libhwy-1.3.0-hab838a1_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.18-h57a12c2_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libintl-0.25.1-h3184127_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libintl-devel-0.25.1-h3184127_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libjpeg-turbo-3.1.0-h6e16a3a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libjxl-0.11.1-h3eb2fc3_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.1-hd471939_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-devel-5.8.1-hd471939_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libmatio-1.5.28-heaf9015_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.67.0-h3338091_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libpng-1.6.50-h84aeda2_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/librsvg-2.58.4-h21a6cfa_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.50.4-h39a8b3b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.1-hed3591d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libtiff-4.7.1-haa3b502_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libvips-8.17.2-hc2b6ce7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libwebp-1.6.0-h5442d53_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libwebp-base-1.6.0-hb807250_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxcb-1.17.0-hf1f96e2_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.13.8-he1bc88e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.1-hd23fc13_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-21.1.0-hf4e0ed4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/lz4-c-1.10.0-h240833e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/lzo-2.10-h4132b18_1002.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/nspr-4.37-hbd2c7f0_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/nss-3.116-h2b2a826_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openjpeg-2.5.4-h87e8dc5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openslide-4.0.0-hfa68862_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.5.3-h230baf5_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pango-1.56.4-h6ef8af8_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pcre2-10.46-ha3e7e28_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pixman-0.46.4-ha059160_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pkg-config-0.29.2-hf7e621a_1009.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/poppler-25.07.0-h912db10_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/poppler-data-0.4.12-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pthread-stubs-0.4-h00291cd_1002.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.4.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.12.11-h9ccd52b_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/rav1e-0.7.1-h371c88c_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h7cca4af_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/svgelements-1.9.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/svt-av1-3.1.2-h21dd04a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-hf689a15_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.2.1-pyhe01879c_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/x265-3.5-hbb4e6a2_3.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/xorg-libice-1.1.2-h6e16a3a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/xorg-libsm-1.2.6-h6e16a3a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/xorg-libx11-1.8.12-h217831a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/xorg-libxau-1.0.12-h6e16a3a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/xorg-libxdmcp-1.1.5-h00291cd_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/xorg-libxext-1.3.6-h00291cd_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/xorg-libxrender-0.9.12-h6e16a3a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/xorg-libxt-1.3.1-h6e16a3a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.3.1-hd23fc13_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-h8210216_2.conda + - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0a/b8/a5e8e583e6c8c1056f4b012b50a03c77a669c2e9bf012b7cf33d6bc4b141/aiohttp-3.12.14-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/8c/2b30c12155ad8de0cf641d76a8b396a16d2c36bc6d50b621a62b7c4567c1/build-1.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/13/e4/eb12450f71b542a53972d19117ea5a5cea1cab3ac9e31b0b5d498df1bd5a/coverage-7.10.7-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/33/b7/1bfe7edf249ddd36ddf574a9532658c0f408b45f2a5c2c04a77240d8d60c/ezdxf-1.3.5-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/9f/56/13ab06b4f93ca7cac71078fbe37fcea175d3216f31f85c3168a6bbd0bb9a/flake8-7.3.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ed/fe/7bd094b59c926acf2304d2151354ddbeb74b94812f3dc943c231db09cb41/fonttools-4.60.1-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/4c/9d/02754159955088cb52567337d1113f945b9e444c4960771ea90eb73de8db/frozenlist-1.7.0-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/58/45c3e75deb8855c36bd66cc1658007589662ba584dbf423d01df478dd1c5/multidict-6.6.4-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/43/ec/43628dcf98466e087812142eec6d1c1a6c6bdfdad30a0aa07b872dc01f6f/numpy-2.2.3-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/33/7c/042abe49f58d6ee7e1028eefc3334d98ca69b030e3b567fe245a2b28ea6f/opencv_python-4.12.0.88-cp37-abi3-macosx_13_0_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/af/6e/21293133beb550f9c901bbece755d582bfaf2176bee4774000bd4dd41884/propcache-0.3.2-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/07/4a/42b26390181a7517718600fa7d98b951da20be982a50cd4afb3d46c2e603/pycairo-1.27.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/8e/8e/eb14eadf054494ad81446e21c4ea163b941747610b0eb9051644395f567e/pyclipper-1.3.0.post6-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/2f/81d580a0fb83baeb066698975cb14a618bdbed7720678566f1b046a95fe8/pyflakes-3.4.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/58/d34e67a79631177e3c08e7d02b5165147f590171f2cae6769502af5f7f7e/pygobject-3.50.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/d1/3f/d9a43ab76ad7a2d6d3a2968513b76760100c33128c6a0d3ac996dfb37c77/pygobject_stubs-2.13.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/92/44/8634af40b0db528b5b37e901c0dc67321354880d251bf8965901d57693a5/PyOpenGL-3.1.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9d/9e/a87f972148971c785773dcc792226530ff78840420e34b3cc51b221693a2/pyopengl_accelerate-3.1.9.tar.gz + - pypi: https://files.pythonhosted.org/packages/10/5e/1aa9a93198c6b64513c9d7752de7422c06402de6600a8767da1524f9570b/pyparsing-3.2.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/83/2cacc506eb322bb31b747bc06ccb82cc9aa03e19ee9c1245e538e49d52be/pypdf-6.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/07/bc/587a445451b253b285629263eb51c2d8e9bcea4fc97826266d186f96f558/pyserial-3.5-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/27/24/c820cf15f87f7b164e83710c1852d4f900d9793961579e5ef64189bc0c10/pyserial_asyncio-0.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/93/2fa34714b7a4ae72f2f8dad66ba17dd9a2c793220719e736dda28b7aec27/pytest_asyncio-1.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5a/cc/06253936f4a7fa2e0f48dfe6d851d9c56df896a9ab09ac019d70b760619c/pytest_mock-3.15.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4c/a2/d8ecd2f7ffa084870ba071a584aac44800a89f3c77b305999be7dc8b7bb3/pyvips-3.0.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/4b/5d/3c78815cbab499610f26b5bae6aed33e227225a9fa5290008a733a64f6fc/scipy-1.15.2-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/ec/78/f91da19e1f4769317fe14a6bacb2be9e21b8fa6262dbd7021e2ab33545f8/vtracer-0.6.11-cp312-cp312-macosx_10_12_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/ec/c5/de30e88557e4d70988ed4d2eabd73fd3e1e52456b9f3a4e9564d86353b6d/websockets-14.2-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/67/38/688577a1cb1e656e3971fb66a3492501c5a5df56d99722e57c98249e5b8a/yarl-1.20.1-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: ./ + win-64: + - conda: https://conda.anaconda.org/conda-forge/win-64/_libavif_api-1.3.0-h57928b3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/adwaita-icon-theme-49.0-win_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aom-3.9.1-he0c23c2_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_8.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.8.3-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cairo-1.18.4-h5782bbf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/dav1d-1.2.1-hcfcfb64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/epoxy-1.5.10-hfd05255_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/expat-2.7.1-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/fontconfig-2.15.0-h765892d_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/freetype-2.14.1-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/fribidi-1.0.16-hfd05255_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/g-ir-build-tools-1.84.0-py313h0754440_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/g-ir-host-tools-1.84.0-h85f1578_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/gdk-pixbuf-2.44.2-h1f5b9c4_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/gettext-0.22.5-h5728263_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/gettext-tools-0.22.5-h5a7288d_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/glib-2.86.0-ha3795fc_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/glib-tools-2.86.0-he647baa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/gobject-introspection-1.84.0-py313h276ecff_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/graphite2-1.3.14-hac47afa_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/gtk4-4.14.1-hab1f0e9_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/harfbuzz-11.5.1-h5f2951f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/hicolor-icon-theme-0.17-h57928b3_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/icu-75.1-he0c23c2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.21.3-hdf4eb48_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/lcms2-2.17-hbcf6048_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/lerc-4.0.0-h6470a55_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libasprintf-0.22.5-h5728263_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libasprintf-devel-0.22.5-h5728263_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libavif16-1.3.0-he916da2_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcurl-8.14.1-h88aaa65_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libde265-1.0.15-h91493d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libdeflate-1.24-h76ddb4d_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libdicom-1.2.0-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.7.1-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.4.6-h537db12_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libfreetype-2.14.1-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libfreetype6-2.14.1-hdbac1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libgettextpo-0.22.5-h5728263_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libgettextpo-devel-0.22.5-h5728263_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libgirepository-1.84.0-hbc1daa9_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libglib-2.86.0-h5f26cbf_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libgraphene-1.10.8-h1d85db8_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libheif-1.19.7-gpl_h2684147_100.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libintl-0.22.5-h5728263_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libintl-devel-0.22.5-h5728263_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libjpeg-turbo-3.1.0-h2466b09_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.1-h2466b09_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-h2466b09_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libpng-1.6.50-h7351971_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/librsvg-2.58.4-ha14e162_4.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.50.4-hf5d6505_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libssh2-1.11.1-h9aa295b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libtiff-4.7.1-h550210a_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.0-h06f855e_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.0-ha29bfb0_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openjpeg-2.5.4-h24db6dd_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openslide-4.0.0-h8836043_6.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.5.3-h725018a_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pango-1.56.4-h03d888a_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pcre2-10.46-h3402e2f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pixman-0.46.4-h5112557_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pkg-config-0.29.2-h88c491f_1009.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/poppler-25.07.0-h813ae87_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/poppler-data-0.4.12-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.4.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.13.7-hdf00ec1_100_cp313.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/rav1e-0.7.1-ha073cba_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/svgelements-1.9.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/svt-av1-3.1.2-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h2c6b04d_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.2.1-pyhe01879c_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_31.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_31.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_31.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.44.35208-h38c0c73_31.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/x265-3.5-h2d74725_3.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-hbeecb71_2.conda + - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/66/5f/8427618903343402fdafe2850738f735fd1d9409d2a8f9bcaae5e630d3ba/aiohttp-3.12.14-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/8c/2b30c12155ad8de0cf641d76a8b396a16d2c36bc6d50b621a62b7c4567c1/build-1.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/b1/b1/a75fd25df44eab52d1931e89980d1ada46824c7a3210be0d3c88a44aaa99/coverage-7.10.7-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/38/d5/2c2d63bde4a13396ad8bd8d26a3127030f5b5ce37b4befb0c3cea3a4562a/ezdxf-1.3.5-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/9f/56/13ab06b4f93ca7cac71078fbe37fcea175d3216f31f85c3168a6bbd0bb9a/flake8-7.3.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/75/4d/b022c1577807ce8b31ffe055306ec13a866f2337ecee96e75b24b9b753ea/fonttools-4.60.1-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/35/89/a487a98d94205d85745080a37860ff5744b9820a2c9acbcdd9440bfddf98/frozenlist-1.7.0-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9d/34/746696dffff742e97cd6a23da953e55d0ea51fa601fa2ff387b3edcfaa2c/multidict-6.6.4-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/97/e7/7d55a86719d0de7a6a597949f3febefb1009435b79ba510ff32f05a8c1d7/numpy-2.2.3-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/fa/80/eb88edc2e2b11cd2dd2e56f1c80b5784d11d6e6b7f04a1145df64df40065/opencv_python-4.12.0.88-cp37-abi3-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d3/f5/b369e026b09a26cd77aa88d8fffd69141d2ae00a2abaaf5380d2603f4b7f/propcache-0.3.2-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/9c/e7/92d6e57deee53229bb8b3f7df6d02c503585be7bdd69cb9e54f34aab089b/pycairo-1.27.0-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/d5/19/9ff4551b42f2068686c50c0d199072fa67aee57fc5cf86770cacf71efda3/pyclipper-1.3.0.post6-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/2f/81d580a0fb83baeb066698975cb14a618bdbed7720678566f1b046a95fe8/pyflakes-3.4.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/58/d34e67a79631177e3c08e7d02b5165147f590171f2cae6769502af5f7f7e/pygobject-3.50.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/d1/3f/d9a43ab76ad7a2d6d3a2968513b76760100c33128c6a0d3ac996dfb37c77/pygobject_stubs-2.13.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/92/44/8634af40b0db528b5b37e901c0dc67321354880d251bf8965901d57693a5/PyOpenGL-3.1.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/03/d3/b0b5b4c5404d7269458f4297b2fe86017daed8f29f40f07eb25ee51c902e/PyOpenGL_accelerate-3.1.9-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/10/5e/1aa9a93198c6b64513c9d7752de7422c06402de6600a8767da1524f9570b/pyparsing-3.2.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/83/2cacc506eb322bb31b747bc06ccb82cc9aa03e19ee9c1245e538e49d52be/pypdf-6.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/07/bc/587a445451b253b285629263eb51c2d8e9bcea4fc97826266d186f96f558/pyserial-3.5-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/27/24/c820cf15f87f7b164e83710c1852d4f900d9793961579e5ef64189bc0c10/pyserial_asyncio-0.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/93/2fa34714b7a4ae72f2f8dad66ba17dd9a2c793220719e736dda28b7aec27/pytest_asyncio-1.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5a/cc/06253936f4a7fa2e0f48dfe6d851d9c56df896a9ab09ac019d70b760619c/pytest_mock-3.15.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4c/a2/d8ecd2f7ffa084870ba071a584aac44800a89f3c77b305999be7dc8b7bb3/pyvips-3.0.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/0d/76/77cf2ac1f2a9cc00c073d49e1e16244e389dd88e2490c91d84e1e3e4d126/scipy-1.15.2-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/e8/ad/2c89d6f2858ec8a1ac093144ebe6cfefc9307920ce95ad4ff045bb72b228/vtracer-0.6.11.tar.gz + - pypi: https://files.pythonhosted.org/packages/14/13/8b7fc4cb551b9cfd9890f0fd66e53c18a06240319915533b033a56a3d520/websockets-14.2-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/ba/ba/39b1ecbf51620b40ab402b0fc817f0ff750f6d92712b44689c2c215be89d/yarl-1.20.1-cp313-cp313-win_amd64.whl + - pypi: ./ + docs: + channels: + - url: https://conda.anaconda.org/conda-forge/ + - url: https://conda.anaconda.org/bioconda/ + - url: https://conda.anaconda.org/msys2/ + - url: https://conda.anaconda.org/coastline/ + indexes: + - https://pypi.org/simple + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/adwaita-icon-theme-49.0-unix_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aom-3.9.1-hac33072_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/at-spi2-atk-2.38.0-h0630a04_3.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/at-spi2-core-2.40.3-h0630a04_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/atk-1.0-2.38.0-h04ea711_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.5-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.8.3-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.18.4-h3394656_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cfitsio-4.6.2-ha0b56bc_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/dav1d-1.2.1-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/dbus-1.16.2-h3c4dab8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/epoxy-1.5.10-hb03c661_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.7.1-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/fftw-3.3.10-nompi_hf1063bd_110.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.15.0-h7e30c49_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/freetype-2.14.1-ha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/fribidi-1.0.16-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/g-ir-build-tools-1.84.0-py312h510a0e2_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/g-ir-host-tools-1.84.0-h5654c37_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gdk-pixbuf-2.44.2-h2b0a6b4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gettext-0.25.1-h3f43e3d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gettext-tools-0.25.1-h3f43e3d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ghostscript-10.06.0-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/giflib-5.2.2-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-2.86.0-he175458_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-tools-2.86.0-hf516916_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gobject-introspection-1.84.0-py312h74c86ee_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/graphviz-13.1.2-h87b6fe6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gtk3-3.24.43-h0c6a113_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gtk4-4.14.1-h96af507_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gts-0.7.6-h977cf35_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-11.5.1-h15599e2_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/hdf5-1.14.6-nompi_h6e4c0c1_103.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/hicolor-icon-theme-0.17-ha770c72_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-75.1-he02047a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/imagemagick-7.1.2_3-gpl_hacdf01b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/jbig-2.1-h7f98852_2003.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.3-h659f571_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.17-h717163a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.44-ha97dd6f_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.0.0-h0aef613_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libaec-1.1.4-h3f801dc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarchive-3.8.1-gpl_h98cc613_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libasprintf-0.25.1-h3f43e3d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libasprintf-devel-0.25.1-h3f43e3d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libavif16-1.3.0-h6395336_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.1.0-hb03c661_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.1.0-hb03c661_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.1.0-hb03c661_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-hb8b1518_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.14.1-h332b0f4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libde265-1.0.15-h00ab1b0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.24-h86f0d12_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libdicom-1.2.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libdrm-2.4.125-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-1.7.0-ha4b6fd6_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-devel-1.7.0-ha4b6fd6_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexif-0.6.21-h7f98852_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.1-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.6-h2dba641_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.1-ha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.1-h73754d4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.1.0-h767d61c_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.1.0-h69a702a_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgd-2.3.3-h6f5c62b_11.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgettextpo-0.25.1-h3f43e3d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgettextpo-devel-0.25.1-h3f43e3d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.1.0-h69a702a_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-ng-15.1.0-h69a702a_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.1.0-hcea5267_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgirepository-1.84.0-h61e2d6e_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgl-1.7.0-ha4b6fd6_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgl-devel-1.7.0-ha4b6fd6_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.86.0-h1fed272_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libglvnd-1.7.0-ha4b6fd6_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-1.7.0-ha4b6fd6_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-devel-1.7.0-ha4b6fd6_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.1.0-h767d61c_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgraphene-1.10.8-hc02c970_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libheif-1.19.7-gpl_hc18d805_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libhwy-1.3.0-h4c17acf_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.0-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libjxl-0.11.1-h6cb5226_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-devel-5.8.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmatio-1.5.28-h3671a80_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.67.0-had1ee68_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpciaccess-0.18-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.50-h421ea60_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/librsvg-2.58.4-he92a37e_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.50.4-h0c1763c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.1.0-h8f9b012_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.1.0-h4852527_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h8261f1e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.2-he9a06e4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libvips-8.17.2-h4d1fd58_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-1.6.0-h9635ea4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxkbcommon-1.11.0-he8b52b9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.13.8-h04c0eec_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lzo-2.10-h280c20c_1002.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/nspr-4.37-h29cc59b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/nss-3.116-h445c969_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openslide-4.0.0-hacc1dc6_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.5.3-h26f9b46_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pango-1.56.4-hadf4263_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.46-h1321c63_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.46.4-h54a6638_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pkg-config-0.29.2-h4bc722e_1009.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/poppler-25.07.0-h13eef12_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/poppler-data-0.4.12-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.11-h9e4cc4f_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rav1e-0.7.1-h8fae777_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8c095d6_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/svgelements-1.9.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/svt-av1-3.1.2-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_hd72426e_102.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.2.1-pyhe01879c_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/wayland-1.24.0-h3e06ad9_0.conda @@ -193,50 +755,77 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-xineramaproto-1.2.1-hb9d3cd8_1002.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-xorgproto-2024.1-hb9d3cd8_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-xproto-7.0.31-hb9d3cd8_1008.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb8e6e7a_2.conda - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/30/a8/81e237f89a32029f9b4a805af6dffc378f8459c7b9942712c809ff9e76e5/aiohttp-3.12.14-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/73/12/2530fb2b08773f717ab2d249ca7a982ac66e32187c62d49e2c86c9bba9b4/aiohttp-3.12.14-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9d/12/4f345407259dd60a0997107758ba3f221cf89a9b5a0f8ed5b961aef97253/backrefs-5.9-py312-none-any.whl - pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cb/8c/2b30c12155ad8de0cf641d76a8b396a16d2c36bc6d50b621a62b7c4567c1/build-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/a2/77/8c6d22bf61921a59bce5471c2f1f7ac30cd4ac50aadde72b8c48d5727902/coverage-7.10.7-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/2e/5a/31e1d7874ee1b6173e57d7d85b33d65fa82b388824ab396f9730cfc16f54/ezdxf-1.3.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/9f/56/13ab06b4f93ca7cac71078fbe37fcea175d3216f31f85c3168a6bbd0bb9a/flake8-7.3.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2d/8b/371ab3cec97ee3fe1126b3406b7abd60c8fec8975fd79a3c75cdea0c3d83/fonttools-4.60.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/72/31/bc8c5c99c7818293458fe745dab4fd5730ff49697ccc82b554eb69f16a24/frozenlist-1.7.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/93/d8/ba13451aa6b745c49536e87b6bf8f629b950e84bd0e8308f7dc6883b67e2/cairocffi-1.7.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/67/48/816bd4aaae93dbf9e408c58598bc32f4a8c65f4b86ab560864cb3ee60adb/cairosvg-2.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/16/ab/0233c3231af734f5dfcf0844aa9582d5a1466c985bbed6cedab85af9bfe3/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/db/d3/9dcc0f5797f070ec8edf30fbadfb200e71d9db6b84d211e3b2085a7589a0/click-8.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0f/e7/aa315e6a749d9b96c2504a1ba0ba031ba2d0517e972ce22682e3fccecb09/cssselect2-0.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4d/c1/ed30f798587199a64db82ea2867fa01ab3260287ceeb762f5108902061fd/ezdxf-1.3.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/c0/ca/4bb48a26ed95a1e7eba175535fe5805887682140ee0a0d10a88e1de84208/fonttools-4.60.1-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/8d/db/48421f62a6f77c553575201e89048e97198046b793f4a089c79a6e3268bd/frozenlist-1.7.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/80/e5/5e22c5bf96a64bdd43518b1834c6d95a4922cc2066b7d8e467dae9b6cee6/multidict-6.6.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/e4/43/619c2c7a0665aafc80efca465ddb1f260287266bdbdce517396f2f145d49/numpy-2.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/a4/ed/1f1afb2e9e7f38a545d628f864d562a5ae64fe6f7a10e28ffb9b185b4e89/importlib_resources-6.5.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/70/ae/44c4a6a4cbb496d93c6257954260fe3a6e91b7bed2240e5dad2a717f5111/markdown-3.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/1a/31b7cd6e4e7a02df4e076162e9783620777592bea9e4bb036389389af99d/mike-2.1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9f/d4/029f984e8d3f3b6b726bd33cafc473b75e9e44c0f7e80a5b29abc466bdea/mkdocs_get_deps-0.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/cf/e9a0ce9da269746906fdc595c030f6df66793dad1487abd1699af2ba44f1/mkdocs_glightbox-0.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/4f/98681c2030375fe9b057dbfb9008b68f46c07dddf583f4df09bf8075e37f/mkdocs_material-9.6.21-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/af/65/753a2d8b05daf496f4a9c367fe844e90a1b2cac78e2be2c844200d10cc4c/multidict-6.6.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/39/04/78d2e7402fb479d893953fb78fa7045f7deb635ec095b6b4f0260223091a/numpy-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/68/1f/795e7f4aa2eacc59afa4fb61a2e35e510d06414dd5a802b51a012d691b37/opencv_python-4.12.0.88-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e4/c9/06dd4a38974e24f932ff5f98ea3c546ce3f8c995d3f0985f8e5ba48bba19/pillow-11.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/af/81/b324c44ae60c56ef12007105f1460d5c304b0626ab0cc6b07c8f2a9aa0b8/propcache-0.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/37/7c/54fd5301ef38505ab235d98827207176a5c9b2aa61939b10a460ca53e123/propcache-0.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/07/4a/42b26390181a7517718600fa7d98b951da20be982a50cd4afb3d46c2e603/pycairo-1.27.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/31/10/c0bf140bee2844e2c0617fdcc8a4e8daf98e71710046b06034e6f1963404/pyclipper-1.3.0.post6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/76/65/cb014acc41cd5bf6bbfa4671c7faffffb9cee01706642c2dec70c5209ac8/pyclipper-1.3.0.post6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/2f/81d580a0fb83baeb066698975cb14a618bdbed7720678566f1b046a95fe8/pyflakes-3.4.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2b/58/d34e67a79631177e3c08e7d02b5165147f590171f2cae6769502af5f7f7e/pygobject-3.50.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/d1/3f/d9a43ab76ad7a2d6d3a2968513b76760100c33128c6a0d3ac996dfb37c77/pygobject_stubs-2.13.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/e4/06/43084e6cbd4b3bc0e80f6be743b2e79fbc6eed8de9ad8c629939fa55d972/pymdown_extensions-10.16.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/92/44/8634af40b0db528b5b37e901c0dc67321354880d251bf8965901d57693a5/PyOpenGL-3.1.9-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6a/95/22c07ec2414928ddb50eb0e35d6cd6343ffef6ad74f42e86fefbaaa6b04e/PyOpenGL_accelerate-3.1.9-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/42/ae/67ddc9674d07c1900b0f094a16d2fa996492ffb25ad974e5af4e53dcad22/PyOpenGL_accelerate-3.1.9-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/10/5e/1aa9a93198c6b64513c9d7752de7422c06402de6600a8767da1524f9570b/pyparsing-3.2.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2c/83/2cacc506eb322bb31b747bc06ccb82cc9aa03e19ee9c1245e538e49d52be/pypdf-6.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/07/bc/587a445451b253b285629263eb51c2d8e9bcea4fc97826266d186f96f558/pyserial-3.5-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/27/24/c820cf15f87f7b164e83710c1852d4f900d9793961579e5ef64189bc0c10/pyserial_asyncio-0.6-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/04/93/2fa34714b7a4ae72f2f8dad66ba17dd9a2c793220719e736dda28b7aec27/pytest_asyncio-1.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/5a/cc/06253936f4a7fa2e0f48dfe6d851d9c56df896a9ab09ac019d70b760619c/pytest_mock-3.15.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/4c/a2/d8ecd2f7ffa084870ba071a584aac44800a89f3c77b305999be7dc8b7bb3/pyvips-3.0.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/03/5a/fc34bf1aa14dc7c0e701691fa8685f3faec80e57d816615e3625f28feb43/scipy-1.15.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/e8/ad/2c89d6f2858ec8a1ac093144ebe6cfefc9307920ce95ad4ff045bb72b228/vtracer-0.6.11.tar.gz - - pypi: https://files.pythonhosted.org/packages/2c/3c/bf9b2c396ed86a0b4a92ff4cdaee09753d3ee389be738e92b9bbd0330b64/websockets-14.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/af/44/46407d7f7a56e9a85a4c207724c9f2c545c060380718eea9088f222ba697/yarl-1.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c0/53/eaada1a414c026673eb983f8b4a55fe5eb172725d33d62c1b21f63ff6ca4/scipy-1.15.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/36/25/64c60da9aec81f2992355b0a3ce00ea1ed99e6f5499868016d6972bd4948/selectolax-0.3.29-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/96/24/07a0a4d12d31c49513823a15deea3c735580819eb67af914676df5cb9c8e/vtracer-0.6.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/da/72f7caabd94652e6eb7e92ed2d3da818626e70b4f2b15a854ef60bf501ec/websockets-14.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/98/28/3ab7acc5b51f4434b181b0cee8f1f4b77a65919700a355fb3617f9488874/yarl-1.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: ./ osx-64: - conda: https://conda.anaconda.org/conda-forge/noarch/adwaita-icon-theme-49.0-unix_0.conda @@ -250,7 +839,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/dav1d-1.2.1-h0dc2134_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/epoxy-1.5.10-h8616949_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/expat-2.7.1-h21dd04a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/fftw-3.3.10-nompi_h292e606_110.conda - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 @@ -262,7 +850,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/freetype-2.14.1-h694c41f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/fribidi-1.0.16-h8616949_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/g-ir-build-tools-1.84.0-py313h75cad1c_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/g-ir-build-tools-1.84.0-py312hf291c09_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/g-ir-host-tools-1.84.0-h4690c84_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gdk-pixbuf-2.44.2-h07555a4_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gettext-0.25.1-he52a196_1.conda @@ -271,7 +859,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/giflib-5.2.2-h10d778d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/glib-2.86.0-h7f22f8f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/glib-tools-2.86.0-h8650975_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/gobject-introspection-1.84.0-py313hdd0212b_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/gobject-introspection-1.84.0-py312h4be7b1d_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/graphite2-1.3.14-h21dd04a_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/graphviz-13.1.2-h42bfd48_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gtk3-3.24.43-h70b172e_5.conda @@ -282,7 +870,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/hicolor-icon-theme-0.17-h694c41f_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-75.1-h120a0e1_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/imagemagick-7.1.2_3-gpl_hd161fd0_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/jbig-2.1-h0d85af4_2003.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.3-h37d8d59_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/lcms2-2.17-h72f5680_0.conda @@ -325,7 +913,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.1-hd471939_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-devel-5.8.1-hd471939_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libmatio-1.5.28-heaf9015_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-h6e16a3a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.67.0-h3338091_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libpng-1.6.50-h84aeda2_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/librsvg-2.58.4-h21a6cfa_3.conda @@ -352,21 +939,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/pcre2-10.46-ha3e7e28_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pixman-0.46.4-ha059160_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pkg-config-0.29.2-hf7e621a_1009.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/poppler-25.07.0-h912db10_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/poppler-data-0.4.12-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pthread-stubs-0.4-h00291cd_1002.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.4.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.13.7-h5eba815_100_cp313.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.12.11-h9ccd52b_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/rav1e-0.7.1-h371c88c_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h7cca4af_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/svgelements-1.9.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/svt-av1-3.1.2-h21dd04a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-hf689a15_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.2.1-pyhe01879c_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/x265-3.5-hbb4e6a2_3.tar.bz2 @@ -378,34 +962,54 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/xorg-libxext-1.3.6-h00291cd_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/xorg-libxrender-0.9.12-h6e16a3a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/xorg-libxt-1.3.1-h6e16a3a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.3.1-hd23fc13_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-h8210216_2.conda - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8d/e7/f73206afa33100804f790b71092888f47df65fd9a4cd0e6800d7c6826441/aiohttp-3.12.14-cp313-cp313-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/0a/b8/a5e8e583e6c8c1056f4b012b50a03c77a669c2e9bf012b7cf33d6bc4b141/aiohttp-3.12.14-cp312-cp312-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9d/12/4f345407259dd60a0997107758ba3f221cf89a9b5a0f8ed5b961aef97253/backrefs-5.9-py312-none-any.whl - pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cb/8c/2b30c12155ad8de0cf641d76a8b396a16d2c36bc6d50b621a62b7c4567c1/build-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/9a/94/b765c1abcb613d103b64fcf10395f54d69b0ef8be6a0dd9c524384892cc7/coverage-7.10.7-cp313-cp313-macosx_10_13_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/7a/5d/49b2767d2161f96665a7aef2f9c406df7399e4e11be0dcd917c0e196d479/ezdxf-1.3.5-cp313-cp313-macosx_10_13_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/9f/56/13ab06b4f93ca7cac71078fbe37fcea175d3216f31f85c3168a6bbd0bb9a/flake8-7.3.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/d6/8a/de9cc0540f542963ba5e8f3a1f6ad48fa211badc3177783b9d5cadf79b5d/fonttools-4.60.1-cp313-cp313-macosx_10_13_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/83/2e/5b70b6a3325363293fe5fc3ae74cdcbc3e996c2a11dde2fd9f1fb0776d19/frozenlist-1.7.0-cp313-cp313-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/93/d8/ba13451aa6b745c49536e87b6bf8f629b950e84bd0e8308f7dc6883b67e2/cairocffi-1.7.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/67/48/816bd4aaae93dbf9e408c58598bc32f4a8c65f4b86ab560864cb3ee60adb/cairosvg-2.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/e9/5e/14c94999e418d9b87682734589404a25854d5f5d0408df68bc15b6ff54bb/charset_normalizer-3.4.3-cp312-cp312-macosx_10_13_universal2.whl + - pypi: https://files.pythonhosted.org/packages/db/d3/9dcc0f5797f070ec8edf30fbadfb200e71d9db6b84d211e3b2085a7589a0/click-8.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0f/e7/aa315e6a749d9b96c2504a1ba0ba031ba2d0517e972ce22682e3fccecb09/cssselect2-0.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/b7/1bfe7edf249ddd36ddf574a9532658c0f408b45f2a5c2c04a77240d8d60c/ezdxf-1.3.5-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/ed/fe/7bd094b59c926acf2304d2151354ddbeb74b94812f3dc943c231db09cb41/fonttools-4.60.1-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/4c/9d/02754159955088cb52567337d1113f945b9e444c4960771ea90eb73de8db/frozenlist-1.7.0-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/4c/aa/8b6f548d839b6c13887253af4e29c939af22a18591bfb5d0ee6f1931dae8/multidict-6.6.4-cp313-cp313-macosx_10_13_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/0e/8b/88b98ed534d6a03ba8cddb316950fe80842885709b58501233c29dfa24a9/numpy-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/a4/ed/1f1afb2e9e7f38a545d628f864d562a5ae64fe6f7a10e28ffb9b185b4e89/importlib_resources-6.5.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/70/ae/44c4a6a4cbb496d93c6257954260fe3a6e91b7bed2240e5dad2a717f5111/markdown-3.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/1a/31b7cd6e4e7a02df4e076162e9783620777592bea9e4bb036389389af99d/mike-2.1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9f/d4/029f984e8d3f3b6b726bd33cafc473b75e9e44c0f7e80a5b29abc466bdea/mkdocs_get_deps-0.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/cf/e9a0ce9da269746906fdc595c030f6df66793dad1487abd1699af2ba44f1/mkdocs_glightbox-0.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/4f/98681c2030375fe9b057dbfb9008b68f46c07dddf583f4df09bf8075e37f/mkdocs_material-9.6.21-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/58/45c3e75deb8855c36bd66cc1658007589662ba584dbf423d01df478dd1c5/multidict-6.6.4-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/43/ec/43628dcf98466e087812142eec6d1c1a6c6bdfdad30a0aa07b872dc01f6f/numpy-2.2.3-cp312-cp312-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/33/7c/042abe49f58d6ee7e1028eefc3334d98ca69b030e3b567fe245a2b28ea6f/opencv_python-4.12.0.88-cp37-abi3-macosx_13_0_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/40/fe/1bc9b3ee13f68487a99ac9529968035cca2f0a51ec36892060edcc51d06a/pillow-11.3.0-cp312-cp312-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/61/99/d606cb7986b60d89c36de8a85d58764323b3a5ff07770a99d8e993b3fa73/propcache-0.3.2-cp313-cp313-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/af/6e/21293133beb550f9c901bbece755d582bfaf2176bee4774000bd4dd41884/propcache-0.3.2-cp312-cp312-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/07/4a/42b26390181a7517718600fa7d98b951da20be982a50cd4afb3d46c2e603/pycairo-1.27.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/0b/db/35843050a3dd7586781497a21ca6c8d48111afb66061cb40c3d3c288596d/pyclipper-1.3.0.post6-cp313-cp313-macosx_10_13_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/8e/eb14eadf054494ad81446e21c4ea163b941747610b0eb9051644395f567e/pyclipper-1.3.0.post6-cp312-cp312-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/2f/81d580a0fb83baeb066698975cb14a618bdbed7720678566f1b046a95fe8/pyflakes-3.4.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2b/58/d34e67a79631177e3c08e7d02b5165147f590171f2cae6769502af5f7f7e/pygobject-3.50.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/d1/3f/d9a43ab76ad7a2d6d3a2968513b76760100c33128c6a0d3ac996dfb37c77/pygobject_stubs-2.13.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/e4/06/43084e6cbd4b3bc0e80f6be743b2e79fbc6eed8de9ad8c629939fa55d972/pymdown_extensions-10.16.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/92/44/8634af40b0db528b5b37e901c0dc67321354880d251bf8965901d57693a5/PyOpenGL-3.1.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9d/9e/a87f972148971c785773dcc792226530ff78840420e34b3cc51b221693a2/pyopengl_accelerate-3.1.9.tar.gz - pypi: https://files.pythonhosted.org/packages/10/5e/1aa9a93198c6b64513c9d7752de7422c06402de6600a8767da1524f9570b/pyparsing-3.2.5-py3-none-any.whl @@ -413,15 +1017,22 @@ environments: - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/07/bc/587a445451b253b285629263eb51c2d8e9bcea4fc97826266d186f96f558/pyserial-3.5-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/27/24/c820cf15f87f7b164e83710c1852d4f900d9793961579e5ef64189bc0c10/pyserial_asyncio-0.6-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/04/93/2fa34714b7a4ae72f2f8dad66ba17dd9a2c793220719e736dda28b7aec27/pytest_asyncio-1.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/5a/cc/06253936f4a7fa2e0f48dfe6d851d9c56df896a9ab09ac019d70b760619c/pytest_mock-3.15.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/4c/a2/d8ecd2f7ffa084870ba071a584aac44800a89f3c77b305999be7dc8b7bb3/pyvips-3.0.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/53/40/09319f6e0f276ea2754196185f95cd191cb852288440ce035d5c3a931ea2/scipy-1.15.2-cp313-cp313-macosx_10_13_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/e8/ad/2c89d6f2858ec8a1ac093144ebe6cfefc9307920ce95ad4ff045bb72b228/vtracer-0.6.11.tar.gz - - pypi: https://files.pythonhosted.org/packages/8e/b7/7484905215627909d9a79ae07070057afe477433fdacb59bf608ce86365a/websockets-14.2-cp313-cp313-macosx_10_13_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/b2/27/584394e1cb76fb771371770eccad35de400e7b434ce3142c2dd27392c968/yarl-1.20.1-cp313-cp313-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4b/5d/3c78815cbab499610f26b5bae6aed33e227225a9fa5290008a733a64f6fc/scipy-1.15.2-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b8/46/2dcae03a94f80f3e0d339c149de8110b5abe1230668b015fd338d9e71a27/selectolax-0.3.29-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/78/f91da19e1f4769317fe14a6bacb2be9e21b8fa6262dbd7021e2ab33545f8/vtracer-0.6.11-cp312-cp312-macosx_10_12_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/12/87/48361531f70b1f87928b045df868a9fd4e253d9ae087fa4cf3f7113be363/watchdog-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/c5/de30e88557e4d70988ed4d2eabd73fd3e1e52456b9f3a4e9564d86353b6d/websockets-14.2-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/67/38/688577a1cb1e656e3971fb66a3492501c5a5df56d99722e57c98249e5b8a/yarl-1.20.1-cp312-cp312-macosx_10_13_x86_64.whl - pypi: ./ win-64: - conda: https://conda.anaconda.org/conda-forge/win-64/_libavif_api-1.3.0-h57928b3_2.conda @@ -433,7 +1044,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/dav1d-1.2.1-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/epoxy-1.5.10-hfd05255_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/expat-2.7.1-hac47afa_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 @@ -457,7 +1067,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/harfbuzz-11.5.1-h5f2951f_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/hicolor-icon-theme-0.17-h57928b3_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/icu-75.1-he0c23c2_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.21.3-hdf4eb48_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/lcms2-2.17-hbcf6048_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/lerc-4.0.0-h6470a55_1.conda @@ -500,11 +1110,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/pcre2-10.46-h3402e2f_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/pixman-0.46.4-h5112557_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/pkg-config-0.29.2-h88c491f_1009.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/poppler-25.07.0-h813ae87_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/poppler-data-0.4.12-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.4.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.13.7-hdf00ec1_100_cp313.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://conda.anaconda.org/conda-forge/win-64/rav1e-0.7.1-ha073cba_3.conda @@ -512,7 +1120,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/svgelements-1.9.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/svt-av1-3.1.2-hac47afa_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h2c6b04d_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.2.1-pyhe01879c_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda @@ -521,33 +1128,53 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_31.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.44.35208-h38c0c73_31.conda - conda: https://conda.anaconda.org/conda-forge/win-64/x265-3.5-h2d74725_3.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-hbeecb71_2.conda - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/66/5f/8427618903343402fdafe2850738f735fd1d9409d2a8f9bcaae5e630d3ba/aiohttp-3.12.14-cp313-cp313-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/10/bf/fa31834dc27a7f05e5290eae47c82690edc3a7b37d58f7fb35a1bdbf355b/backrefs-5.9-py313-none-any.whl - pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cb/8c/2b30c12155ad8de0cf641d76a8b396a16d2c36bc6d50b621a62b7c4567c1/build-1.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/93/d8/ba13451aa6b745c49536e87b6bf8f629b950e84bd0e8308f7dc6883b67e2/cairocffi-1.7.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/67/48/816bd4aaae93dbf9e408c58598bc32f4a8c65f4b86ab560864cb3ee60adb/cairosvg-2.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/b1/b1/a75fd25df44eab52d1931e89980d1ada46824c7a3210be0d3c88a44aaa99/coverage-7.10.7-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/9a/8f/ae790790c7b64f925e5c953b924aaa42a243fb778fed9e41f147b2a5715a/charset_normalizer-3.4.3-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/db/d3/9dcc0f5797f070ec8edf30fbadfb200e71d9db6b84d211e3b2085a7589a0/click-8.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0f/e7/aa315e6a749d9b96c2504a1ba0ba031ba2d0517e972ce22682e3fccecb09/cssselect2-0.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/d5/2c2d63bde4a13396ad8bd8d26a3127030f5b5ce37b4befb0c3cea3a4562a/ezdxf-1.3.5-cp313-cp313-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/9f/56/13ab06b4f93ca7cac71078fbe37fcea175d3216f31f85c3168a6bbd0bb9a/flake8-7.3.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/75/4d/b022c1577807ce8b31ffe055306ec13a866f2337ecee96e75b24b9b753ea/fonttools-4.60.1-cp313-cp313-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/35/89/a487a98d94205d85745080a37860ff5744b9820a2c9acbcdd9440bfddf98/frozenlist-1.7.0-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/ed/1f1afb2e9e7f38a545d628f864d562a5ae64fe6f7a10e28ffb9b185b4e89/importlib_resources-6.5.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/70/ae/44c4a6a4cbb496d93c6257954260fe3a6e91b7bed2240e5dad2a717f5111/markdown-3.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/1a/31b7cd6e4e7a02df4e076162e9783620777592bea9e4bb036389389af99d/mike-2.1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9f/d4/029f984e8d3f3b6b726bd33cafc473b75e9e44c0f7e80a5b29abc466bdea/mkdocs_get_deps-0.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/cf/e9a0ce9da269746906fdc595c030f6df66793dad1487abd1699af2ba44f1/mkdocs_glightbox-0.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/4f/98681c2030375fe9b057dbfb9008b68f46c07dddf583f4df09bf8075e37f/mkdocs_material-9.6.21-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9d/34/746696dffff742e97cd6a23da953e55d0ea51fa601fa2ff387b3edcfaa2c/multidict-6.6.4-cp313-cp313-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/97/e7/7d55a86719d0de7a6a597949f3febefb1009435b79ba510ff32f05a8c1d7/numpy-2.2.3-cp313-cp313-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/fa/80/eb88edc2e2b11cd2dd2e56f1c80b5784d11d6e6b7f04a1145df64df40065/opencv_python-4.12.0.88-cp37-abi3-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/23/85/397c73524e0cd212067e0c969aa245b01d50183439550d24d9f55781b776/pillow-11.3.0-cp313-cp313-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d3/f5/b369e026b09a26cd77aa88d8fffd69141d2ae00a2abaaf5380d2603f4b7f/propcache-0.3.2-cp313-cp313-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/9c/e7/92d6e57deee53229bb8b3f7df6d02c503585be7bdd69cb9e54f34aab089b/pycairo-1.27.0-cp313-cp313-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/d5/19/9ff4551b42f2068686c50c0d199072fa67aee57fc5cf86770cacf71efda3/pyclipper-1.3.0.post6-cp313-cp313-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/2f/81d580a0fb83baeb066698975cb14a618bdbed7720678566f1b046a95fe8/pyflakes-3.4.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2b/58/d34e67a79631177e3c08e7d02b5165147f590171f2cae6769502af5f7f7e/pygobject-3.50.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/d1/3f/d9a43ab76ad7a2d6d3a2968513b76760100c33128c6a0d3ac996dfb37c77/pygobject_stubs-2.13.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/e4/06/43084e6cbd4b3bc0e80f6be743b2e79fbc6eed8de9ad8c629939fa55d972/pymdown_extensions-10.16.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/92/44/8634af40b0db528b5b37e901c0dc67321354880d251bf8965901d57693a5/PyOpenGL-3.1.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/03/d3/b0b5b4c5404d7269458f4297b2fe86017daed8f29f40f07eb25ee51c902e/PyOpenGL_accelerate-3.1.9-cp313-cp313-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/10/5e/1aa9a93198c6b64513c9d7752de7422c06402de6600a8767da1524f9570b/pyparsing-3.2.5-py3-none-any.whl @@ -555,13 +1182,20 @@ environments: - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/07/bc/587a445451b253b285629263eb51c2d8e9bcea4fc97826266d186f96f558/pyserial-3.5-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/27/24/c820cf15f87f7b164e83710c1852d4f900d9793961579e5ef64189bc0c10/pyserial_asyncio-0.6-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/04/93/2fa34714b7a4ae72f2f8dad66ba17dd9a2c793220719e736dda28b7aec27/pytest_asyncio-1.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/5a/cc/06253936f4a7fa2e0f48dfe6d851d9c56df896a9ab09ac019d70b760619c/pytest_mock-3.15.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/4c/a2/d8ecd2f7ffa084870ba071a584aac44800a89f3c77b305999be7dc8b7bb3/pyvips-3.0.0.tar.gz - pypi: https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0d/76/77cf2ac1f2a9cc00c073d49e1e16244e389dd88e2490c91d84e1e3e4d126/scipy-1.15.2-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/0e/17/5a3951da22a4ad8f959088ddc370c68b28dad03190d91fcd137a52410fb9/selectolax-0.3.29-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e8/ad/2c89d6f2858ec8a1ac093144ebe6cfefc9307920ce95ad4ff045bb72b228/vtracer-0.6.11.tar.gz + - pypi: https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/14/13/8b7fc4cb551b9cfd9890f0fd66e53c18a06240319915533b033a56a3d520/websockets-14.2-cp313-cp313-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/ba/ba/39b1ecbf51620b40ab402b0fc817f0ff750f6d92712b44689c2c215be89d/yarl-1.20.1-cp313-cp313-win_amd64.whl - pypi: ./ @@ -604,7 +1238,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/freetype-2.14.1-ha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/fribidi-1.0.16-hb03c661_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/g-ir-build-tools-1.84.0-py313hff75e6e_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/g-ir-build-tools-1.84.0-py312h510a0e2_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/g-ir-host-tools-1.84.0-h5654c37_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gdk-pixbuf-2.44.2-h2b0a6b4_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gettext-0.25.1-h3f43e3d_1.conda @@ -613,7 +1247,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/giflib-5.2.2-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-2.86.0-he175458_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-tools-2.86.0-hf516916_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/gobject-introspection-1.84.0-py313h07c7e49_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gobject-introspection-1.84.0-py312h74c86ee_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/graphviz-13.1.2-h87b6fe6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gtk3-3.24.43-h0c6a113_5.conda @@ -680,8 +1314,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-devel-5.8.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libmatio-1.5.28-h3671a80_3.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.67.0-had1ee68_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpciaccess-0.18-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.50-h421ea60_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/librsvg-2.58.4-he92a37e_3.conda @@ -695,6 +1329,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-1.6.0-h9635ea4_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libxkbcommon-1.11.0-he8b52b9_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.13.8-h04c0eec_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda @@ -716,11 +1351,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/poppler-data-0.4.12-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/pyinstaller-6.16.0-py313h2ed12c8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyinstaller-6.16.0-py312hdd98396_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyinstaller-hooks-contrib-2025.9-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.4.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.7-h2b335a9_100_cp313.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.11-h9e4cc4f_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rav1e-0.7.1-h8fae777_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8c095d6_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda @@ -766,33 +1401,33 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb8e6e7a_2.conda - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/30/a8/81e237f89a32029f9b4a805af6dffc378f8459c7b9942712c809ff9e76e5/aiohttp-3.12.14-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/73/12/2530fb2b08773f717ab2d249ca7a982ac66e32187c62d49e2c86c9bba9b4/aiohttp-3.12.14-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cb/8c/2b30c12155ad8de0cf641d76a8b396a16d2c36bc6d50b621a62b7c4567c1/build-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/a2/77/8c6d22bf61921a59bce5471c2f1f7ac30cd4ac50aadde72b8c48d5727902/coverage-7.10.7-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/2e/5a/31e1d7874ee1b6173e57d7d85b33d65fa82b388824ab396f9730cfc16f54/ezdxf-1.3.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/a6/90/a64aaacab3b37a17aaedd83e8000142561a29eb262cede42d94a67f7556b/coverage-7.10.7-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/4d/c1/ed30f798587199a64db82ea2867fa01ab3260287ceeb762f5108902061fd/ezdxf-1.3.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/9f/56/13ab06b4f93ca7cac71078fbe37fcea175d3216f31f85c3168a6bbd0bb9a/flake8-7.3.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2d/8b/371ab3cec97ee3fe1126b3406b7abd60c8fec8975fd79a3c75cdea0c3d83/fonttools-4.60.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/72/31/bc8c5c99c7818293458fe745dab4fd5730ff49697ccc82b554eb69f16a24/frozenlist-1.7.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/c0/ca/4bb48a26ed95a1e7eba175535fe5805887682140ee0a0d10a88e1de84208/fonttools-4.60.1-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/8d/db/48421f62a6f77c553575201e89048e97198046b793f4a089c79a6e3268bd/frozenlist-1.7.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/80/e5/5e22c5bf96a64bdd43518b1834c6d95a4922cc2066b7d8e467dae9b6cee6/multidict-6.6.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/e4/43/619c2c7a0665aafc80efca465ddb1f260287266bdbdce517396f2f145d49/numpy-2.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/af/65/753a2d8b05daf496f4a9c367fe844e90a1b2cac78e2be2c844200d10cc4c/multidict-6.6.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/39/04/78d2e7402fb479d893953fb78fa7045f7deb635ec095b6b4f0260223091a/numpy-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/68/1f/795e7f4aa2eacc59afa4fb61a2e35e510d06414dd5a802b51a012d691b37/opencv_python-4.12.0.88-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/af/81/b324c44ae60c56ef12007105f1460d5c304b0626ab0cc6b07c8f2a9aa0b8/propcache-0.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/37/7c/54fd5301ef38505ab235d98827207176a5c9b2aa61939b10a460ca53e123/propcache-0.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/07/4a/42b26390181a7517718600fa7d98b951da20be982a50cd4afb3d46c2e603/pycairo-1.27.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/31/10/c0bf140bee2844e2c0617fdcc8a4e8daf98e71710046b06034e6f1963404/pyclipper-1.3.0.post6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/76/65/cb014acc41cd5bf6bbfa4671c7faffffb9cee01706642c2dec70c5209ac8/pyclipper-1.3.0.post6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/2f/81d580a0fb83baeb066698975cb14a618bdbed7720678566f1b046a95fe8/pyflakes-3.4.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2b/58/d34e67a79631177e3c08e7d02b5165147f590171f2cae6769502af5f7f7e/pygobject-3.50.0.tar.gz - pypi: https://files.pythonhosted.org/packages/d1/3f/d9a43ab76ad7a2d6d3a2968513b76760100c33128c6a0d3ac996dfb37c77/pygobject_stubs-2.13.0.tar.gz - pypi: https://files.pythonhosted.org/packages/92/44/8634af40b0db528b5b37e901c0dc67321354880d251bf8965901d57693a5/PyOpenGL-3.1.9-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6a/95/22c07ec2414928ddb50eb0e35d6cd6343ffef6ad74f42e86fefbaaa6b04e/PyOpenGL_accelerate-3.1.9-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/42/ae/67ddc9674d07c1900b0f094a16d2fa996492ffb25ad974e5af4e53dcad22/PyOpenGL_accelerate-3.1.9-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/10/5e/1aa9a93198c6b64513c9d7752de7422c06402de6600a8767da1524f9570b/pyparsing-3.2.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2c/83/2cacc506eb322bb31b747bc06ccb82cc9aa03e19ee9c1245e538e49d52be/pypdf-6.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl @@ -802,11 +1437,11 @@ environments: - pypi: https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5a/cc/06253936f4a7fa2e0f48dfe6d851d9c56df896a9ab09ac019d70b760619c/pytest_mock-3.15.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/4c/a2/d8ecd2f7ffa084870ba071a584aac44800a89f3c77b305999be7dc8b7bb3/pyvips-3.0.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/03/5a/fc34bf1aa14dc7c0e701691fa8685f3faec80e57d816615e3625f28feb43/scipy-1.15.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/e8/ad/2c89d6f2858ec8a1ac093144ebe6cfefc9307920ce95ad4ff045bb72b228/vtracer-0.6.11.tar.gz - - pypi: https://files.pythonhosted.org/packages/2c/3c/bf9b2c396ed86a0b4a92ff4cdaee09753d3ee389be738e92b9bbd0330b64/websockets-14.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/af/44/46407d7f7a56e9a85a4c207724c9f2c545c060380718eea9088f222ba697/yarl-1.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/c0/53/eaada1a414c026673eb983f8b4a55fe5eb172725d33d62c1b21f63ff6ca4/scipy-1.15.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/96/24/07a0a4d12d31c49513823a15deea3c735580819eb67af914676df5cb9c8e/vtracer-0.6.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/81/da/72f7caabd94652e6eb7e92ed2d3da818626e70b4f2b15a854ef60bf501ec/websockets-14.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/98/28/3ab7acc5b51f4434b181b0cee8f1f4b77a65919700a355fb3617f9488874/yarl-1.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: ./ osx-64: - conda: https://conda.anaconda.org/conda-forge/noarch/adwaita-icon-theme-49.0-unix_0.conda @@ -833,7 +1468,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/freetype-2.14.1-h694c41f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/fribidi-1.0.16-h8616949_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/g-ir-build-tools-1.84.0-py313h75cad1c_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/g-ir-build-tools-1.84.0-py312hf291c09_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/g-ir-host-tools-1.84.0-h4690c84_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gdk-pixbuf-2.44.2-h07555a4_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gettext-0.25.1-he52a196_1.conda @@ -842,7 +1477,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/giflib-5.2.2-h10d778d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/glib-2.86.0-h7f22f8f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/glib-tools-2.86.0-h8650975_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/gobject-introspection-1.84.0-py313hdd0212b_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/gobject-introspection-1.84.0-py312h4be7b1d_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/graphite2-1.3.14-h21dd04a_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/graphviz-13.1.2-h42bfd48_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gtk3-3.24.43-h70b172e_5.conda @@ -897,7 +1532,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.1-hd471939_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-devel-5.8.1-hd471939_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libmatio-1.5.28-heaf9015_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-h6e16a3a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.67.0-h3338091_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libpng-1.6.50-h84aeda2_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/librsvg-2.58.4-h21a6cfa_3.conda @@ -930,11 +1564,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/poppler-data-0.4.12-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pthread-stubs-0.4-h00291cd_1002.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/pyinstaller-6.16.0-py313h472b75b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pyinstaller-6.16.0-py312h1e69131_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyinstaller-hooks-contrib-2025.9-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.4.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.13.7-h5eba815_100_cp313.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.12.11-h9ccd52b_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/rav1e-0.7.1-h371c88c_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h7cca4af_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda @@ -957,26 +1591,26 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.3.1-hd23fc13_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-h8210216_2.conda - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8d/e7/f73206afa33100804f790b71092888f47df65fd9a4cd0e6800d7c6826441/aiohttp-3.12.14-cp313-cp313-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/0a/b8/a5e8e583e6c8c1056f4b012b50a03c77a669c2e9bf012b7cf33d6bc4b141/aiohttp-3.12.14-cp312-cp312-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cb/8c/2b30c12155ad8de0cf641d76a8b396a16d2c36bc6d50b621a62b7c4567c1/build-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/9a/94/b765c1abcb613d103b64fcf10395f54d69b0ef8be6a0dd9c524384892cc7/coverage-7.10.7-cp313-cp313-macosx_10_13_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/7a/5d/49b2767d2161f96665a7aef2f9c406df7399e4e11be0dcd917c0e196d479/ezdxf-1.3.5-cp313-cp313-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/13/e4/eb12450f71b542a53972d19117ea5a5cea1cab3ac9e31b0b5d498df1bd5a/coverage-7.10.7-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/33/b7/1bfe7edf249ddd36ddf574a9532658c0f408b45f2a5c2c04a77240d8d60c/ezdxf-1.3.5-cp312-cp312-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/9f/56/13ab06b4f93ca7cac71078fbe37fcea175d3216f31f85c3168a6bbd0bb9a/flake8-7.3.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/d6/8a/de9cc0540f542963ba5e8f3a1f6ad48fa211badc3177783b9d5cadf79b5d/fonttools-4.60.1-cp313-cp313-macosx_10_13_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/83/2e/5b70b6a3325363293fe5fc3ae74cdcbc3e996c2a11dde2fd9f1fb0776d19/frozenlist-1.7.0-cp313-cp313-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/ed/fe/7bd094b59c926acf2304d2151354ddbeb74b94812f3dc943c231db09cb41/fonttools-4.60.1-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/4c/9d/02754159955088cb52567337d1113f945b9e444c4960771ea90eb73de8db/frozenlist-1.7.0-cp312-cp312-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/4c/aa/8b6f548d839b6c13887253af4e29c939af22a18591bfb5d0ee6f1931dae8/multidict-6.6.4-cp313-cp313-macosx_10_13_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/0e/8b/88b98ed534d6a03ba8cddb316950fe80842885709b58501233c29dfa24a9/numpy-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/99/58/45c3e75deb8855c36bd66cc1658007589662ba584dbf423d01df478dd1c5/multidict-6.6.4-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/43/ec/43628dcf98466e087812142eec6d1c1a6c6bdfdad30a0aa07b872dc01f6f/numpy-2.2.3-cp312-cp312-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/33/7c/042abe49f58d6ee7e1028eefc3334d98ca69b030e3b567fe245a2b28ea6f/opencv_python-4.12.0.88-cp37-abi3-macosx_13_0_x86_64.whl - pypi: https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/61/99/d606cb7986b60d89c36de8a85d58764323b3a5ff07770a99d8e993b3fa73/propcache-0.3.2-cp313-cp313-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/af/6e/21293133beb550f9c901bbece755d582bfaf2176bee4774000bd4dd41884/propcache-0.3.2-cp312-cp312-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/07/4a/42b26390181a7517718600fa7d98b951da20be982a50cd4afb3d46c2e603/pycairo-1.27.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/0b/db/35843050a3dd7586781497a21ca6c8d48111afb66061cb40c3d3c288596d/pyclipper-1.3.0.post6-cp313-cp313-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/8e/8e/eb14eadf054494ad81446e21c4ea163b941747610b0eb9051644395f567e/pyclipper-1.3.0.post6-cp312-cp312-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/2f/81d580a0fb83baeb066698975cb14a618bdbed7720678566f1b046a95fe8/pyflakes-3.4.0-py2.py3-none-any.whl @@ -993,11 +1627,11 @@ environments: - pypi: https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5a/cc/06253936f4a7fa2e0f48dfe6d851d9c56df896a9ab09ac019d70b760619c/pytest_mock-3.15.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/4c/a2/d8ecd2f7ffa084870ba071a584aac44800a89f3c77b305999be7dc8b7bb3/pyvips-3.0.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/53/40/09319f6e0f276ea2754196185f95cd191cb852288440ce035d5c3a931ea2/scipy-1.15.2-cp313-cp313-macosx_10_13_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/e8/ad/2c89d6f2858ec8a1ac093144ebe6cfefc9307920ce95ad4ff045bb72b228/vtracer-0.6.11.tar.gz - - pypi: https://files.pythonhosted.org/packages/8e/b7/7484905215627909d9a79ae07070057afe477433fdacb59bf608ce86365a/websockets-14.2-cp313-cp313-macosx_10_13_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/b2/27/584394e1cb76fb771371770eccad35de400e7b434ce3142c2dd27392c968/yarl-1.20.1-cp313-cp313-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/4b/5d/3c78815cbab499610f26b5bae6aed33e227225a9fa5290008a733a64f6fc/scipy-1.15.2-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/ec/78/f91da19e1f4769317fe14a6bacb2be9e21b8fa6262dbd7021e2ab33545f8/vtracer-0.6.11-cp312-cp312-macosx_10_12_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/ec/c5/de30e88557e4d70988ed4d2eabd73fd3e1e52456b9f3a4e9564d86353b6d/websockets-14.2-cp312-cp312-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/67/38/688577a1cb1e656e3971fb66a3492501c5a5df56d99722e57c98249e5b8a/yarl-1.20.1-cp312-cp312-macosx_10_13_x86_64.whl - pypi: ./ win-64: - conda: https://conda.anaconda.org/conda-forge/win-64/_libavif_api-1.3.0-h57928b3_2.conda @@ -1207,10 +1841,10 @@ packages: version: 2.6.1 sha256: f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8 requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/30/a8/81e237f89a32029f9b4a805af6dffc378f8459c7b9942712c809ff9e76e5/aiohttp-3.12.14-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/0a/b8/a5e8e583e6c8c1056f4b012b50a03c77a669c2e9bf012b7cf33d6bc4b141/aiohttp-3.12.14-cp312-cp312-macosx_10_13_x86_64.whl name: aiohttp version: 3.12.14 - sha256: cdea089caf6d5cde975084a884c72d901e36ef9c2fd972c9f51efbbc64e96fbd + sha256: 0400f0ca9bb3e0b02f6466421f253797f6384e9845820c8b05e976398ac1d81a requires_dist: - aiohappyeyeballs>=2.5.0 - aiosignal>=1.4.0 @@ -1241,10 +1875,10 @@ packages: - brotli ; platform_python_implementation == 'CPython' and extra == 'speedups' - brotlicffi ; platform_python_implementation != 'CPython' and extra == 'speedups' requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/8d/e7/f73206afa33100804f790b71092888f47df65fd9a4cd0e6800d7c6826441/aiohttp-3.12.14-cp313-cp313-macosx_10_13_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/73/12/2530fb2b08773f717ab2d249ca7a982ac66e32187c62d49e2c86c9bba9b4/aiohttp-3.12.14-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl name: aiohttp version: 3.12.14 - sha256: 3d62ac3d506cef54b355bd34c2a7c230eb693880001dfcda0bf88b38f5d7af7e + sha256: 9888e60c2c54eaf56704b17feb558c7ed6b7439bca1e07d4818ab878f2083660 requires_dist: - aiohappyeyeballs>=2.5.0 - aiosignal>=1.4.0 @@ -1416,6 +2050,35 @@ packages: - mypy>=1.11.1 ; python_full_version >= '3.10' and platform_python_implementation == 'CPython' and extra == 'tests-mypy' - pytest-mypy-plugins ; python_full_version >= '3.10' and platform_python_implementation == 'CPython' and extra == 'tests-mypy' requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl + name: babel + version: 2.17.0 + sha256: 4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2 + requires_dist: + - pytz>=2015.7 ; python_full_version < '3.9' + - tzdata ; sys_platform == 'win32' and extra == 'dev' + - backports-zoneinfo ; python_full_version < '3.9' and extra == 'dev' + - freezegun~=1.0 ; extra == 'dev' + - jinja2>=3.0 ; extra == 'dev' + - pytest-cov ; extra == 'dev' + - pytest>=6.0 ; extra == 'dev' + - pytz ; extra == 'dev' + - setuptools ; extra == 'dev' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/10/bf/fa31834dc27a7f05e5290eae47c82690edc3a7b37d58f7fb35a1bdbf355b/backrefs-5.9-py313-none-any.whl + name: backrefs + version: '5.9' + sha256: cc37b19fa219e93ff825ed1fed8879e47b4d89aa7a1884860e2db64ccd7c676b + requires_dist: + - regex ; extra == 'extras' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/9d/12/4f345407259dd60a0997107758ba3f221cf89a9b5a0f8ed5b961aef97253/backrefs-5.9-py312-none-any.whl + name: backrefs + version: '5.9' + sha256: 7fdf9771f63e6028d7fee7e0c497c81abda597ea45d6b8f89e8ad76994f5befa + requires_dist: + - regex ; extra == 'extras' + requires_python: '>=3.9' - pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl name: blinker version: 1.9.0 @@ -1573,6 +2236,41 @@ packages: purls: [] size: 1524254 timestamp: 1741555212198 +- pypi: https://files.pythonhosted.org/packages/93/d8/ba13451aa6b745c49536e87b6bf8f629b950e84bd0e8308f7dc6883b67e2/cairocffi-1.7.1-py3-none-any.whl + name: cairocffi + version: 1.7.1 + sha256: 9803a0e11f6c962f3b0ae2ec8ba6ae45e957a146a004697a1ac1bbf16b073b3f + requires_dist: + - cffi>=1.1.0 + - sphinx ; extra == 'doc' + - sphinx-rtd-theme ; extra == 'doc' + - pytest ; extra == 'test' + - ruff ; extra == 'test' + - numpy ; extra == 'test' + - pikepdf ; extra == 'test' + - xcffib>=1.4.0 ; extra == 'xcb' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/67/48/816bd4aaae93dbf9e408c58598bc32f4a8c65f4b86ab560864cb3ee60adb/cairosvg-2.8.2-py3-none-any.whl + name: cairosvg + version: 2.8.2 + sha256: eab46dad4674f33267a671dce39b64be245911c901c70d65d2b7b0821e852bf5 + requires_dist: + - cairocffi + - cssselect2 + - defusedxml + - pillow + - tinycss2 + - sphinx ; extra == 'doc' + - sphinx-rtd-theme ; extra == 'doc' + - pytest ; extra == 'test' + - flake8 ; extra == 'test' + - isort ; extra == 'test' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl + name: certifi + version: 2025.8.3 + sha256: f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5 + requires_python: '>=3.7' - pypi: https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl name: cffi version: 2.0.0 @@ -1580,17 +2278,17 @@ packages: requires_dist: - pycparser ; implementation_name != 'PyPy' requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl name: cffi version: 2.0.0 - sha256: 00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb + sha256: 3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba requires_dist: - pycparser ; implementation_name != 'PyPy' requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl name: cffi version: 2.0.0 - sha256: c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26 + sha256: 6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d requires_dist: - pycparser ; implementation_name != 'PyPy' requires_python: '>=3.9' @@ -1619,6 +2317,28 @@ packages: purls: [] size: 697242 timestamp: 1753286975548 +- pypi: https://files.pythonhosted.org/packages/16/ab/0233c3231af734f5dfcf0844aa9582d5a1466c985bbed6cedab85af9bfe3/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: charset-normalizer + version: 3.4.3 + sha256: 1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/9a/8f/ae790790c7b64f925e5c953b924aaa42a243fb778fed9e41f147b2a5715a/charset_normalizer-3.4.3-cp313-cp313-win_amd64.whl + name: charset-normalizer + version: 3.4.3 + sha256: cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/e9/5e/14c94999e418d9b87682734589404a25854d5f5d0408df68bc15b6ff54bb/charset_normalizer-3.4.3-cp312-cp312-macosx_10_13_universal2.whl + name: charset-normalizer + version: 3.4.3 + sha256: e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1 + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/db/d3/9dcc0f5797f070ec8edf30fbadfb200e71d9db6b84d211e3b2085a7589a0/click-8.3.0-py3-none-any.whl + name: click + version: 8.3.0 + sha256: 9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc + requires_dist: + - colorama ; sys_platform == 'win32' + requires_python: '>=3.10' - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda sha256: ab29d57dc70786c1269633ba3dff20288b81664d3ff8d21af995742e2bb03287 md5: 962b9857ee8e7018c22f2776ffa0b2d7 @@ -1630,17 +2350,17 @@ packages: - pkg:pypi/colorama?source=hash-mapping size: 27011 timestamp: 1733218222191 -- pypi: https://files.pythonhosted.org/packages/9a/94/b765c1abcb613d103b64fcf10395f54d69b0ef8be6a0dd9c524384892cc7/coverage-7.10.7-cp313-cp313-macosx_10_13_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/13/e4/eb12450f71b542a53972d19117ea5a5cea1cab3ac9e31b0b5d498df1bd5a/coverage-7.10.7-cp312-cp312-macosx_10_13_x86_64.whl name: coverage version: 7.10.7 - sha256: 981a651f543f2854abd3b5fcb3263aac581b18209be49863ba575de6edf4c14d + sha256: 7bb3b9ddb87ef7725056572368040c32775036472d5a033679d1fa6c8dc08417 requires_dist: - tomli ; python_full_version <= '3.11' and extra == 'toml' requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/a2/77/8c6d22bf61921a59bce5471c2f1f7ac30cd4ac50aadde72b8c48d5727902/coverage-7.10.7-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/a6/90/a64aaacab3b37a17aaedd83e8000142561a29eb262cede42d94a67f7556b/coverage-7.10.7-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl name: coverage version: 7.10.7 - sha256: 10b6ba00ab1132a0ce4428ff68cf50a25efd6840a42cdf4239c9b99aad83be8b + sha256: 314f2c326ded3f4b09be11bc282eb2fc861184bc95748ae67b360ac962770be7 requires_dist: - tomli ; python_full_version <= '3.11' and extra == 'toml' requires_python: '>=3.9' @@ -1651,6 +2371,18 @@ packages: requires_dist: - tomli ; python_full_version <= '3.11' and extra == 'toml' requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/0f/e7/aa315e6a749d9b96c2504a1ba0ba031ba2d0517e972ce22682e3fccecb09/cssselect2-0.8.0-py3-none-any.whl + name: cssselect2 + version: 0.8.0 + sha256: 46fc70ebc41ced7a32cd42d58b1884d72ade23d21e5a4eaaf022401c13f0e76e + requires_dist: + - tinycss2 + - webencodings + - sphinx ; extra == 'doc' + - furo ; extra == 'doc' + - pytest ; extra == 'test' + - ruff ; extra == 'test' + requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/linux-64/dav1d-1.2.1-hd590300_0.conda sha256: 22053a5842ca8ee1cf8e1a817138cdb5e647eb2c46979f84153f6ad7bde73020 md5: 418c6ca5929a611cbd69204907a83995 @@ -1697,6 +2429,11 @@ packages: purls: [] size: 437860 timestamp: 1747855126005 +- pypi: https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl + name: defusedxml + version: 0.7.1 + sha256: a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61 + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*' - conda: https://conda.anaconda.org/conda-forge/linux-64/epoxy-1.5.10-hb03c661_2.conda sha256: a5b51e491fec22bcc1765f5b2c8fff8a97428e9a5a7ee6730095fb9d091b0747 md5: 057083b06ccf1c2778344b6dabace38b @@ -1789,10 +2526,10 @@ packages: purls: [] size: 234623 timestamp: 1752719798470 -- pypi: https://files.pythonhosted.org/packages/2e/5a/31e1d7874ee1b6173e57d7d85b33d65fa82b388824ab396f9730cfc16f54/ezdxf-1.3.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/33/b7/1bfe7edf249ddd36ddf574a9532658c0f408b45f2a5c2c04a77240d8d60c/ezdxf-1.3.5-cp312-cp312-macosx_10_13_x86_64.whl name: ezdxf version: 1.3.5 - sha256: 5850a508ba78e65b3729be26e65170011c0d0d7199e718f3a3737b7cd7e44c5d + sha256: 623ccf1c5a0b4b0f08481298549727cd4597810c121f31c996a13589c25ef938 requires_dist: - pyparsing>=2.0.1 - typing-extensions>=4.6.0 @@ -1857,10 +2594,10 @@ packages: - matplotlib ; extra == 'dev5' - pymupdf>=1.20.0 ; extra == 'dev5' requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/7a/5d/49b2767d2161f96665a7aef2f9c406df7399e4e11be0dcd917c0e196d479/ezdxf-1.3.5-cp313-cp313-macosx_10_13_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/4d/c1/ed30f798587199a64db82ea2867fa01ab3260287ceeb762f5108902061fd/ezdxf-1.3.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl name: ezdxf version: 1.3.5 - sha256: 8a756e48b11123a0e2751aaf5f7ba3bb23b967f38aac62e598fe6138fee8e111 + sha256: 4fc459fc6dea1e05eeb605f097a924de1dd8d750be963c9f0e86a869e5ab3fe3 requires_dist: - pyparsing>=2.0.1 - typing-extensions>=4.6.0 @@ -2027,10 +2764,10 @@ packages: purls: [] size: 4102 timestamp: 1566932280397 -- pypi: https://files.pythonhosted.org/packages/2d/8b/371ab3cec97ee3fe1126b3406b7abd60c8fec8975fd79a3c75cdea0c3d83/fonttools-4.60.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/75/4d/b022c1577807ce8b31ffe055306ec13a866f2337ecee96e75b24b9b753ea/fonttools-4.60.1-cp313-cp313-win_amd64.whl name: fonttools version: 4.60.1 - sha256: b33a7884fabd72bdf5f910d0cf46be50dce86a0362a65cfc746a4168c67eb96c + sha256: a3db56f153bd4c5c2b619ab02c5db5192e222150ce5a1bc10f16164714bc39ac requires_dist: - lxml>=4.0 ; extra == 'lxml' - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' @@ -2061,10 +2798,10 @@ packages: - skia-pathops>=0.5.0 ; extra == 'all' - uharfbuzz>=0.23.0 ; extra == 'all' requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/75/4d/b022c1577807ce8b31ffe055306ec13a866f2337ecee96e75b24b9b753ea/fonttools-4.60.1-cp313-cp313-win_amd64.whl +- pypi: https://files.pythonhosted.org/packages/c0/ca/4bb48a26ed95a1e7eba175535fe5805887682140ee0a0d10a88e1de84208/fonttools-4.60.1-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl name: fonttools version: 4.60.1 - sha256: a3db56f153bd4c5c2b619ab02c5db5192e222150ce5a1bc10f16164714bc39ac + sha256: 8177ec9676ea6e1793c8a084a90b65a9f778771998eb919d05db6d4b1c0b114c requires_dist: - lxml>=4.0 ; extra == 'lxml' - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' @@ -2095,10 +2832,10 @@ packages: - skia-pathops>=0.5.0 ; extra == 'all' - uharfbuzz>=0.23.0 ; extra == 'all' requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/d6/8a/de9cc0540f542963ba5e8f3a1f6ad48fa211badc3177783b9d5cadf79b5d/fonttools-4.60.1-cp313-cp313-macosx_10_13_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/ed/fe/7bd094b59c926acf2304d2151354ddbeb74b94812f3dc943c231db09cb41/fonttools-4.60.1-cp312-cp312-macosx_10_13_x86_64.whl name: fonttools version: 4.60.1 - sha256: eedacb5c5d22b7097482fa834bda0dafa3d914a4e829ec83cdea2a01f8c813c4 + sha256: 839565cbf14645952d933853e8ade66a463684ed6ed6c9345d0faf1f0e868877 requires_dist: - lxml>=4.0 ; extra == 'lxml' - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' @@ -2194,15 +2931,15 @@ packages: version: 1.7.0 sha256: 52109052b9791a3e6b5d1b65f4b909703984b770694d3eb64fad124c835d7cba requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/72/31/bc8c5c99c7818293458fe745dab4fd5730ff49697ccc82b554eb69f16a24/frozenlist-1.7.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/4c/9d/02754159955088cb52567337d1113f945b9e444c4960771ea90eb73de8db/frozenlist-1.7.0-cp312-cp312-macosx_10_13_x86_64.whl name: frozenlist version: 1.7.0 - sha256: 8bd7eb96a675f18aa5c553eb7ddc24a43c8c18f22e1f9925528128c052cdbe00 + sha256: 1f5906d3359300b8a9bb194239491122e6cf1444c2efb88865426f170c262cdb requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/83/2e/5b70b6a3325363293fe5fc3ae74cdcbc3e996c2a11dde2fd9f1fb0776d19/frozenlist-1.7.0-cp313-cp313-macosx_10_13_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/8d/db/48421f62a6f77c553575201e89048e97198046b793f4a089c79a6e3268bd/frozenlist-1.7.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl name: frozenlist version: 1.7.0 - sha256: d1a81c85417b914139e3a9b995d4a1c84559afc839a93cf2cb7f15e6e5f6ed2d + sha256: 488d0a7d6a0008ca0db273c542098a0fa9e7dfaa7e57f70acef43f32b3f69dca requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/noarch/future-1.0.0-pyhd8ed1ab_2.conda sha256: 45dfd037889b7075c5eb46394f93172de0be0b1624c7f802dd3ecc94b814d8e0 @@ -2215,37 +2952,37 @@ packages: - pkg:pypi/future?source=hash-mapping size: 364561 timestamp: 1738926525117 -- conda: https://conda.anaconda.org/conda-forge/linux-64/g-ir-build-tools-1.84.0-py313hff75e6e_3.conda - sha256: 968c4d1bd7fe8d1f51598fdf673f502cf3e1bb16058126c26cb0de40d6c470e8 - md5: fbc5e4968a9a1775af28acb1708477f0 +- conda: https://conda.anaconda.org/conda-forge/linux-64/g-ir-build-tools-1.84.0-py312h510a0e2_3.conda + sha256: 34d61824b19c2b6c942b2dc5a67f9405582ecd5fb585c5030aa541428985b284 + md5: 64421218f5033fb42d1a87fee170b849 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libglib >=2.86.0,<3.0a0 - pkg-config - - python >=3.13,<3.14.0a0 - - python_abi 3.13.* *_cp313 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 - setuptools license: LGPL-2.0-or-later license_family: LGPL purls: [] - size: 357703 - timestamp: 1757424086846 -- conda: https://conda.anaconda.org/conda-forge/osx-64/g-ir-build-tools-1.84.0-py313h75cad1c_3.conda - sha256: 36ca7179efa11fd79353588b1ac02b0f87773e1c5a349d5acfe0057f1ef77bbe - md5: 66f68424d38de89c7dc28fcd8e0bf5c8 + size: 355134 + timestamp: 1757424097832 +- conda: https://conda.anaconda.org/conda-forge/osx-64/g-ir-build-tools-1.84.0-py312hf291c09_3.conda + sha256: 26104cdc8a39c6d174be3a6f7f2ba578c1287774fdb34e3a1b8d112f7e93649e + md5: a00bc2b6511b8a98537cd9a96479067e depends: - __osx >=10.13 - libglib >=2.86.0,<3.0a0 - pkg-config - - python >=3.13,<3.14.0a0 - - python_abi 3.13.* *_cp313 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 - setuptools license: LGPL-2.0-or-later license_family: LGPL purls: [] - size: 354234 - timestamp: 1757424417376 + size: 352045 + timestamp: 1757424322647 - conda: https://conda.anaconda.org/conda-forge/win-64/g-ir-build-tools-1.84.0-py313h0754440_3.conda sha256: 9641b2c5df2c1fa623ceaafb2a7b78844a60526cf3b4fb6cb8e3880a217b1791 md5: bf15a3c89b2ba727ba15970443e0741e @@ -2467,6 +3204,16 @@ packages: purls: [] size: 61758826 timestamp: 1759142984251 +- pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl + name: ghp-import + version: 2.1.0 + sha256: 8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619 + requires_dist: + - python-dateutil>=2.8.1 + - twine ; extra == 'dev' + - markdown ; extra == 'dev' + - flake8 ; extra == 'dev' + - wheel ; extra == 'dev' - conda: https://conda.anaconda.org/conda-forge/linux-64/giflib-5.2.2-hd590300_0.conda sha256: aac402a8298f0c0cc528664249170372ef6b37ac39fdc92b40601a6aed1e32ff md5: 3bf7b9fd5a7136126e0234db4b87c8b6 @@ -2566,43 +3313,43 @@ packages: purls: [] size: 98188 timestamp: 1757403854799 -- conda: https://conda.anaconda.org/conda-forge/linux-64/gobject-introspection-1.84.0-py313h07c7e49_3.conda - sha256: 8668718d49ac8e1462e5e76a692e9a05cedd41950814ee7fe8fcd119bf9d431f - md5: 481804f9663b0bd12d6b6eda994bdd5c +- conda: https://conda.anaconda.org/conda-forge/linux-64/gobject-introspection-1.84.0-py312h74c86ee_3.conda + sha256: f24852aa3bfa5e1573a9eba9c6496b9041416def38a21d35fbab31ad1162a7a2 + md5: c00ae81745f11cd2daddfa1842086770 depends: - __glibc >=2.17,<3.0.a0 - cairo >=1.18.4,<2.0a0 - - g-ir-build-tools 1.84.0 py313hff75e6e_3 + - g-ir-build-tools 1.84.0 py312h510a0e2_3 - g-ir-host-tools 1.84.0 h5654c37_3 - libffi >=3.4.6,<3.5.0a0 - libgcc >=14 - libgirepository 1.84.0 h61e2d6e_3 - libglib >=2.86.0,<3.0a0 - - python >=3.13,<3.14.0a0 - - python_abi 3.13.* *_cp313 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 license: LGPL-2.0-or-later license_family: LGPL purls: [] - size: 1015813 - timestamp: 1757424120166 -- conda: https://conda.anaconda.org/conda-forge/osx-64/gobject-introspection-1.84.0-py313hdd0212b_3.conda - sha256: 929fd1b1e3a0b399cad21d809a4b4cf417642e9ff1962f2a645eab773b55fa03 - md5: 44dee9f796a164b4317a8dc8d2afedc7 + size: 1007863 + timestamp: 1757424133302 +- conda: https://conda.anaconda.org/conda-forge/osx-64/gobject-introspection-1.84.0-py312h4be7b1d_3.conda + sha256: 61d3a7ccbf0cf51acf676d25d842a4839c78ed87936e33609693e4faccd7e5bf + md5: 6a8fd6eec2c1249364c0be4b0f3fc74d depends: - __osx >=10.13 - cairo >=1.18.4,<2.0a0 - - g-ir-build-tools 1.84.0 py313h75cad1c_3 + - g-ir-build-tools 1.84.0 py312hf291c09_3 - g-ir-host-tools 1.84.0 h4690c84_3 - libffi >=3.4.6,<3.5.0a0 - libgirepository 1.84.0 h40d85bd_3 - libglib >=2.86.0,<3.0a0 - - python >=3.13,<3.14.0a0 - - python_abi 3.13.* *_cp313 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 license: LGPL-2.0-or-later license_family: LGPL purls: [] - size: 1003717 - timestamp: 1757424495890 + size: 1006488 + timestamp: 1757424391104 - conda: https://conda.anaconda.org/conda-forge/win-64/gobject-introspection-1.84.0-py313h276ecff_3.conda sha256: fe615072b79f1da59cade532be0585fc4e527c0bfcdd36e4d16bd4a90965a2b1 md5: 5d6a09446aa5fad272dccf7f2c3d6844 @@ -3155,6 +3902,27 @@ packages: - pkg:pypi/importlib-metadata?source=hash-mapping size: 34641 timestamp: 1747934053147 +- pypi: https://files.pythonhosted.org/packages/a4/ed/1f1afb2e9e7f38a545d628f864d562a5ae64fe6f7a10e28ffb9b185b4e89/importlib_resources-6.5.2-py3-none-any.whl + name: importlib-resources + version: 6.5.2 + sha256: 789cfdc3ed28c78b67a06acb8126751ced69a3d5f79c095a98298cd8a760ccec + requires_dist: + - zipp>=3.1.0 ; python_full_version < '3.10' + - pytest>=6,!=8.1.* ; extra == 'test' + - zipp>=3.17 ; extra == 'test' + - jaraco-test>=5.4 ; extra == 'test' + - sphinx>=3.5 ; extra == 'doc' + - jaraco-packaging>=9.3 ; extra == 'doc' + - rst-linker>=1.9 ; extra == 'doc' + - furo ; extra == 'doc' + - sphinx-lint ; extra == 'doc' + - jaraco-tidelift>=1.4 ; extra == 'doc' + - pytest-checkdocs>=2.4 ; extra == 'check' + - pytest-ruff>=0.2.1 ; sys_platform != 'cygwin' and extra == 'check' + - pytest-cov ; extra == 'cover' + - pytest-enabler>=2.2 ; extra == 'enabler' + - pytest-mypy ; extra == 'type' + requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_1.conda sha256: 0ec8f4d02053cd03b0f3e63168316530949484f80e16f5e2fb199a1d117a89ca md5: 6837f3eff7dcea42ecd714ce1ac2b108 @@ -3184,6 +3952,14 @@ packages: purls: [] size: 43203 timestamp: 1621515162252 +- pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl + name: jinja2 + version: 3.1.6 + sha256: 85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67 + requires_dist: + - markupsafe>=2.0 + - babel>=2.7 ; extra == 'i18n' + requires_python: '>=3.7' - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda sha256: 0960d06048a7185d3542d850986d807c6e37ca2e644342dd0c72feefcf26c2a4 md5: b38117a3c920364aff79f870c984b4a3 @@ -4635,27 +5411,6 @@ packages: purls: [] size: 197065 timestamp: 1746547236394 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb9d3cd8_0.conda - sha256: 3aa92d4074d4063f2a162cd8ecb45dccac93e543e565c01a787e16a43501f7ee - md5: c7e925f37e3b40d893459e625f6a53f1 - depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=13 - license: BSD-2-Clause - license_family: BSD - purls: [] - size: 91183 - timestamp: 1748393666725 -- conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-h6e16a3a_0.conda - sha256: 98299c73c7a93cd4f5ff8bb7f43cd80389f08b5a27a296d806bdef7841cc9b9e - md5: 18b81186a6adb43f000ad19ed7b70381 - depends: - - __osx >=10.13 - license: BSD-2-Clause - license_family: BSD - purls: [] - size: 77667 - timestamp: 1748393757154 - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-h2466b09_0.conda sha256: fc529fc82c7caf51202cc5cec5bb1c2e8d90edbac6d0a4602c966366efe3c7bf md5: 74860100b2029e2523cf480804c76b9b @@ -4701,6 +5456,17 @@ packages: purls: [] size: 605680 timestamp: 1756835898134 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda + sha256: 927fe72b054277cde6cb82597d0fcf6baf127dcbce2e0a9d8925a68f1265eef5 + md5: d864d34357c3b65a4b731f78c0801dc4 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: LGPL-2.1-only + license_family: GPL + purls: [] + size: 33731 + timestamp: 1750274110928 - conda: https://conda.anaconda.org/conda-forge/linux-64/libpciaccess-0.18-hb9d3cd8_0.conda sha256: 0bd91de9b447a2991e666f284ae8c722ffb1d84acb594dbd0c031bd656fa32b2 md5: 70e3400cbbfa03e96dcde7fc13e38c7b @@ -5116,6 +5882,15 @@ packages: purls: [] size: 323770 timestamp: 1727278927545 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + sha256: 6ae68e0b86423ef188196fff6207ed0c8195dd84273cb5623b85aa08033a410c + md5: 5aa797f8787fe7a17d1b0821485b5adc + depends: + - libgcc-ng >=12 + license: LGPL-2.1-or-later + purls: [] + size: 100393 + timestamp: 1702724383534 - conda: https://conda.anaconda.org/conda-forge/linux-64/libxkbcommon-1.11.0-he8b52b9_0.conda sha256: 23f47e86cc1386e7f815fa9662ccedae151471862e971ea511c5c886aa723a54 md5: 74e91c36d0eef3557915c68b6c2bef96 @@ -5304,29 +6079,168 @@ packages: - pkg:pypi/macholib?source=hash-mapping size: 38653 timestamp: 1695643239171 +- pypi: https://files.pythonhosted.org/packages/70/ae/44c4a6a4cbb496d93c6257954260fe3a6e91b7bed2240e5dad2a717f5111/markdown-3.9-py3-none-any.whl + name: markdown + version: '3.9' + sha256: 9f4d91ed810864ea88a6f32c07ba8bee1346c0cc1f6b1f9f6c822f2a9667d280 + requires_dist: + - importlib-metadata>=4.4 ; python_full_version < '3.10' + - coverage ; extra == 'testing' + - pyyaml ; extra == 'testing' + - mkdocs>=1.6 ; extra == 'docs' + - mkdocs-nature>=0.6 ; extra == 'docs' + - mdx-gh-links>=0.2 ; extra == 'docs' + - mkdocstrings[python] ; extra == 'docs' + - mkdocs-gen-files ; extra == 'docs' + - mkdocs-section-index ; extra == 'docs' + - mkdocs-literate-nav ; extra == 'docs' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl + name: markupsafe + version: 3.0.3 + sha256: 9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: markupsafe + version: 3.0.3 + sha256: d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl + name: markupsafe + version: 3.0.3 + sha256: d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e + requires_python: '>=3.9' - pypi: https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl name: mccabe version: 0.7.0 sha256: 6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e requires_python: '>=3.6' -- pypi: https://files.pythonhosted.org/packages/4c/aa/8b6f548d839b6c13887253af4e29c939af22a18591bfb5d0ee6f1931dae8/multidict-6.6.4-cp313-cp313-macosx_10_13_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + name: mergedeep + version: 1.3.4 + sha256: 70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307 + requires_python: '>=3.6' +- pypi: https://files.pythonhosted.org/packages/fd/1a/31b7cd6e4e7a02df4e076162e9783620777592bea9e4bb036389389af99d/mike-2.1.3-py3-none-any.whl + name: mike + version: 2.1.3 + sha256: d90c64077e84f06272437b464735130d380703a76a5738b152932884c60c062a + requires_dist: + - importlib-metadata + - importlib-resources + - jinja2>=2.7 + - mkdocs>=1.0 + - pyparsing>=3.0 + - pyyaml>=5.1 + - pyyaml-env-tag + - verspec + - coverage ; extra == 'dev' + - flake8-quotes ; extra == 'dev' + - flake8>=3.0 ; extra == 'dev' + - shtab ; extra == 'dev' + - coverage ; extra == 'test' + - flake8-quotes ; extra == 'test' + - flake8>=3.0 ; extra == 'test' + - shtab ; extra == 'test' +- pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl + name: mkdocs + version: 1.6.1 + sha256: db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e + requires_dist: + - click>=7.0 + - colorama>=0.4 ; sys_platform == 'win32' + - ghp-import>=1.0 + - importlib-metadata>=4.4 ; python_full_version < '3.10' + - jinja2>=2.11.1 + - markdown>=3.3.6 + - markupsafe>=2.0.1 + - mergedeep>=1.3.4 + - mkdocs-get-deps>=0.2.0 + - packaging>=20.5 + - pathspec>=0.11.1 + - pyyaml-env-tag>=0.1 + - pyyaml>=5.1 + - watchdog>=2.0 + - babel>=2.9.0 ; extra == 'i18n' + - babel==2.9.0 ; extra == 'min-versions' + - click==7.0 ; extra == 'min-versions' + - colorama==0.4 ; sys_platform == 'win32' and extra == 'min-versions' + - ghp-import==1.0 ; extra == 'min-versions' + - importlib-metadata==4.4 ; python_full_version < '3.10' and extra == 'min-versions' + - jinja2==2.11.1 ; extra == 'min-versions' + - markdown==3.3.6 ; extra == 'min-versions' + - markupsafe==2.0.1 ; extra == 'min-versions' + - mergedeep==1.3.4 ; extra == 'min-versions' + - mkdocs-get-deps==0.2.0 ; extra == 'min-versions' + - packaging==20.5 ; extra == 'min-versions' + - pathspec==0.11.1 ; extra == 'min-versions' + - pyyaml-env-tag==0.1 ; extra == 'min-versions' + - pyyaml==5.1 ; extra == 'min-versions' + - watchdog==2.0 ; extra == 'min-versions' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/9f/d4/029f984e8d3f3b6b726bd33cafc473b75e9e44c0f7e80a5b29abc466bdea/mkdocs_get_deps-0.2.0-py3-none-any.whl + name: mkdocs-get-deps + version: 0.2.0 + sha256: 2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134 + requires_dist: + - importlib-metadata>=4.3 ; python_full_version < '3.10' + - mergedeep>=1.3.4 + - platformdirs>=2.2.0 + - pyyaml>=5.1 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/30/cf/e9a0ce9da269746906fdc595c030f6df66793dad1487abd1699af2ba44f1/mkdocs_glightbox-0.5.1-py3-none-any.whl + name: mkdocs-glightbox + version: 0.5.1 + sha256: f47af0daff164edf8d36e553338425be3aab6e34b987d9cbbc2ae7819a98cb01 + requires_dist: + - selectolax==0.3.29 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/cf/4f/98681c2030375fe9b057dbfb9008b68f46c07dddf583f4df09bf8075e37f/mkdocs_material-9.6.21-py3-none-any.whl + name: mkdocs-material + version: 9.6.21 + sha256: aa6a5ab6fb4f6d381588ac51da8782a4d3757cb3d1b174f81a2ec126e1f22c92 + requires_dist: + - babel~=2.10 + - backrefs~=5.7.post1 + - colorama~=0.4 + - jinja2~=3.1 + - markdown~=3.2 + - mkdocs-material-extensions~=1.3 + - mkdocs~=1.6 + - paginate~=0.5 + - pygments~=2.16 + - pymdown-extensions~=10.2 + - requests~=2.26 + - mkdocs-git-committers-plugin-2>=1.1,<3 ; extra == 'git' + - mkdocs-git-revision-date-localized-plugin~=1.2,>=1.2.4 ; extra == 'git' + - cairosvg~=2.6 ; extra == 'imaging' + - pillow>=10.2,<12.0 ; extra == 'imaging' + - mkdocs-minify-plugin~=0.7 ; extra == 'recommended' + - mkdocs-redirects~=1.2 ; extra == 'recommended' + - mkdocs-rss-plugin~=1.6 ; extra == 'recommended' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl + name: mkdocs-material-extensions + version: 1.3.1 + sha256: adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/99/58/45c3e75deb8855c36bd66cc1658007589662ba584dbf423d01df478dd1c5/multidict-6.6.4-cp312-cp312-macosx_10_13_x86_64.whl name: multidict version: 6.6.4 - sha256: 22e38b2bc176c5eb9c0a0e379f9d188ae4cd8b28c0f53b52bce7ab0a9e534657 + sha256: d191de6cbab2aff5de6c5723101705fd044b3e4c7cfd587a1929b5028b9714b3 requires_dist: - typing-extensions>=4.1.0 ; python_full_version < '3.11' requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/80/e5/5e22c5bf96a64bdd43518b1834c6d95a4922cc2066b7d8e467dae9b6cee6/multidict-6.6.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/9d/34/746696dffff742e97cd6a23da953e55d0ea51fa601fa2ff387b3edcfaa2c/multidict-6.6.4-cp313-cp313-win_amd64.whl name: multidict version: 6.6.4 - sha256: 497a2954adc25c08daff36f795077f63ad33e13f19bfff7736e72c785391534f + sha256: 40cd05eaeb39e2bc8939451f033e57feaa2ac99e07dbca8afe2be450a4a3b6cf requires_dist: - typing-extensions>=4.1.0 ; python_full_version < '3.11' requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/9d/34/746696dffff742e97cd6a23da953e55d0ea51fa601fa2ff387b3edcfaa2c/multidict-6.6.4-cp313-cp313-win_amd64.whl +- pypi: https://files.pythonhosted.org/packages/af/65/753a2d8b05daf496f4a9c367fe844e90a1b2cac78e2be2c844200d10cc4c/multidict-6.6.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl name: multidict version: 6.6.4 - sha256: 40cd05eaeb39e2bc8939451f033e57feaa2ac99e07dbca8afe2be450a4a3b6cf + sha256: b8eb3025f17b0a4c3cd08cda49acf312a19ad6e8a4edd9dbd591e6506d999402 requires_dist: - typing-extensions>=4.1.0 ; python_full_version < '3.11' requires_python: '>=3.9' @@ -5401,20 +6315,20 @@ packages: purls: [] size: 1926796 timestamp: 1757675119718 -- pypi: https://files.pythonhosted.org/packages/0e/8b/88b98ed534d6a03ba8cddb316950fe80842885709b58501233c29dfa24a9/numpy-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/39/04/78d2e7402fb479d893953fb78fa7045f7deb635ec095b6b4f0260223091a/numpy-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl name: numpy version: 2.2.3 - sha256: 7bfdb06b395385ea9b91bf55c1adf1b297c9fdb531552845ff1d3ea6e40d5aba + sha256: 3b787adbf04b0db1967798dba8da1af07e387908ed1553a0d6e74c084d1ceafe requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/97/e7/7d55a86719d0de7a6a597949f3febefb1009435b79ba510ff32f05a8c1d7/numpy-2.2.3-cp313-cp313-win_amd64.whl +- pypi: https://files.pythonhosted.org/packages/43/ec/43628dcf98466e087812142eec6d1c1a6c6bdfdad30a0aa07b872dc01f6f/numpy-2.2.3-cp312-cp312-macosx_10_13_x86_64.whl name: numpy version: 2.2.3 - sha256: 5b732c8beef1d7bc2d9e476dbba20aaff6167bf205ad9aa8d30913859e82884b + sha256: 12c045f43b1d2915eca6b880a7f4a256f59d62df4f044788c8ba67709412128d requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/e4/43/619c2c7a0665aafc80efca465ddb1f260287266bdbdce517396f2f145d49/numpy-2.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/97/e7/7d55a86719d0de7a6a597949f3febefb1009435b79ba510ff32f05a8c1d7/numpy-2.2.3-cp313-cp313-win_amd64.whl name: numpy version: 2.2.3 - sha256: 52659ad2534427dffcc36aac76bebdd02b67e3b7a619ac67543bc9bfe6b7cdb1 + sha256: 5b732c8beef1d7bc2d9e476dbba20aaff6167bf205ad9aa8d30913859e82884b requires_python: '>=3.10' - pypi: https://files.pythonhosted.org/packages/33/7c/042abe49f58d6ee7e1028eefc3334d98ca69b030e3b567fe245a2b28ea6f/opencv_python-4.12.0.88-cp37-abi3-macosx_13_0_x86_64.whl name: opencv-python @@ -5604,6 +6518,14 @@ packages: - pkg:pypi/packaging?source=hash-mapping size: 62477 timestamp: 1745345660407 +- pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + name: paginate + version: 0.5.7 + sha256: b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591 + requires_dist: + - pytest ; extra == 'dev' + - tox ; extra == 'dev' + - black ; extra == 'lint' - conda: https://conda.anaconda.org/conda-forge/linux-64/pango-1.56.4-hadf4263_0.conda sha256: 3613774ad27e48503a3a6a9d72017087ea70f1426f6e5541dbdb59a3b626eaaf md5: 79f71230c069a287efe3a8614069ddf1 @@ -5667,6 +6589,11 @@ packages: purls: [] size: 454854 timestamp: 1751292618315 +- pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl + name: pathspec + version: 0.12.1 + sha256: a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08 + requires_python: '>=3.8' - conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.46-h1321c63_0.conda sha256: 5c7380c8fd3ad5fc0f8039069a45586aa452cf165264bc5a437ad80397b32934 md5: 7fa07cb0fb1b625a089ccc01218ee5b1 @@ -5718,6 +6645,96 @@ packages: - pkg:pypi/pefile?source=hash-mapping size: 66610 timestamp: 1675867719479 +- pypi: https://files.pythonhosted.org/packages/23/85/397c73524e0cd212067e0c969aa245b01d50183439550d24d9f55781b776/pillow-11.3.0-cp313-cp313-win_amd64.whl + name: pillow + version: 11.3.0 + sha256: 0bce5c4fd0921f99d2e858dc4d4d64193407e1b99478bc5cacecba2311abde51 + requires_dist: + - furo ; extra == 'docs' + - olefile ; extra == 'docs' + - sphinx>=8.2 ; extra == 'docs' + - sphinx-autobuild ; extra == 'docs' + - sphinx-copybutton ; extra == 'docs' + - sphinx-inline-tabs ; extra == 'docs' + - sphinxext-opengraph ; extra == 'docs' + - olefile ; extra == 'fpx' + - olefile ; extra == 'mic' + - pyarrow ; extra == 'test-arrow' + - check-manifest ; extra == 'tests' + - coverage>=7.4.2 ; extra == 'tests' + - defusedxml ; extra == 'tests' + - markdown2 ; extra == 'tests' + - olefile ; extra == 'tests' + - packaging ; extra == 'tests' + - pyroma ; extra == 'tests' + - pytest ; extra == 'tests' + - pytest-cov ; extra == 'tests' + - pytest-timeout ; extra == 'tests' + - pytest-xdist ; extra == 'tests' + - trove-classifiers>=2024.10.12 ; extra == 'tests' + - typing-extensions ; python_full_version < '3.10' and extra == 'typing' + - defusedxml ; extra == 'xmp' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/40/fe/1bc9b3ee13f68487a99ac9529968035cca2f0a51ec36892060edcc51d06a/pillow-11.3.0-cp312-cp312-macosx_10_13_x86_64.whl + name: pillow + version: 11.3.0 + sha256: fdae223722da47b024b867c1ea0be64e0df702c5e0a60e27daad39bf960dd1e4 + requires_dist: + - furo ; extra == 'docs' + - olefile ; extra == 'docs' + - sphinx>=8.2 ; extra == 'docs' + - sphinx-autobuild ; extra == 'docs' + - sphinx-copybutton ; extra == 'docs' + - sphinx-inline-tabs ; extra == 'docs' + - sphinxext-opengraph ; extra == 'docs' + - olefile ; extra == 'fpx' + - olefile ; extra == 'mic' + - pyarrow ; extra == 'test-arrow' + - check-manifest ; extra == 'tests' + - coverage>=7.4.2 ; extra == 'tests' + - defusedxml ; extra == 'tests' + - markdown2 ; extra == 'tests' + - olefile ; extra == 'tests' + - packaging ; extra == 'tests' + - pyroma ; extra == 'tests' + - pytest ; extra == 'tests' + - pytest-cov ; extra == 'tests' + - pytest-timeout ; extra == 'tests' + - pytest-xdist ; extra == 'tests' + - trove-classifiers>=2024.10.12 ; extra == 'tests' + - typing-extensions ; python_full_version < '3.10' and extra == 'typing' + - defusedxml ; extra == 'xmp' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/e4/c9/06dd4a38974e24f932ff5f98ea3c546ce3f8c995d3f0985f8e5ba48bba19/pillow-11.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + name: pillow + version: 11.3.0 + sha256: 676b2815362456b5b3216b4fd5bd89d362100dc6f4945154ff172e206a22c024 + requires_dist: + - furo ; extra == 'docs' + - olefile ; extra == 'docs' + - sphinx>=8.2 ; extra == 'docs' + - sphinx-autobuild ; extra == 'docs' + - sphinx-copybutton ; extra == 'docs' + - sphinx-inline-tabs ; extra == 'docs' + - sphinxext-opengraph ; extra == 'docs' + - olefile ; extra == 'fpx' + - olefile ; extra == 'mic' + - pyarrow ; extra == 'test-arrow' + - check-manifest ; extra == 'tests' + - coverage>=7.4.2 ; extra == 'tests' + - defusedxml ; extra == 'tests' + - markdown2 ; extra == 'tests' + - olefile ; extra == 'tests' + - packaging ; extra == 'tests' + - pyroma ; extra == 'tests' + - pytest ; extra == 'tests' + - pytest-cov ; extra == 'tests' + - pytest-timeout ; extra == 'tests' + - pytest-xdist ; extra == 'tests' + - trove-classifiers>=2024.10.12 ; extra == 'tests' + - typing-extensions ; python_full_version < '3.10' and extra == 'typing' + - defusedxml ; extra == 'xmp' + requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.46.4-h54a6638_1.conda sha256: 43d37bc9ca3b257c5dd7bf76a8426addbdec381f6786ff441dc90b1a49143b6a md5: c01af13bdc553d1a8fbfff6e8db075f0 @@ -5911,15 +6928,15 @@ packages: purls: [] size: 2348171 timestamp: 1675353652214 -- pypi: https://files.pythonhosted.org/packages/61/99/d606cb7986b60d89c36de8a85d58764323b3a5ff07770a99d8e993b3fa73/propcache-0.3.2-cp313-cp313-macosx_10_13_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/37/7c/54fd5301ef38505ab235d98827207176a5c9b2aa61939b10a460ca53e123/propcache-0.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl name: propcache version: 0.3.2 - sha256: 9ecb0aad4020e275652ba3975740f241bd12a61f1a784df044cf7477a02bc252 + sha256: ee6f22b6eaa39297c751d0e80c0d3a454f112f5c6481214fcf4c092074cecd67 requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/af/81/b324c44ae60c56ef12007105f1460d5c304b0626ab0cc6b07c8f2a9aa0b8/propcache-0.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/af/6e/21293133beb550f9c901bbece755d582bfaf2176bee4774000bd4dd41884/propcache-0.3.2-cp312-cp312-macosx_10_13_x86_64.whl name: propcache version: 0.3.2 - sha256: 4c1396592321ac83157ac03a2023aa6cc4a3cc3cfdecb71090054c09e5a7cce3 + sha256: 28710b0d3975117239c76600ea351934ac7b5ff56e60953474342608dbbb6154 requires_python: '>=3.9' - pypi: https://files.pythonhosted.org/packages/d3/f5/b369e026b09a26cd77aa88d8fffd69141d2ae00a2abaaf5380d2603f4b7f/propcache-0.3.2-cp313-cp313-win_amd64.whl name: propcache @@ -5957,14 +6974,14 @@ packages: version: 1.27.0 sha256: b0349d744c068b6644ae23da6ada111c8a8a7e323b56cbce3707cba5bdb474cc requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/0b/db/35843050a3dd7586781497a21ca6c8d48111afb66061cb40c3d3c288596d/pyclipper-1.3.0.post6-cp313-cp313-macosx_10_13_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/76/65/cb014acc41cd5bf6bbfa4671c7faffffb9cee01706642c2dec70c5209ac8/pyclipper-1.3.0.post6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl name: pyclipper version: 1.3.0.post6 - sha256: 188fbfd1d30d02247f92c25ce856f5f3c75d841251f43367dbcf10935bc48f38 -- pypi: https://files.pythonhosted.org/packages/31/10/c0bf140bee2844e2c0617fdcc8a4e8daf98e71710046b06034e6f1963404/pyclipper-1.3.0.post6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 58eae2ff92a8cae1331568df076c4c5775bf946afab0068b217f0cf8e188eb3c +- pypi: https://files.pythonhosted.org/packages/8e/8e/eb14eadf054494ad81446e21c4ea163b941747610b0eb9051644395f567e/pyclipper-1.3.0.post6-cp312-cp312-macosx_10_13_x86_64.whl name: pyclipper version: 1.3.0.post6 - sha256: 5c9c80b5c46eef38ba3f12dd818dc87f5f2a0853ba914b6f91b133232315f526 + sha256: 32cd7fb9c1c893eb87f82a072dbb5e26224ea7cebbad9dc306d67e1ac62dd229 - pypi: https://files.pythonhosted.org/packages/d5/19/9ff4551b42f2068686c50c0d199072fa67aee57fc5cf86770cacf71efda3/pyclipper-1.3.0.post6-cp313-cp313-win_amd64.whl name: pyclipper version: 1.3.0.post6 @@ -6014,9 +7031,9 @@ packages: - pre-commit ; extra == 'dev' - pygobject ; extra == 'dev' requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/linux-64/pyinstaller-6.16.0-py313h2ed12c8_0.conda - sha256: dabf7946a0534fb705c12a5445ed6dc9dffc195bdd910d037809e0d1c870fbdb - md5: 482dda1504b5789086cb28d758d0b04e +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyinstaller-6.16.0-py312hdd98396_0.conda + sha256: 4f7d46283f9d11a6621ad0dfbdcab1dbd2a54cedd11c691cd8b85219f80f4926 + md5: 8bdf94a7a265cb93880474c5975b0431 depends: - __glibc >=2.17,<3.0.a0 - altgraph @@ -6024,18 +7041,18 @@ packages: - libzlib >=1.3.1,<2.0a0 - packaging >=22.0 - pyinstaller-hooks-contrib >=2025.8 - - python >=3.13,<3.14.0a0 - - python_abi 3.13.* *_cp313 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 - setuptools >=42.0.0 license: GPL-2.0-or-later WITH Bootloader-exception license_family: GPL purls: - pkg:pypi/pyinstaller?source=hash-mapping - size: 1674667 - timestamp: 1758195819701 -- conda: https://conda.anaconda.org/conda-forge/osx-64/pyinstaller-6.16.0-py313h472b75b_0.conda - sha256: a3fb31072953ce1111b6636e66b0171d378bfe34a61719f46efdd6a0a2415a5d - md5: 5f7e600b34005d7367f006fe514b44d2 + size: 1661832 + timestamp: 1758195762403 +- conda: https://conda.anaconda.org/conda-forge/osx-64/pyinstaller-6.16.0-py312h1e69131_0.conda + sha256: 1d0e5e0a6e1e8c159435aabf5f105e7f1ff1eae129d31f4638a564c7fe7ba33b + md5: 464fd91500d0dce6f89747d98c72e40f depends: - __osx >=10.13 - altgraph @@ -6043,15 +7060,15 @@ packages: - macholib >=1.8 - packaging >=22.0 - pyinstaller-hooks-contrib >=2025.8 - - python >=3.13,<3.14.0a0 - - python_abi 3.13.* *_cp313 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 - setuptools >=42.0.0 license: GPL-2.0-or-later WITH Bootloader-exception license_family: GPL purls: - pkg:pypi/pyinstaller?source=hash-mapping - size: 1694333 - timestamp: 1758196225786 + size: 1685096 + timestamp: 1758196096708 - conda: https://conda.anaconda.org/conda-forge/win-64/pyinstaller-6.16.0-py313h1175282_0.conda sha256: 8780e4e4f3f22c8b6b19983daca3b9b1746173903215d0bea74bb6bf50ed21d2 md5: aede38ba6a2cff3deb2b226264121928 @@ -6088,6 +7105,15 @@ packages: - pkg:pypi/pyinstaller-hooks-contrib?source=hash-mapping size: 154671 timestamp: 1758727917140 +- pypi: https://files.pythonhosted.org/packages/e4/06/43084e6cbd4b3bc0e80f6be743b2e79fbc6eed8de9ad8c629939fa55d972/pymdown_extensions-10.16.1-py3-none-any.whl + name: pymdown-extensions + version: 10.16.1 + sha256: d6ba157a6c03146a7fb122b2b9a121300056384eafeec9c9f9e584adfdb2a32d + requires_dist: + - markdown>=3.6 + - pyyaml + - pygments>=2.19.1 ; extra == 'extra' + requires_python: '>=3.9' - pypi: https://files.pythonhosted.org/packages/92/44/8634af40b0db528b5b37e901c0dc67321354880d251bf8965901d57693a5/PyOpenGL-3.1.9-py3-none-any.whl name: pyopengl version: 3.1.9 @@ -6096,10 +7122,10 @@ packages: name: pyopengl-accelerate version: 3.1.9 sha256: ed02cc9abd7662e787bc7491bf7f78f6536cf550a148d0fbff6727bed9b57124 -- pypi: https://files.pythonhosted.org/packages/6a/95/22c07ec2414928ddb50eb0e35d6cd6343ffef6ad74f42e86fefbaaa6b04e/PyOpenGL_accelerate-3.1.9-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/42/ae/67ddc9674d07c1900b0f094a16d2fa996492ffb25ad974e5af4e53dcad22/PyOpenGL_accelerate-3.1.9-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl name: pyopengl-accelerate version: 3.1.9 - sha256: 10ab017316dc8bced13b2426b9cc6ab9aeb627ca020e9bc0836ef92b5e0942ea + sha256: 2b6f1f3680f33f10e67bb679ac0fb6946905a22e52d2eba71a66bf9d3ef94b33 - pypi: https://files.pythonhosted.org/packages/9d/9e/a87f972148971c785773dcc792226530ff78840420e34b3cc51b221693a2/pyopengl_accelerate-3.1.9.tar.gz name: pyopengl-accelerate version: 3.1.9 @@ -6208,57 +7234,55 @@ packages: - pytest-asyncio ; extra == 'dev' - tox ; extra == 'dev' requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.7-h2b335a9_100_cp313.conda - build_number: 100 - sha256: 16cc30a5854f31ca6c3688337d34e37a79cdc518a06375fe3482ea8e2d6b34c8 - md5: 724dcf9960e933838247971da07fe5cf +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.11-h9e4cc4f_0_cpython.conda + sha256: 6cca004806ceceea9585d4d655059e951152fc774a471593d4f5138e6a54c81d + md5: 94206474a5608243a10c92cefbe0908f depends: - __glibc >=2.17,<3.0.a0 - bzip2 >=1.0.8,<2.0a0 - ld_impl_linux-64 >=2.36.1 - - libexpat >=2.7.1,<3.0a0 + - libexpat >=2.7.0,<3.0a0 - libffi >=3.4.6,<3.5.0a0 - - libgcc >=14 + - libgcc >=13 - liblzma >=5.8.1,<6.0a0 - - libmpdec >=4.0.0,<5.0a0 - - libsqlite >=3.50.4,<4.0a0 + - libnsl >=2.0.1,<2.1.0a0 + - libsqlite >=3.50.0,<4.0a0 - libuuid >=2.38.1,<3.0a0 + - libxcrypt >=4.4.36 - libzlib >=1.3.1,<2.0a0 - ncurses >=6.5,<7.0a0 - - openssl >=3.5.2,<4.0a0 - - python_abi 3.13.* *_cp313 + - openssl >=3.5.0,<4.0a0 - readline >=8.2,<9.0a0 - tk >=8.6.13,<8.7.0a0 - tzdata + constrains: + - python_abi 3.12.* *_cp312 license: Python-2.0 purls: [] - size: 33583088 - timestamp: 1756911465277 - python_site_packages_path: lib/python3.13/site-packages -- conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.13.7-h5eba815_100_cp313.conda - build_number: 100 - sha256: 581e4db7462c383fbb64d295a99a3db73217f8c24781cbe7ab583ff9d0305968 - md5: 1759e1c9591755521bd50489756a599d + size: 31445023 + timestamp: 1749050216615 +- conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.12.11-h9ccd52b_0_cpython.conda + sha256: ebda5b5e8e25976013fdd81b5ba253705b076741d02bdc8ab32763f2afb2c81b + md5: 06049132ecd09d0c1dc3d54d93cf1d5d depends: - __osx >=10.13 - bzip2 >=1.0.8,<2.0a0 - - libexpat >=2.7.1,<3.0a0 + - libexpat >=2.7.0,<3.0a0 - libffi >=3.4.6,<3.5.0a0 - liblzma >=5.8.1,<6.0a0 - - libmpdec >=4.0.0,<5.0a0 - - libsqlite >=3.50.4,<4.0a0 + - libsqlite >=3.50.0,<4.0a0 - libzlib >=1.3.1,<2.0a0 - ncurses >=6.5,<7.0a0 - - openssl >=3.5.2,<4.0a0 - - python_abi 3.13.* *_cp313 + - openssl >=3.5.0,<4.0a0 - readline >=8.2,<9.0a0 - tk >=8.6.13,<8.7.0a0 - tzdata + constrains: + - python_abi 3.12.* *_cp312 license: Python-2.0 purls: [] - size: 12575616 - timestamp: 1756911460182 - python_site_packages_path: lib/python3.13/site-packages + size: 13571569 + timestamp: 1749049058713 - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.13.7-hdf00ec1_100_cp313.conda build_number: 100 sha256: b86b5b3a960de2fff0bb7e0932b50846b22b75659576a257b1872177aab444cd @@ -6283,6 +7307,24 @@ packages: size: 16386672 timestamp: 1756909324921 python_site_packages_path: Lib/site-packages +- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl + name: python-dateutil + version: 2.9.0.post0 + sha256: a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 + requires_dist: + - six>=1.5 + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*' +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda + build_number: 8 + sha256: 80677180dd3c22deb7426ca89d6203f1c7f1f256f2d5a94dc210f6e758229809 + md5: c3efd25ac4d74b1584d2f7a57195ddf1 + constrains: + - python 3.12.* *_cpython + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 6958 + timestamp: 1752805918820 - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda build_number: 8 sha256: 210bffe7b121e651419cb196a2a63687b087497595c9be9d20ebe97dd06060a7 @@ -6338,21 +7380,28 @@ packages: - pkg:pypi/pywin32-ctypes?source=hash-mapping size: 57622 timestamp: 1755891964298 -- pypi: https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl name: pyyaml version: 6.0.2 - sha256: 70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5 + sha256: c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab requires_python: '>=3.8' -- pypi: https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl name: pyyaml version: 6.0.2 - sha256: efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba + sha256: 80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476 requires_python: '>=3.8' - pypi: https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl name: pyyaml version: 6.0.2 sha256: 8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563 requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl + name: pyyaml-env-tag + version: '1.1' + sha256: 17109e1a528561e32f026364712fee1264bc2ea6715120891174ed1b980d2e04 + requires_dist: + - pyyaml + requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/linux-64/rav1e-0.7.1-h8fae777_3.conda sha256: 6e5e704c1c21f820d760e56082b276deaf2b53cf9b751772761c3088a365f6f4 md5: 2c42649888aac645608191ffdc80d13a @@ -6392,7 +7441,7 @@ packages: timestamp: 1746622805379 - pypi: ./ name: rayforge - version: 0.22.post138+git.863e65ee.dirty + version: 0.22.post160+git.c5e4b363.dirty sha256: 4d95bd5006eed225238af03b8f81304da33a52111678ebf629a21010a5e52b73 requires_dist: - aiohttp==3.12.14 @@ -6442,10 +7491,22 @@ packages: purls: [] size: 256712 timestamp: 1740379577668 -- pypi: https://files.pythonhosted.org/packages/03/5a/fc34bf1aa14dc7c0e701691fa8685f3faec80e57d816615e3625f28feb43/scipy-1.15.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl + name: requests + version: 2.32.5 + sha256: 2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6 + requires_dist: + - charset-normalizer>=2,<4 + - idna>=2.5,<4 + - urllib3>=1.21.1,<3 + - certifi>=2017.4.17 + - pysocks>=1.5.6,!=1.5.7 ; extra == 'socks' + - chardet>=3.0.2,<6 ; extra == 'use-chardet-on-py3' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/0d/76/77cf2ac1f2a9cc00c073d49e1e16244e389dd88e2490c91d84e1e3e4d126/scipy-1.15.2-cp313-cp313-win_amd64.whl name: scipy version: 1.15.2 - sha256: fb530e4794fc8ea76a4a21ccb67dea33e5e0e60f07fc38a49e821e1eae3b71a0 + sha256: a5080a79dfb9b78b768cebf3c9dcbc7b665c5875793569f48bf0e2b1d7f68f6f requires_dist: - numpy>=1.23.5,<2.5 - pytest ; extra == 'test' @@ -6485,10 +7546,10 @@ packages: - doit>=0.36.0 ; extra == 'dev' - pydevtool ; extra == 'dev' requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/0d/76/77cf2ac1f2a9cc00c073d49e1e16244e389dd88e2490c91d84e1e3e4d126/scipy-1.15.2-cp313-cp313-win_amd64.whl +- pypi: https://files.pythonhosted.org/packages/4b/5d/3c78815cbab499610f26b5bae6aed33e227225a9fa5290008a733a64f6fc/scipy-1.15.2-cp312-cp312-macosx_10_13_x86_64.whl name: scipy version: 1.15.2 - sha256: a5080a79dfb9b78b768cebf3c9dcbc7b665c5875793569f48bf0e2b1d7f68f6f + sha256: c4697a10da8f8765bb7c83e24a470da5797e37041edfd77fd95ba3811a47c4fd requires_dist: - numpy>=1.23.5,<2.5 - pytest ; extra == 'test' @@ -6528,10 +7589,10 @@ packages: - doit>=0.36.0 ; extra == 'dev' - pydevtool ; extra == 'dev' requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/53/40/09319f6e0f276ea2754196185f95cd191cb852288440ce035d5c3a931ea2/scipy-1.15.2-cp313-cp313-macosx_10_13_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/c0/53/eaada1a414c026673eb983f8b4a55fe5eb172725d33d62c1b21f63ff6ca4/scipy-1.15.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl name: scipy version: 1.15.2 - sha256: 01edfac9f0798ad6b46d9c4c9ca0e0ad23dbf0b1eb70e96adb9fa7f525eff0bf + sha256: 2b871df1fe1a3ba85d90e22742b93584f8d2b8e6124f8372ab15c71b73e428b8 requires_dist: - numpy>=1.23.5,<2.5 - pytest ; extra == 'test' @@ -6571,6 +7632,24 @@ packages: - doit>=0.36.0 ; extra == 'dev' - pydevtool ; extra == 'dev' requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/0e/17/5a3951da22a4ad8f959088ddc370c68b28dad03190d91fcd137a52410fb9/selectolax-0.3.29-cp313-cp313-win_amd64.whl + name: selectolax + version: 0.3.29 + sha256: e13befacff5f78102aa11465055ecb6d4b35f89663e36f271f2b506bcab14112 + requires_dist: + - cython==3.0.11 ; extra == 'cython' +- pypi: https://files.pythonhosted.org/packages/36/25/64c60da9aec81f2992355b0a3ce00ea1ed99e6f5499868016d6972bd4948/selectolax-0.3.29-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: selectolax + version: 0.3.29 + sha256: 8377c317bf1d5fd6ccc56dfb5a0928bbcbea3e800b7af54761cfbbb99dc94cb9 + requires_dist: + - cython==3.0.11 ; extra == 'cython' +- pypi: https://files.pythonhosted.org/packages/b8/46/2dcae03a94f80f3e0d339c149de8110b5abe1230668b015fd338d9e71a27/selectolax-0.3.29-cp312-cp312-macosx_10_13_x86_64.whl + name: selectolax + version: 0.3.29 + sha256: 97b9971bb37b54ef4440134f22792d15c9ee12d890a526a7fe0b376502240143 + requires_dist: + - cython==3.0.11 ; extra == 'cython' - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda sha256: 972560fcf9657058e3e1f97186cc94389144b46dbdf58c807ce62e83f977e863 md5: 4de79c071274a53dcaf2a8c749d1499e @@ -6582,6 +7661,11 @@ packages: - pkg:pypi/setuptools?source=hash-mapping size: 748788 timestamp: 1748804951958 +- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl + name: six + version: 1.17.0 + sha256: 4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*' - conda: https://conda.anaconda.org/conda-forge/noarch/svgelements-1.9.6-pyhd8ed1ab_0.conda sha256: 3bb745d94bc632a6213b252f9e167d0e99d4ca5bd6126b6fbb7f5eac69116dd0 md5: 91460757d3d2c631f1a25d1e42921ad1 @@ -6628,6 +7712,17 @@ packages: purls: [] size: 1862756 timestamp: 1756086862067 +- pypi: https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl + name: tinycss2 + version: 1.4.0 + sha256: 3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289 + requires_dist: + - webencodings>=0.4 + - sphinx ; extra == 'doc' + - sphinx-rtd-theme ; extra == 'doc' + - pytest ; extra == 'test' + - ruff ; extra == 'test' + requires_python: '>=3.8' - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_hd72426e_102.conda sha256: a84ff687119e6d8752346d1d408d5cf360dee0badd487a472aa8ddedfdc219e1 md5: a0116df4f4ed05c303811a837d5b39d8 @@ -6704,6 +7799,17 @@ packages: purls: [] size: 694692 timestamp: 1756385147981 +- pypi: https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl + name: urllib3 + version: 2.5.0 + sha256: e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc + requires_dist: + - brotli>=1.0.9 ; platform_python_implementation == 'CPython' and extra == 'brotli' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'brotli' + - h2>=4,<5 ; extra == 'h2' + - pysocks>=1.5.6,!=1.5.7,<2.0 ; extra == 'socks' + - zstandard>=0.18.0 ; extra == 'zstd' + requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_31.conda sha256: cb357591d069a1e6cb74199a8a43a7e3611f72a6caed9faa49dbb3d7a0a98e0b md5: 28f4ca1e0337d0f27afb8602663c5723 @@ -6741,6 +7847,16 @@ packages: purls: [] size: 113963 timestamp: 1753739198723 +- pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + name: verspec + version: 0.1.0 + sha256: 741877d5633cc9464c45a469ae2a31e801e6dbbaa85b9675d481cda100f11c31 + requires_dist: + - coverage ; extra == 'test' + - flake8>=3.7 ; extra == 'test' + - mypy ; extra == 'test' + - pretend ; extra == 'test' + - pytest ; extra == 'test' - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.44.35208-h38c0c73_31.conda sha256: 8b20152d00e1153ccb1ed377a160110482f286a6d85a82b57ffcd60517d523a7 md5: d75abcfbc522ccd98082a8c603fce34c @@ -6751,11 +7867,42 @@ packages: purls: [] size: 18249 timestamp: 1753739241918 +- pypi: https://files.pythonhosted.org/packages/96/24/07a0a4d12d31c49513823a15deea3c735580819eb67af914676df5cb9c8e/vtracer-0.6.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: vtracer + version: 0.6.11 + sha256: 1f804d3b4f23b512a5bcf687944e1eb7a38069e0b2bec4edf4ae9810a13d5953 + requires_python: '>=3.7' - pypi: https://files.pythonhosted.org/packages/e8/ad/2c89d6f2858ec8a1ac093144ebe6cfefc9307920ce95ad4ff045bb72b228/vtracer-0.6.11.tar.gz name: vtracer version: 0.6.11 sha256: 407e147362366e14e2666155bf328814bdc345899a6cce18a7729724ff25c01e requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/ec/78/f91da19e1f4769317fe14a6bacb2be9e21b8fa6262dbd7021e2ab33545f8/vtracer-0.6.11-cp312-cp312-macosx_10_12_x86_64.whl + name: vtracer + version: 0.6.11 + sha256: 4ac53a37dd1729f16ed64feae4f40b8dae1cf61dfe0d6bf26e9d399d48a25250 + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/12/87/48361531f70b1f87928b045df868a9fd4e253d9ae087fa4cf3f7113be363/watchdog-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl + name: watchdog + version: 6.0.0 + sha256: c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860 + requires_dist: + - pyyaml>=3.10 ; extra == 'watchmedo' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl + name: watchdog + version: 6.0.0 + sha256: 20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2 + requires_dist: + - pyyaml>=3.10 ; extra == 'watchmedo' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl + name: watchdog + version: 6.0.0 + sha256: cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680 + requires_dist: + - pyyaml>=3.10 ; extra == 'watchmedo' + requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/linux-64/wayland-1.24.0-h3e06ad9_0.conda sha256: ba673427dcd480cfa9bbc262fd04a9b1ad2ed59a159bd8f7e750d4c52282f34c md5: 0f2ca7906bf166247d1d760c3422cb8a @@ -6770,20 +7917,24 @@ packages: purls: [] size: 330474 timestamp: 1751817998141 +- pypi: https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl + name: webencodings + version: 0.5.1 + sha256: a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 - pypi: https://files.pythonhosted.org/packages/14/13/8b7fc4cb551b9cfd9890f0fd66e53c18a06240319915533b033a56a3d520/websockets-14.2-cp313-cp313-win_amd64.whl name: websockets version: '14.2' sha256: b439ea828c4ba99bb3176dc8d9b933392a2413c0f6b149fdcba48393f573377f requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/2c/3c/bf9b2c396ed86a0b4a92ff4cdaee09753d3ee389be738e92b9bbd0330b64/websockets-14.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/81/da/72f7caabd94652e6eb7e92ed2d3da818626e70b4f2b15a854ef60bf501ec/websockets-14.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl name: websockets version: '14.2' - sha256: 669c3e101c246aa85bc8534e495952e2ca208bd87994650b90a23d745902db9a + sha256: a39d7eceeea35db85b85e1169011bb4321c32e673920ae9c1b6e0978590012a3 requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/8e/b7/7484905215627909d9a79ae07070057afe477433fdacb59bf608ce86365a/websockets-14.2-cp313-cp313-macosx_10_13_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/ec/c5/de30e88557e4d70988ed4d2eabd73fd3e1e52456b9f3a4e9564d86353b6d/websockets-14.2-cp312-cp312-macosx_10_13_x86_64.whl name: websockets version: '14.2' - sha256: 4da98b72009836179bb596a92297b1a61bb5a830c0e483a7d0766d45070a08ad + sha256: 647b573f7d3ada919fd60e64d533409a79dcf1ea21daeb4542d1d996519ca967 requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/linux-64/x265-3.5-h924138e_3.tar.bz2 sha256: 76c7405bcf2af639971150f342550484efac18219c0203c5ee2e38b8956fe2a0 @@ -7266,19 +8417,19 @@ packages: purls: [] size: 73315 timestamp: 1726845753874 -- pypi: https://files.pythonhosted.org/packages/af/44/46407d7f7a56e9a85a4c207724c9f2c545c060380718eea9088f222ba697/yarl-1.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/67/38/688577a1cb1e656e3971fb66a3492501c5a5df56d99722e57c98249e5b8a/yarl-1.20.1-cp312-cp312-macosx_10_13_x86_64.whl name: yarl version: 1.20.1 - sha256: d1a4fbb50e14396ba3d375f68bfe02215d8e7bc3ec49da8341fe3157f59d2ff5 + sha256: b29a2c385a5f5b9c7d9347e5812b6f7ab267193c62d282a540b4fc528c8a9d2a requires_dist: - idna>=2.0 - multidict>=4.0 - propcache>=0.2.1 requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/b2/27/584394e1cb76fb771371770eccad35de400e7b434ce3142c2dd27392c968/yarl-1.20.1-cp313-cp313-macosx_10_13_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/98/28/3ab7acc5b51f4434b181b0cee8f1f4b77a65919700a355fb3617f9488874/yarl-1.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl name: yarl version: 1.20.1 - sha256: 14f326acd845c2b2e2eb38fb1346c94f7f3b01a4f5c788f8144f9b630bfff9a3 + sha256: a97d67108e79cfe22e2b430d80d7571ae57d19f17cda8bb967057ca8a7bf5bfd requires_dist: - idna>=2.0 - multidict>=4.0 diff --git a/pixi.toml b/pixi.toml index ac6c78cda..19edd2da5 100644 --- a/pixi.toml +++ b/pixi.toml @@ -7,6 +7,7 @@ platforms = ["linux-64", "osx-64", "win-64"] [environments] default = { features = ["test"], solve-group = "default" } windows-build = { features = ["windows-build", "test"], solve-group = "default" } +docs = { features = ["docs"], solve-group = "default" } [dependencies] adwaita-icon-theme = "*" @@ -79,6 +80,14 @@ pytest-cov = "*" pygobject-stubs = "*" flake8 = "*" + +[feature.docs.pypi-dependencies] +mkdocs-material = ">=9.5" +mkdocs-glightbox = "*" +mike = ">=2.0" +pillow = "*" +cairosvg = "*" + [feature.windows-build.dependencies] pyinstaller = "*" @@ -93,8 +102,8 @@ cmd = "rayforge" env = { GI_TYPELIB_PATH = "$(pkgconf --variable=typelibdir gobject-introspection-1.0)"} cmd = "pytest -v" -[tasks] +[tasks] lint = "flake8 --ignore=E127,E128,E121,E123,E126,E203,E226,E24,E704,W503,W504 --builtins=_ rayforge" update-translations = "bash scripts/update_translations.sh" compile-translations = "bash scripts/update_translations.sh --compile-only" @@ -142,3 +151,23 @@ depends-on = ["compile-translations"] # Builds a source package, ready for upload to a PPA. cmd = "bash scripts/build-deb.sh --source" depends-on = ["compile-translations"] + +# Documentation tasks - these wrap the feature.docs tasks for convenience +[tasks.docs-serve] +cmd = "pixi run -e docs _docs-serve" + +[tasks.docs-build] +cmd = "pixi run -e docs _docs-build" + +[tasks.docs-deploy] +cmd = "pixi run -e docs _docs-deploy" + +# Internal docs tasks (called by the wrapper tasks above) +[feature.docs.tasks._docs-serve] +cmd = "mkdocs serve" + +[feature.docs.tasks._docs-build] +cmd = "mkdocs build" + +[feature.docs.tasks._docs-deploy] +cmd = "mike deploy --push --update-aliases $VERSION latest" diff --git a/scripts/scrub_non_utf8.py b/scripts/scrub_non_utf8.py new file mode 100644 index 000000000..6c2ead6dc --- /dev/null +++ b/scripts/scrub_non_utf8.py @@ -0,0 +1,49 @@ + +import sys +import os + +def scrub_file(filepath): + """ + Reads a file, removes non-UTF-8 characters, and writes it back. + """ + try: + if not os.path.isfile(filepath): + print(f"Skipping directory: {filepath}") + return + + # Read as bytes + with open(filepath, 'rb') as f: + original_bytes = f.read() + + # Decode to string, ignoring errors + cleaned_string = original_bytes.decode('utf-8', 'ignore') + + # Encode back to bytes + cleaned_bytes = cleaned_string.encode('utf-8') + + if original_bytes != cleaned_bytes: + print(f"Scrubbing non-UTF-8 characters from {filepath}") + with open(filepath, 'wb') as f: + f.write(cleaned_bytes) + else: + print(f"No changes needed for {filepath}") + + + except Exception as e: + print(f"Error processing {filepath}: {e}", file=sys.stderr) + +if __name__ == "__main__": + if len(sys.argv) < 2: + print("Usage: python scrub_non_utf8.py ...", file=sys.stderr) + sys.exit(1) + + for path_arg in sys.argv[1:]: + if os.path.isdir(path_arg): + for dirpath, _, filenames in os.walk(path_arg): + for filename in filenames: + filepath = os.path.join(dirpath, filename) + scrub_file(filepath) + elif os.path.isfile(path_arg): + scrub_file(path_arg) + else: + print(f"Path not found: {path_arg}", file=sys.stderr) From 6f639095b5e3d3ad20ecf52a421995967b787d83 Mon Sep 17 00:00:00 2001 From: Kyle Heath Date: Fri, 3 Oct 2025 20:05:59 -0700 Subject: [PATCH 2/4] feat: add branch_name input to workflow_dispatch for flexibility --- .github/workflows/docs.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 6a5e57b86..226265b26 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -10,6 +10,12 @@ on: branches: - main workflow_dispatch: + inputs: + branch_name: + description: 'Branch to run workflow on' + required: true + default: 'feature/mkdocs' + permissions: contents: write From aa8af1a69c7cccdc32fc4d3bfd48a92287bb91e3 Mon Sep 17 00:00:00 2001 From: Kyle Heath Date: Fri, 3 Oct 2025 20:16:56 -0700 Subject: [PATCH 3/4] fix: add mkdocs-glightbox to dependencies for enhanced documentation features --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 226265b26..5a5a82db3 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -40,7 +40,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install mkdocs-material mike pillow cairosvg + pip install mkdocs-material mike pillow cairosvg mkdocs-glightbox - name: Configure Git for mike run: | From b1d633e2966ddda2c1f5aab8b88ee3416c6cd4cb Mon Sep 17 00:00:00 2001 From: Kyle Heath Date: Fri, 3 Oct 2025 20:27:15 -0700 Subject: [PATCH 4/4] fix: remove strict flag from mkdocs build command for improved flexibility --- .github/workflows/docs.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 5a5a82db3..809aeb8af 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -63,7 +63,8 @@ jobs: - name: Build documentation for pull request if: github.event_name == 'pull_request' - run: mkdocs build --strict + run: mkdocs build + #run: mkdocs build --strict - name: Deploy development docs if: github.event_name == 'push' && github.ref == 'refs/heads/main'