You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用System.Drawing2D LinearGradientBrush填充椭圆出现异常结果

问题分析与修复方案

你的核心问题出在椭圆边缘点的计算逻辑,以及对LinearGradientBrush渐变范围的匹配上,以下是具体问题和修复步骤:

1. 椭圆边缘点计算错误

你当前用单位向量u直接乘以ovalRect.Width/2来计算边缘偏移量,这只适用于正圆(宽高相等的情况)。如果是椭圆,X轴和Y轴的半径分别是ovalRect.Width/2和ovalRect.Height/2,需要分别对单位向量的X、Y分量进行缩放,才能得到真正的椭圆边缘点:

修正后的边缘点计算代码:

Vector3 u = FBody.Unit(ovalCenter);
// 分别按椭圆X/Y轴半径计算边缘偏移
Vector3 fromBodyCenterToEdge = new Vector3(
    u.X * ovalRect.Width / 2.0f,
    u.Y * ovalRect.Height / 2.0f,
    u.Z // 2D渲染可忽略Z分量
);
Vector3 darkSidePoint = ovalCenter + fromBodyCenterToEdge;
Vector3 sunSidePoint = ovalCenter - fromBodyCenterToEdge;

2. 确保渐变与椭圆边界匹配

LinearGradientBrush的渐变范围是从darkSide到sunSide的直线,但填充椭圆时,渐变会覆盖整个ovalRect区域。可以添加一行代码禁用渐变平铺,避免边缘出现重复渐变的异常效果:

bl.WrapMode = WrapMode.Clamp;

3. 验证坐标投影正确性

确认ovalCenter的3D向量转2D平面时,Z轴的投影逻辑正确(比如是否用了透视投影或正交投影),如果Z分量处理不当,会导致darkSidePoint和sunSidePoint的2D坐标偏移,进而影响渐变方向。

修复后的完整代码片段

Vector3 u = FBody.Unit(ovalCenter);
Vector3 fromBodyCenterToEdge = new Vector3(
    u.X * ovalRect.Width / 2.0f,
    u.Y * ovalRect.Height / 2.0f,
    u.Z
);
Vector3 darkSidePoint = ovalCenter + fromBodyCenterToEdge;
Vector3 sunSidePoint = ovalCenter - fromBodyCenterToEdge;

PointF darkSide = new PointF(darkSidePoint.X, darkSidePoint.Y);
PointF sunSide = new PointF(sunSidePoint.X, sunSidePoint.Y); 
Color darkSideColor = Color.Black;
Color sunSideColor = penBody.Color;

LinearGradientBrush bl = new LinearGradientBrush(darkSide, sunSide, darkSideColor, sunSideColor);
bl.WrapMode = WrapMode.Clamp; // 禁用平铺,避免多余渐变

g.FillEllipse(bl, ovalRect);

内容的提问来源于stack exchange,提问作者DMP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 05:40:19