简介这是一套Cityengine城市规划功能分区规则库面向城乡规划、城市设计及三维建模学习者用于快速生成符合用地性质的街区模型。资源包将住宅、商业、工业、绿地、交通网络等常用功能区的规则进行模块化封装支持在Cityengine中直接导入调用减少重复建模工作适合方案推敲与课程实践。压缩包约26KB共8个文件核心文件包括3个cgb规则包、1个cga规则脚本以及project工程文件、xml配置文件和txt说明文档cgb用于组织规则资产cga实现建筑体量、高度、退线等生成逻辑project则提供可直接运行的示例工程。目前已有457人学习下载。通过阅读这套规则库读者可以掌握不同功能区对应的参数设定思路如住宅区的楼高与密度控制、商业区的开放空间占比、绿地系统的路径布局等并能够在此基础上修改规则适配自己的规划场景为精细化城市建模提供可复用的起始模板。1. 功能分区 01 规则库能“长”出规划方案也能“拆”给新手学Cityengine 城市规划功能分区 01 这套规则库解压出来是文件夹加配置文件rules、assets、data、scenes、scripts。多数规划师把它当黑匣子——只敢点 Generate不敢拆开改 .cga。这恰恰是最亏的因为它是参数化规则包不是成品模型。你给它任意一块带边界的地它按住宅、商业、工业、绿地、交通的分区定义自动生成对应的建筑体量、贴图和街道形态。规划上要调指标改规则参数就行不用重建模型。适合想快速出多版比选方案的规划设计师也适合刚入门 Cityengine 的新手拿它当教材顺着 .cga 逆向学规则怎么写。反直觉的结论是决定项目最终效果的主要是规则里的属性字段和 split 语句不是贴图素材。2. 规则库的项目构成.project、rules、assets 各管什么事2.1 解压后的目录全景别急着点 Generate把 .rar 放在纯英文目录下解压。我一般用 7-Zip命令行解压方便脚本化更好Windows 下直接右键 WinRAR 也行。命令如下mkdir -p D:/cityengine_workspace/zone01 7z x 城市规划功能分区01.rar -oD:/cityengine_workspace/zone01-o 后面跟解压目标目录参数大小写敏感如果机器没装 7z用 WinRAR 手动解压效果一样。解压后你会看到十几个目录和配置文件我把它们整理成一张职责表目录/文件实际作用需要动它吗.projectEclipse/CityEngine 工程入口Open Project 时靠它识别工程根目录不动rules/CGA 规则源码全部功能区逻辑都在这里这是核心改参数主要改这里assets/贴图、模型、植物等素材资源库按需替换素材data/GIS shp、属性表等输入数据按需替换scenes/.cej 场景文件保存图层与视图状态双击打开images/ maps/分析图、地图缓存只读scripts/Python 脚本用于数据预处理和字段映射按需执行Development bin/ models/编译缓存和调试中间模型不用管.version.txt记录工程创建版本提示版本兼容.pydevproject .resolvemap.xml工程配置与资源解析映射迁移时不要删为什么说不要直接双击 .cga 打开因为单独打开规则文件只是文本编辑器没有场景和图层上下文你试 Generate 会提示 No selected shapes。标准流程一定是先 File - Open Project... 选中 .project让整个工程以项目结构加载场景里的地块图层才能跟规则挂上。见过不少新手直接拖 rules 文件夹到界面然后说“这个规则库根本不能用”——其实第一步就错了。另一个值得留意的是 .resolvemap.xml。它记录的是资源路径映射说人话就是 Cityengine 用它在换机器时重新找到 assets 和 data 的位置。如果你的工程拷给别人之后贴图全丢大概率是它没跟过去或者导入资源时选的是绝对路径。后面避坑章节会专门展开。2.2 Rule Package 与 CGA功能分区是怎么“长”到地块上的Cityengine 的规则引擎用的是 CGAComputer Generated Architecture语法一个规则库本质上是若干 .cga 文件。文件内部是一组 shape grammar执行引擎从初始形状开始把传入的地块边界不断替换成更小的几何体直到所有规则都以 NIL 结束或生成了实际模型。“城市规划功能分区01”这个名字里的“功能分区”在工程里通常表现为入口规则用 case 分支做分发按地块上带的分区属性走不同子规则。看一段最常见的入口分发逻辑/* * 功能分区入口把 Lot 分发给各功能区规则 * 语法上 CGA 跟 JavaScript 长得像但它是 ESRI 专有语法 */ StartRule Lot -- case zoneType residential: Residential() case zoneType commercial: Commercial() case zoneType industrial: Industrial() case zoneType green: GreenSpace() else: Passive()代码逻辑StartRule 是规则入口修饰符Generate 时每个地块都从这个标签开始执行zoneType 是地块属性可以从 GIS 导入也可以手动在 Inspector 里选case/as/else 做字符串分发。这样写的好处是五个功能区互相隔离住宅区规则改出问题不会污染商业区。常见做法是把每个功能区拆成独立 .cga 文件再通过 include 或复制进工程的方式组织。这套功能分区 01 的 rules 目录基本就是按这个思路分文件。Passive() 那段兜底逻辑也不是随手写的我一般会在最后 else 分支放一个简单体块至少让你知道“有地块没有拿到分区属性”而不是默默消失。再看一个生成体量的最小规则Residential -- extrude(rand(12, 30)) comp(f) { front: Facade | top: Roof }extrude 是拉伸rand(12, 30) 表示楼层高度随机取 12 到 30 米comp(f) 是分解面f 表示 face把拉出来的侧面拆成立面 Facade顶面拆成屋顶 Roof后续可以分别细化。这就是 Cityengine 规则库最核心的两个操作拉伸 分解。理解了这两行再看复杂规则就不会晕。那 Rule Package.rpk又是什么它是把整套规则打包成不分源码的编译文件用于分发给别人。功能分区 01 工程里看到的是源码形态开发阶段改起来很方便等规则调好了File - Export - Rule Package 打包出去别人加载 rpk 时只能调暴露的属性改不了内部逻辑。这个特性对团队协作很重要规则负责人把关键参数暴露出来使用方不会误删结构。另一个需要建立的概念是 scope。CGA 里每个当前形状都有一个局部坐标系包含原点、尺寸和方向extrude、split、setback 都基于这个 scope 运算。规则链从头到尾是顺序执行碰到 NIL 就停止。这个执行顺序是排查“生成空白”的钥匙先确认哪一步把形状变成 NIL基本就能定位问题在哪个规则段。2.3 参数不是写在规则顶部就行attr 与 Inspector 的联动新手最容易误解的是“改参数直接改 .cga 文件顶部的数字”。在功能分区 01 里参数分两层一层是规则文件里的 attr属性定义另一层是 Inspector 面板里显示出的可调项。想让某个数字出现在 Inspector 里必须先把它声明成 attr而且最好加上 Group 和 Range 修饰Group(住宅区) Order(1) Range(6, 100) attr residentialHeightMax 30 Group(住宅区) Order(2) Range(0, 20) attr residentialSetback 4有了这几行Inspector 里就会出现一个“住宅区”分组滑杆范围 6-100默认值 30。这样设计的好处很明显出方案的人不需要懂 CGA只动滑杆就能试不同高度规则维护者也不用担心别人把参数改成非法值。常见做法是把规划条件里容易变的部分限高、退距、容积率做成 attr把结构逻辑拉伸、分解、贴面留在规则内部。对照上面 2.1 的表rules 目录里的每个 .cga 文件都按这个思路分好了“可调参数区”和“核心逻辑区”。assets 目录也顺带提一句。它底下通常按 textures、models、plants 分子目录贴图也好树木模型也好都通过相对路径被 .cga 引用。你如果要替换材质不要改文件名的引用关系直接替换同名文件最保险。整套工程能跨机器复现靠的就是“规则文件引相对路径 assets 随工程走”这套纪律。3. 把功能分区 01 跑起来从导入工程到批量生成模型3.1 导入 .project 前先核对版本和路径拿到工程后第一件事不是导入而是看 .version.txt。Cityengine 从 2020 年到 2024 年迭代了好几轮高版本打开低版本工程时会提示是否需要 Upgrading。如果工程是旧版本创建升级后规则里某些 deprecated 写法可能报 Warnings但不影响大体。导入路径有个算不上硬伤但很磨人的坑项目路径一定不要出现中文和空格。比如 D:\城市设计\功能分区01 这种路径CGA 编译器在 Windows 上偶尔会报代码中有非法字符实际上代码完全正常。我一般会在 D 盘建一个 cityengine_workspace 作为固定工作空间解压、建工程都放这里。步骤是这样的打开 Cityengine进入主窗口确认工作空间Workspace是一个空目录。File - Open Project...定位到解压后的目录选中其中的 .project 文件。弹出 Upgrading 提示时选 OK 等待升级完成然后立刻 CtrlS 保存一遍。在 Navigator左侧工程树里展开工程双击 scenes 下的场景文件打开 3D 视图。如果第 2 步选错了文件比如选成了 .pydevproject系统会把它当普通文本打开没有任何图标这就是典型的导入翻车。正确的 .project 在 Navigator 里显示为一个带城市图标的工程节点而不是文件。3.2 先小范围验证把规则挂到一块地上整个场景全选 Generate 是效率最低的死法——一旦规则有编译错几千个地块同时报错导航器刷屏找原因找半小时。我自己的血泪经验是先画一个测试多边形或选择现有场景里最小的一个地块单独跑一遍。操作路径在 3D 视图中用选择工具选中一个地块或用 Layer 里的小方块只点亮一个图层。在 Inspector 面板里找到 Assign Rule File 属性点击右侧文件夹图标选择 rules 下的入口规则文件通常是根目录那个包含 StartRule 的 .cga。点 Generate或快捷键 CtrlG看这个地块的模型是否生成。如果生成失败看底部的 CGA Console 日志定位到具体行号。我个人习惯是在测试地块上故意创建一个“脏数据”比如把一个地块的属性设成不存在的 zoneType看兜底 Passive() 会不会执行。这能确认 else 分支的鲁棒性也能让你看懂整个规则的执行链条。小范围验证还有一个好处执行时间短改参数试错成本低全城批量生成时动辄几分钟等得起但没必要。3.3 批量生成与图层组织从地块到功能分区模型验证通过后才谈得上批量。批量生成有两种方式一是选中多个地块批量生成二是通过 File - Import - Shapefile 导入分区边界后给导入的图层赋规则再 Generate。功能分区 01 工程里 data 目录放的就是这类 GIS 数据scenes 里通常已经建好了图层导入后直接看效果。这套规则库我按功能区分成五个规则组使用时的对应关系如下表功能分区规则文件典型命名核心控制参数产出物住宅区Residential.cga楼高区间、退距、绿化率多层/高层住宅体块、宅间绿地商业区Commercial.cga裙房层数、塔楼高度、贴面裙房塔楼组合体工业区Industrial.cga跨度、檐口高度、退界大跨厂房、场地硬化绿地公园GreenSpace.cga树木间距、路径宽度树木点位、步行道交通网络Street.cga车道数、人行道宽、交叉口道路断面、街块图层组织也按这个逻辑分每个功能分区独立一个图层生成后模型也落在对应图层里。批量生成时如果发现某类地块没有反应先回图层看它的属性里 zoneType 字段是不是空规则分发靠的就是这个属性属性丢了规则再复杂也没用。批量生成的性能也要提一下。Inspector 里 Generate 相关选项有一个 Tile Size默认按当前视图范围切块。地块数量上万时把 Tile Size 调小内存占用会平稳很多地块少就调大减少接缝。这个参数不改变规则结果只影响生成性能但调不好容易内存溢出。3.4 GIS 数据字段映射zoneType 从哪来如果地块是从 shp 导入的功能分区属性不一定直接叫 zoneType可能叫 CODE、用地性质、用地代码之类。Cityengine 不会自动把字段名翻译给规则用需要在规则里读 shp 字段或者导入后用 Python 脚本做字段映射。scripts 目录下的 .py 一般就是干这个的。导入 shp 的标准流程File - Import - Shapefile...注意选择坐标系。如果 shp 没有投影Cityengine 会默认按 WGS84 经纬度导入地块坐标会变成天文数字规则生成的小楼看不见。常见做法是先统一成 UTM 投影再导入数值都在米级后续规则里的退距、层高才有实际意义。字段映射的常见做法是这样先在 Inspector 里看地块属性面板确认 shp 里哪个字段存的是“R2”“C1”“M1”这类用地代码然后在 .cga 里用 attr 接收原始字段值再做一个转换attr landUseCode R2 StartRule Lot -- case landUseCode R2 || landUseCode R3: Residential() case landUseCode C1 || landUseCode C2: Commercial() else: NIL这里有个很隐蔽的坑shp 属性字段名如果带了空格或中文CGA 里引用它会一直编译不过。解决办法是在 data 目录里先用 Python 把字段重命名或者导入时在 Attribute Mapping 面板里手动映射字段名。我一般会保留一份原始 shp再另存一份字段名干净的数据源避免来回折腾。4. 按规划意图改规则住宅、商业、工业、绿地的参数控制点4.1 住宅区规则高度、退距、绿化率改哪里住宅区是设计条件最碎的。很多城市控规会同时卡三个指标建筑高度、退让距离、绿地率。这三个指标在规则里对应三个位置高度是 extrude 的参数退距是 setback 的参数绿地率靠 setback 后留下的前/后院面积占比来近似。下面这段住宅区规则是精简版逻辑是“每个地块先向内退一圈退出来的边角料做成绿地里面的核心块再拉伸成楼体”StartRule Lot -- setback(residentialSetback) { All GardenArea } alignScopeToGeometry(yUp, 0, 0) ResidentialFootprint residentialSetback 4 // 退距米 residentialHeightMin 12 // 最小高度米 residentialHeightMax 30 // 最大高度米 ResidentialFootprint -- extrude(rand(residentialHeightMin, residentialHeightMax)) comp(f) { front: Facade | top: Roof } GardenArea -- color(0.42, 0.72, 0.35) primitiveCube() s(1, 0.05, 1) t(0, -0.02, 0)参数怎么调residentialSetback 是退距从道路红线和用地边界往里退 4 米改成 6 或 8 就是更严格的城市要求heightMin/Max 是楼高随机区间如果要在同一街块做出错落感保持随机区间如果做标准小区把 min/max 设为同一个值。GardenArea 这里只是用色块示意实际项目里要换成绿地材质或插入树木模型。这里有一个容易产生误解的点setback 的返回值不是“剩下一个简单矩形”而是把原始多边形分成若干块All GardenArea 表示所有退出的边界块都执行绿地规则。规则里真正的建筑体量是 setback 之后剩余的内廓生成的这跟手工建模“拉一个体块放边上”完全不同——它是几何减运算的结果保证建筑不会压到退距线。要做出能看的住宅立面还得在 Facade 里继续切分。comp(f) 分解出来的 front 只是一整个侧面通常用 split(y) 按层高切成一层一层每层再 split(x) 做窗户和墙的交替。楼层数不需要单独传参直接拿 extrude 的最终高度除以层高就能算出来规则里floorCount buildingHeight / floorHeight这行就是干这个的。4.2 商业区与工业区体量逻辑与贴面控制的差异商业地块和高密度住宅的核心差异是“裙房塔楼”的组合逻辑。下面是常见的控制写法Commercial -- extrude(rand(commercialHeightMin, commercialHeightMax)) comp(f) { front: Facade | top: Roof } split(y) { podiumFloorCount * 4: Podium | ~1: Tower } commercialHeightMin 24 commercialHeightMax 80 podiumFloorCount 3split(y) 按高度方向切分前三维是裙房层高按 4 米一层算podiumFloorCount 设为 3就得到 12 米裙房剩下的 ~1 表示“剩余高度全部给 Tower”。这个 ~ 符号的意思是无限延伸正确写法是~1不是1。很多人在这写错结果 tower 变成一层楼。工业区逻辑相反厂房高度不高但跨度大重点在 footprint 的完整性。规则里通常不做退距式 setback而是用 footprint 直接拉伸并且不做立面开窗细分用简单贴图替代。关键参数是屋檐高度和屋顶坡度因为在工业地块里规划审查更关心建筑退界和绿地率不关心立面漂亮不漂亮。有一点要提醒商业塔楼和住宅楼在功能分区 01 里虽然都是 extrude comp但分区的意义在于后续贴面细分逻辑不同。商业会强调立面广告位和玻璃面比例住宅强调阳台和窗墙比这些细分通常在 Facade 规则里用 split 和 texture 完成。不要只调高度就以为完成了一个功能区的修改。4.3 绿地与道路地物摆放和道路断面的规则写法绿地和交通这两类规则在“城市规划功能分区01”里看着不起眼但它们是给场景加“规划感”的关键。绿地规则最常见的写法是用 insert 把 assets 目录里的植物模型实例化到地块上配合 randomize 做布局GreenSpace -- split(x) { ~treeSpacing: InsertTree }* InsertTree -- insert(assets/models/tree_01.fbx) s(1, rand(0.8, 1.2), 1)注意*是循环split(x) 沿 X 方向重复切分每隔 treeSpacing 插入一棵树。如果想得到更自然的效果可以用 random 分割而不是均匀分割。道路规则更偏 Street Rule 的内置模块一般在工程里是以 street 属性控制车道数、人行道宽度规则文件打开的是一整条街的断面参数不是单独一栋建筑。调整道路断面时不要动 geometry 本身而是优先调 Inspector 里的 street width、lane count 这类属性。Cityengine 的道路生成逻辑是先按中心线生成路面再按宽度参数生成人行道和绿化带你如果直接拖拽道路线节点的顶点会把断面规则整个搞乱之后 Generate 出的模型会沿着每个节点分开断头。这是很多新手把道路模型做得断断续续的主要原因。绿地规则里还有个容易被忽略的点插入树木模型的数量和间距直接决定场景面数。一棵高精度树动辄几千面一个公园插入几百棵场景马上卡顿。我一般会在方案比选阶段用低模树用 billboard 或者简化几何体表达式替代等确定方案再换成精模。4.4 把参数暴露给使用者attr 分组与默认值设计规则库能不能给团队其他人用关键在于参数面板规不规范。功能分区 01 开发版里参数大多已经分好组如果你要自己扩展记住三个修饰符就够了Group(商业区) Order(1) Range(0, 200) attr commercialHeightMax 80 Group(商业区) Order(2) Range(0, 10) attr podiumFloorCount 3 Hidden attr assetPath assets/models/tower_01.fbxGroup 决定参数在 Inspector 里出现在哪个折叠分组Order 控制上下顺序Range 给滑杆范围Hidden 隐藏不需要使用者碰的内部资源路径。把容易误改的资源路径做成 Hidden是防止“同事把贴图路径改成乱码”的后悔药。参数表设计得好新手也能安全地调方案。我建议每个功能区的 .cga 顶部保留一张参数清单用注释写清楚“哪个参数对应控规哪个指标”。比如住宅区的高度做两个队组一个管下限一个管上限比只给一个 Height 参数灵活得多。参数范围也别拍脑袋最好对着城市设计导则填Range 的上下限就是一道无形的审查门槛。参数名类型范围默认影响residentialHeightMaxfloat6-10030住宅楼高上限podiumFloorCountint0-103商业裙房层数treeSpacingfloat2-206绿地植树间距5. 避坑与排查规则库落地最常见的五个翻车点5.1 生成后场景一片空白现象选中地块点 GenerateCGA Console 也没有红色报错但场景里什么都长出来。原因最常见的有三种。一是规则入口没执行完就遇到了 NIL比如 StartRule 之后的 case 没有匹配又没写 else整个 Lot 被当作空对象丢掉二是混淆了“规则文件”和“规则包”的默认入口Inspector 里选错了 .cga 文件三是地块形状太小规则里 extrude 数字又太大生成结果视角下看不见。解决先打开 CGA Console 看有没有黄色 Warning再看规则里有没有兜底 else。我自己的习惯是在入口规则末尾加一行else: print(lot type zoneType)把每块地的分区属性打出来一看就知道属性是不是空的。如果 Console 没有输出那就是选错规则文件或者图层没挂上。另外视角下看不见不代表没生成用 A 键放大到框选范围往往楼就在那里。5.2 改高度参数重新 Generate 却没有变化现象Inspector 里把 Max Building Height 从 60 改成 120点 Generate 后楼还是原来的高度像是没生效。原因规则里被硬编码覆盖了。常见的写法有两种一种是在 .cga 文件里直接写了attr height 60Inspector 里改的是同名属性但规则内部用的是另一个局部变量另一种是规则文件里用了const修饰常量不允许外部修改Inspector 的输入框会变成只读状态改不动。解决打开 .cga 文件CtrlF 搜 height 相关关键字看属性定义处有没有 const。再把需要外部控制的参数提成 attr并且用 Group、Range 包一层。改完之后先 Edit - Delete Generated Models 清一次缓存再重新 Generate。Cityengine 的生成结果是有缓存的旧模型不清新参数有时会被覆盖这步不算玄学但极隐蔽。5.3 中文目录导致规则编译报错现象工程名或路径里有中文比如 D:\规划\功能分区 01CGA 编译报 “Illegal character”但代码本身没有语法错误。原因Cityengine 底层基于 EclipseEclipse 对非 ASCII 路径的工程支持一直不算稳定CGA 编译器在解析资源相对路径时遇到中文会直接把路径当成非法字符。解决把整个工程目录挪到纯英文路径下D:\CityengineProjects\Zone01 这种。工程名也改掉不要保留中文。注意挪完目录后要重新 Open Project不要再双击旧路径的 .project。如果已经跑过多次就把 scenes 下生成的模型清掉重导一次。5.4 贴图变成紫红色现象生成后模型某些面显示成紫红色明显不是设计时用的贴图。原因assets 贴图路径失效。工程在自己机器上能正常显示是因为 .resolvemap.xml 记录的是本机的路径拷给别人或换机器后路径找不到材质就会变成默认的紫红。另一个常见原因是规则里写了texture(C:/...)这种绝对路径打包 rpk 时没有把这些外部资源收进去。解决把规则里的贴图路径全部改成相对路径以工程根目录为参考写法是texture(assets/textures/building_01.jpg)。同时在 rpk 导出时勾选 Include Dependencies 和纹理资源。如果手头工程已经是绝对路径用 .resolvemap.xml 重映射或者在脚本里批量替换成相对路径。这个习惯要从第一天养成否则每次迁移都是一次废案重做。5.5 打包 rpk 后 Report 和图层信息丢失现象把规则库打成 rpk 发给同事他能生成模型但 Report 面板看不到容积率等指标导出的图层也只剩默认层。原因rpk 打包的是编译后的规则和资源Report 里输出的自定义指标不是模型几何属性没有在导出时同步保留图层信息更是工程层面的状态rpk 本身不保存图层组织必须连同 scenes 或者导出配置一起给。解决如果你需要汇报指标不要用 Report 面板截图而是在规则里用report(key, value)然后在 Window - Report 导出 CSV同时把 scene 文件也发出去。如果只需要三维模型导出前把每个功能分区放在独立图层File - Export - Layers 里只勾选需要输出的层。我自己评标用的指标表就是规则里 Report 出来导成 CSV再喂给 Excel 套公式比手工量快得多。6. 把规则库当“后悔药”Report 指标与随机种子做方案比选6.1 在规则里写 Report让每一次 Generate 都有据可查规划比选最烦的一件事是方案改了十轮最后说不清哪个版本容积率是多少。人工去数楼不现实。常见做法是在规则里埋 Report生成的同时输出指标StartRule Lot -- extrude(buildingHeight) comp(f) { front: Facade | top: Roof } Report buildingHeight 24 Report -- report(lotArea, geometry.area) report(floorArea, geometry.area * buildingHeight / 3.0) report(volume, geometry.volume) report(height, buildingHeight)这里的 report() 是 Cityengine 内置函数字段名自定义。生成完成后在 Window - Report 面板能看到整张表的汇总按字段排序也可以导出 CSV 供 Excel 做图表。要注意的是楼面面积按层高折算很粗糙只用于比选阶段横向对比不是报批用的精确指标。6.2 用随机种子做多版本比选同一套地块只换 seed不改任何参数能跑出不同的建筑排布。在规则开头加一行seed(20260117)每次 Generate 前改这个数字相当于把方案历史记住。我的习惯是每个方案建一个 scene 存档seed 和关键参数写在场景名里比如zone01_v2_seed2026.cej。这样比选汇报时能随时回到两周前的版本而不是靠“我记得当时好像改过”。这套方法不需要额外插件规则库原生的 seed 和 Report 就能完成。从那以后我每次拿到别人的规则库都会先建一个空场景挂一个测试地块跑 Report 确认基准指标再动任何参数改了哪些参数、用的什么 seed 全部记录在场景名里。规则库最大的价值不是那一次生成结果而是你能在几分钟内翻出十几种方案——希望帮到你。本文还有配套的精品资源点击获取