【教学类-103-02】20250607立体纸盘(3边形-22边形,角度30、45……75、90)
背景需求
之前打印了10-45(间隔5)的圆盘图纸,
【教学类-103-01】20250605立体纸盘(3边形-22边形,角度5、10……40,45)-CSDN博客文章浏览阅读444次,点赞8次,收藏8次。【教学类-103-01】20250605立体纸盘(3边形-22边形,角度5、10……40,45)
https://blog.csdn.net/reasonsummer/article/details/148456885?spm=1011.2415.3001.5331
但是老师和2位幼儿实际操作后,
1.灰色比较深,幼儿看不见黑色的裁剪线条
2.间隔5太窄了,要剪很多次,要贴很多次,而且容易贴不住。
3.而且4边形时,我想要90度角的纸盒。结果40度时还是40倾斜角。并没有变成直角,也就是黏贴的区域需要90度。
15变形的黏贴后呈现90度角,但是贴的很多,速度太慢
所以我把角度改成30-90的15间隔数
灰色从gray改成lightgray
代码展示
'''
自助餐纸盘 角度20,3-22边形(再大就灰色部分就贴不满了。角度30,45、60,75,90
手动删除部分肯定不能黏贴的
deepseek,阿夏
20250607
'''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(30, 105, 15):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='lightgray', width=10)# 绘制并填充三角形for i in range(xx):triangle_points = [poly_points[i],black_intersections[i],gray_intersections[i]]draw.polygon(triangle_points, fill='lightgray', 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='lightgray', 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("文档中没有表格")
# continue# table = 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: # 只处理前两张图片
# break# cell = 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.LEFT
# else:
# 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 = False# pdf_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()# # 合并PDF
# if 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("处理完成!")
115张图
手动删除部分
超过10边形的都可以删除了。
最后页就三边形和四边形可以贴直角,其他用了直角,会重叠贴
合并代码
'''
自助餐纸盘 角度20,3-22边形(再大就灰色部分就贴不满了。角度10、15、20、25、30、35、40、45
手动删除部分肯定不能黏贴的
6张9,1
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, '立体餐盘6张.docx')# 获取所有PNG图片
png_files = [f for f in os.listdir(new) if f.lower().endswith('.png')]
print("找到的PNG文件:", png_files)# 复制1份每种图片(测试用,正式使用时可改为10份)
expanded_png_files = []
for png in png_files:expanded_png_files.extend([png] * 1) # 正式使用时改为 *10print("扩展后的图片列表:", len(expanded_png_files))# 将图片分成6个一组
image_groups = [expanded_png_files[i:i+6] for i in range(0, len(expanded_png_files), 6)]
print("图片分组数量:", len(image_groups))# 处理Word文档
for idx, group in enumerate(image_groups, start=1):try:doc = Document(docx_template)if len(doc.tables) == 0:print("文档中没有表格")continuetable = doc.tables[0]# 检查表格是否有2行3列if len(table.rows) < 2 or len(table.rows[0].cells) < 3:print("表格格式不符合要求,需要至少2行3列")continue# 清除单元格内容for row in range(2): # 清除两行内容for col in range(3): # 每行3列cell = table.rows[row].cells[col]# 清除所有段落for paragraph in cell.paragraphs:p = paragraph._elementp.getparent().remove(p)# 添加两个空段落cell.add_paragraph()cell.add_paragraph()# 插入图片并设置大小和对齐方式for i, img_name in enumerate(group[:6]): # 确保只处理6张图片# 决定放在哪一行row = 0 if i < 3 else 1 # 前3张放第一行,后3张放第二行col = i % 3 # 列号(0,1,2)cell = table.rows[row].cells[col]img_path = os.path.join(new, img_name)# 选择段落 - 第一行用第一个段落,第二行用第二个段落paragraph_index = 0 if row == 0 else 1# 确保单元格有足够的段落while len(cell.paragraphs) <= paragraph_index:cell.add_paragraph()paragraph = cell.paragraphs[paragraph_index]# 设置对齐方式if col == 0: # 第一列(00,10)左对齐paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.LEFTelif col == 1: # 第二列(01,11)居中对齐paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTERelse: # 第三列(02,12)右对齐paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT# 添加图片run = paragraph.add_run()run.add_picture(img_path, width=Cm(9), height=Cm(9))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, "餐盘合并6张4590度灰色.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("处理完成!")