背景需求
在《自助餐》活动中,
【教学类-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立体纸盘图片的旋转效果