笔记
0工具
0此页用于记录用户反馈问题后的每一次改进
关于
“写笔记”支持四种格式——Word 文档、Excel 表格、Markdown、纯文本,起稿或二次编辑时都能随时切换,同一篇笔记想用哪种形态来记,都由你说了算。
md、txt、csv、json 这类纯文本则原样载入,不做多余加工。拿一张现成的表倒进来、改几笔、再导出去,等于白用一台免费的格式转换器。
要带走就在右上角点“下载”,可导出 PDF、Word、Markdown、Excel、TXT 等格式;列表卡片“⋯”菜单里,也有同样的下载入口。
在“工具”页点“+ 上传工具”即可发布:填好名称与链接,再用 Markdown 把使用方法写清楚——能解决什么问题、怎么装、怎么用,比堆介绍实在。
要分发安装包就一并上传压缩包(ZIP、RAR、7Z、TAR.GZ,最大 35MB),别人在详情页一键下载;只放链接不带附件也可以。
工具按大家的收藏热度排序,好用的自然会被顶上来。发布后可在详情页或卡片菜单里编辑、下架。
写笔记时勾上“隐藏”,这篇就只存在于你自己的账号里:不进列表、不进搜索、不上首页精选,也不会出现在任何公开的页面,链接发给别人同样打不开。
适合放密码、草稿、日记这类只给自己看的内容;想公开,去“发布”打开它,把“隐藏”的勾去掉再保存,之后编辑会默认保持原状态,不会悄悄变回公开。
不想公开、只想临时给人看:点“分享”生成一条带密码和有效期的链接,到期自动失效,你也能随时撤销。
你的内容会同时保存在多个副本上,系统定期做备份与完整性校验,再配合异地容灾机制:就算某台机器出问题,数据也不会丢,可以长期放心存放;特别重要的资料,仍建议你另外再留一份备份。
全站跑在容器化、模块化的现代架构上,更新、部署、回滚都很快,扩展性和稳定性都按长期运营的标准来设计(Built for reliability, designed to scale)。
这个网站最早只是一个人的笔记仓库,后来慢慢长成现在的知识中枢。设计上很克制——没有广告、没有追踪、没有推荐算法,只是干干净净地存放一些东西;既然做好了,就公开出来,万一有人用得上呢。
不做大而全,不做平台梦,保持简单、保持克制、保持好奇。所有内容都由用户贡献、由用户维护:不会突然冒出付费墙,不会在角落塞广告位,也不会把你的数据卖给第三方。
产品会持续迭代,站内日志页记录着每一次改动,改了什么都有迹可循;想了解这个站是怎么一步步走到今天的,翻翻日志就能看到来龙去脉。
如果在这里看到涉嫌违规的内容,点对应卡片右侧的“举报”按钮就能提交,我们会尽快核实处理;也谢谢你花一点时间,一起把这里维护干净。
趋势
曲率贝塞尔:改进经典曲线的不朽配方
通过直接控制曲率而非切线长度,重新设计贝塞尔曲线编辑方式,使曲线编辑更直观稳定。
贝塞尔曲线是计算机辅助设计(CAD)和计算机图形学的基石。就像 Bic 圆珠笔一样,这个设计已有数十年历史,却无处不在。在各类插画和动画工具中,它常常是默认甚至唯一的选择。它由 Paul de Casteljau 于 1959 年构思,后经 Pierre Bézier 在 1960 年代于雷诺公司完善,其持久魅力在于简单。尽管更复杂的曲线已被发明,新的也不断被提出,但它们往往局限于特定领域,如高精度 CAD 或道路设计。在通用场景中,贝塞尔曲线顽固地拒绝被取代,尽管它有诸多缺点。因此,贝塞尔曲线是我们似乎摆脱不了的“遗留技术”。作为软件工程师,我的问题是:我们能否在不废弃所有基于它构建的技术的前提下,让贝塞尔变得更好?答案是肯定的。
插值:贝塞尔的核心
绘制贝塞尔曲线是一个出奇简单且线性的过程(提示:文中所有图表都是可交互的)。给定一系列控制点,我们用线段连接它们,然后在这些线段上同时取点,产生新点,再连接,重复此过程直至只剩一个点,该点即落在曲线上。这种构造使贝塞尔比乍看起来更规则。线性插值(lerp)可总结为紧凑公式,例如四个控制点 $(A, B, C, D)$ 的三次贝塞尔:
$$ \gamma(t) = A(1-t)^3 + 3B(1-t)^2 t + 3C(1-t)t^2 + D t^3 $$
规则很简单:$(1-t)$ 的幂递减,$t$ 的幂递增,系数取自帕斯卡三角的第 n 行(例如 1,3,3,1)。对于 2D 和 3D 曲线,公式分别应用于 X、Y、Z 坐标。
虽然贝塞尔可构造任意数量的控制点,但实践中只用 4 个控制点的三次贝塞尔,因为曲线只保证穿过首尾控制点,高次贝塞尔更难塑形。更大曲线通常由多个三次贝塞尔段拼接而成,对齐切线以形成看似平滑的分段曲线——这就是常见的三次贝塞尔样条。大多数绘图应用中的“钢笔工具”实际上是在编辑控制点,而非直接绘制曲线。
一个到处流传的谎言
钢笔工具通常提供几种控制点模式:对称切线、非对称切线、单侧切线等。直觉上这些代表不同程度的平滑性:对称切线被认为最平滑,放松约束则损失部分平滑性。但实际上这是完全错误的,而且容易证明。
贝塞尔曲线可以被精确分割:通过从插值图中读出新的控制点,左段和右段与原始曲线 100% 一致,且总是在接缝处完美连接。然而,除了接近中点的一个分割点外,中间的切线将是不对称的。这可以通过曲率梳(curvature comb)来确认,它表示每个点的曲率半径的倒数。曲率梳保持连续,没有跳跃。这意味着相邻切线长度是否相等(即对称)完全无关紧要。试图用这种方式绘制平滑直观的贝塞尔曲线是徒劳的。
一个简单的改进是将切线视为相对值而非绝对值。例如,让切线长度与每个段的首尾距离成比例。这种样条更容易编辑,因为当你移动曲线点时,相邻段会自然弯曲让路,产生更少的尖点。然而,如果我们再次绘制曲率,会发现这不是一个好方案:按比例缩放切线不能保证编辑时曲率保持不变,也不能保证段间曲率连续。这也表明,向用户提供曲率梳可视化作为“有用工具”其实很刻薄:调整一端的曲率会影响另一端,需要反复来回调整直到接近目标。
直接处理曲率
更有效的策略是直接使用曲率。虽然这通常是一个难题,但这里存在一些令人惊讶的关系,我们可以直接观察:考虑段 $A-B-C-D$ 起始处的曲率,它只受 $A$、$B$、$C$ 的位置影响,点 $D$ 可以自由移动(若它与 $C$ 不连接)。此外,由于切线 $A-B$ 是水平的,只有 $C$ 的垂直位置起作用。这是底层线性插值的结果,最终在公式中抵消了许多项。因此,$A$ 处的曲率只受 $A-B$ 的长度和 $C$ 到 $A-B$ 的垂直距离影响。另一端的 $D$ 同理,只受 $C-D$ 长度和 $B$ 到 $C-D$ 的垂直距离影响。
但这本身并不太有用。当我们移动曲线点($A$ 或 $D$)时,通常相邻控制点($B$ 或 $C$)也会移动以保持切线。而且当我们旋转对称或非对称切线时,相邻段的切线也旋转相同角度,改变了那侧的曲率。尽管如此,这显示了保持曲率并非疯狂的想法,可以通过适当缩放切线简单实现。规则很简单:
- 移动曲线点时,必须保持相邻段的起始和结束曲率。
- 移动切线时,必须保持当前段对端曲率,以及相邻段两侧的曲率。
这应该产生一个尊重用户意图的编辑体验。但还不完全:移动曲线点效果很好,但旋转切线时,切线长度本身并不能很好代表用户意图。微小变化可能导致曲率巨大变化,曲线可能意外跳动和爆炸,因为它试图找到匹配解。因此,更好的做法是使用曲率手柄(curvature handles),其中手柄长度直接对应曲率。与曲率梳不同,手柄长度是非反转的曲率半径,这是更自然的选择。这些手柄非常稳定,可以即时转换为经典贝塞尔控制点,无需来回转换。这也有助于避免数值漂移。
求解切线长度
为了实现这一点,我们需要在给定所需曲率 $k_0$ 和 $k_1$、起点和终点 $A$ 和 $D$、以及起点和终点的单位切线向量的情况下,求解切线长度 $l_0$ 和 $l_1$。
给定曲线 $\gamma(t)$,单位切向量 $\mathbf{T}(t)$ 可表示为归一化导数:
$$ \mathbf{T}(t) = \frac{\gamma'(t)}{|\gamma'(t)|} $$
曲率向量 $\mathbf{K}(t)$ 可通过两个向量叉积得到:
$$ \mathbf{K}(t) = \mathbf{T}(t) \times \frac{\gamma''(t)}{|\gamma'(t)|^2} \times \mathbf{T}(t) $$
叉积确保 $\mathbf{K}(t)$ 垂直于 $\mathbf{T}(t)$,其模长就是曲率。对于三次贝塞尔,我们可以写出 $\gamma'(t)$ 和 $\gamma''(t)$ 的显式公式,然后代入端点 $t=0$ 和 $t=1$,得到曲率与切线长度之间的关系。具体来说,在 $t=0$ 处,曲率 $k_0$ 与 $l_0$ 成反比,与 $C$ 到 $AB$ 的垂直距离成正比。类似地,$t=1$ 处曲率 $k_1$ 与 $l_1$ 成反比。
因此,给定目标曲率,我们可以解出 $l_0$ 和 $l_1$。由于曲率与长度成反比,解是直接的:$l_0 = \frac{\text{某常数}}{k_0}$,$l_1 = \frac{\text{某常数}}{k_1}$。这里的常数取决于其他几何量(如控制点位置和切线方向)。
实现与稳定性
在实际实现中,我们维护曲率手柄(长度代表曲率半径),而不是直接编辑切线长度。当用户拖动曲率手柄时,我们即时计算对应的贝塞尔控制点位置。由于曲率与长度成反比,手柄长度越大,曲率越小,这符合直觉。
为了保持数值稳定,我们避免来回转换,而是直接从曲率手柄计算出贝塞尔控制点。这减少了浮点误差的累积。此外,由于曲率手柄是全局的(每个曲线点都有两个手柄,分别控制两侧曲率),编辑时不会出现“调整一端影响另一端”的循环问题。
结论
通过将曲率作为编辑的直接对象,我们可以在不改变底层贝塞尔表示的前提下,显著改善编辑体验。这种方法保留了所有现有技术(如渲染、求值、分割等)的兼容性,同时让用户更直观地控制曲线形状。这展示了“遗留技术”也可以通过重新思考交互方式来进化,而非彻底替换。