C# 将一行缩短若干像素

C# 将一行缩短若干像素,c#,.net,geometry,gdi+,drawing,C#,.net,Geometry,Gdi+,Drawing,我正在使用.NETGDI+绘制业务对象的自定义图表。除其他外,该图由连接对象的几条线组成 在一个特定的场景中,我需要将一条线缩短特定数量的像素,比如说10个像素,也就是说,在这条线的端点前10个像素处找到这条线上的点 想象一个半径r=10像素的圆,以及一条起点(x1,y1)和终点(x2,y2)的线。如下图所示,圆位于直线端点的中心 如何计算标有红色圆圈的点,即圆圈与直线的交点?这将给我线的新端点,将其缩短10像素 解决方案 感谢您的回答,从中我可以总结出以下步骤。我把它命名为LengthL

我正在使用.NETGDI+绘制业务对象的自定义图表。除其他外,该图由连接对象的几条线组成

在一个特定的场景中,我需要将一条线缩短特定数量的像素,比如说10个像素,也就是说,在这条线的端点前10个像素处找到这条线上的点

想象一个半径r=10像素的圆,以及一条起点(x1,y1)和终点(x2,y2)的线。如下图所示,圆位于直线端点的中心

如何计算标有红色圆圈的点,即圆圈与直线的交点?这将给我线的新端点,将其缩短10像素


解决方案 感谢您的回答,从中我可以总结出以下步骤。我把它命名为LengthLine,因为我发现如果我想缩短线条,传递负数像素会更自然

具体地说,我试图组合一个函数,可以用圆角画一条线,可以找到

public void lengthline(PointF startPoint、ref PointF endPoint、float pixelCount)
{
if(起始点等于(终点))
return;//不是一行
double dx=endPoint.X-startPoint.X;
double dy=endPoint.Y-startPoint.Y;
如果(dx==0)
{
//垂直线:
if(端点Y<起点Y)
端点Y-=像素计数;
其他的
端点.Y+=像素计数;
}
else如果(dy==0)
{
//水平线:
if(端点.X<起点.X)
端点.X-=像素计数;
其他的
端点.X+=像素计数;
}
其他的
{
//非水平、非垂直线:
双倍长度=数学Sqrt(dx*dx+dy*dy);
双比例=(长度+像素计数)/长度;
dx*=刻度;
dy*=刻度;
endPoint.X=startPoint.X+Convert.ToSingle(dx);
endPoint.Y=startPoint.Y+Convert.ToSingle(dy);
}
}

找到方向向量,即让位置向量为(使用浮点数)B=(x2,y2)和A=(x1,y1),然后AB=B-A。通过除以向量的长度(数学Sqrt(xx+yy))来规范化该向量。然后将方向向量AB乘以原始长度减去圆的半径,再加回到直线的起始位置:

double dx = x2 - x1;
double dy = y2 - y1;
double length = Math.Sqrt(dx * dx + dy * dy);
if (length > 0)
{
    dx /= length;
    dy /= length;
}
dx *= length - radius;
dy *= length - radius;
int x3 = (int)(x1 + dx);
int y3 = (int)(y1 + dy);
编辑:修复了代码,aa并修复了最初的解释(以为您希望直线从圆的中心延伸到圆的周长:p)

可以使用类似的三角形。对于主三角形,
d
是斜边,
r
的延伸是与直角相交的垂直线。在圆内有一个较小的三角形,斜边长度
r

r/d = (x2-a0)/(x2-x1) = (y2-b0)/(y2-y1) a0 = x2 + (x2-x1)r/d b0 = y2 + (y2-y1)r/d r/d=(x2-a0)/(x2-x1)=(y2-b0)/(y2-y1) a0=x2+(x2-x1)r/d b0=y2+(y2-y1)r/d
我不知道你为什么要介绍这个圈子。对于从
(x2,y2)
延伸到
(x1,y1)
的直线,可以计算该直线上的任何点,如下所示:

(x2+p*(x1-x2),y2+p*(y1-y2))
其中,
p
是您希望沿着线路的百分比

要计算百分比,您只需要:

p = r/L
因此,在您的情况下,
(x3,y3)
可以计算为:

(x2+(10/L)*(x1-x2),y2+(10/L)*(y1-y2))
例如,如果你有两点
(x2=1,y2=5)
(x1=-6,y1=22)
,它们的长度为sqrt(72+172或18.38477631,10除以0.543928293。将所有这些数字放入上面的等式中:

  (x2 + (10/l)      * (x1-x2) , y2 + (10/l)      * (y1-y2))
= (1  + 0.543928293 * (-6- 1) , 5  + 0.543928293 * (22- 5))
= (1  + 0.543928293 * -7      , 5  + 0.543928293 * 17     )
= (x3=-2.807498053,y3=14.24678098)

(x3,y3)
(x1,y1)
之间的距离是sqrt(3.1925019472+7.7532190152)或者8.384776311,10到1亿分之一之间的差值,这只是因为我的计算器上存在舍入误差。

我很高兴你试图缩短一条有限线。因为我不知道如何缩短一条无限线:-)哈哈,哦。多次改写标题的结果。我再修改一次:)我想你要找的术语是‘线段’=)@unholysampler:我已经贡献了我的手绘照片。如果您不喜欢它,只需回滚:-)请记住,您必须注意坡度为无穷大或为零(即垂直线和水平线)或接近该坡度足以导致溢出的情况-在这些情况下,您的分割将失败。不幸的是,图像已死亡,您甚至可以“优化”(与微优化不同)通过预先计算乘法因子
double scale=(length-radius)/length
,我会考虑逐步向量运算。当dx和dy都等于零时,length才是0,所以你应该在昂贵的平方根之前检查
if(dx==0&&dy==0)
。如果长度为零会发生什么?当长度为零时,为什么还要乘以长度
  (x2 + (10/l)      * (x1-x2) , y2 + (10/l)      * (y1-y2))
= (1  + 0.543928293 * (-6- 1) , 5  + 0.543928293 * (22- 5))
= (1  + 0.543928293 * -7      , 5  + 0.543928293 * 17     )
= (x3=-2.807498053,y3=14.24678098)