基于二值化图像转GCode的单向扫描实现

  • 基于二值化图像转GCode的单向扫描实现
    • 什么是单向扫描
    • 单向扫描代码示例

基于二值化图像转GCode的单向扫描实现

什么是单向扫描

激光雕刻单向扫描

在激光雕刻中,单向扫描(Unidirectional Scanning)是一种雕刻技术,其中激光头只在一个方向上移动,而不是来回移动。这种移动方式主要应用于通过激光逐行扫描图像表面的过程。

具体而言,单向扫描的过程通常包括以下步骤:

  1. 横向移动(X轴): 激光头沿X轴方向移动到图像的一侧。

  2. 纵向移动(Y轴): 激光头沿Y轴方向开始逐行移动,刻蚀图像表面。这一过程是单向的,即在每一行上激光头只在一个方向上移动。

  3. 返回横向移动: 一旦一行完成,激光头返回到图像的一侧,准备进行下一行的刻蚀。

  4. 循环重复: 重复以上步骤,直到整个图像都被刻蚀完成。

相比于双向扫描,单向扫描通常更加简单,因为它只需沿一个方向移动。然而,它的缺点是激光头在返回时的空闲时间较多,可能导致整体雕刻速度较慢。选择使用单向或双向扫描通常取决于具体的激光雕刻机型和雕刻需求。

总体而言,单向扫描是一种常见的激光雕刻方式,特别适用于需要简单操作且对雕刻速度要求不是很高的场景。

单向扫描代码示例

#include <optional>
#include <string>
#include <print>
#include <format>
#include <vector>
#include <fstream>
#include <ranges>

struct G0 {
    std::optional<float> x, y;
    std::optional<int> s;

    std::string toString() {
        std::string command = "G0";
        if(x.has_value()) {
            command += std::format(" X{:.3f}", x.value());
        }
        if(y.has_value()) {
            command += std::format(" Y{:.3f}", y.value());
        }
        if(s.has_value()) {
            command += std::format(" S{:d}", s.value());
        }
        return command;
    }

    explicit operator std::string() const {
        std::string command = "G0";
        if(x.has_value()) {
            command += std::format(" X{:.3f}", x.value());
        }
        if(y.has_value()) {
            command += std::format(" Y{:.3f}", y.value());
        }
        if(s.has_value()) {
            command += std::format(" S{:d}", s.value());
        }
        return command;
    }
};

struct G1 {
    std::optional<float> x, y;
    std::optional<int> s;

    std::string toString() {
        std::string command = "G1";
        if(x.has_value()) {
            command += std::format(" X{:.3f}", x.value());
        }
        if(y.has_value()) {
            command += std::format(" Y{:.3f}", y.value());
        }
        if(s.has_value()) {
            command += std::format(" S{:d}", s.value());
        }
        return command;
    }

    explicit operator std::string() const {
        std::string command = "G1";
        if(x.has_value()) {
            command += std::format(" X{:.3f}", x.value());
        }
        if(y.has_value()) {
            command += std::format(" Y{:.3f}", y.value());
        }
        if(s.has_value()) {
            command += std::format(" S{:d}", s.value());
        }
        return command;
    }
};

inline bool ExportGCode(const std::string &fileName, std::vector<std::string> &&gcode) {
    std::fstream file;
    file.open(fileName, std::ios_base::out | std::ios_base::trunc);
    if(!file.is_open()) {
        return false;
    }

    for(auto &&v: gcode | std::views::transform([](auto item) { return item += "\n"; })) {
        file.write(v.c_str(), v.length());
    }

    return true;
}

int main() {
    constexpr int imageWidth  = 10;
    constexpr int imageHeight = 10;
    // clang-format off
    // 假设图像数据,0表示非激光刻蚀部分,1表示进行激光刻蚀的区域
    constexpr int image[imageWidth][imageHeight] = {
        {0, 1, 1, 1, 0, 1, 1, 1, 0, 0}, // G0 G1 G1 G1 G0 G1 G1 G1 G0 G0
        {1, 0, 1, 0, 1, 0, 1, 0, 1, 0},
        {1, 1, 1, 0, 0, 1, 1, 1, 1, 1},
        {0, 0, 1, 1, 1, 1, 1, 0, 0, 0},
        {1, 1, 0, 0, 1, 0, 0, 1, 1, 1},
        {0, 1, 1, 0, 0, 1, 0, 0, 0, 0},
        {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
        {1, 0, 0, 0, 1, 0, 1, 0, 0, 0},
        {0, 1, 0, 1, 0, 1, 0, 1, 0, 1},
        {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
    };
    // clang-format on

    std::vector<std::string> command;
    for(int y = 0; y < imageHeight; ++y) {
        command.emplace_back(G0 {0, y, 0});
        for(int x = 0; x < imageWidth; ++x) {
            if(auto const value = image[y][x];value) {
                command.emplace_back(G1 {x, std::nullopt, 1000});  // 最大激光功率 S=1000
            } else {
                command.emplace_back(G0 {x, std::nullopt, 0});
            }
        }
    }

    // 导出GCode
    ExportGCode("gcode.nc",std::move(command));
    std::println("Export data to gcode.nc");
    return 0;
}

激光雕刻单向扫描仿真

上述示例展示了一个10x10的二维图像数据,其中0表示非激光刻蚀部分,1表示进行激光刻蚀的区域。通过遍历图像数据,代码生成了相应的G代码指令序列,用于描述激光头在工件表面的运动路径。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/359549.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Vue】二、Vue 组件展示控制的优雅解决方案

vue项目中展示的组件&#xff0c;我平常都是通过v-show进行展示控制&#xff0c;类似这样 通常情况下&#xff0c;一个正常展示组件的流程&#xff0c;是通过前端用户点击触发函数&#xff0c;在函数中对data数据进行操作&#xff0c;从而展示不同的页面 showWork: false, sho…

如何用Docker+jenkins 运行 python 自动化?

1.在 Linux 服务器安装 docker 2.创建 jenkins 容器 3.根据自动化项目依赖包构建 python 镜像(构建自动化 python 环境) 4.运行新的 python 容器&#xff0c;执行 jenkins 从仓库中拉下来的自动化项目 5.执行完成之后删除容器 前言 环境准备 Linux 服务器一台(我的是 CentOS7)…

GitHub工作流的使用笔记

文章目录 前言1. 怎么用2. 怎么写前端案例1&#xff1a;自动打包到新分支前端案例2&#xff1a;自动打包推送到gitee的build分支案例3&#xff1a;暂时略 前言 有些东西真的就是要不断的试错不断地试错才能摸索到一点点&#xff0c;就是摸索到凌晨两三点第二天要8点起床感觉要…

通过例子说明-动态规划

选择>行动>思考&#xff0c;好像是个死循环 -song。 动态规划&#xff08;Dynamic Programming&#xff0c;简称DP&#xff09;是一种解决问题的数学优化方法&#xff0c;通常用于解决具有重叠子问题和最优子结构性质的问题。它的基本思想是将问题拆分成小的子问题&#…

革新性技术:基于搜索操作的存内计算

文章目录 革新性技术&#xff1a;基于搜索操作的存内计算CSDN首个存内计算开发者社区NVALT&#xff1a;近似查找表的艺术MAP&#xff1a;存内计算的未来SQL-PIM&#xff1a;数据库的未来内存计算架构与技术小结从NVALT到NVQuery&#xff1a;存内计算的探索与前景NVQuery&#x…

242. 有效的字母异位词(力扣)(C语言题解)

✨欢迎来到脑子不好的小菜鸟的文章✨ &#x1f388;创作不易&#xff0c;麻烦点点赞哦&#x1f388; 所属专栏&#xff1a;刷题 我的主页&#xff1a;脑子不好的小菜鸟 文章特点&#xff1a;关键点和步骤讲解放在 代码相应位置 题目链接&#xff1a; 242. 有效的字母异位词 …

UE5 C++ 读取本地图片并赋值到UI上

目录 结果图 节点样式 主要代码 调试代码 结果图 节点样式 主要代码 &#xff08;注释纯属个人理解&#xff0c;可能存在错误&#xff09; // Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h&q…

Mysql进阶篇

1.Mysql服务架构 连接层: 处理客户端连接请求,对用户进行认证 服务层: 可以接收sql,调用存储过程,优化sql,缓存数据.... 引擎层: 负责实际与文件层进行交互操作的,可以有不同的引擎选择. 物理文件层: 存储表数据 以及 各种日志文件. 2.Mysql引擎 存储引擎就是存储数据&…

TSINGSEE青犀视频智慧电梯管理平台,执行精准管理、提升乘梯安全

一、方案背景 随着城市化进程的不断加快&#xff0c;我国已经成为全球最大的电梯生产和消费市场&#xff0c;电梯也成为人们日常生活中不可或缺的一部分。随着电梯数量的激增&#xff0c;电梯老龄化&#xff0c;维保数据不透明&#xff0c;物业管理成本高&#xff0c;政府监管…

StarRocks-3.1.0 单节点部署

1. 相关环境准备 FE&#xff1a; /opt/starrocks BE&#xff1a; /opt/starrocks 安装包下载 wget https://releases.starrocks.io/starrocks/StarRocks-3.1.0.tar.gz解压缩 tar -zxvf StarRocks-3.1.0.tar.gz 安装jdk (v2.5 及以上版本建议安装 JDK 11&#xff0c;我们使用…

腾讯mini项目总结-指标监控服务重构

项目概述 本项目的背景是&#xff0c;当前企业内部使用的指标监控服务的方案的成本很高&#xff0c;无法符合用户的需求&#xff0c;于是需要调研并对比测试市面上比较热门的几款开源的监控方案&#xff08;选择了通用的OpenTelemetry协议&#xff1a;Signoz&#xff0c;otel-…

MedSAM:深度学习通用医学影像分割模型,更快、更准确地自动识别诊断疾病

MedSAM是一款基于深度学习的医学影像分割工具&#xff0c;它能够自动识别和描绘医学影像中的重要区域&#xff0c;如肿瘤或其他组织的病变。该工具通过学习大量医学影像和对应的掩模&#xff08;即正确的分割结果&#xff09;&#xff0c;能够处理各种不同的医学影像和复杂情况…

数据库之TiDB基础讲解

文章目录 1 TiDB1.1 引言1.2 TiDB介绍1.3 系统架构1.3.1 TIDB Server1.3.2 PD Server1.3.3 TIKV Server1.3.4 TiKV如何不丢失数据1.3.5 分布式事务支持 1.4 与MySQL的对比1.5 性能测试1.5.1 测试一1.5.2 系统测试报告 2 1 TiDB 1.1 引言 当我们使用 Mysql 数据库到达一定量级…

使用nginx对视频、音频、图片等静态资源网址,加token签权

目前很多静态资源&#xff0c;都可以无权限验证&#xff0c;进行访问或转发&#xff0c;对有价值的资源进行签权&#xff0c;限制转发无法在代码中实现拦截&#xff0c;我们可以使用nginx对视频、音频、图片等静态资源网址&#xff0c;加token签权 如&#xff1a; http://192…

Win10 双网卡实现同时上内外网

因为需要同时上内网和外网&#xff0c;但公司做了网络隔离&#xff0c;不能同时上内外网&#xff0c;所以多加了块无线网卡&#xff0c;配置双网关实现同时上内外网&#xff0c;互不影响 打开 Windows PowerShell&#xff08;管理员&#xff09;&#xff0c;输入&#xff1a;ro…

CCF-CSP 202312-2 因子化简(Java、C++、Python)

文章目录 因子化简题目背景问题描述输入格式输出格式样例输入样例输出样例解释子任务 满分代码JavaCPython线性筛法 因子化简 题目背景 质数&#xff08;又称“素数”&#xff09;是指在大于 1 的自然数中&#xff0c;除了 1 和它本身以外不再有其他因数的自然数。 问题描述…

房屋租赁系统-java

思维导图&#xff1a;业务逻辑 类的存放&#xff1a; 工具类 Utility package study.houserent.util; import java.util.*; /***/ public class Utility {//静态属性。。。private static Scanner scanner new Scanner(System.in);/*** 功能&#xff1a;读取键盘输入的一个菜单…

DevOps落地笔记-02|影响地图:产品规划和需求分析的利器

从这一讲开始&#xff0c;我们进入 DevOps 正题。按照端到端的顺序&#xff0c;讲解 DevOps 中的最佳实践如何在软件开发过程中发挥作用。所谓端到端&#xff0c;是指从需求提出到需求被发布到生产环境交付给用户的整个过程&#xff0c;可以理解为软件开发的全生命周期。所谓最…

06 SB3之Thymeleaf实现视图返回

1快速尝试一个返回视图的项目 1.1创建器添加Web, Thymeleaf, lombok依赖创建项目 1.2 编写Controller Controller public class QuickController {RequestMapping("/exam/quick") public String quick(Model model){//业务处理结果数据&#xff0c;放入到 Model 模…

【lesson1】高并发内存池项目介绍

文章目录 这个项目做的是什么&#xff1f;这个项目的要求的知识储备和难度&#xff1f;什么是内存池池化技术内存池内存池主要解决的问题malloc 这个项目做的是什么&#xff1f; 当前项目是实现一个高并发的内存池&#xff0c;他的原型是google的一个开源项目tcmalloc&#xf…