利用Winform作图,是非常便利的。最近在做一个几何阴影相交求解的程序。程序包含了五角星的画法,月牙的画法。以及它们相交阴影部分的面积求法。(重点判断点是否在五角星内)
效果图
画五角星
//画五角星操作
private Five_star_struct draw_five(List<Point> ps) {
//ps[0]中心, ps[1]任意点
float r = ComputeOpter.getDist(ps[0], ps[1]);
Point[] vPoints = new Point[5];
five(ps[0], r,ref vPoints);
//vPoints 线段组,ps[0]为中心点
Five_star_struct five_struct = new Five_star_struct(vPoints, ps[0],r);
return five_struct;
}
//五角星
private void five(Point cen, float r,ref Point[] vPoints)
{
double vAngle = 2.0 * Math.PI / 4 + Math.PI;
for (int i = 0; i < vPoints.Length; i++)
{
vAngle += 2.0 * Math.PI / (double)vPoints.Length;
Point temp = new Point(
(float)(Math.Cos(vAngle) * r) + cen.X,
(float)(Math.Sin(vAngle) * r) + cen.Y);
float ang= ComputeOpter.GetAngle(temp, cen);
vPoints[i] = ComputeOpter.PointRotate(cen, temp, ang+90);
}
for (int i=1;i<5;i++) {
gra.DrawLine(Pens.Black, vPoints[i].X, vPoints[i].Y, vPoints[i-1].X, vPoints[i-1].Y);
if (i == 4) {
gra.DrawLine(Pens.Black, vPoints[0].X, vPoints[0].Y, vPoints[4].X, vPoints[4].Y);
}
}
}
图例
画月牙
//画两个圆弧
private List<Arc_struct> draw_arc(List<Point> ptemp) {
//ptemp[0] 起点, ptemp[1] 终点, ptemp[2] 任意点
List<Arc_struct> cen_radius = new List<Arc_struct>();
Point[] duandian = { ptemp[0], ptemp[1]};
for (int i = 0; i < 2; i++)
{
float R = 0;
Point PCenter = new Point(0, 0);
ComputeOpter.GetCircular(ptemp[0], ptemp[1], ptemp[i + 2], ref R, ref PCenter);
Arc_struct item = new Arc_struct(duandian,PCenter, R);
//draw_point(PCenter);
//draw_line(PCenter, ptemp[0]);
cen_radius.Add(item);
arc(ptemp[0], ptemp[1], ptemp[i + 2], PCenter, R);
}
return cen_radius;
}
//画一个圆弧
private void arc(Point p1, Point p2, Point p3, Point cen, float R) {
//绘制圆弧
//p1 第一个点 p2 第二个点 cen 圆心
Graphics g = this.CreateGraphics();
Pen redPen = new Pen(Color.DarkRed, 5);
float startangle = ComputeOpter.GetAngle(p1, cen);
float scanangle = ComputeOpter.includeAngle(cen, p1, p2);
if (p3.Y>p1.Y|| p3.Y > p2.Y) {
scanangle = -scanangle;
}
gra.DrawArc(new Pen(Color.Blue, 2), cen.X - R, cen.Y - R, 2 * R, 2 * R, -startangle, scanangle);
}
图例
判断点是否在五角星内
方法:由于五角星对应一个正六边形,一个正六边形对应一个圆。那么五角星就可以看做有一个圆心。在图上任意一点与圆心的连线记作L,判断L如果与五角星的五个坐标点连成的线段(一共五条)相交,如果相交数小于等于1,则在五角星内,如果大于1,则说明不在五角星内。
1.在五角星内
2.不在五角星内
判断点线段是否相交相交
引用:https://blog.csdn.net/HowardEmily/article/details/75451854利用叉积求解,
代码:引用上述链接。
private static int GetIntersection(Point a, Point b, Point c, Point d, ref Point intersection)
{
//判断异常
if (Math.Abs(b.X - a.Y) + Math.Abs(b.X - a.X) + Math.Abs(d.Y - c.Y) + Math.Abs(d.X - c.X) == 0)
{
if (c.X - a.X == 0)
{
MessageBox.Show("ABCD是同一个点!");
}
else
{
MessageBox.Show("AB是一个点,CD是一个点,且AC不同!");
}
return 0;
}
if (Math.Abs(b.Y - a.Y) + Math.Abs(b.X - a.X) == 0)
{
if ((a.X - d.X) * (c.Y - d.Y) - (a.Y - d.Y) * (c.X - d.X) == 0)
{
// MessageBox.Show("A、B是一个点,且在CD线段上!");
}
else
{
//MessageBox.Show("A、B是一个点,且不在CD线段上!");
}
return 0;
}
if (Math.Abs(d.Y - c.Y) + Math.Abs(d.X - c.X) == 0)
{
if ((d.X - b.X) * (a.Y - b.Y) - (d.Y - b.Y) * (a.X - b.X) == 0)
{
// MessageBox.Show("C、D是一个点,且在AB线段上!");
}
else
{
// MessageBox.Show("C、D是一个点,且不在AB线段上!");
}
}
if ((b.Y - a.Y) * (c.X - d.X) - (b.X - a.X) * (c.Y - d.Y) == 0)
{
//MessageBox.Show("线段平行,无交点!");
return 0;
}
intersection.X = ((b.X - a.X) * (c.X - d.X) * (c.Y - a.Y) - c.X * (b.X - a.X) * (c.Y - d.Y) + a.X * (b.Y - a.Y) * (c.X - d.X)) / ((b.Y - a.Y) * (c.X - d.X) - (b.X - a.X) * (c.Y - d.Y));
intersection.Y = ((b.Y - a.Y) * (c.Y - d.Y) * (c.X - a.X) - c.Y * (b.Y - a.Y) * (c.X - d.X) + a.Y * (b.X - a.X) * (c.Y - d.Y)) / ((b.X - a.X) * (c.Y - d.Y) - (b.Y - a.Y) * (c.X - d.X));
if ((intersection.X - a.X) * (intersection.X - b.X) <= 0 && (intersection.X - c.X) * (intersection.X - d.X) <= 0 && (intersection.Y - a.Y) * (intersection.Y - b.Y) <= 0 && (intersection.Y - c.Y) * (intersection.Y - d.Y) <= 0)
{
//MessageBox.Show("线段相交于点(" + intersection.X + "," + intersection.Y + ")!");
return 1; //'相交
}
else
{
// MessageBox.Show("线段相交于虚交点(" + intersection.X + "," + intersection.Y + ")!");
return 0; //'相交但不在线段上
}
}
求面积
//判别面积
public void discriminate(Five_star_struct lc,List<Arc_struct> cr) {
int startp_x = Convert.ToInt16(lc.cenp.X - lc.R);
int endp_x = Convert.ToInt16(lc.cenp.X + lc.R);
int startp_y = Convert.ToInt16(lc.cenp.Y - lc.R);
int endp_y = Convert.ToInt16(lc.cenp.Y+ lc.R);
int f = ComputeOpter.Distinguish_up_down(cr[0].Points[0], cr[0].Points[1],cr[0].cenp,cr[1].cenp);
int count=0;
if (f == -1) {//圆心在同侧
for (int i = startp_x; i < endp_x; i++)
{
for (int j = startp_y; j < endp_y; j++)
{
Point testp = new Point(i, j);
if (ComputeOpter.getDist(testp, cr[0].cenp) < cr[0].R)
{
if (ComputeOpter.getDist(testp, cr[1].cenp) < cr[1].R)
{
int intersect_num = getcount(lc.lines, testp, lc.cenp);
if (intersect_num <= 1)
{
draw_point(testp);
count += 1;
}
}
}
}
}
}
if (f == 0)
{//圆心在同不同侧
for (int i = startp_x; i < endp_x; i++)
{
for (int j = startp_y; j < endp_y; j++)
{
Point testp = new Point(i, j);
if ((ComputeOpter.getDist(testp, cr[0].cenp) < cr[0].R&& ComputeOpter.getDist(testp, cr[1].cenp) > cr[1].R )
|| (ComputeOpter.getDist(testp, cr[0].cenp) > cr[0].R && ComputeOpter.getDist(testp, cr[1].cenp) < cr[1].R))
{
int intersect_num = getcount(lc.lines, testp,lc.cenp);
if (intersect_num <= 1)
{
draw_point(testp);
count += 1;
}
}
}
}
}
this.textBox1.Text="面积:" + count;
}
源码下载:https://download.csdn.net/download/qq_26654503/10938886