背景需求
在《自助餐》活動中,
【教學類-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立體紙盤圖片的旋轉效果