我想根据给定的点构造一个多边形。为此,我执行格雷厄姆算法的第 1 点和第 2 点。接下来,我计划执行步骤 3,看看执行步骤 3 后点数组是否不同,因为如果是这样,那么我可以说最初多边形不是凸的。也就是说,我需要从位于随机坐标的随机数量的顶点构建一个多边形,然后判断构建的多边形是否是凸的。我受到这篇文章的启发:https://habr.com/ru/articles/144921/,但是,多边形尚未构建(我尚未开始第3步)。
我尝试了不同的方法,但最终选择了格雷厄姆的算法。显然,插入排序在其中无法正常工作,因为多边形的边有时会相交。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TrueLab4_habrEdition
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Graphics g;
private void Form1_Paint(object sender, PaintEventArgs e)
{
g = CreateGraphics();
Random random = new Random();
int z = random.Next(6, 8);
Point[] points = new Point[z];
int[,] pointsS = new int[z, 2];
Point[] newPoints = new Point[z];
int[] P = new int[z];
// генерация точек
for (int i = 0; i < z; i++)
{
int x = random.Next(50, 100);
int y = random.Next(70, 170);
points[i] = new Point(x, y);
}
// заполнение массива индексов точек
for (int i = 0; i < z; i++)
{
P[i] = i;
}
// копирование массива points в pointsS
for (int i = 0; i < z; i++)
{
pointsS[i, 0] = points[i].X;
pointsS[i, 1] = points[i].Y;
}
grahamscan(pointsS, P);
int j = 0;
for (int i = 0; i < P.Length; i++)
{
int x = pointsS[P[i], 0];
int y = pointsS[P[i], 1];
newPoints[j++] = new Point(x, y);
Console.WriteLine(P[i]);
}
show2d(pointsS);
Pen pen = new Pen(Color.Red, 1);
g.DrawPolygon(pen, newPoints);
}
void grahamscan(int[,] pointsS, int[]P)
{
for (int i = 1; i < pointsS.GetLength(0); i++)
{
if (pointsS[P[i], 0] < pointsS[0, 0])
{
(P[i], P[0]) = (P[0], P[i]);
}
}
for (int i = 2; i < pointsS.GetLength(0); i++)
{
int j = i;
int[] a = { pointsS[P[0], 0], pointsS[P[0], 1] };
int[] b = { pointsS[P[j-1], 0], pointsS[P[j-1], 1] };
int[] c = { pointsS[P[j], 0], pointsS[P[j], 1] };
while (j > 1 && rotate(a, b, c) < 0)
{
(P[j], P[j-1]) = (P[j-1], P[j]);
j -= 1;
}
}
}
double rotate(int[] A, int[] B, int[] C)
{
return (B[0] - A[0]) * (C[1] - B[1]) - (B[1] - A[1]) * (C[0] - B[0]);
}
void show2d(int[,] p)
{
for (int i = 0; i < p.GetLength(0); i++)
{
for (int j = 0; j < p.GetLength(1); j++)
{
Console.Write(p[i, j] + "\t");
}
Console.WriteLine();
}
}
}
}
为了使格雷厄姆的遍历正确工作,必须对点进行排序。否则,遍历有权画自相交的折线,就是你看到的样子。
要将一组点转换为多边形,不需要构造凸包: