Path.FillType的四种类型
·
1. 背景:画图时,什么是“内部”?
在二维平面上,如果你画了一个简单的实心圆,什么是“里面”,什么是“外面”,一目了然。
但是,如果你画了一个五角星,或者画了两个嵌套的圆(甜甜圈),甚至这些线条彼此交叉缠绕,计算机的 GPU 该如何判断哪些像素点该涂色(内部),哪些该留白(外部)?
核心问题: GPU 需要一套绝对的数学定理,来判断屏幕上的任意一个坐标点 (x,y)(x, y)(x,y),到底属于这团乱麻线条的“内部”还是“外部”。
这套底层数学定理,就是 射线法 (Ray-Casting)。
2. 射线判定法则
为了搞清楚一个像素点到底在不在图形里,底层的算法逻辑是这样的:
从该像素点出发,向任意方向(通常是水平向右)发射一条无限长的数学射线,去和 Path 的边界发生相交。
根据这条射线与边界的交点规律,衍生出了两种截然不同的物理判定模型。
3. 四种 FillType
理解了射线法,这四种类型就能被拆解为两种基础物理模型 + 它们的布尔非(NOT)运算。
模型一:基于“矢量方向”的判定(非零环绕数规则)
1. Path.FillType.WINDING(Android 默认值)
- 物理本质: 承认 Path 的每一条线都是有方向的向量(顺时针画还是逆时针画,结果完全不同)。
- 底层计算逻辑: 射线穿过图形边界时,不仅要记下相交,还要看边界线是“怎么穿过”射线的。
- 设定一个计数器,初始为 0。
- 如果 Path 是从射线的左边穿到右边,计数器 +1。
- 如果 Path 是从射线的右边穿到左边,计数器 -1。
- 裁决: 只要最终的计数器结果 不等于 0,这个点就是“内部”(填充);如果等于 0,就是“外部”(不填充)。
- 物理结果: 假设你画了一个五角星的 Path(通常是一笔连贯画完)。用射线法一扫,中间那个五边形里的射线相交结果往往不为 0。所以
WINDING模式下的五角星,中间是实心涂满的。如果你画了两个同心圆想要挖空中间,必须保证两个圆的绘制方向相反,这样射线穿过两次时,一次 +1,一次 -1,相互抵消为 0,中间才会空出来。
模型二:基于“几何奇偶”的判定(奇偶规则)
2. Path.FillType.EVEN_ODD
- 物理本质: 抛弃方向(无论顺时针还是逆时针),只看纯粹的物理边界隔断。
- 底层计算逻辑: 射线穿过图形边界时,只做最简单的累加计数。
- 穿过一条边,交点数就 +1。
- 裁决: 如果总交点数是奇数(Odd),该点在“内部”(填充)。如果是偶数(Even),该点在“外部”(不填充)。
- 物理结果: 同样是一个一笔画出的五角星,从最中心的点发射一条射线出去,它必定会穿过五角星的 2 条边(偶数)。按照
EVEN_ODD定理,偶数判定为外部。所以EVEN_ODD模式下的五角星,中间的五边形是空心的。它极其适合用来做“镂空”效果,因为它完全不需要你操心绘制线条时的顺逆时针方向。
模型的布尔反转(NOT 门)
接下来的两种,没有任何新的几何定理,它们仅仅是前两者的物理反相。相当于在最终的渲染结果上套了一个布尔代数里的 NOT 门。
3. Path.FillType.INVERSE_WINDING
- 底层逻辑: 执行
WINDING算法,然后反转结果。 - 物理结果: 原本被判定为“内部”的实心部分变成透明;原本的整个无限画布(外部)被填充上了颜色。相当于你在墙上剪出了一个实心五角星的破洞。
4. Path.FillType.INVERSE_EVEN_ODD
- 底层逻辑: 执行
EVEN_ODD算法,然后反转结果。 - 物理结果: 无限画布被填满,只镂空出
EVEN_ODD规则计算出的内部区域(比如一个中间带有透明五边形孔洞的五角星破洞)。
总结:如何做工程选择?
从第一性原理来看,怎么选?
- 当你面对有向连通图(比如你需要严密控制同心圆的相互抵消,绘制复杂的自定义物理组件),使用默认的
WINDING。 - 当你只想要简单的几何镂空(比如做扫码框周围的半透明遮罩,或者把几个图形拼在一起挖去重叠部分),坚决使用
EVEN_ODD。它可以让你免受 Path 方向计算的心智负担,直接通过拓扑奇偶性完成任务。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)