的目標很簡單的和可信的:
而遊戲規則也很簡單:
- 無論是點和差距是默認的正方形。
- 所有線條均採用
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它是不同的 –