#8 Layouts and content_for

本文介绍了一种使用 content_for 方法在 Ruby on Rails 中自定义布局的方法。这种方法允许开发者在模板级别指定可以放置在任何布局中的视图代码片段。示例展示了如何在特定页面中引入额外的 CSS 文件,从而实现更灵活的设计控制。
If you want to change something in the layout on a per-template basis, content_for is your answer! This allows templates to specify view code that can be placed anywhere in a layout.

<!-- projects/index.rhtml -->
<% content_for :head do %>
<%= stylesheet_link_tag 'projects' %>
<% end %>

<!-- layouts/application.rhtml -->
<head>
<title>Todo List</title>
<%= stylesheet_link_tag 'application' %>
<%= yield :head %>
</head>

import klayout.pya as pya from collections import defaultdict from pptx import Presentation from pptx.util import Inches, Pt from pptx.enum.text import PP_ALIGN from pptx.dml.color import RGBColor from pptx.enum.shapes import MSO_SHAPE import os import re import pandas as pd from PIL import Image, ImageDraw # 新增PIL库用于图像处理 # 算坐标,左下右上 def extract_coordinates(poly_str): # 使用正则表达式提取括号内的所有坐标 match = re.search(r&#39;\(([\d\.,;]+)\)&#39;, poly_str) if not match: raise ValueError("无效的坐标字符串格式") # 分割坐标点并转换为浮点数列表 points = [] for pair in match.group(1).split(&#39;;&#39;): if &#39;,&#39; in pair: x, y = map(float, pair.split(&#39;,&#39;)) points.append((x, y)) if not points: raise ValueError("未找到有效坐标点") # 找到左下角坐标 (x最小, y最小) ll = min(points, key=lambda p: (p[0], p[1])) # 找到右上角坐标 (x最大, y最大) ur = max(points, key=lambda p: (p[0], p[1])) return ll[0], ll[1], ur[0], ur[1] def saveImageAll(lx, ly, rx, ry, output_image_name, lv): # 设置导出区域(单位为微米)- 添加缓冲区 buffer = 1000 # 微米单位的缓冲区大小 # 3. 更新视图 lv.update_content() # 设置导出区域(单位为微米) export_region = pya.DBox(lx - buffer, ly - buffer, rx + buffer, ry + buffer) # 左下x, 左下y, 右上x, 右上y for layer in lv.each_layer(): layer.visible = True # layer.frame_color = 0x00FFFF # 3. 更新视图 lv.update_content() # 设置视图区域 lv.zoom_box(export_region) # 导出图片 width = 2000 height = 1100 linewidth = 1 oversampling = -2 resolution = 0.0 # 使用正确的参数格式调用save_image_with_options lv.save_image_with_options(output_image_name, width, height, linewidth, oversampling, resolution, export_region, False) &#39;&#39;&#39;===== 新增部分:添加黄色矩形边框 =====&#39;&#39;&#39; try: # 打开导出的图片 img = Image.open(output_image_name) draw = ImageDraw.Draw(img) # 计算图片坐标比例 img_width, img_height = img.size region_width = (rx + buffer) - (lx - buffer) region_height = (ry + buffer) - (ly - buffer) # 将布局坐标转换为图片坐标 def layout_to_image_coords(layout_x, layout_y): """将布局坐标转换为图片像素坐标""" x_percent = (layout_x - (lx - buffer)) / region_width y_percent = 1.0 - ((layout_y - (ly - buffer)) / region_height) # 反转Y轴 img_x = int(x_percent * img_width) img_y = int(y_percent * img_height) return img_x, img_y # 计算矩形边界在图片上的坐标 top_left = layout_to_image_coords(lx, ry) # 左上角 (lx, ry) bottom_right = layout_to_image_coords(rx, ly) # 右下角 (rx, ly) # 绘制黄色矩形边框 (RGB: 255, 255, 0) border_width = 10 # 边框宽度(像素) draw.rectangle( [top_left, bottom_right], outline=(0, 255, 255), # 黄色 width=border_width ) # 保存处理后的图片 img.save(output_image_name) # print(f"已添加亮蓝色矩形边框: {output_image_name}") except Exception as e: print(f"All添加亮蓝色矩形边框异常: {str(e)}") &#39;&#39;&#39;===============================&#39;&#39;&#39; def saveImageByLayer(lx, ly, rx, ry, output_image_name, lv, target_layer_number, data_type,violation_info): # 方案1: 使用re.search() match = re.search(r&#39;\((.*?)\)&#39;, violation_info[0]) # 非贪婪匹配 if match: result = match.group(1) # group(1)直接获取括号内的内容 print(result) # 输出: 0,0;0,5000;5000,5000;5000,0 else: result = "" # 或无匹配时的处理 # 获取源图层信息 for layer in lv.each_layer(): source_layer = layer.source_layer # print(f"层索引 {layer.layer_index()}: Layer Name={source_layer}") # 1. 首先将所有图层设置为不可见 for layer in lv.each_layer(): layer.visible = False # 2. 只将目标图层设置为可见 found = False for layer in lv.each_layer(): # 比较源层号而不是层索引 if layer.source_layer == target_layer_number and layer.source_datatype == data_type: layer.visible = True found = True layer.frame_color = 0xFF0000 # 红色轮廓 # print(f"已设置层号 {target_layer_number} (索引 {layer.layer_index()}) 为可见") if not found: print(f"警告: 未找到层号 {target_layer_number}") # 3. 更新视图 lv.update_content() top_cell = lv.create_cell("TOP") # 定义图层 layer_index = lv.insert_layer(pya.LayerInfo(1, 0)) points = [pya.DPoint(*map(float, pair.split(&#39;,&#39;))) for pair in result.split(&#39;;&#39;)] # 创建多边形并添加到布局 polygon = pya.DPolygon(points) top_cell.shapes(layer_index).insert(polygon) # 3. 更新视图 lv.update_content() # # 设置导出区域(单位为微米)- 添加缓冲区 # buffer = 1000 # 微米单位的缓冲区大小 # export_region = pya.DBox(lx - buffer, ly - buffer, rx + buffer, ry + buffer) # 设置导出范围(包含整个多边形) bbox = polygon.bbox() margin = 1.0 # 添加1微米边距 export_box = pya.DBox(bbox.left - margin, bbox.bottom - margin, bbox.right + margin, bbox.top + margin) # 设置视图区域 lv.zoom_box(export_box) # 导出图片 width = 2000 height = 1100 linewidth = 1 oversampling = -2 resolution = 0.0 # 导出原始图像 lv.save_image_with_options(output_image_name, width, height, linewidth, oversampling, resolution, export_box, False) # print(f"原始图片已导出到: {output_image_name}") &#39;&#39;&#39;===== 新增部分:添加黄色矩形边框 =====&#39;&#39;&#39; # try: # # 打开导出的图片 # img = Image.open(output_image_name) # draw = ImageDraw.Draw(img) # # # 计算图片坐标比例 # img_width, img_height = img.size # region_width = (rx + buffer) - (lx - buffer) # region_height = (ry + buffer) - (ly - buffer) # # # 将布局坐标转换为图片坐标 # def layout_to_image_coords(layout_x, layout_y): # """将布局坐标转换为图片像素坐标""" # x_percent = (layout_x - (lx - buffer)) / region_width # y_percent = 1.0 - ((layout_y - (ly - buffer)) / region_height) # 反转Y轴 # # img_x = int(x_percent * img_width) # img_y = int(y_percent * img_height) # return img_x, img_y # # # 计算矩形边界在图片上的坐标 # top_left = layout_to_image_coords(lx, ry) # 左上角 (lx, ry) # bottom_right = layout_to_image_coords(rx, ly) # 右下角 (rx, ly) # # # 绘制黄色矩形边框 (RGB: 255, 255, 0) # border_width = 10 # 边框宽度(像素) # draw.rectangle( # [top_left, bottom_right], # outline=(0, 255, 255), # 黄色 # width=border_width # ) # # # 保存处理后的图片 # img.save(output_image_name) # # print(f"已添加亮蓝色矩形边框: {output_image_name}") # except Exception as e: # print(f"ByLayer添加亮蓝色矩形边框异常: {str(e)}") # &#39;&#39;&#39;===============================&#39;&#39;&#39; # 加载DRC报告数据库 report_db = pya.ReportDatabase().load("NEPTUNEZ_FIN.out") # 确保文件存在 gds_path = "NEPTUNEZ_FIN.oas" if not os.path.exists(gds_path): raise FileNotFoundError(f"GDS文件未找到: {gds_path}") # 创建LayoutView实例 lv = pya.LayoutView() # 加载GDS文件 lv.load_layout(gds_path) # 获取当前布局和顶层单元 lv.max_hier() # Show full hierarchy lv.zoom_fit() # Zoom to fit content # 存储所有类别的数据结构 all_categories = [] category_counter = defaultdict(int) # 用于统计每个类别的总项目数 # 遍历所有cell和item for item_cell in report_db.each_cell(): layer_name = item_cell.name() cell_category_data = defaultdict(lambda: {"description": "", "items": []}) for item_id in item_cell.each_item(): category = report_db.category_by_id(item_id.category_id()) cat_name = category.name() # 更新全局类别计数器 category_counter[cat_name] += 1 # 只保存每个类别的前三个项目 if len(cell_category_data[cat_name]["items"]) >= 3: continue # 保存类别描述 if not cell_category_data[cat_name]["description"]: cell_category_data[cat_name]["description"] = category.description # 收集当前项目的所有值 item_values = [str(item_value) for item_value in item_id.each_value()] cell_category_data[cat_name]["items"].append(item_values) # 收集这个cell的所有类别数据 for cat_name, data in cell_category_data.items(): if data["items"]: category_entry = { "layerName": layer_name, "ruleName": cat_name, "description": data["description"], "items": list(data["items"]) } all_categories.append(category_entry) # 创建PPT演示文稿 prs = Presentation() # 读取Excel文件 file_path = &#39;layerInfo202509051508.xlsx&#39; df = pd.read_excel(file_path) # 创建以layerName为键的字典 layer_dict = {} for _, row in df.iterrows(): layer_name = row[&#39;Layer Name&#39;] layer_dict[layer_name] = { &#39;GDS&#39;: row[&#39;GDS&#39;], &#39;Data Type&#39;: row[&#39;Data Type&#39;], } # 为每个违规类别创建详细页 for category in all_categories: slide = prs.slides.add_slide(prs.slide_layouts[6]) # === 规则描述处理 === full_description = category["description"] rule_name = category["ruleName"] prefix_rule_name = rule_name.split(&#39;_&#39;, 1)[0] total_errors = category_counter[rule_name] pattern = r&#39;Rule File Pathname:.*?Rule File Title:&#39; full_description = re.sub(pattern, &#39;Rule File Title:&#39;, full_description, flags=re.DOTALL) # 规则描述超过50字符时显示省略号 if len(full_description) > 300: display_description = full_description[:300] + "..." else: display_description = full_description # === 将完整描述添加到备注 === notes_slide = slide.notes_slide notes_text_frame = notes_slide.notes_text_frame notes_text_frame.text = f"Rule Detail:\n{full_description}" # === 左侧区域:规则描述 === left_start = Inches(0.2) left_width = Inches(2.8) # 左侧区域宽度 # 添加标题(图层+规则名) title_box = slide.shapes.add_textbox(left_start, Inches(-0.2), left_width, Inches(1)) title_frame = title_box.text_frame title_para = title_frame.add_paragraph() title_para.text = f"{category[&#39;layerName&#39;]} - {category[&#39;ruleName&#39;]}" title_para.font.size = Pt(24) title_para.font.bold = True title_para.alignment = PP_ALIGN.LEFT # 添加规则描述区域 desc_box = slide.shapes.add_textbox(left_start, Inches(0.8), left_width, Inches(2.0)) desc_frame = desc_box.text_frame desc_frame.word_wrap = True # 添加描述文本 desc_para = desc_frame.add_paragraph() desc_para.text = "Rule Detail:" desc_para.font.size = Pt(14) desc_para.font.bold = True desc_content = desc_frame.add_paragraph() desc_content.text = display_description desc_content.font.size = Pt(10) desc_content.font.color.rgb = RGBColor(70, 70, 70) # ===== Zensemi Comment文本框 ===== risk_box_y = Inches(0.8) + Inches(2.0) + Inches(0.2) risk_box = slide.shapes.add_textbox(left_start, risk_box_y, left_width, Inches(0.8)) risk_frame = risk_box.text_frame risk_frame.word_wrap = True # 标题 risk_title = risk_frame.add_paragraph() risk_title.text = "Zensemi comment:" risk_title.font.size = Pt(14) risk_title.font.bold = True risk_title.font.color.rgb = RGBColor(200, 0, 0) # ===== 评论(CTM Comment)文本框 ===== comment_box_y = risk_box_y + Inches(0.8) + Inches(0.5) comment_box = slide.shapes.add_textbox(left_start, comment_box_y, left_width, Inches(1.5)) comment_frame = comment_box.text_frame comment_frame.word_wrap = True # 标题 comment_title = comment_frame.add_paragraph() comment_title.text = "CTM comment(Please input \u2713):" comment_title.font.size = Pt(14) comment_title.font.bold = True comment_title.font.color.rgb = RGBColor(0, 100, 200) # 内容(占位符) comment_content = comment_frame.add_paragraph() comment_content.text = "#Waive:" comment_content.font.size = Pt(12) comment_content.font.color.rgb = RGBColor(100, 100, 100) # 内容(占位符) comment_content = comment_frame.add_paragraph() comment_content.text = "#Update GDS:" comment_content.font.size = Pt(12) comment_content.font.color.rgb = RGBColor(100, 100, 100) # ===== remark文本框 ===== remark_box_y = comment_box_y + Inches(0.8) + Inches(0.5) remark_box = slide.shapes.add_textbox(left_start, remark_box_y, left_width, Inches(1.5)) remark_frame = remark_box.text_frame remark_frame.word_wrap = True remark_content = remark_frame.add_paragraph() remark_content.text = "Remark:" remark_content.font.size = Pt(14) remark_content.font.bold = True remark_content.font.color.rgb = RGBColor(34, 139, 34) # === 右侧区域:违规表格 === right_start = left_start + left_width + Inches(0.3) right_width = Inches(5.0) # 表格标题 table_title = slide.shapes.add_textbox(right_start, Inches(0.1), right_width, Inches(0.2)) title_frame = table_title.text_frame title_para = title_frame.add_paragraph() title_para.font.size = Pt(14) title_para.font.bold = True title_para.alignment = PP_ALIGN.CENTER # 添加违规项目表格 if category["items"]: num_items = len(category["items"]) rows = num_items + 1 cols = 4 # 创建表格 table_shape = slide.shapes.add_table( rows, cols, right_start, Inches(1.0), right_width, Inches(1.0 * rows) ) table = table_shape.table # 设置表头样式 headers = ["#", f"Error[{total_errors}]", "ALL", f"{prefix_rule_name}"] for col in range(cols): cell = table.cell(0, col) cell.text = headers[col] cell.fill.solid() cell.fill.fore_color.rgb = RGBColor(59, 89, 152) cell.text_frame.paragraphs[0].font.color.rgb = RGBColor(255, 255, 255) cell.text_frame.paragraphs[0].font.bold = True # 设置列宽比例 if col == 0: table.columns[col].width = Inches(0.3) elif col == 1: table.columns[col].width = Inches(1.6) else: table.columns[col].width = Inches(2.4) # 缩短表头行高 table.rows[0].height = Inches(0.5) # 填充数据行 for row_idx in range(1, rows): # 序号列 table.cell(row_idx, 0).text = str(row_idx) table.cell(row_idx, 0).text_frame.paragraphs[0].font.bold = True table.cell(row_idx, 0).text_frame.paragraphs[0].font.size = Pt(12) # 违规信息列 violation_info = category["items"][row_idx - 1] coordinates = extract_coordinates(&#39;&#39;.join(violation_info)) saveImageAll(coordinates[0], coordinates[1], coordinates[2], coordinates[3], f"screenshots/{category[&#39;ruleName&#39;]}.png", lv) if prefix_rule_name in layer_dict: info = layer_dict[prefix_rule_name] saveImageByLayer(coordinates[0], coordinates[1], coordinates[2], coordinates[3], f"screenshots/{category[&#39;ruleName&#39;]}_{info[&#39;GDS&#39;]}_{info[&#39;Data Type&#39;]}.png", lv, info[&#39;GDS&#39;], info[&#39;Data Type&#39;],violation_info) info_cell = table.cell(row_idx, 1) info_cell.text = "\n".join(violation_info) info_cell.text_frame.paragraphs[0].font.size = Pt(11) info_cell.text_frame.word_wrap = True # 调整行高 table.rows[row_idx].height = Inches(2.0) # 截图列 for col_idx in [2, 3]: cell = table.cell(row_idx, col_idx) cell.text = "" # 计算单元格位置 cell_left = table_shape.left + sum([table.columns[c].width for c in range(col_idx)]) cell_top = table_shape.top + sum([table.rows[r].height for r in range(row_idx)]) # 图片尺寸 pic_width = table.columns[col_idx].width - Inches(0.1) pic_height = table.rows[row_idx].height - Inches(0.1) # 添加图片占位符 placeholder = slide.shapes.add_shape( MSO_SHAPE.ROUNDED_RECTANGLE, cell_left + Inches(0.05), cell_top + Inches(0.05), pic_width, pic_height ) placeholder.fill.solid() placeholder.fill.fore_color.rgb = RGBColor(230, 230, 230) screenshot_path = f"1.png" if col_idx == 2: screenshot_path = f"screenshots/{category[&#39;ruleName&#39;]}.png" elif col_idx == 3: if prefix_rule_name in layer_dict: info = layer_dict[prefix_rule_name] screenshot_path = f"screenshots/{category[&#39;ruleName&#39;]}_{info[&#39;GDS&#39;]}_{info[&#39;Data Type&#39;]}.png" # 添加截图 if os.path.exists(screenshot_path): slide.shapes.add_picture( screenshot_path, cell_left + Inches(0.05), cell_top + Inches(0.05), width=pic_width, height=pic_height ) # 保存PPT文件 # === 动态生成PPT文件名 === oas_base_name = os.path.splitext(os.path.basename(gds_path))[0] ppt_filename = f"{oas_base_name}_DRCReport.pptx" prs.save(ppt_filename) print("PPT报告生成完成")这是我的,下面是画多边形的 import pya import os # 创建输出目录 output_dir = r"D:\out" os.makedirs(output_dir, exist_ok=True) # 创建新布局 layout = pya.Layout() top_cell = layout.create_cell("TOP") # 定义图层 layer_index = layout.insert_layer(pya.LayerInfo(1, 0)) # 输入坐标点字符串并解析 coord_str = "614.22,0.5;614.22,3;615.335,4.11;615.335,4.945;613.665,4.945;613.665,4.39;613.11,4.39;613.11,5.5;615.89,5.5;615.89,3.835;614.78,2.72;614.78,0.5" points = [pya.DPoint(*map(float, pair.split(&#39;,&#39;))) for pair in coord_str.split(&#39;;&#39;)] # 创建多边形并添加到布局 polygon = pya.DPolygon(points) top_cell.shapes(layer_index).insert(polygon) # 获取当前视图 view = pya.Application.instance().main_window().current_view() view.select_cell(top_cell.cell_index(), 0) view.max_hier() # 设置导出范围(包含整个多边形) bbox = polygon.bbox() margin = 1.0 # 添加1微米边距 export_box = pya.DBox(bbox.left - margin, bbox.bottom - margin, bbox.right + margin, bbox.top + margin) # 导出图片到指定路径 view.save_image("D:/out/output.png", 2048, 2048) # 参数:文件名、宽度、高度这是高亮多边形的,帮我修改saveImageByLayer的代码
09-17
【无人机】基于改进粒子群算法的无人机路径规划研究[和遗传算法、粒子群算法进行比较](Matlab代码实现)内容概要:本文围绕基于改进粒子群算法的无人机路径规划展开研究,重点探讨了在复杂环境中利用改进粒子群算法(PSO)实现无人机三维路径规划的方法,并将其与遗传算法(GA)、标准粒子群算法等传统优化算法进行对比分析。研究内容涵盖路径规划的多目标优化、避障策略、航路点约束以及算法收敛性和寻优能力的评估,所有实验均通过Matlab代码实现,提供了完整的仿真验证流程。文章还提到了多种智能优化算法在无人机路径规划中的应用比较,突出了改进PSO在收敛速度和全局寻优方面的优势。; 适合人群:具备一定Matlab编程基础和优化算法知识的研究生、科研人员及从事无人机路径规划、智能优化算法研究的相关技术人员。; 使用场景及目标:①用于无人机在复杂地形或动态环境下的三维路径规划仿真研究;②比较不同智能优化算法(如PSO、GA、蚁群算法、RRT等)在路径规划中的性能差异;③为多目标优化问题提供算法选型和改进思路。; 阅读建议:建议读者结合文中提供的Matlab代码进行实践操作,重点关注算法的参数设置、适应度函数设计及路径约束处理方式,同时可参考文中提到的多种算法对比思路,拓展到其他智能优化算法的研究与改进中。
标题中的"EthernetIP-master.zip"压缩文档涉及工业自动化领域的以太网通信协议EtherNet/IP。该协议由罗克韦尔自动化公司基于TCP/IP技术架构开发,已广泛应用于ControlLogix系列控制设备。该压缩包内可能封装了协议实现代码、技术文档或测试工具等核心组件。 根据描述信息判断,该资源主要用于验证EtherNet/IP通信功能,可能包含测试用例、参数配置模板及故障诊断方案。标签系统通过多种拼写形式强化了协议主题标识,其中"swimo6q"字段需结合具体应用场景才能准确定义其技术含义。 从文件结构分析,该压缩包采用主分支命名规范,符合开源项目管理的基本特征。解压后预期可获取以下技术资料: 1. 项目说明文档:阐述开发目标、环境配置要求及授权条款 2. 核心算法源码:采用工业级编程语言实现的通信协议栈 3. 参数配置文件:预设网络地址、通信端口等连接参数 4. 自动化测试套件:包含协议一致性验证和性能基准测试 5. 技术参考手册:详细说明API接口规范与集成方法 6. 应用示范程序:展示设备数据交换的标准流程 7. 工程构建脚本:支持跨平台编译和部署流程 8. 法律声明文件:明确知识产权归属及使用限制 该测试平台可用于构建协议仿真环境,验证工业控制器与现场设备间的数据交互可靠性。在正式部署前开展此类测试,能够有效识别系统兼容性问题,提升工程实施质量。建议用户在解压文件后优先查阅许可协议,严格遵循技术文档的操作指引,同时需具备EtherNet/IP协议栈的基础知识以深入理解通信机制。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值