的目标很简单的和可信的:
而游戏规则也很简单:
- 无论是点和差距是默认的正方形。
- 所有线条均采用
PenAlignment.Center
绘制。
不幸的是,组合的后果是相当复杂的,所以我承担......
让我们先来看看第一个规则;让我们忽略其他DashStyles
并留在DashStyle.Dot
。默认情况下,每个点和每个间隙的两侧都有Pen.Width
像素。这导致右转入第一问题:
- 如果我们的线的宽度不能
Pen.Width
分,我们就有麻烦了。
- 要开始和结束点我们想要有
n
点和n-1
的空白。
还有更多,但让我们来看看第二条规则;来说明吧,我画这个10倍放大图像:
这是创建着色部代码:
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
差)
- 水平线开始,并在合适的坐标结束,但他们要么扩大向下(如果他们的Pen.Width = 1 )或高于和低于γ-辅酸盐。
- 当然,垂直线条也是一样。
问题是,他们只是不会在(外)边缘放在一起。
那么我们该怎么办?我不认为DashOffset
可以提供帮助。但有另一个选项来调整Pen
:我们可以将其设置为DashPattern
以使用自定义值。
我们需要的值是两个floats
,包含缩放的点和空白。默认情况下,这两个值都是1f
。我决定保持点平方,只修改差距。这里是通过
- 解决该问题通过在两侧上半笔宽度扩展的线宽度,以便外边缘满足
- 扩大的间隙根据需要,以适应线路长度的函数
这里是画线功能;它需要Graphics
对象,一个Pen
,两端Points
和一个byte
告诉我们该线是否意味着独立或将连接到其他行,如我们的示例中。
为了使良好的连接,将与半tranparent很好地工作刷我们需要在开头或结尾,甚至两者,例如跳过一个点的能力当我们想要插入一个正交线,如下面我的测试。
跳过值为0
跳过没有,1 or 2
跳过第一个或最后一个点和3
跳过这两个。当然,您也可以使用enumeration
。
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);
}
我真的希望人们可以简单地使用DrawLines
避免了连接问题,但这并没有工作,找出这个解决方案后,我并不是真的很惊讶它没有..
这是[放大的结果绘图](http://i.stack.imgur.com/ARXbp.png)。绘图有什么问题,你期望什么? (虚线是原始的虚线图,红线显示的是用于绘制的框。 –
@RezaAghaei为什么会有偏移?从技术上讲,线应该重合,因为第一行的终点和第一行的起点第二行是相同的 – kakkarot
你可以使用链接的图像,并在图像上显示意想不到的部分,同时显示期望的结果,我不明白你提到的偏移量是什么,它是一个虚线,宽度为2它是不同的 –