总图概念设计

SKILL效率
效率 未标注权限 许可证不明确
安装这个技能

总图概念设计 / 场地方案生成 / 总平面图自动布图 / 技术经济指标测算 / 总图规范核查 / ZWCAD 出图 / 中望 CAD 连接器(COM 直驱真实落图)/ DWG 输入(甲方地形图、单体轮廓图直接传 DWG)。触发词:总图设计、总平面图、概念总图、场地布置、总图排布、强排方案、指标测算、总图规范核查、生成 DXF、DWG 转 DXF、上传 DWG 地形图、上传 DWG 楼栋轮廓、甲方 DWG、中望 CAD 布图、中望 CAD 连接器、CAD 实际绘制、消防车道、停车位配建、绿地率、建筑密度、容积率勾稽。输入规划条件、甲方需求、地形红线(DWG / DXF),自动排出建筑轮廓+道路+车位+消防车道+绿地,按 GB 55031 / GB 50352 / GB 50016 / GB 55019 通用口径核查,输出 DXF + DWG(中望 COM 直驱实绘)+ 指标表 + 待补规范清单。 支持X402协议支付调用,按次付费。

一句话选型结论

按资料字段整理

总图概念设计是效率类的 Agent Skill,安装方式未标注,权限级别未标注,许可证不明确,有可直接复制的安装命令。技能本质是给模型读的说明书,效果取决于模型与客户端;装完先用一个小任务验证,再放进正式流程。

分类效率 安装方式未标注 权限级别未标注权限 许可证许可证不明确
累计安装 未标注 本周 未标注
GitHub 星标 未标注 仓库 未标注
下载量 未标注 技能市场下载数
权限级别 未标注权限 安装前请确认风险范围
许可证 许可证不明确 未说明

安装

未标注
在支持 Skills 的客户端里执行,装完问一句「你有哪些技能」验证
skillhub install user_b24dc7bf/site-planning
  1. 1
    确认客户端支持

    确认你的客户端支持 Skills(Claude、Codex、Cursor 等),并升级到较新的版本。

  2. 2
    拿到技能文件

    执行上面的命令安装;也可以把仓库里的 SKILL.md 手动放进客户端的 skills 目录。

  3. 3
    刷新技能列表

    重新打开客户端,或刷新技能列表,让新放进来的技能被加载。

  4. 4
    验证是否生效

    问一句「你有哪些技能」,确认列表里出现它,再拿一个小任务试跑。

技能档案

效率
字段来自技能仓库与公开索引,中文说明由本站标注
作者 / 维护方user_b24dc7bf仓库 未标注 · 版本 未标注
宿主客户端未标注技能可被这些客户端加载
安装方式未标注安装包 community
权限级别未标注权限安装前请确认风险范围
许可证未说明许可证不明确,商用前请自行确认条款
仓库可用性available技能仓库当前是否可访问
最近核验2026-11-06上游最后核验时间 · 数据更新 2026-11-06
正文体量42.0 KBSKILL.md 原文大小,越大说明说明书写得越细

典型使用场景

3 类
按分类整理的常见用法,具体以 SKILL.md 为准
整理待办与日程

把零散任务收进清单,排出优先级。

批量处理重复任务

把固定动作做成模板,重复执行。

把流程写成清单

把口头流程整理成可复用的步骤。

选择建议

装之前先看这几条
按条目字段给出的判断,不替你决定用不用

值得选的地方

  • 有可直接复制的安装命令,不用自己翻文档找入口。

先想清楚的地方

  • 没有标注权限级别,实际能做什么要装好后确认。
  • 许可证不明确,商用或二次分发前先到仓库确认条款。
  • 没有做站内核验,内容以作者仓库为准。
  • 技能只是说明书,实际效果取决于模型与客户端,装完先用小任务试一遍。

更适合

  • 需要在效率场景里给模型补一套做法的人。
  • 愿意先读一遍 SKILL.md、确认它会让模型做什么的人。

不太适合

  • 对许可证要求很严、必须明确可商用的人。
  • 只想装完就自动变强、不打算看说明书的人。

同类对比

6 个同类
同分类里挑最接近的几条,字段以各自详情页为准
技能权限级别安装方式累计安装宿主客户端安装命令
总图概念设计当前 未标注权限 未标注 未标注 未标注 有
Nano PDF 文档 联网访问 ClawHub 市场 424.9 万 OpenClaw 有
自动更新程序 浏览器控制 ClawHub 市场 296.4 万 OpenClaw 有
Gemini 助手 联网访问 ClawHub 市场 254.7 万 OpenClaw 有
word DOCX 文档 联网访问 ClawHub 市场 239.6 万 OpenClaw 有
Excel XLSX 前端 联网访问 ClawHub 市场 227.0 万 OpenClaw 有

SKILL.md 全文

42.0 KB
模型实际读到的说明书原文,来自技能仓库

总图概念设计(site-planning)

把「规划条件 + 甲方需求 + 地形红线」变成一份可落地到 CAD 的概念总平面图,
并且在排布过程中就把国家规范的硬约束算进去,而不是画完再人工查。

Boundary(不做什么)

  • 不做施工图深度:出的是概念总图(轮廓级),不含基础、结构、管网、竖向高程、边坡支挡。
  • 不做日照分析:本机无日照间距系数与地方规定,此项一律标 manual。
  • 不做竖向与土方:无等高线高程时,坡度类判据一律标 manual。
  • 不替代地方标准:停车位配建、退线、绿地折算、人防、海绵城市指标均为地方口径,
    本技能只给通用替代值并强制列入「待补规范清单」。
  • 不联网:全部本机计算,不上传任何数据。

Core Workflow

输入 payload.json(规划条件 / 甲方需求 / 地形 / brief 描述性指令)
  → sp_dwg        DWG 输入条件 → DXF(ODA 或中望 COM),可选前置步
  → sp_intent     描述性文字指令 → directives(认不出的句子原样回报,不猜)
  → sp_validate   契约校验 + 降级 + 白名单过滤
  → sp_geom       红线归一化 → 退线内缩 → 栅格化(S0–S1)
  → sp_layout     道路骨架 → 地块 → 建筑体块 → 出入口接驳 → 消防 → 停车 → 绿地(S2–S7)
                  ├ 多栋落位保障:骨架 full→no_sub→ring 逐级简化 + 外轮廓试旋转,取「排得最多」那套
                  ├ 道路:分环道/主轴/支路/接驳道四类**净增面积**(之和 = 道路总面积)+ 路面矩形 bands
                  ├ 绿地:剩余可用格按连通域归并为地块,给出位置(东北/中部…)、范围、面积
                  └ 出入口:每栋选「指令指定朝向 → 接驳距离最短」的边设出口,铺 ≥4m 接驳道连到道路
  → sp_variants   **一次出 10 个候选方案**(固定枚举,不是随机)→ 评分排序 → 取最高分作为主方案
  → sp_metrics    技术经济指标(唯一口径)
  → sp_rules      SITE_RULES 30 条机算判定 + 待补标记
  → sp_dxf / sp_scr / sp_svg / sp_report   出图与报告(主方案 + 10 个方案各自一套)
  → sp_zwcad / zwcad_cli                   连上中望 CAD,COM 直驱把图**画进去**并存 DWG
  → result.json

命令行:

"C:/Users/<user>/.workbuddy/binaries/python/versions/3.11.9/python.exe" \
  scripts/siteplan_cli.py --in <payload.json> --out <输出目录>

输出目录:六件套(主结果)+ 方案01…方案10/ 子目录(每个方案独立 SVG/DXF/SCR/报告/result.json)
+ 方案对比.html(横向指标与平面图)+ variants.json(10 个方案的轻量摘要,供页面切换条用)。
六件套 = input.json / 总平面图.dxf / 总平面图.svg / 布图.scr / result.json / 总图设计报告.html。

中望 CAD 连接器(COM 直驱,真实落图)

sp_zwcad.py + zwcad_cli.py 把总平面图真的画进中望 CAD,而不是"把 DXF 丢给 CAD 打开":

PY=scripts/../python  # "C:/Users/<user>/.workbuddy/binaries/python/versions/3.11.9/python.exe"
"$PY" scripts/zwcad_cli.py --action status --live                 # 连接器状态(探安装/注册表/进程 + 实测附着)
"$PY" scripts/zwcad_cli.py --action plan --result out/result.json  # 只看绘制计划,不碰 CAD
"$PY" scripts/zwcad_cli.py --action draw --result out/result.json --out out \
      --scale 1000 --target new [--no-save-dwg] [--no-zoom]
  • 执行层做四件事:建 11 个图层(与 sp_dxf.LAYER_DEFS 同源)→ 用 AddLightWeightPolyline
    / AddText / AddCircle 逐条绘实体(几何与 DXF 同源,都读 result.json 的 geometry)
    → ZoomExtents → 另存 <out>/中望CAD绘制/总平面图.dwg。
  • 图层/文字样式:SP-RED / SP-SETBACK / SP-ROAD / SP-ROADCL / SP-BUILD / SP-PARK / SP-FIRELN / SP-FIELD / SP-GREEN / SP-ENTRY / SP-TEXT;文字样式 SP-CN(simsun.ttc),否则中文不显示。
  • 单位:--scale 1000(默认,米→毫米,CAD 常规)/ --scale 1(与 DXF 一致)。指令单内部一律「米」。
  • 目标图纸:--target new(默认,新建图纸,空白的 DrawingN.dwg 会复用;用户已开的图一律不碰)
    / --target active(画进当前图纸)。
  • 同名 DWG 正被 CAD 打开时(上一轮画完没关),另存会自动退避到 总平面图_<时间戳>.dwg,
    并在 dwg_note 里说明 —— 不会因为文件锁而白画一场。

三个坑(改这块代码前必读)

  1. 点坐标必须 _midlSAFEARRAY(c_double).create([x, y, z]) 直传。
    传 list/tuple 或 VARIANT(VT_ARRAY|VT_R8, …) 一律 COMError -2147352567 发生意外;
    中望只认裸 SAFEARRAY 指针,且点要 3 维。
  2. 附着只能 GetActiveObject(progid, dynamic=True)。 dynamic=False 会让 comtypes 为类型库
    生成包装模块,中文 Windows 下以 mbcs 读回生成文件 → SyntaxError 直接失败。
  3. 绘制几何不要用 Document.SendCommand()。 它同步、要求精确回车数,少一个换行就把 CAD
    卡在命令中途(实测 PLINE 卡死);只用 Add* 实体接口。

桥接侧对应两个端点:GET /api/siteplan/cad/status[?live=1]、POST /api/siteplan/cad/draw
({scale, target, save_dwg, zoom, base_name});连接器单开短命进程执行(COM 是套间绑定模型,
长驻进程跨线程复用 COM 指针易挂起)。

base_name 为「底图」:把甲方地形图 DWG 原样打开当底图,再在上面叠画本方案(--base <dwg>)。
打开失败(文件被占/版本过高)会自动回退新建图纸,原因写入回执 base_note;doc_open 记录打开时的原图名。

DWG 输入条件(地形图 / 单体轮廓图)

甲方给的 CAD 条件图基本都是 DWG,而内部几何内核只吃 DXF(ezdxf 不解 DWG)。
sp_dwg.py 负责把 DWG 转成 DXF,两条引擎链路按优先级自动选:

引擎 触发 原理 本机状态
odafc 装了 ODA File Converter 命令行批量转(ODA_OUT_VER=ACAD2018/ODA_OUT_TYPE=DXF) 未安装,装了即自动优先
zwcad 本机有中望 CAD COM 开图 → SaveAs(…, 13=DXF) → Close(False) 可用,实测 2.6–6.1 s
PY="C:/Users/<user>/.workbuddy/binaries/python/versions/3.11.9/python.exe"
"$PY" scripts/zwcad_cli.py --action convert --src 甲方地形图.dwg --out <输出目录> --engine auto
# → {ok, engine, dxf, ms, dwg_bytes, dxf_bytes, from_dxf, warn, err}
  • 入口:sp_dwg.convert(src, out_dir=None, engine="auto", timeout=180);已装 ODA 优先用它
    (快且不弹 CAD),没有则回落中望;engine=odafc|zwcad 可强制。
  • 传进来就是 DXF 时走 passthrough(from_dxf=True,不动文件)。
  • MAX_DWG_BYTES = 200 MB,超限在开 CAD 之前拦截;DWG 版本过高(中望打不开)→ 报错,不硬试。
  • 转出的 DXF 是 AC1032,sp_bld_dxf.parse_outline / _parse_terrain_redline 可直接读。

上传即转、只用文件名(关键设计)

DWG 转换在桥接侧完成,浏览器↔桥接之间只传文件名,不传几十 MB 的 DXF 正文:

浏览器 --POST /api/siteplan/dwg?name=xxx.dwg (二进制体)--> 桥接
        桥接:_safe_dwg_name 净化 → _looks_like_dwg 嗅探 → sha1 缓存命中?→ 开 CAD 转 DXF
        DXF 落盘 <SP_OUT>/上传源文件/xxx.dxf(DWG 留档同名 .dwg,旁证 .sha1)
浏览器 --POST /api/siteplan {redline_dxf_upload:"xxx.dxf", outline_dxf_upload:[…]}--> 桥接
        siteplan_cli._resolve_upload 按相对路径取文件 → 解析 → 出图
  • 端点:POST /api/siteplan/dwg?name=(二进制)、GET /api/siteplan/dwg/status(双引擎 + uploads 清单)。
  • sha1 缓存:旁证 <名>.dwg.sha1 命中则直接复用已转 DXF(实测 0 ms,不再开 CAD)。
  • payload 键名用 *_upload 后缀 —— sp_validate._strip_paths 会剥掉键名含 path/dir/file/folder/root
    的字段,上传系列键名必须避开这些词。
  • 前端:spFileKey / spUploadDwg / spReadCond,结果卡片显示「DWG 已转 DXF」与来源回溯(#spSrcNote)。
    楼栋外轮廓文件选择器只收 .dwg(accept=".dwg",标签「外轮廓 DWG」);地形图红线收 .dwg,.dxf。
    引擎侧仍兼容传入的 DXF 文本(兜底,界面上不宣传)。

三个坑(改这块代码前必读)

  1. 文件名要三重净化:桥接 _safe_dwg_name(只留末段 + 后缀统一小写)、
    sp_validate._upload_name、siteplan_cli._resolve_upload(os.path.basename(name) != name 一律拒)。
    少一层就可能被 ../ 逃逸出输出目录。
  2. 体积上限必须在开 CAD 前拦。等中望打开一个 500 MB 的图再报错,用户要等很久且可能把 CAD 卡死。
  3. 别把 DXF 正文塞进 payload。几十 MB 基文本在桥接↔浏览器往返两趟会直接把页面卡住;
    一律「上传即转、只传文件名」,DXF 由 siteplan_cli 自己从 <out>/上传源文件/ 取。

多栋落位与路网骨架自适应(改这块代码前必读)

「先路后房」的致命前提是路网骨架不能比楼栋还密。build_roads 固定「外环 + 长边中线主轴干道 +
每 road.block_depth_m(默认 70m)一道支路」,会把瘦长用地的可建宽度一分为二:
实测 116×470 的红线(退线后约 106m)配 1 栋 52.5×185.4 的单体,长边中线主路把 106m 切成两半(各约 49.5m),
4 栋楼只排上 1 栋,其余全进 unmet。四项对策(都在 sp_layout.build / place_buildings):

  1. 骨架逐级简化:build_roads(..., level=) 支持三档 ——
    full(环道 + 主轴干道 + 支路,原行为)/ no_sub(去支路)/ ring(仅环道)。
    build() 先按 full 排;只要还有 unmet 就依次试 no_sub、ring,按 (落位数, -未排数) 取优,
    严格更优才替换(同分保留骨架更完整的那套,避免无谓改动),排干净即 break。
    环道任何一档都保留(GB 50016 7.1.2 消防车道);降级必须往 warn 写一条带档位名的说明
    (不许静默改路网)。当前档位记在 stats.road_level,三档中文名见 _ROAD_LEVEL_NAME。
  2. 外轮廓试旋转:place_buildings 对带 outline 的楼栋先试原朝向 (ow, oh),排不下才试 (oh, ow);
    旋转时多边形要跟着转([[x + (oh - (p[1] - ob[1])), y + (p[0] - ob[0])] …]),并记 rec['rotated']。
    原朝向优先是硬要求:既有测试锁死了 w=30/h=20,改成旋转优先会把既有结论改掉。
  3. 高度以用户填写值为准:sp_validate._owner 透传 height_m(兼容 h_m),place_buildings 优先用它,
    未填才退回 floors × floor_h_m。防火间距 / 登高场地判的是真实高度,不能被默认层高带偏。
  4. 未排布要说清差在哪:unmet 每条带 need_m(该栋需的外接框)与 max_block_m(当前最大地块),
    build() 据此生成「需 W×H m 外接框,最大地块仅 W×H m」的告警。

> 前端 index.html 结果卡指标表末尾同步显示「路网骨架」(读 geometry.stats.road_level,非 full 标黄)
> 与「未排布单体」两行。

描述性文字指令(brief → directives)

甲方/设计的意图常常是「主入口设在南侧、道路宽 6 米、冷库放东侧、绿地集中在西北角」这种话。
sp_intent.parse_brief(text, warn) 把它解析为 sp_layout.build(..., directives=) 能直接消费的 dict。

能认的(按固定规则顺序匹配,命中即给出 human 说明):

类别 写法示例 产出键
场地出入口方位 主入口设在北侧 / 出入口设在东北角 entry_dirs
道路宽度 道路宽 6 米 / 主干道宽 9m / 支路宽 4 米 road_main_w / road_sub_w
路网密度 不要支路 / 只设环形道路 / 加密支路 road_level(+ block_depth_m)
支路间距 支路间距 60 米 block_depth_m
楼栋朝向 楼栋南北向 / 建筑东西朝向 orient
建筑间距 楼间距不小于 10 米 / 加大楼间距 gap_min_m / gap_extra_m
退线 退线 8 米 setback_m
绿地率 绿地率 35% green_min_pct
地上车位 地上车位 30 个 / 停车全部地下 parking_above / parking_underground
绿地集中方位 绿地集中在西北角 green_focus
楼栋定位 冷库放在东侧 / 1# 布置在西北角 bld_dir
楼栋出口朝向 1#出口朝南 bld_entry

三条硬规矩:

  1. 认不出的短句原样进 unparsed,并往 warn 写一条「有 N 句未能识别,未参与布局」;
    页面与报告都如实列出。宁可说不懂,也不猜 —— 猜错会排错图且用户无从察觉。
  2. 只覆盖指令确实提到的项,其余键不出现(.get() 取不到就退回规划条件 / site-defaults.json),
    绝不把「没说」当成「用默认值覆盖规划条件」。
  3. 最易误伤的一处:「支路间距 50 米」说的是路网,不是楼间距。_r_gap 必须先排掉
    (支路|路网|道路|消防车道|环路|环道)间距,否则会把建筑间距拉成 50m。

指令明确指定 road_level 时不再自动简化骨架(尊重甲方口径,排不下就如实告警 + 记 force_level 说明)。
结果经 result.json 的 directives: {raw, applied[], unparsed[], keys[]} 回传,前端 spRenderDirective 原样展示。

三个坑(指令解析,改这块代码前必读)

  1. road_level 是「强限定词优先」,不是「子句先后」。_CLAUSE_SPLIT 会把
    「不要支路,环形路网」切成两句,若按 d[k] = v 的后写覆盖语义,第二句的 ring
    会盖掉第一句的 no_sub,结果与用户本意完全相反。故 _r_road_level 先在子句上扫
    否定/加密词并锁定 d['road_level'],后续子句一律不改写。
  2. 「中部/中心」不是象限。「绿地集中在中部」若塞进 green_focus 的方位列表,
    _quadrant() 永远匹配不上 → 指令静默失效。必须走独立键 green_focus_center:
    place_parking 按到场地中心的归一化距离排序(中心块最后停车 → 剩下的自然集中),
    green_patches(focus_center=True) 按中心距离排序 —— 后者直接决定哪块地被
    classify_greens() 当作主景园。
  3. 矛盾整句不猜。「环形路网,多设支路」自相矛盾:parse_brief 入口做整句预检,
    命中则整句进 unparsed 回报用户确认,而不是靠子句顺序决定结果。
    另外,已被 road_level 吸收掉的邻句措辞不报 unparsed(报出来用户只会困惑「我都写了啊」)。

道路 / 绿地 / 楼栋出入口(位置 + 面积)

旧版只给「道路广场用地 X㎡」「绿地率 Y%」两个数,看不出在哪。现在三类要素都落到图上并进明细:

  • 道路:build_roads / place_building_entries / fire_provision 都接同一个 kind_r 字典,
    按 ring / main / sub / access / fire 各建一张分类栅格;_stamp_line 只对首次成为道路的格计入本类
    → 各类面积之和恒等于道路总面积(交叉口不重复计,这个勾稽关系已写成断言)。
    每条路另带 bands(逐段路面矩形,供 DXF/SVG 填充)与 area_m2(本条净增)。
    ⚠ fire_provision 补画的消防车道也必须传 kind_r(归入 fire),否则它占了 road_r
    却不计入任何一类,勾稽就断了。
  • 绿地:green_patches(green_r, min_area, site_bbox, focus=, focus_center=) 把剩余可用格按连通域归并成地块,
    输出 id / area / bbox / center / size_m / pos(位置用「东北 / 中部」等相对方位描述)。
    green.min_patch_area_m2(默认 60㎡)以下碎斑不单列;focus 非空时指定方位的地块排最前;
    focus_center=True 时按到场地中心的归一化距离排(决定主景园落在哪)。
    口径:集中绿地(各块之和) + 退线带绿地 = 绿地总面积,报告与前端都按此拆分。
  • 楼栋出入口:place_building_entries(S4.5,排在消防之前 —— 出入口是「必须有」,先占地)
    对每栋取四条边中点作候选,按 指令指定朝向 → 接驳距离最短 → N/E/S/W 固定序 选一个,
    从该点铺一条 road.access_width_m(默认 4.0m,不足 3.5 抬到 3.5,兼顾消防车道最小净宽)的
    接驳道到最近道路中心线。引道压到其它建筑的边(_seg_blocked)直接弃用;四边都不行则只标位置并告警。
    接驳道长 >30m 会提示「偏长,建议增设内部道路」。kind='access' 的道路不参与接驳目标计算
    (否则 A 栋会去接 B 栋的引道)。

出图:sp_dxf 把接驳道画成路面矩形(色 30)+ 「接驳·X栋」、绿地逐块画外接框与面积、出口画圆点加
「X栋出口·东」;sp_svg 同要素(接驳道橙色、绿地浅绿虚线、出口方块);sp_report 新增
「场地要素明细」章节(指令回执 / 红线内道路 / 绿地布置 / 楼栋出入口与接驳 四张表)。

10 个候选方案(多方案比选)

同一份「楼栋尺寸 + 地块尺寸」本来就有多种排法。概念阶段的价值是把排法摆出来比,
而不是只交一个"看起来还行"的解。sp_variants.py 一次生成 10 个方案:

变体 = 4 个维度写死的枚举(sp_variants.VARIANTS,顺序不要动 —— 方案编号与报告、页面、测试对得上):

维度 取值 落在哪
路网骨架 level full 完整 / no_sub 去支路 / ring 仅环道 sp_layout.build_roads(level=),锁定后不再自动简化
落位部位 anchor sw / nw / ne / se / center / spread(spread = 尽量远离已落位楼栋) _search_in_block(anchor=),评分里占 0.9 权重
排布次序 order area_desc 大栋优先 / area_asc 小栋优先 / input 按输入顺序 place_buildings 的 demand 排序
朝向策略 rotate auto 原朝向优先 / none 不旋转 / force 优先转 90° place_buildings 的 size_plans 顺序

硬约束:确定性。不用 random,10 个变体是常量表 —— 同一输入跑一万次,方案 1 永远是方案 1
(test_sp_variants.TestVariantEngine.test_deterministic 断言两次跑的落位逐字节一致)。
否则上次选中的方案下次就变了,没法比选。

评分(score_of,权重明写、不黑箱):落位 +40/栋、未排布 −18/栋、规范不符合 −6/条、
人工复核 −0.5/条(概念阶段不可避免,轻罚)、绿地率达标 ±10、栋间距达标 +8/−12、
道路占地占比越接近 12% 越优(+6)、景观品质 0~14(landscape_bonus)。
排序后取最高分为主方案,其余进各自子目录。

landscape_bonus 四项按比例给分:树冠覆盖 6(30% 满分)/ 绿量丰度 3(100 株/ha 满分)/
主景园 3(按完整度给分) / 园路长度 2(200m 满分)。
⚠ 主景园那 3 分必须看完整度:环形路网变体会把建筑间空地连成碎形连通域
(20773㎡、完整度 0.57),只按面积判就给它满分,结果「四面楼房围着 3278㎡ 水面、
园路只有 50m」的方案胜出。旧数据无 compactness 字段时按 1.0 处理(向后兼容)。

输出:<out>/方案NN_骨架-部位-次序[-转90]/ 下放 总平面图.svg · 总平面图.dxf · 布图.scr · 总图设计报告.html · result.json;<out>/方案对比.html 横向比指标 + 逐方案平面(<img> 引相对路径);
<out>/variants.json 是 10 个方案的轻量摘要。所有方案共用 siteplan_cli._make_res,
口径与主方案完全一致(比选的前提是数字可比)。

页面:结果卡顶部「候选方案」切换条,点一下即换该方案的预览 / 报告 / 指标 / 核查;
「📊 方案对比页」把对比页装进报告 iframe(平台内看,不开外部浏览器)。
桥接两个新端点:GET /api/siteplan/variant?dir=<子目录>(取该方案 result.json)、
GET /api/siteplan/file?name=svg&sub=<子目录>(取该方案的图);sub 做了纵深净化
(只认 SP_OUT 下的直接子目录名,含 .. / : / / / \ 一律拒绝)。

⚠ 单方案(不传 variant)行为完全不变:仍走「骨架逐级简化直到排得下」的旧路径。
⚠ 指令锁定骨架时优先级为 指令 > 变体 > 自动简化:此时 10 个方案都在该骨架下变,只换部位/次序/朝向。

建筑构图评分(让总图"看起来是设计过的")

规范解不止一个。sp_layout._composition_score() 在落点搜索时叠一层美学评分,
让引擎在同等合规的解里挑出构图更好的那个:

分项 权重 判据
对位 0.5 建筑长边与地块主轴平行
均质 0.25 与已落位楼栋的净距接近平均值(避免孤零一角)
向心 0.25 靠边布置,把中心让给绿地(对 _search_in_block 的 anchor 偏好弱化)

总权重 0.75 < 「放得下」的基线 1.0 —— 这是刻意的:构图只能在合规解里优选,
绝不放松任何规范间距。compose=False 可整体关闭退回旧行为(build(..., compose=) /
place_buildings(..., compose=) / _search_in_block(..., compose=) 逐层透传)。
stats.compose_on 留痕。

⚠ 构图开启后,单维度变体扰动几乎拉不开差距(score 主导项相同),_collision_fixes 因此
新增「关构图 + 换 anchor/order」的组合扰动维度。

园林化景观层(绿化做到园林效果)

scripts/sp_landscape.py —— 在布局与绿地归并之后叠加一层景观(S7.5 段)。
纯叠加图层:只读栅格、绝不回写,所以绿地率 / 建筑面积 / 道路面积的口径完全不变
(test_sp_landscape.TestNoSideEffect 逐项断言开/关指标相等)。

绿地角色分区(园林的主次骨架)

classify_greens() 把碎形绿地连通域分成 5 种角色,各有不同配植手法:
core 主景园(最大、最完整、有水面)/ cluster 组团绿地 / belt 防护林带 /
edge 边界绿地(密植屏障)/ scratch 零星绿地(点缀)。

⚠ 主景园不按面积最大选,要过三道判据(classify_greens):

  1. 完整度:_compactness(g) = 面积 / 外接框面积,门槛 CORE_COMPACT_MIN = 0.62。
    原因:环形路网(无支路切分)时建筑之间的剩余空地会连成一整片碎形连通域 ——
    实测 20773㎡ 但完整度只有 0.41;把它当主景园会导致水面 3278㎡ 却园路全落不下。
  2. 形状:_shape_ok(g) 要求外接框最短边 ≥ CORE_MIN_SIDE_M = 12m。
    ⚠ 纯几何完整度识别不了细长绿带:一条 74m × 2.5m 的横向隔离带,185㎡/185㎡
    = 完整度 1.000(满分),实测把 10362㎡ 的真主景园顶掉了。园林主景的物理条件
    是「放得下水面与环园路」,狭长绿带只能做防护绿带/行道绿带。
  3. 规模:候选面积须 ≥ 最大绿地的 CORE_AREA_RATIO = 0.25。
    防止「完整度刚过线的小绿地」压过「面积大数倍但略碎的大绿地」——后者才是园林主景。

三道都过 → 按(完整度↓,面积↓)排序取第一;一个都没过 → 按面积降级选取,
并打 _core_degraded 标记让调用方如实告警(绝不出现「全场无主景」)。
分组用索引而非 dict 本身(两个连通域可能 area/bbox 完全相同,按值比较会混淆)。
报告的绿地角色表列出完整度,便于人工复核选块是否合理。

配植口径(真实设计经验值,不是随手撒点)

  • 乔木按株/ha 而非按面积比例:主景园 70、组团 110、边界 140(site-defaults.json 可调)。
  • 行道树只沿环路/主干道,间距 10m、退线 2.5m;停车场遮荫树间距 12m;防护林带 6m、内缩 2m。
  • 绿篱/灌木层(_shrub_layer,园林「乔灌草」的中间层,缺了它绿化就是散的):
    建筑周边(沿两条长边内退 1.5m)、园路两侧(退 width/2 + 1.3m)、水岸(外退 1.5m),
    株距 1.2m,上限 hedge_max_count=900。去重网格必须按层分档:
    乔木 3.0m(冠幅尺度)、绿篱 1.0m(栽植株距)——共用 3.0m 会把绿篱整排吃掉。
  • 树冠覆盖率是双向指标,且阈值按绿地率折算:下限 max(8, min(配置15%, 实际绿地率×0.40))、
    上限 max(配置45%, 下限×2)。居住区经验带 20~40%,但工业/仓储地块绿地率下限
    本就只要 10~20%
    (GB 50187),在那种地块上要求 15% 覆盖率是误报 ——
    用地本来就该硬质化,把露天种满乔木反而妨碍装卸与消防扑救。8% 是绝对地板,
    保证「乔木几乎为零」这种真问题一定会被报出来。
    必须算并集——Σπr² 会把重叠树冠重复计入导致虚高,
    故 _canopy_union() 用 2m 格网做布尔并(按 x 分桶,避免 O(格×树))。
    且只统计乔木层,绿篱不计入遮荫(它挡视线不遮荫)。
  • 冠幅按常见成年乔木冠径之半:孤赏大乔 4.5 / 遮荫乔 3.2 / 组团乔 3.0 / 行道 2.5m(半径)。
  • 层次:上层乔木 + 行道亚乔 + 灌木绿篱(TREE_SPECIES 七类,分 canopy/sub/hedge 三层)。
  • 限量也按层分开(MAX_TREES=1400 只管乔木,HEDGE_LIMIT=900 只管绿篱)——
    合并截断会把绿篱整片砍掉。
  • SVG 渲染:乔木逐株 &lt;circle&gt;,绿篱合并成单个 &lt;path&gt;(半径/样式固定,多段子路径),
    否则几百株 circle 会把 SVG 撑到 MB 级。

空间序列:到景线

入口集散广场 → 园路 → 主景园(置水面,借景倒影加倍景深)→ 环园路(可停留可游览)。
place_building_entries 排在消防车道之前;kind=&#x27;access&#x27; 不参与接驳目标计算。

三个坑(改这块代码前必读)

  1. 不能用外接框中心判落位。绿地块是碎形连通域,外接框中心常压在道路/建筑上;
    园路是环形,中心根本不在环内 → 表现为"水面和园路恒为 0"。
    必须用 _fit_ratio():按 1.5m 格网采样算图形实际落在空地上的面积占比。
  2. Raster 定义了 __slots__,挂不了 _occ 属性 → 占地栅格
    occ=(road_r, build_r, park_r, fire_r) 由 sp_layout 显式传参。
  3. 入口广场固定位置必然落空(主入口处必有车行道)。要「进深 × 面宽」双维度搜索、
    取最优解而非首个达标解,并用绝对下限 plaza_fit_floor=0.62 判定
    —— 不能因为没有完美位置就不设广场。

三个坑(大绿块场景,改这块代码前必读)

小样例(2 万㎡、2 栋)全绿,大绿块(4.6 万㎡、6 栋、环形路网)里散着 6 栋楼 + 道路,
落位阈值稍严要素就会整体消失。三个坑都是这么暴露的:

要素 阈值问题 修法
水面 先卡「≥ 目标比 × 45%」再找落位;但 30% 收缩的几何上限本身只有 389㎡ < 门槛 447㎡ → 全部 continue 改为枚举尺寸档 × 落位,取面积最大的达标者;面积门槛改在找到之后判(floor = area * ratio_eff * 0.10)。_fit_ratio 的 need 由 0.90 降到 0.70(主景园里散布着场地与园路,边缘被切过正是"有驳岸"的样子)
园路 环园路是四条边带,190×190m 绿块任何一圈都有大半压在建筑上 → 整体落不下 按 fit 降序在多档内缩里取最优;仍不达标时降级为曲尺形游步道(只取上、左两条边),园林上同样成立
宅前场地 只试两条长边 + 固定尺寸 + need=0.85 → 6 栋全落空,铺装只剩入口广场 280㎡ 四条边全试 × 三档尺寸,need 降到 0.70,取落位最好的一处

另:入口广场的横向维度不可省。主入口坐标常落在用地边缘(如 y=5.0),
只沿法向推进 11×6m 越不过车行道 + 落客带 + 绿篱带时最优解为 0,广场直接不生成。

三个坑(industrial 地块实测——低绿地率会暴露居住区口径的假设)

sp_landscape 最初是按住宅区调的参数,拿到 4.7 万㎡ / 绿地率下限 10% 的工业园区
一跑就出三处问题,都是「数据在、图上有、报告里看不见」这类隐性错误:

  1. metrics 必须自描述。enabled 只写在返回 dict 的顶层、没写进 metrics 里,
    而 sp_report 判的是 lsm = ls[&#x27;metrics&#x27;] 再取 .enabled → 拿到 None →
    整个「景观设计(园林化)」专节被跳过,而 sp_metrics 走的是顶层取法所以指标行照常出现。
    表现:result.json 里有景观数据、SVG 上画了树和水面、HTML 报告里却找不到景观章节。
    → metrics 字典第一行就写 &#x27;enabled&#x27;: True,_empty_metrics() 写 False。
    测试 test_report_has_landscape_section 专门锁这个(当时它还顺带抓出了下一个 bug)。
  2. fmt_tree_line() 里的 fmt_num 未定义。from sp_metrics import fmt_num 写在
    landscape_rows() 函数体内,fmt_tree_line() 是另一个作用域 → NameError。
    被坑 1 掩盖了一整天:专节从没渲染过,所以这段代码从没被执行过。
    → 两个函数各自 import(不能提到模块级:sp_metrics 会 import 本模块,构成循环依赖)。
  3. 细长绿带能凭满分完整度抢走主景园。74m × 2.5m 的横向隔离带,
    185㎡ / 185㎡ = 1.000(完整度满分),把 10362㎡ 的真主景园顶掉了。
    纯几何「面积/外接框面积」识别不了细长条 → 增加 _shape_ok() 最短边 ≥12m 的形状判据,
    并配套 CORE_AREA_RATIO = 0.25 的规模判据(详见上文「主景园三道判据」)。
    必须再加横向偏移 ±2 档(lane * (w*0.75 + 3.0))——那里正是红线内退让带,
    集散广场该在那儿。

确定性

禁用 random,铺点用等距步进 + R2 低差异序列
(a1=0.7548776662466927, a2=0.5698402909980532)。上限 MAX_TREES=1400、
去重间距 TREE_DEDUPE_M=3.0、单绿地角色上限 6 处。

贯通链路

sp_layout(S7.5) → sp_metrics(m[&#x27;landscape&#x27;] 透传 + 条件追加 8 行指标,
禁用时仍 27 行,向后兼容)→ sp_svg(铺装→园路→水面→乔木 分层渲染 + 左上图例)→
sp_report(绿地布置节后新增「景观设计(园林化)」:绿地角色表 + 树种统计 + 水/路/铺装)→
sp_variants(landscape_bonus 0~14 分:树冠覆盖 6 / 绿量丰度 3 / 主景园 3 / 园路成环 2)→
siteplan_cli(geometry.landscape 透传)。开关 build(..., landscape=True)。

⚠ 变体去重必须用双签名:_layout_sig(排序 + 完整 bbox,几何占位判重)
加 _order_sig(不排序 + 起点角点,与页面呈现一致),以 _order_sig 为权威键。
只按 bbox 排序判重会漏判「角点相同但进深不同」的两个方案,导致不足 10 个。

性能:大 DXF 的代理对象剔除

真实地形图(DWG→DXF)里 ACAD_PROXY_OBJECT 动辄十万个:实测一份 85MB / 704 万行 / 350 万组码的
地形图里有 101,597 个,ezdxf 纯 Python 解析要 ~150s;而代理对象的内容对 ezdxf 本就不透明,
对轮廓提取毫无用处。sp_bld_dxf._read_doc 因此对 > 3MB 的 ASCII DXF 先流式剔除代理组
(_trim_proxies:按「组码 0 + 类型名」切组丢弃,命中即跳过该组全部组码,其余原样保留),再交给 ezdxf。

  • 实测 85MB → 12.8MB、~150s → 13.7s,解析结果与不剔除完全一致(面积 / bbox / 候选环数不变)。
  • 二进制 DXF(以 AutoCAD Binary DXF 开头)不能按行拆组码,_is_ascii_dxf 先判后跳过剔除。
  • 剔除失败静默退回原文件,绝不因优化丢数据。

Runtime

  • Python 3.11.9(python),ezdxf 1.4.4
  • 除此之外零第三方依赖(几何/栅格/规则全部标准库实现);连中望走 comtypes 1.4.16(受管解释器自带,不需要 pywin32)
  • ZWCAD:&lt;本地路径&gt; Files\ZWSOFT\ZWCAD 2026\ZWCAD.exe,/b 必须置于参数末位
  • COM ProgID:ZWCAD.Application / ZWCAD.Application.2026(环境变量 WB_ZWCAD 可覆盖 exe 路径)
  • DWG→DXF(可选):装了 ODA File Converter 会自动优先使用,
    路径可用环境变量 WB_ODAFC 覆盖;未装则退回中望 COM,两者都没有 → 转换失败并提示「请安装 ODA 或先另存 DXF」
  • 全部输出 UTF-8;.scr 例外,必须纯 ASCII

三条硬约束(改动时不要破坏)

  1. 指标唯一口径:sp_metrics.py 一处算,HTML 报告 / DXF 指标表 / SVG 图签三处同用,禁止各算。
  2. 确定性:布局搜索禁用 random,枚举顺序固定,score 相同取先者 —— 否则回归无法断言。
  3. 免责印记四处同步:HTML 报告每页页眉、SVG 右下角、DXF 图签栏、前端结果卡片顶部红条。
    文案固定为「本方案依据为通用规范(GB 55031 / GB 50352 / GB 50016 / GB 55019),
    日照间距系数与地方停车位配建标准需人工补充;不得直接作为报审依据。」
    红线为假设矩形时,追加「红线为假设矩形,非真实地形,仅用于指标测算」。

参考文件

  • references/site-rules.json — 30 条机算规则
  • references/site-defaults.json — 全部可调参数(改这里,不要改代码里的魔数)
  • references/pending-specs.md — 待补规范 12 条(UI 面板数据源)
  • references/dxf-layer-map.md — 图层 / 颜色 / 线型(GB/T 50103-2010)
  • references/layout-algorithm.md — 算法说明与调参指南

测试

PY=&quot;C:/Users/&lt;user&gt;/.workbuddy/binaries/python/versions/3.11.9/python.exe&quot;
&quot;$PY&quot; -m unittest discover -s tests -v      # 16 组共 373 例(约 39 分钟)
  • 纯逻辑组:test_sp_geom / test_sp_layout / test_sp_metrics / test_sp_rules / test_sp_dxf
  • 景观组:test_sp_landscape(56 例) —— TestNoSideEffect(开/关景观层指标逐项相等、异常降级不崩)、
    TestDeterminism(两次运行逐字段一致、源码无 random/import time)、
    TestContent(树量密度 40~160 株/ha、覆盖率在可信带、树不压建筑/道路、主景园最大、园路水面广场存在、
    metrics 自带 enabled、低绿地率不误报遮荫)、
    TestRobustness(无绿地/极小地块/无楼栋/空栅格)、TestMetrics(透传、指标行增补、禁用时仍 27 行)、
    TestComposition(构图不改栋数与间距、评分 [0,1]、偏好轴线对位与靠边)、TestSvg(渲染树/水/园路/铺装/图例、
    绿篱合并成单个 path、报告必须真出现景观专节)。
    ⚠ 并集面积断言要留量化余量(≤ Σπr² × 1.15 + 1)——2m 格网离散误差约 ±格数×格面积。
  • TestCoreSelection(3 例) 锁主景园三道判据,最关键的一条是
    细长绿带(74m×2.5m,完整度 1.000)不能当主景——这是工业地块实测踩出来的。
  • TestLargeGarden(12 例) 是大绿块场景的专属闸门(4.6 万㎡ / 6 栋 / 环形路网 / 绿地集中在中部):
    主景园唯一、完整度 ≥0.62 且面积不悬殊、完整度字段逐块给出、水面存在且占比 <25%、
    园路存在(环园路或降级游步道)、宅前场地覆盖 n−1 栋以上、入口广场存在、
    三层植栽均有量、用地指标不受景观层影响、两次运行一致、
    完整度足够时不告警 / 碎形主景园时必须告警。
    ⚠ 小样例全绿不代表大绿块也全绿 —— 改落位阈值后必须跑这一组。
  • 指令组补充:test_sp_intent(42 例)含「环形路网」名词短语识别与跨子句矛盾预检
    (「环形路网,多设支路」整句判为不可解析,不靠子句先后决定结果)。
  • 输入条件组:test_bld_dxf(外轮廓 + 代理对象剔除)、test_terrain_dxf(地形红线)、test_dwg_input(DWG 上传)、test_sp_dwg(DWG 转换)
  • 指令组:test_sp_intent(38 例:各类指令解析、确定性、未识别回报、误伤回归——支路间距≠楼间距)
  • 交叉组:test_consistency(多口径勾稽)、test_parking_above(地上车位强制)
  • 连接器组:test_sp_zwcad(绘制计划/DXF 同源,--live 走真 COM)
  • test_sp_layout 里与多栋落位相关的类:TestRoadSkeletonLevel(骨架三档)、TestOutlineRotation(原朝向优先/旋转/未排布差值)、
    TestHeightPassthrough(height_m 透传)、TestMultiBuildingPlacement(4 栋全落位 / 计数一致 / 含旋转仍确定)
  • test_sp_layout 里与场地要素相关的类:TestRoadAreaByKind(分类面积之和 = 总面积)、TestGreenPatches(地块/位置/碎斑过滤/集中方位/中心优先 + 确定性)、
    TestBuildingEntries(每栋有出口 + 接驳道 ≥4m + 指令朝向)、TestDirectivesEndToEnd(指令走 CLI 全链路生效 + 未识别回报)、
    TestSiteElementsInResult(结果含三张明细、分类面积勾稽、指标表新增行)
  • 多方案组:test_sp_variants(29 例)——TestVariantTable(10 个变体、key/目录名唯一、字段合法、无 random)、
    TestVariantEngine(10 个方案都出得来、两次跑落位一致、按分降序、骨架等级被锁定、
    anchor 真的改变落点、评分惩罚未排布、stats.variant 留痕)、
    TestVariantsEndToEnd(CLI 真的写出 10 个子目录 + 对比页 + 恰好 1 个推荐)、
    TestLandscapeBonus(景观加分 0~14、规整主景园得分必须高于同面积碎形主景园、园路长度分差、缺 compactness 向后兼容)
  • test_dwg_input 与 test_sp_dwg 里带 live 标记的用例走真实 DWG↔中望,默认跳过,
    设 WB_LIVE_CAD=1 才跑(需本机装中望且未被占用)。
  • 耗时提醒:CLI 子进程用例占大头(38 次子进程 ≈ 173s,其中 import ezdxf 就 5s)。
    纯逻辑用例请直接调函数(如 L.build(norm, defaults, env))而不是跑 CLI,可省掉进程启动开销。

<!-- PAYGATE:BEGIN -->

付费与交付(X402 微信 Agent Pay · 微信支付 AI 专属卡 · ¥0.01/次)

费用由用户直接支付给服务提供方。SkillHub 仅提供展示、投诉处理及平台服务,不作为收款方。请在支付前确认服务内容、计费单元、单价与退款规则。

  • 单价:¥0.01 / 次(以支付网关价目表与 SkillHub 后台配置为准)
  • 计费单元:每次完整服务需求,支付确认后开始服务
  • 免费操作:支付前的需求沟通、订单状态查询

Agent 行为准则

  • 首次调用返回 402 时,原样向用户出示支付信息并申请授权;不得自行判定支付成功,不得改用免费方式替代履约。
  • 牢记 out_trade_no(订单号),支付后用同一订单号重试,不会重复扣费。

红线

  1. 未拿到 status=paid 收据前,严禁执行任何实质性服务、严禁产出结果。
  2. 所有支付只通过 node scripts/client.js,严禁手动调用微信支付接口。
  3. 严禁向用户展示/朗读 payment_code、transaction_id、私钥等敏感字段。
  4. 设备不满足要求时只输出引导并停止,严禁绕过支付。

付费四步(X402 协议)

  1. 前置检查:当前 Agent 是否具备 weixinpay_pay 能力,不具备则终止并提示。
  2. 请求资源:node scripts/client.js require --skill &quot;site-planning&quot; --subject &quot;&lt;需求简述&gt;&quot;,未付返回 402,含 WeixinPay-Required 与 X-Out-Trade-No。
  3. 同时保存“支付码”和“订单号”;系统自动弹出微信支付 AI 专属卡,用户手机授权扣款(Agent 不得自行判断成功)。
  4. 原样重试 require(CLI 自动带 X-Out-Trade-No),服务端查单到账返回 status=paid 收据后,才开始履约。

订单状态免费查询(免费、幂等):node scripts/client.js status --out-trade-no &quot;&lt;订单号&gt;&quot;
<!-- PAYGATE:END -->

常见问题

5 问
答案由本站依据条目字段整理
总图概念设计怎么安装?

在支持 Skills 的客户端里执行:skillhub install user_b24dc7bf/site-planning。安装方式为未标注。装完刷新技能列表或重开客户端。

总图概念设计支持哪些客户端?

资料没有标注宿主客户端,但只要客户端支持 Skills(Claude、Codex、Cursor 等),一般都能加载。

总图概念设计权限高吗,安全吗?

权限级别为未标注权限。安装前先看它会读取或写入哪些内容。

总图概念设计收费吗?

本站不代收费用,也没有标注具体价格。是否收费取决于技能本身和所用的模型或客户端,正式使用前按作者说明确认。

总图概念设计用什么许可证?

许可证标注为 未说明(许可证不明确)。商用或二次分发前请到仓库确认条款原文。

热门专题

按场景挑技能
全部专题 →

技能内容以作者仓库为准;分类、权限级别与许可证状态的中文说明为中文整理,最近核验 2026-11-06。