GraphicsPathを使うことで、文字を任意角度で表示することが出来るのを知った元メカ屋な私。
これは寸法線の描画に使えそう!
と思い、寸法線の描画部分をクラスにまとめたものを作成してみました。
実行画面
寸法線描画のクラス↓
public class Dimension
{
///<summary>
/// 線の色を取得設定します。
/// </summary>
public static Color LineColor { get; set; } = Color.Green;
/// <summary>
/// 文字の色を取得設定します。
/// </summary>
public static Color TextColor { get; set; } = Color.DeepSkyBlue;
/// <summary>
/// フォントの名前を取得設定します。
/// </summary>
public static FontFamily Family { get; set; } = new FontFamily("Arial");
/// <summary>
/// フォントのスタイルを取得設定します。
/// </summary>
public static FontStyle Style { get; set; } = FontStyle.Regular;
/// <summary>
/// 文字のサイズ(emスクエア)を取得設定します。
/// </summary>
public static float EmSize { get; set; } = 18.0f;
/// <summary>
/// 文字の書式設定を取得設定します。
/// </summary>
public static StringFormat Format { get; set; } = new StringFormat();
/// <summary>
/// 寸法値の表示位置の中心からのズレを取得設定します。
/// </summary>
public static float TextOffsetX { get; set; } = 0.0f;
/// <summary>
/// 寸法値の表示位置の寸法線からの距離を取得設定します。
/// </summary>
public static float TextOffsetY { get; set; } = 8.0f;
/// <summary>
/// 寸法線の線幅を取得設定します。
/// </summary>
public static float LineWidth { get; set; } = 1f;
/// <summary>
/// 矢印の大きさを取得設定します。
/// </summary>
public static float ArrowSize { get; set; } = 8f;
/// <summary>
/// 寸法線の描画
/// </summary>
/// <param name="g">描画先のGraphicsオブジェクトを指定します。</param>
/// <param name="StartPoint">寸法を引き出す位置を指定します。(開始点側)</param>
/// <param name="EndPoint">寸法を引き出す位置を指定します。(終了点側)</param>
/// <param name="Offset">指定した点から寸法線を表示するまでの距離を指定します。</param>
/// <param name="Text">寸法値に表示する文字を指定します。</param>
public static void DrawDimension(Graphics g, PointF StartPoint, PointF EndPoint, float Offset, string Text)
{
// 2点間の中心座標
PointF center = new PointF((StartPoint.X + EndPoint.X) / 2f, (StartPoint.Y + EndPoint.Y) / 2f);
// 文字の回転角度
float thRad = (float)Math.Atan2(EndPoint.Y - StartPoint.Y, EndPoint.X - StartPoint.X); // ラジアン
float th = thRad * 180.0f / (float)Math.PI;
// パスの作成
var pathText = new System.Drawing.Drawing2D.GraphicsPath();
//////////////////////////////////////////////////////////////////
// 寸法値の描画
pathText.AddString(
Text,
Family,
(int)Style,
EmSize,
new PointF(0, 0),
Format);
// 文字の領域取得
RectangleF rect = pathText.GetBounds();
// アフィン変換行列の計算
var mat = new System.Drawing.Drawing2D.Matrix();
// いったん文字を原点へ移動(文字領域の中心下側が基準)
mat.Translate(-rect.Width / 2f, -rect.Height, System.Drawing.Drawing2D.MatrixOrder.Append);
// オフセット分の移動(Y方向は逆に移動する)
mat.Translate(TextOffsetX, -TextOffsetY - Offset, System.Drawing.Drawing2D.MatrixOrder.Append);
// 寸法線に合わせた回転
mat.Rotate(th, System.Drawing.Drawing2D.MatrixOrder.Append);
// 表示位置まで移動
mat.Translate(center.X, center.Y, System.Drawing.Drawing2D.MatrixOrder.Append);
// パスをアフィン変換
pathText.Transform(mat);
// 寸法値用ブラシの作成
var brushText = new SolidBrush(TextColor);
// 描画
g.FillPath(brushText, pathText);
//////////////////////////////////////////////////////////////////
// 寸法補助線の描画
// 寸法線用ペンの作成
var penLine = new Pen(LineColor, LineWidth);
float lineLength = Offset + 5f; // 少し飛び出させる
// StartPoint側の描画
var StartPointDst = new PointF(
StartPoint.X + lineLength * (float)Math.Cos(thRad - Math.PI / 2.0),
StartPoint.Y + lineLength * (float)Math.Sin(thRad - Math.PI / 2.0)
);
g.DrawLine(penLine, StartPoint, StartPointDst);
// EndPoint側の描画
var EndPointDst = new PointF(
EndPoint.X + lineLength * (float)Math.Cos(thRad - Math.PI / 2.0),
EndPoint.Y + lineLength * (float)Math.Sin(thRad - Math.PI / 2.0)
);
g.DrawLine(penLine, EndPoint, EndPointDst);
//////////////////////////////////////////////////////////////////
// 寸法線(矢印)の描画
System.Drawing.Drawing2D.AdjustableArrowCap arrow
= new System.Drawing.Drawing2D.AdjustableArrowCap(ArrowSize, ArrowSize, false);
penLine.CustomStartCap = arrow;
penLine.CustomEndCap = arrow;
var StartPointOffset = new PointF(
StartPoint.X + Offset * (float)Math.Cos(thRad - Math.PI / 2.0),
StartPoint.Y + Offset * (float)Math.Sin(thRad - Math.PI / 2.0)
);
var EndPointOffset = new PointF(
EndPoint.X + Offset * (float)Math.Cos(thRad - Math.PI / 2.0),
EndPoint.Y + Offset * (float)Math.Sin(thRad - Math.PI / 2.0)
);
// 矢印の描画
g.DrawLine(penLine, StartPointOffset, EndPointOffset);
}
}
使用する側はこんな感じで↓
private void Form1_Paint(object sender, PaintEventArgs e)
{
var StartPoint = new PointF();
var EndPoint = new PointF();
// 四角形の描画
var p = new Pen(Brushes.Black, 2);
e.Graphics.DrawRectangle(p, 100, 100, 200, 200);
e.Graphics.DrawRectangle(p, 100, 100, 400, 300);
///////////////////////////////////////////////////////////////
// 横方向の寸法線の描画
StartPoint.X = 100; StartPoint.Y = 100;
EndPoint.X = 300; EndPoint.Y = 100;
Dimension.DrawDimension(e.Graphics, StartPoint, EndPoint, 20, "200");
StartPoint.X = 100; StartPoint.Y = 100;
EndPoint.X = 500; EndPoint.Y = 100;
Dimension.DrawDimension(e.Graphics, StartPoint, EndPoint, 50, "400");
///////////////////////////////////////////////////////////////
// 縦方向の寸法線の描画
StartPoint.X = 100; StartPoint.Y = 300;
EndPoint.X = 100; EndPoint.Y = 100;
Dimension.DrawDimension(e.Graphics, StartPoint, EndPoint, 20, "200");
StartPoint.X = 100; StartPoint.Y = 400;
EndPoint.X = 100; EndPoint.Y = 100;
Dimension.DrawDimension(e.Graphics, StartPoint, EndPoint, 50, "300");
///////////////////////////////////////////////////////////////
// 斜めの寸法線の描画
StartPoint.X = 100; StartPoint.Y = 100;
EndPoint.X = 500; EndPoint.Y = 400;
Dimension.DrawDimension(e.Graphics, StartPoint, EndPoint, 20, "500");
}
プログラムはこちら↓に置いておきました。
DrawDimensionLine.zip(Visual Studio 2015)
機械製図的には寸法線の引き出し方向など、怪しい部分もありそうなので、良い感じになるように修正してみて下さい。
←画像処理のためのC#へ戻る