- 2008-12-04 (木) 2:23
- Study
経済学で使う無差別曲線をてきとーに書けるソフトがほしいけど、そんな都合のいいものはないらしい。んだらば自分で作るしかないんだけど、てけとーにマウスで引いたギザギザな線が微妙にきれいなるようにするのってどうすりゃいいんだろうか。さっぱり訳わかめ。
とりあえず、サンプルを作ってみた。左みたいに適当に書くと、右のようにちょっときれいになる。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace SampleBezierDraw
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private bool isDragging = false;
List<Point> bezierPoints = new List<Point>();
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
isDragging = true;
bezierPoints.Clear();
bezierPoints.Add(e.Location);
}
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (isDragging)
{
bezierPoints.Add(e.Location);
using (Pen pen = new Pen(Color.Black, 3.0f))
using (Bitmap b = new Bitmap(ClientRectangle.Width, ClientRectangle.Height))
using (Graphics g1 = Graphics.FromImage(b))
using (Graphics g2 = Graphics.FromHwnd(Handle))
{
g1.FillRectangle(SystemBrushes.Window, ClientRectangle);
g1.DrawLines(pen, bezierPoints.ToArray());
g2.DrawImage(b, 0, 0);
}
}
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
if (isDragging && e.Button == MouseButtons.Left)
{
bezierPoints.Add(e.Location);
using (Graphics g = Graphics.FromHwnd(Handle))
using (Pen pen = new Pen(Color.Black, 3.0f))
{
g.FillRectangle(SystemBrushes.Window, ClientRectangle);
if (bezierPoints.Count <= 0)
{
/* Do nothing */
}
else if (bezierPoints.Count <= 3)
{
g.DrawLines(pen, bezierPoints.ToArray());
}
else
{
/* 全体の20%(または20個)まで点を間引く */
int LIMIT_OF_POINT_COUNT = Math.Max(20, bezierPoints.Count * 20 / 100);
while (bezierPoints.Count > LIMIT_OF_POINT_COUNT)
{
List<Point> p = new List<Point>();
p.Add(bezierPoints[0]); /* 始点を追加 */
for (int i = 2; i <= bezierPoints.Count - 2; i += 2)
{
p.Add(new Point(
(bezierPoints[i - 1].X + bezierPoints[i].X) / 2,
(bezierPoints[i - 1].Y + bezierPoints[i].Y) / 2));
}
p.Add(bezierPoints[bezierPoints.Count - 1]);
bezierPoints = p; /* 終点を追加 */
}
g.SmoothingMode = SmoothingMode.HighQuality;
g.DrawCurve(pen, bezierPoints.ToArray());
}
}
isDragging = false;
}
}
}
}
速さとかまったく度外視。
List<> とか、やめれ、自分。
わたしゃ文系人間なので、こういう時ってちゃんと数学的知識がある人がうらやましくなるなぁ…。こういうの詳しい方、ご教授くださいorz
PS:
最初、Bezier曲線で書こうと思ったけど、なんかエラーでた。
DrawCurve にしたら直ったんだけど、DrawBziers の引数って 4n+3 個のPoint配列じゃないとだめとか?多すぎるとあかんのかなぁー
ベジェ曲線(ベジェきょくせん、Bézier Curve)またはベジエ曲線とは、N 個の制御点から得られる N – 1 次曲線である。
from ベジェ曲線 – Wikipedia
だいたい、これを読んで(@@?な時点でダメなんだとも思うんだけどw
VS2008 .NET 3.5
- Newer: 撤退ではない。戦略的後退だっ!
- Older: Windows Live 一新!これは気に入った!

