Penrose 多边形形状 Polygon 完全指南:Style 属性、SVG 渲染与实战示例

发布时间:2026/9/27 21:14:36
Penrose 多边形形状 Polygon 完全指南:Style 属性、SVG 渲染与实战示例 开发工具数据可视化【免费下载链接】penroseCreate beautiful diagrams just by typing notation in plain text.项目地址https://gitcode.com/gh_mirrors/pe/penrose点击查看免费下载本篇指南围绕 Penrose 仓库中packages/docs-site/docs/ref/style/shapes/polygon.md所定义的Polygon多边形形状展开深入讲解该形状在 Style 语言中的全部属性、默认值与采样行为并结合packages/core的源码与packages/examples中的真实.style示例说明其从样式声明到 SVGpolygon输出的完整渲染链路。读完本文你将掌握如何在 Penrose Style 程序中声明、配置与优化多边形形状并能读懂其属性表的生成机制与底层类型约束。一、Polygon 是什么在 Penrose 的 Style 语言中Polygon是用于绘制封闭多边形区域的内建形状。它的最核心特征是points属性由一组二维顶点组成的点列渲染器会将首尾顶点自动相连形成一个闭合的填充/描边区域。与Polyline折线不闭合相比Polygon天然自带区域语义适合表达三角形、四边形、网格单元、平面投影等几何对象。从源码结构看Polygon在 Penrose 的类型体系中位于 packages/core/src/types/shapes.ts其属性接口定义为export interface PolygonPropsT extends NamedT, StrokeT, FillT, ScaleT, PolyT {}也就是说一个Polygon形状由五组能力接口组合而成接口提供的属性语义NamedTname、ensureOnCanvas形状命名与画布约束StrokeTstrokeWidth、strokeStyle、strokeColor、strokeDasharray描边样式FillTfillColor填充颜色ScaleTscale整体缩放系数PolyTpoints多边形顶点列表二、Polygon 属性总览完整属性表polygon.md通过ShapeProps shape-namePolygon /组件动态渲染属性表。该表的数据并非手工维护而是由 packages/docs-site/scripts/shapedefs.js 调用penrose/core的sampleShape对每个形状采样两次两次采样结果相同的属性归入 defaulted默认值、不同的归入 sampled采样值最终写入 JSON 供ShapeProps.vue渲染。Polygon属性表的完整内容直接来源于 packages/core/src/shapes/Polygon.ts 中的samplePolygon实现export const samplePolygon ( context: Context, _canvas: Canvas, ): PolygonPropsad.Num ({ name: strV(defaultPolygon), strokeWidth: floatV(0), strokeStyle: strV(solid), strokeColor: noPaint(), strokeDasharray: strV(), fillColor: sampleColor(context), scale: floatV(1), points: ptListV([ [0, 0], [0, 10], [10, 0], ]), ensureOnCanvas: boolV(true), });由此得到完整属性表如下属性Property类型Type默认值Default来源nameStrVdefaultPolygondefaultedstrokeWidthFloatV0defaultedstrokeStyleStrVsoliddefaultedstrokeColorColorVnone()无描边defaultedstrokeDasharrayStrV实线defaultedfillColorColorV随机采样见下文sampledscaleFloatV1defaultedpointsPtListV[[0,0],[0,10],[10,0]]默认三角形defaultedensureOnCanvasBoolVtruedefaulted唯一会被自动采样sampled的属性是fillColor。在 packages/core/src/shapes/Samplers.ts 中sampleColor会对 R、G、B 三个通道各取uniform(0.1, 0.9)的随机值并把 alpha 固定为0.5export const sampleColor ({ makeInput }: Context): ColorVad.Num { const [min, max] [0.1, 0.9]; return colorV({ tag: RGBA, contents: [ makeInput({ init: { tag: Sampled, sampler: uniform(min, max) }, stages: All }), makeInput({ init: { tag: Sampled, sampler: uniform(min, max) }, stages: All }), makeInput({ init: { tag: Sampled, sampler: uniform(min, max) }, stages: All }), 0.5, ], }); };这意味着如果 Style 程序里不为fillColor显式赋值Penrose 会为每次布局每个 variation 种子生成不同的半透明填充色并且该颜色还会参与后续能量优化stages: All。其余属性均为固定默认值defaulted其中points的默认值是[[0,0],[0,10],[10,0]]——一个内置的示例三角形。strokeColor默认是noPaint()即不描边strokeWidth默认0strokeDasharray默认空字符串实线strokeStyle默认solid。三、在 Style 中声明 Polygon参照 packages/docs-site/docs/ref/style/shapes-overview.md 的通用形状声明语法一个Polygon实例在某个 selector 块内通过如下形式创建x.myShape Polygon { attribute1: value1 attribute2: value2 -- ... }points属性的取值方式有三种均已在仓库示例中得到验证1. 直接书写顶点坐标list of vec2shape tri Polygon { points: [(0, 0), (0, 10), (10, 0)] fillColor: rgba(0.9, 0.2, 0.2, 0.8) strokeColor: #000 strokeWidth: 1 }2. 引用 Substance 对象的成员变量动态布局推荐packages/examples/src/arc-mesh/arc-mesh.style 中三个顶点来自线段起点构造出一个由三条直线段围成的区域shape t.straightRegion Polygon { points: [ t.pi, t.pj, t.pk ] fillColor: none() strokeColor: none() }3. 引用密集点列如曲线离散采样packages/examples/src/curve-examples/blobs/blobs.style 用一个包含 100 个二维点p0~p99均为(?, ?)形式的待优化变量的列表构造多边形轮廓shape m.poly Polygon { points: [p0, p1, p2, ..., p98, p99] strokeWidth: settings.lineThickness strokeColor: #000 }这些(?, ?)顶点会被 Penrose 视为优化变量结合ensure lessThan(...)等约束与centerOfMass、perimeter等目标函数在能量优化过程中被塑形成目标曲线。这正是 Polygon 在 Penrose 中作为可优化几何载体的核心价值。4. 透视投影后的坐标packages/examples/src/curve-examples/space-curves/space-curves.style 先将三维空间曲线做透视投影得到二维坐标再用Polygon绘制地面网格平面vec2 Kp00 canvas.width * (KQ00[0],KQ00[1] - 0)/(KQ00[2] - cZ) -- ... 其余三个角点同理 shape groundPlane Polygon { points: ( Kp00, Kp10, Kp11, Kp01 ) fillColor: rgba(0.5,0.5,.9,0.2) strokeColor: rgba(.7,0.7,1,0) strokeWidth: .5 ensureOnCanvas: false }注意此处points用的是圆括号元组形式( Kp00, Kp10, Kp11, Kp01 )同样合法。四、points 的类型约束与隐式转换Penrose 对形状参数实行严格类型检查见 shapes-overview.md 的 Strict Typing on Shape Parameters 一节。points的期望类型是PtListV点列即二维向量的列表。如果传入不兼容类型会报错Shape property myShape.points expects type PtListV and does not accept type BoolV. // [!code error]不过 Penrose 支持若干隐式类型转换实际书写时可以更宽松ListV与VectorV互相隐式转换MatrixV、LListV、PtListV互相隐式转换TupV可以转换为ListV/VectorV反之不行。因此points除了标准的[p0, p1, p2]列表写法也接受(p0, p1, p2)元组写法如 space-curves 示例因为它们最终都会被解析为点列值。值得注意的是类型转字符串StrV目前不支持隐式转换。五、Polygon 的 SVG 渲染原理Polygon的渲染实现位于 packages/core/src/renderer/Polygon.ts。它创建一个 SVGpolygon元素并按固定顺序处理各属性const RenderPolygon ( shape: Polygonnumber, { canvasSize, titleCache }: RenderProps, ): SVGPolygonElement { const elem document.createElementNS(http://www.w3.org/2000/svg, polygon); const attrToNotAutoMap: string[] []; attrToNotAutoMap.push(...attrFill(shape, elem)); attrToNotAutoMap.push(...attrStroke(shape, elem)); attrToNotAutoMap.push(...attrTitle(shape, elem, titleCache)); attrToNotAutoMap.push(...attrScale(shape, elem)); attrToNotAutoMap.push(...attrPolyPoints(shape, canvasSize, elem)); attrAutoFillSvg(shape, elem, attrToNotAutoMap); return elem; };各辅助函数均在 packages/core/src/renderer/AttrHelper.ts 中的映射逻辑attrFill将fillColor映射为 SVGfill与fill-opacitynone()对应fillnone。RGBA/HSVA 颜色经toSvgPaintProperty转为十六进制色值。attrStroke将strokeWidth、strokeStyle、strokeColor、strokeDasharray映射为 SVG 的stroke-width、stroke-dasharray等属性。attrScale将scale映射为transformscale(k)若已有其他 transform 则追加。scale为 0 或未定义时按 1 处理export const attrScale (properties: Scalenumber, elem: SVGElement): string[] { let scale properties.scale.contents; scale scale || 1; elem.setAttribute(transform, scale(${scale})); return [scale]; };attrPolyPoints这是 Polygon 的关键一步——把数学坐标系中的顶点转换到屏幕坐标系再写入 SVGpoints属性export const attrPolyPoints ( shape: Polynumber, canvasSize: [number, number], elem: SVGElement, ): string[] { const pointsTransformed shape.points.contents.map((p: number[]) toScreen([p[0], p[1]], canvasSize), ); elem.setAttribute(points, pointsTransformed.toString()); return [points]; };其中toScreen定义于 packages/core/src/utils/Util.ts完成坐标系翻转export const toScreen ([x, y]: [number, number], canvasSize: [number, number]): [number, number] { const [width, height] canvasSize; return [width / 2 x, height / 2 - y]; };即 Penrose 的数学坐标以画布中心为原点、y 轴向上渲染时平移到画布中心并翻转 y 轴。这也是为什么space-curves.style中需要先做透视投影、再交给 Polygon 显示。attrAutoFillSvg处理passthrough中未被上述函数映射的透传属性见 passthrough.md允许把任意 SVG 属性直接下发给polygon元素。六、Polygon 与其他形状的区分对比项PolygonPolylinePath是否闭合是SVGpolygon自动闭合否SVGpolyline取决于d路径命令核心属性points: PtListVpoints: PtListVd: PathDataListV典型用途区域、网格单元、平面折线、坐标轴任意贝塞尔/圆弧路径在 packages/core/src/utils/Util.ts 的bBoxDims中Polygon与Polyline、Path一样暂时使用固定的[20, 20]作为包围盒估算源码注释标注TODO: find a better measure而Circle、Ellipse、Rectangle等则有精确的包围盒计算。这在实现层面印证了Polygon 的精确包围盒尚未实现若你的布局依赖形状尺寸需自行用points计算。七、ensureOnCanvas 与画布约束所有形状包括 Polygon都有ensureOnCanvas属性默认true。它是一条特殊的约束保证形状始终落在 Style 文件顶部声明的画布包围矩形内。若多边形较大或需要自由越界如 space-curves 示例中故意铺满整个画布的groundPlane应显式关闭ensureOnCanvas: false八、makePolygon 与形状对象模型除采样外packages/core/src/shapes/Polygon.ts 还导出了makePolygon它在采样默认值之上合并用户传入的属性并打上shapeType: Polygon标记同时生成一个合成样式路径fakePath(defaultPolygon)export const makePolygon ( context: Context, canvas: Canvas, properties: PartialPolygonPropsad.Num, ): Polygonad.Num ({ ...samplePolygon(context, canvas), ...properties, shapeType: Polygon, passthrough: new Map(), path: fakePath(defaultPolygon), });完整形状类型PolygonT则由ShapeCommonT含shapeType、passthrough、path与PolygonPropsT组合而成。这一对象模型贯穿编译、优化与渲染三阶段points、fillColor中的ad.Num值既是可微分的优化变量也是最终渲染的数值输入。九、属性表的生成机制理解文档数据来源如果你好奇polygon.md中那张属性表为何自动更新其数据链路是packages/docs-site/scripts/shapedefs.js 遍历penrose/core导出的shapeTypes对每个形状调用sampleShape两次比较两次采样的 JSON相同属性记为defaulted不同记为sampled输出为 shapedefs JSONpackages/docs-site/src/components/ShapeProps.vue 读取该 JSON 并按sampled/defaulted分组渲染表格packages/docs-site/src/components/PropValue.vue 负责把值展示为代码文本none()显示为none()RGBA 显示为rgba(r,g,b,a)并附带色块预览。因此只要Polygon.ts中samplePolygon的默认值发生变化文档表会随构建自动同步——这也是官方文档属性表与源码高度一致的原因。十、实战小结一个最小可运行示例综合以上内容一个完整的最小 Polygon 用法结合 Substance Style 两段式声明如下-- Style 文件片段 forall Point x; Point y; Point z { x.a (0, 0) y.b (5, 8) z.c (10, 0) shape tri Polygon { points: [x.a, y.b, z.c] fillColor: rgba(0.3, 0.6, 0.9, 0.6) strokeColor: #224466 strokeWidth: 2 scale: 1 } }关键要点回顾points接受点列列表或元组形式可引用 Substance 变量参与布局优化fillColor不写则随机采样半透明写则严格生效不写strokeColor则无描边none()默认strokeWidth为 0scale作用于整个形状默认 1ensureOnCanvas默认开启越界的大图形需显式关闭所有属性均受严格类型检查但PtListV/MatrixV/LListV之间可隐式互转。如需进一步了解 Polygon 在真实项目中的运用可继续阅读 packages/examples/src/arc-mesh/arc-mesh.style、packages/examples/src/curve-examples/blobs/blobs.style 与 packages/examples/src/curve-examples/closed-elastic-curve.style 中的完整约束与目标函数写法。赞分享开发工具数据可视化【免费下载链接】penroseCreate beautiful diagrams just by typing notation in plain text.项目地址https://gitcode.com/gh_mirrors/pe/penrose点击查看免费下载相关推荐Penrose Rectangle 形状完全指南Style 属性、默认值与 SVG 渲染原理Penrose Rectangle 形状完全指南Style 属性、默认值与 SVG 渲染原理 导读 Penrose 允许你通过纯文本符号Substance开发工具数据可视化Penrose Style 语言中的 Circle 形状属性体系、采样机制与 SVG 渲染全解Penrose Style 语言中的 Circle 形状属性体系、采样机制与 SVG 渲染全解 在 Penrose 中 Circle 是 Style 程序里开发工具数据可视化Penrose 文本形状Text Shape完全指南属性、默认行为与 SVG 渲染原理Penrose 文本形状Text Shape完全指南属性、默认行为与 SVG 渲染原理 导读 Text 是 Penrose 中用于显示纯文本的基础形状s开发工具数据可视化上一篇PX4飞控系统Holybro Pix32 v5快速接线指南下一篇Okio文件系统模块深度解析跨平台文件操作的艺术创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考