C# 两端拉线偏移量
我正在尝试使用C# 两端拉线偏移量,c#,winforms,drawing,C#,Winforms,Drawing,我正在尝试使用DrawLine方法绘制虚线。但是,它会向端点添加一个微小的偏移,这会使线条看起来很难看。如何防止向端点添加偏移 protected override void OnPaint (PaintEventArgs e) { Graphics g = e.Graphics; g.DrawLine (Dot, new Point (10, 50), new Point (70, 50)); g.DrawLine (Dot, new Point (70, 50), new
DrawLine
方法绘制虚线。但是,它会向端点添加一个微小的偏移,这会使线条看起来很难看。如何防止向端点添加偏移
protected override void OnPaint (PaintEventArgs e) {
Graphics g = e.Graphics;
g.DrawLine (Dot, new Point (10, 50), new Point (70, 50));
g.DrawLine (Dot, new Point (70, 50), new Point (70, 100));
}
Pen Dot = new Pen (Brushes.Black, 2) { DashStyle = DashStyle.Dot };
输出
预期结果
您提供的坐标是指向结果线左上角位置的点。因此,当绘制两像素宽的直线时,应计算起点和终点,以包括该直线的宽度
在这种情况下,您可能希望将垂直线稍微向左和向上偏移(精确地说是通过borderwith
)
因此,通过添加(或减去)等于线条宽度的偏移量,结果如下:
protected override void OnPaint (PaintEventArgs e) {
Graphics g = e.Graphics;
g.DrawLine (Dot, new Point (10, 50), new Point (70, 50));
g.DrawLine (Dot, new Point (69, 49), new Point (69, 100));
}
Pen Dot = new Pen (Brushes.Black, 2) { DashStyle = DashStyle.Dot };
目标很简单,也很合理:
- 我们希望我们的线条以一个点开始
- 默认情况下,点和间隙都是正方形
- 所有线条都是用
绘制的PenAlignment.Center
DashStyle
,继续使用DashStyle.Dot
。默认情况下,每个点和每个间隙的两侧都有Pen.Width
像素。这就引出了第一个问题:
- 如果线条的宽度不能用钢笔的宽度来划分,我们就有麻烦了
- 要以点开始和结束,我们需要
点和n
间隙n-1
g.FillRectangle(Brushes.Yellow, 15, 15, 10, 10);
g.DrawRectangle(Pens.Orange, 10, 10, 10, 10);
g.DrawLine(Pens.OrangeRed, 10, 5, 40, 5);
using (Pen pen = new Pen(Color.Red, 2f) { DashStyle = DashStyle.Dot })
g.DrawLine(pen, 10, 30, 48, 30);
using (Pen pen = new Pen(Color.Crimson, 2f))
g.DrawLine(pen, 10, 40, 48, 40);
using (Pen pen = new Pen(Color.DarkMagenta, 3f))
g.DrawLine(pen, 10, 50, 48, 50);
仔细看看这些线是怎么画的
(旁白:您可能还想看看DrawRectangle
和FillRectangle
的区别!)
- 水平线在右坐标处开始和结束,但它们要么向下扩展(如果其画笔宽度=1),要么在y坐标的上方和下方扩展
- 当然,垂直线也会这样做
DashOffset
能帮上忙。但是还有另一个选项可以调整画笔
:我们可以将其DashPattern
设置为使用自定义值
我们需要的值是两个浮动
,包含点和间隙的缩放。默认情况下,这两个值都是1f
。我决定保持点为正方形,只修改间隙。下面是一个函数,它通过
- 将两侧的线宽扩大一半,使外部边缘相交
- 根据需要扩大间隙以适应线长度
图形
对象、一支笔
、两端的点
和一个字节
,告诉我们该行是要独立运行还是将连接到其他行,如我们的示例中所示
为了建立一个良好的连接,这将很好地与半Transparent笔刷配合使用,我们需要能够在开头或结尾跳过一个点a,甚至在两者之间跳过一个点a,例如,当我们想插入一条三角线时,如我下面的测试中所示
跳过值为0
跳过无,1或2
跳过第一个或最后一个点,3
跳过这两个点。当然,您可能希望使用枚举
void DrawDottedLine(Graphics g, Pen pen_, Point pa_, Point pb, byte skipDots)
{
float pw = pen_.Width;
float pw2 = pen_.Width / 2f;
Pen pen = (Pen)pen_.Clone();
// find out directions:
int sigX = Math.Sign(pb_.X - pa_.X);
int sigY = Math.Sign(pb_.Y - pa_.Y);
// move the end points out a bit:
PointF pa = new PointF(pa_.X - pw2 * sigX, pa_.Y - pw2 * sigY);
PointF pb = new PointF(pb_.X + pw2 * sigX, pb_.Y + pw2 * sigY);
// find line new length:
float lw = (float)(Math.Abs(pb.X - pa.X));
float lh = (float)(Math.Abs(pb.Y - pa.Y));
float ll = (float)(Math.Sqrt(lw * lw + lh * lh));
// dot length:
float dl = ll / pw;
// dot+gap count: round to nearest odd int:
int dc = (int)(2 * Math.Round((dl + 1) / 2) - 1);
// gap count:
int gc = dc / 2 ;
// dot count:
dc = gc + 1;
// gap scaling
float gs = (ll - dc * pw) / (pw * gc);
// our custom dashpattern
pen.DashPattern = new float[] { 1, gs };
// maybe skip 1st and/or last dots:
if (skipDots % 2 == 1) pa = new PointF(pa_.X + pw * sigX, pa_.Y + pw * sigY);
if (skipDots > 1) pb = new PointF(pb_.X - pw * sigX, pb_.Y - pw * sigY);
// finally we can draw the line:
g.DrawLine(pen, pa, pb);
// dispose of pen clone
pen.Dispose();
}
在做了一些明显的准备之后,我将这些点移动了一点,然后计算出垂直线或水平线的点数和间距。然后我计算修改后的间隙比例
以下是按比例放大4倍的结果,即绘制四条线以形成一个矩形,笔宽从1/3到10/3不等:
这是我使用的试验台;请注意,使用半透明黑色来说明如何正确绘制角点,即不重叠:
Pen Dot = new Pen(Color.Black, 1f);
Point pa = new Point(10, 50);
Point pb = new Point(70, 50);
Point pc = new Point(70, 100);
Point pd = new Point(10, 100);
for (int i = 1; i < 10; i++ )
{
Dot = new Pen(Color.FromArgb(128, Color.Black), i / 3f){ DashStyle = DashStyle.Dot };
g.TranslateTransform(10, 10);
DrawDottedLine(g, Dot, pa, pb, 2);
DrawDottedLine(g, Dot, pb, pc, 2);
DrawDottedLine(g, Dot, pc, pd, 2);
DrawDottedLine(g, Dot, pd, pa, 2);
DrawDottedLine(g, Dot, pd, pb, 3);
}
笔点=新笔(颜色:黑色,1f);
点pa=新点(10,50);
点pb=新点(70,50);
点pc=新点(70100);
点pd=新点(10100);
对于(int i=1;i<10;i++)
{
点=新笔(Color.FromArgb(128,Color.Black),i/3f){DashStyle=DashStyle.Dot};
g、 翻译形式(10,10);
DrawDottedLine(g、Dot、pa、pb、2);
DrawDottedLine(g、Dot、pb、pc、2);
DrawDottedLine(g、Dot、pc、pd、2);
DrawDottedLine(g、Dot、pd、pa、2);
DrawDottedLine(g、Dot、pd、pb、3);
}
我真的希望可以通过简单地使用抽绳来避免连接问题,但这不起作用,在找到这个解决方案后,我并不感到惊讶,它没有…以下是答案。这幅画出了什么问题,你希望它怎么样?(虚线是原始的虚线图,红线显示用于绘制的方框。@RezaAghaei为什么会有偏移?从技术上讲,两条线应该重合,因为第一条线的终点和第二条线的起点是相同的。您可以使用链接图像并在图像上显示意外的部分。还可以显示什么这是预期的结果。我不明白你提到的偏移量是多少。它是一条宽度为2的虚线,怎么可能不同。当点不适合给定长度时,与其说是偏移量,不如说是余数。您可以通过添加偏移量或使用自定义点宽度或组合来成功地操纵线条。。我想我终于搞定了,请尝试改进的版本!我不明白您在说什么。一点代码可能会有所帮助。67,49和67100看起来不错perfect@kakkarot,在这种情况下,您必须合并fact显示这些点有间隙,因此偏移量可以更大或更小