【教学类】20250605立体纸盘(3边形-22边形,角度5、10……40,45)

背景需求

在《自助餐》活动中,

【教学类-53-01】20240918自助餐餐盘-CSDN博客文章浏览阅读984次,点赞29次,收藏11次。【教学类-53-01】20240918自助餐餐盘 https://blog.csdn.net/reasonsummer/article/details/142340542?spm=1011.2415.3001.5331

我发现提供的纸盘是平面的,不能装纸片(容易洒在地上、桌上),

所以最后还是用纸碗来装、用胶水黏在平面纸盘

我想把平面纸盘变成有立体的纸盘

简单做了一个四边形碗。

但是我的黏贴角度是很随机的。在已有黑色图案的纸盘上画画,线条不明显,我还是重做一个白底的模型。

我想测算黏贴多少角度,可以变出一个凹形的碗

经过deepseek求助,绘画相应的草图,实现我想要的效果

自制圆形,设计3边形-22边形的立体纸盘,其中黏贴角的角度为5度、10度、15度、20度、25度、30度、35度、40度、45度。

'''
自助餐纸盘 角度20,3-22边形(再大就灰色部分就贴不满了。角度10、15、20、25、30、35、40、45
手动删除部分肯定不能黏贴的
deepseek,阿夏
20250605
'''from PIL import Image, ImageDraw, ImageFont
import math
import os
import shutil
from docx import Document
from docx.shared import Cm
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
import pythoncom
from win32com.client import Dispatch
from PyPDF2 import PdfMerger# 加载黑体字体(使用系统自带的黑体)
try:font = ImageFont.truetype("simhei.ttf", 50)  # Windows系统黑体
except:try:font = ImageFont.truetype("Arial Unicode.ttf", 50)  # Mac系统备用字体except:font = ImageFont.load_default()  # 默认字体# 各种角度旋转10、15、20...45
for angles in range(10, 50, 5):first = 3last = 25x = list(range(first, last+1))path = r'C:\Users\jg2yXRZ\OneDrive\桌面\20250605餐盘'new = os.path.join(path, '00图片')os.makedirs(new, exist_ok=True)for i, xx in enumerate(x):# 创建1000x1000白色画布width, height = 1000, 1000image = Image.new('RGB', (width, height), 'white')draw = ImageDraw.Draw(image)# 画一个1000x1000的白色填充黑色圆形,10磅粗细draw.ellipse([(0, 0), (width-1, height-1)], fill='white', outline='black', width=10)# 计算正多边形的顶点def calculate_polygon_points(center_x, center_y, size, sides):points = []for i in range(sides):angle_deg = 360/sides * i - 30  # 旋转30度使顶点朝上angle_rad = math.pi / 180 * angle_degx = center_x + size * math.cos(angle_rad)y = center_y + size * math.sin(angle_rad)points.append((x, y))return points# 中心点center_x, center_y = width // 2, height // 2poly_size = 300  # 多边形大小circle_radius = 500  # 大圆半径# 计算多边形顶点poly_points = calculate_polygon_points(center_x, center_y, poly_size, xx)# 存储所有交点坐标black_intersections = []gray_intersections = []# 从多边形顶点延伸到画布边缘 (黑线)for point in poly_points:# 计算方向向量dx = point[0] - center_xdy = point[1] - center_y# 归一化length = math.sqrt(dx*dx + dy*dy)dx /= lengthdy /= length# 计算延伸到边缘的点edge_x = point[0] + dx * (circle_radius - poly_size)edge_y = point[1] + dy * (circle_radius - poly_size)black_intersections.append((edge_x, edge_y))# 画线draw.line([(point[0], point[1]), (edge_x, edge_y)], fill='black', width=10)# 从多边形顶点偏移指定角度延伸到画布边缘 (灰线)for point in poly_points:# 计算当前顶点的角度angle = math.atan2(point[1] - center_y, point[0] - center_x)# 计算偏移指定角度的方向angle_offset = angle + math.radians(angles)dx_offset = math.cos(angle_offset)dy_offset = math.sin(angle_offset)# 计算延伸到边缘的点 - 使用直线与圆的交点公式a = dx_offset**2 + dy_offset**2b = 2*(dx_offset*(point[0]-center_x) + dy_offset*(point[1]-center_y))c = (point[0]-center_x)**2 + (point[1]-center_y)**2 - circle_radius**2discriminant = b**2 - 4*a*cif discriminant >= 0:t1 = (-b + math.sqrt(discriminant))/(2*a)t2 = (-b - math.sqrt(discriminant))/(2*a)t = max(t1, t2)  # 选择正的、较大的t值edge_x_offset = point[0] + t*dx_offsetedge_y_offset = point[1] + t*dy_offsetelse:# 如果没有交点,使用原来的方法作为备用edge_x_offset = point[0] + dx_offset * (circle_radius - poly_size)edge_y_offset = point[1] + dy_offset * (circle_radius - poly_size)gray_intersections.append((edge_x_offset, edge_y_offset))# 画偏移线draw.line([(point[0], point[1]), (edge_x_offset, edge_y_offset)], fill='gray', width=10)# 绘制并填充三角形for i in range(xx):triangle_points = [poly_points[i],black_intersections[i],gray_intersections[i]]draw.polygon(triangle_points, fill='gray', outline=None)# 虚线绘制函数def draw_dashed_polygon(draw, points, fill, outline, width, dash_pattern):lines = []for i in range(len(points)):start = points[i]end = points[(i+1)%len(points)]lines.append((start, end))for start, end in lines:dx = end[0] - start[0]dy = end[1] - start[1]length = math.sqrt(dx*dx + dy*dy)dx /= lengthdy /= lengthdrawn_length = 0dash_index = 0while drawn_length < length:segment_length = dash_pattern[dash_index % len(dash_pattern)]segment_end = min(drawn_length + segment_length, length)if dash_index % 2 == 0:segment_start_x = start[0] + dx * drawn_lengthsegment_start_y = start[1] + dy * drawn_lengthsegment_end_x = start[0] + dx * segment_endsegment_end_y = start[1] + dy * segment_enddraw.line([(segment_start_x, segment_start_y), (segment_end_x, segment_end_y)], fill=outline, width=width)drawn_length = segment_enddash_index += 1# 最后画中心多边形,使用虚线轮廓poly_points = calculate_polygon_points(center_x, center_y, poly_size, xx)draw.polygon(poly_points, fill='white', outline=None)draw_dashed_polygon(draw, poly_points, fill=None, outline='gray', width=5, dash_pattern=[10, 10])# 在中心添加文字说明text = f"{xx}边形 角度{angles}"text_width, text_height = draw.textsize(text, font=font)text_x = center_x - text_width // 2text_y = center_y - text_height // 2draw.text((text_x, text_y), text, fill='black', font=font)# 再画大圆,盖在最上面draw.ellipse([(0, 0), (width-1, height-1)], outline='black', width=10)# 保存图像image.save(os.path.join(new, f'{i+1:02}边形角度{angles}.png'))# print("所有图片生成完成!")# 第二部分:处理Word文档和PDF转换
output_folder = os.path.join(path, '零时')
os.makedirs(output_folder, exist_ok=True)
docx_template = os.path.join(path, '立体餐盘.docx')# 获取所有PNG图片
png_files = [f for f in os.listdir(new) if f.lower().endswith('.png')]
print("找到的PNG文件:", png_files)# 复制10份每种图片(通过重复列表实现)
expanded_png_files = []
for png in png_files:# expanded_png_files.extend([png] * 10)expanded_png_files.extend([png] * 1)        # 测试一份print("扩展后的图片列表:", len(expanded_png_files))# 将图片分成2个一组
image_pairs = [expanded_png_files[i:i+2] for i in range(0, len(expanded_png_files), 2)]
print("图片分组数量:", len(image_pairs))# 处理Word文档
for idx, pair in enumerate(image_pairs, start=1):try:doc = Document(docx_template)if len(doc.tables) == 0:print("文档中没有表格")continuetable = doc.tables[0]if len(table.rows) < 1 or len(table.rows[0].cells) < 2:print("表格格式不符合要求")continue# 清除单元格内容for i in range(2):for paragraph in table.rows[0].cells[i].paragraphs:for run in paragraph.runs:run.clear()# 插入图片并设置大小和对齐方式for i, img_name in enumerate(pair):if i >= 2:  # 只处理前两张图片breakcell = table.rows[0].cells[i]img_path = os.path.join(new, img_name)# 创建段落并设置对齐方式paragraph = cell.paragraphs[0] if cell.paragraphs else cell.add_paragraph()# 00格子左对齐,01格子右对齐if i == 0:paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.LEFTelse:paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT# 添加图片run = paragraph.add_run()run.add_picture(img_path, width=Cm(13.5), height=Cm(13.5))output_docx = os.path.join(output_folder, f"{idx:03}.docx")doc.save(output_docx)print(f"已生成: {output_docx}")except Exception as e:print(f"处理第{idx}组时出错:", str(e))# 转换为PDF
try:pythoncom.CoInitialize()word = Dispatch('Word.Application')word.Visible = Falsepdf_files = []for file in sorted(os.listdir(output_folder)):if file.endswith('.docx'):docx_path = os.path.join(output_folder, file)pdf_path = os.path.join(output_folder, f"{os.path.splitext(file)[0]}.pdf")try:doc = word.Documents.Open(os.path.abspath(docx_path))doc.SaveAs(os.path.abspath(pdf_path), FileFormat=17)  # 17是PDF格式doc.Close()pdf_files.append(pdf_path)print(f"已转换为PDF: {pdf_path}")except Exception as e:print(f"转换{file}为PDF时出错:", str(e))word.Quit()pythoncom.CoUninitialize()# 合并PDFif pdf_files:merger = PdfMerger()for pdf in sorted(pdf_files):try:merger.append(pdf)except Exception as e:print(f"合并{pdf}时出错:", str(e))merged_pdf = os.path.join(path, f"餐盘合并_{first}-{last}边形_角度{angles}.pdf")merger.write(merged_pdf)merger.close()print(f"已合并PDF: {merged_pdf}")
except Exception as e:print("PDF处理过程中出错:", str(e))# 清理临时文件(可选)
shutil.rmtree(output_folder)print("处理完成!")

结果:184张

手动删除一些目测就不能用的图片

合并代码

'''
自助餐纸盘 角度20,3-22边形(再大就灰色部分就贴不满了。角度10、15、20、25、30、35、40、45
手动删除部分肯定不能黏贴的
deepseek,阿夏
20250605
'''from PIL import Image, ImageDraw
import math
import os,time
import shutil
from docx import Document
from docx.shared import Cm
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
import pythoncom
from win32com.client import Dispatch
from PyPDF2 import PdfMergerpath = r'C:\Users\jg2yXRZ\OneDrive\桌面\20250605餐盘'
new = os.path.join(path, '00图片')
os.makedirs(new, exist_ok=True)
# 第二部分:处理Word文档和PDF转换
output_folder = os.path.join(path, '零时')
os.makedirs(output_folder, exist_ok=True)
docx_template = os.path.join(path, '立体餐盘.docx')# 获取所有PNG图片
png_files = [f for f in os.listdir(new) if f.lower().endswith('.png')]
print("找到的PNG文件:", png_files)# 复制10份每种图片(通过重复列表实现)
expanded_png_files = []
for png in png_files:# expanded_png_files.extend([png] * 10)expanded_png_files.extend([png] * 1)        # 测试一份print("扩展后的图片列表:", len(expanded_png_files))# 将图片分成2个一组
image_pairs = [expanded_png_files[i:i+2] for i in range(0, len(expanded_png_files), 2)]
print("图片分组数量:", len(image_pairs))# 处理Word文档
for idx, pair in enumerate(image_pairs, start=1):try:doc = Document(docx_template)if len(doc.tables) == 0:print("文档中没有表格")continuetable = doc.tables[0]if len(table.rows) < 1 or len(table.rows[0].cells) < 2:print("表格格式不符合要求")continue# 清除单元格内容for i in range(2):for paragraph in table.rows[0].cells[i].paragraphs:for run in paragraph.runs:run.clear()# 插入图片并设置大小和对齐方式for i, img_name in enumerate(pair):if i >= 2:  # 只处理前两张图片breakcell = table.rows[0].cells[i]img_path = os.path.join(new, img_name)# 创建段落并设置对齐方式paragraph = cell.paragraphs[0] if cell.paragraphs else cell.add_paragraph()# 00格子左对齐,01格子右对齐if i == 0:paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.LEFTelse:paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT# 添加图片run = paragraph.add_run()run.add_picture(img_path, width=Cm(13.5), height=Cm(13.5))output_docx = os.path.join(output_folder, f"{idx:03}.docx")doc.save(output_docx)print(f"已生成: {output_docx}")except Exception as e:print(f"处理第{idx}组时出错:", str(e))# 转换为PDF
try:pythoncom.CoInitialize()word = Dispatch('Word.Application')word.Visible = Falsepdf_files = []for file in sorted(os.listdir(output_folder)):if file.endswith('.docx'):docx_path = os.path.join(output_folder, file)pdf_path = os.path.join(output_folder, f"{os.path.splitext(file)[0]}.pdf")try:doc = word.Documents.Open(os.path.abspath(docx_path))doc.SaveAs(os.path.abspath(pdf_path), FileFormat=17)  # 17是PDF格式doc.Close()pdf_files.append(pdf_path)print(f"已转换为PDF: {pdf_path}")except Exception as e:print(f"转换{file}为PDF时出错:", str(e))word.Quit()pythoncom.CoUninitialize()# 合并PDFif pdf_files:merger = PdfMerger()for pdf in sorted(pdf_files):try:merger.append(pdf)except Exception as e:print(f"合并{pdf}时出错:", str(e))merged_pdf = os.path.join(path, f"餐盘合并.pdf")# merged_pdf = os.path.join(path, f"餐盘合并_{first}-{last}边形_角度{angles}.pdf")merger.write(merged_pdf)time.sleep(5)merger.close()print(f"已合并PDF: {merged_pdf}")
except Exception as e:print("PDF处理过程中出错:", str(e))# 清理临时文件(可选)
shutil.rmtree(output_folder)print("处理完成!")

结果展示

一个有趣的旋转图

20250605立体纸盘图片的旋转效果

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GC1809:高性能24bit/192kHz音频接收芯片解析

1. 芯片概述 GC1809 是数字音频接收芯片&#xff0c;支持IEC60958、S/PDIF、AES3等协议&#xff0c;集成8选1输入切换、低抖动时钟恢复和24bit DAC&#xff0c;适用于家庭影院、汽车音响等高保真场景。 核心特性 高精度&#xff1a;24bit分辨率&#xff0c;动态范围105dB&…

Next.js 中间件鉴权绕过漏洞 CVE-2025-29927

前言:CVE-2025-29927 是一个影响 Next.js 的严重漏洞&#xff0c;源于开发者信任了客户端请求中携带的 X-Middleware-Rewrite 头部字段。攻击者可以手动构造该头部&#xff0c;实现绕过中间件逻辑&#xff0c;访问本应受保护的资源或 API。 影响版本&#xff1a;Next.js < …

第1章 数据分析简介

第1章 数据分析简介 1.1 数据分析 当今世界对信息技术依赖日深,每天产生和存储海量数据,来源于自动检测系统、传感器、科学仪器,以及银行取钱、买东西、写博客、发微博等日常行为。 数据与信息在形式上不同:数据是无形式可言的字节流,难理解其本质;信息是对数据集处理后…

边缘计算网关赋能沸石转轮运行故障智能诊断的配置实例

一、项目背景 在环保行业&#xff0c;随着国家对大气污染治理要求的不断提高&#xff0c;VOCs废气处理成为了众多企业的重要任务。沸石转轮作为一种高效的VOCs治理设备&#xff0c;被广泛应用于石油化工、汽车制造、印刷包装等主流行业。这些行业生产规模大、废气排放量多&…

20250602在Ubuntu20.04.6下修改压缩包的日期和时间

rootrootrootroot-X99-Turbo:~$ ll -rwxrwxrwx 1 rootroot rootroot 36247187308 5月 23 10:23 Android13.0地面站.tgz* rootrootrootroot-X99-Turbo:~$ touch 1Android13.0地面站.tgz rootrootrootroot-X99-Turbo:~$ ll -rwxrwxrwx 1 rootroot rootroot 36247187308 6月…

windows无法安装到这个磁盘,选中的磁盘采用gpt分区仪式

解决办法&#xff1a; 我才用的是一个网友分享的微软官方解决办法&#xff0c;成功了&#xff0c;但是不知道会不会i有什么影响。将所有分区删掉&#xff0c;这时磁盘变成为分配的空间。我个人是两块固态&#xff0c;一块m.2&#xff0c;一块sata&#xff1b;所以我直接将500g…

使用Composer创建公共类库

概述 如果多个项目中存在使用相同类库、模块的情况&#xff0c;此时可以考虑将类库或者模块单独抽取出来&#xff0c;形成独立类库&#xff0c;通过composer 来进行依赖管理&#xff0c;这样可以更方便维护&#xff0c;大大提升开发效率。 优势 可以对特定模块进行统一维护和…

Ubuntu中TFTP服务器安装使用

TFTP服务器 在 Ubuntu 下使用 TFTP&#xff08;Trivial File Transfer Protocol&#xff09; 服务&#xff0c;通常用于简单的文件传输&#xff08;如网络设备固件更新、嵌入式开发等&#xff09;。 1 TFTP服务器安装 sudo apt-get install tftp-hpa sudo apt-get install…

前端面试总结

1.请做下自我介绍 技术栈 工作经历 2.挑一个项目详细讲一下 介绍了一个项目的业务&#xff0c;重点讲了一个动态表单的实现&#xff0c;从业务、扩展性、可维护性、性能提升 3.场景题&#xff1a;问答怎么做&#xff0c;表单之间关联&#xff0c;回答不同问题跳转到不同的下一个…

Python训练打卡Day38

Dataset和Dataloader类 知识点回顾&#xff1a; Dataset类的__getitem__和__len__方法&#xff08;本质是python的特殊方法&#xff09;Dataloader类minist手写数据集的了解 在遇到大规模数据集时&#xff0c;显存常常无法一次性存储所有数据&#xff0c;所以需要使用分批训练的…

web3-区块链基础:从区块添加机制到哈希加密与默克尔树结构

区块链基础&#xff1a;从区块添加机制到哈希加密与默克尔树结构 什么是区块链 抽象的回答: 区块链提供了一种让多个参与方在没有一个唯一可信方的情况下达成合作 若有可信第三方 > 不需要区块链 [金融系统中常常没有可信的参与方] 像股票市场&#xff0c;或者一个国家的…

MySQL 索引:为使用 B+树作为索引数据结构,而非 B树、哈希表或二叉树?

在数据库的世界里&#xff0c;性能是永恒的追求。而索引&#xff0c;作为提升查询速度的利器&#xff0c;其底层数据结构的选择至关重要。如果你深入了解过 MySQL&#xff08;尤其是其主流存储引擎 InnoDB&#xff09;&#xff0c;你会发现它不约而同地选择了 B树 作为索引的主…

Kafka broker 写消息的过程

Producer → Kafka Broker → Replication → Consumer|Partition chosen (by key or round-robin)|Message appended to end of log (commit log)上面的流程是kafka 写操作的大体流程。 kafka 不会特意保留message 在内存中&#xff0c;而是直接写入了disk。 那么消费的时候&…

leetcode hot100(两数之和、字母异位词分组、最长连续序列)

两数之和 题目链接 参考链接&#xff1a; 题目描述&#xff1a; 暴力法 双重循环查找目标值 class Solution {public int[] twoSum(int[] nums, int target) {int[] res new int[2];for(int i 0 ; i < nums.length ; i){boolean isFind false;for(int j i 1 ; j …

SkyWalking架构深度解析:分布式系统监控的利器

一、SkyWalking概述 SkyWalking是一款开源的APM(应用性能监控)系统&#xff0c;专门为微服务、云原生和容器化架构设计。它由Apache软件基金会孵化并毕业&#xff0c;已成为分布式系统监控领域的明星项目。 核心特性 ‌分布式追踪‌&#xff1a;跨服务调用链路的完整追踪‌服务…

Matlab程序设计基础

matlab程序设计基础 程序设计函数文件1.函数文件的基本结构2.创建并使用函数文件的示例3.带多个输出的函数示例4.包含子函数的函数文件 流程控制1. if 条件语句2. switch 多分支选择语句3. try-catch 异常处理语句ME与lasterr 4. while 循环语句5. for 循环语句break和continue…

Client-Side Path Traversal 漏洞学习笔记

近年来,随着Web前端技术的飞速发展,越来越多的数据请求和处理逻辑被转移到客户端(浏览器)执行。这大大提升了用户体验,但也带来了新的安全威胁。其中,Client-Side Path Traversal(客户端路径穿越,CSPT)作为一种新兴的漏洞类型,逐渐受到安全研究者和攻击者的关注。本文…

基于Socketserver+ThreadPoolExecutor+Thread构造的TCP网络实时通信程序

目录 介绍&#xff1a; 源代码&#xff1a; Socketserver-服务端代码 Socketserver客户端代码&#xff1a; 介绍&#xff1a; socketserver是一种传统的传输层网络编程接口&#xff0c;相比WebSocket这种应用层的协议来说&#xff0c;socketserver比较底层&#xff0c;soc…

【无标题】平面图四色问题P类归属的严格论证——基于拓扑收缩与动态调色算法框架

平面图四色问题P类归属的严格论证——基于拓扑收缩与动态调色算法框架 --- #### **核心定理** 任意平面图 \(G (V, E)\) 的四色着色问题可在多项式时间 \(O(|V|^2)\) 内求解&#xff0c;且算法正确性由以下三重保证&#xff1a; 1. **拓扑不变性**&#xff08;Kuratowsk…

HALCON 深度学习训练 3D 图像的几种方式优缺点

HALCON 深度学习训练 3D 图像的几种方式优缺点 ** 在计算机视觉和工业检测等领域&#xff0c;3D 图像数据的处理和分析变得越来越重要&#xff0c;HALCON 作为一款强大的机器视觉软件&#xff0c;提供了多种深度学习训练 3D 图像的方式。每种方式都有其独特的设计思路和应用场…