沿着纵坐标有一条曲线和一条直线,我需要在直线的左右两侧获得闭合的多边形点,这是由于直线与曲线的交点而形成的。
在图中有一条曲线和一条直线,封闭的多边形相对于直线形成在左右两侧,我需要得到不同的列表。
对任务的共同理解的插图。颜色是为了清晰起见,有必要分别为左右两种情况获得两个多边形列表。
你能用gdi实现吗?
答案 0 :(得分:2)
要做的第一件事是数据结构。
假设您正在
中收集鼠标位置List<Point> allPoints = new List<Point>();
然后我们需要将这些点划分为左右多边形列表,即两个点列表列表..:
List<List<Point>> leftList = new List<List<Point>>();
List<List<Point>> rightList = new List<List<Point>>();
接下来我们需要进行分区。在一般解决方案中,我们需要一个函数(点,线),它确定该点所在的半球。
让我们写完整的签名int OnSideOff(Point p, Point p1, Point p2)
,然后作弊:
int OnSideOff(Point p, Point p1, Point p2)
{
// simplistic test, for vertical lines only
if (p.X < p1.X) return -1;
else if (p.X > p1.X) return 1;
else return 0;
}
这显然只适用于垂直行;如果你尝试,你可以找到一般情况的帖子。
在我们完成分区之前,我们需要另一个辅助函数:
我们不能指望所有甚至任何一点实际上都在线上。因此,我们需要在线上开始和结束每个多边形,最好是最后一个点和当前点之间的交叉点。
你会发现线路交叉码的帖子,但我会惊讶的是:再次作弊 ......:
Point Crossing(Point p, Point p0, Point p1, Point p2)
{
// simplistic again
return new Point(p1.X, (p.Y + p0.Y) / 2 );
}
现在我们已经准备好进行分区了:
List<Point> curLeft = new List<Point>();
List<Point> curRight = new List<Point>();
bool left = OnSideOff(allPoints[0], P1, P2) > 0;
for (int i = 1; i < allPoints.Count; i++) // *
{
Point p = allPoints[i];
Point cross = Crossing(p, allPoints[i-1], P1, P2);
if ( OnSideOff(p, P1, P2) >= 0) // right
{
if (left) // was left
{
curLeft.Add(cross);
leftList.Add(curLeft.ToList()); //**
left = false;
curLeft.Clear();
curRight.Add(cross);
}
curRight.Add(p);
}
else // left
{
if (!left) // was right
{
curRight.Add(cross);
rightList.Add(curRight.ToList()); //**
left = true;
curRight.Clear();
curLeft.Add(cross);
}
curLeft.Add(p);
}
}
代码使用以下变量:
Size sz = pictureBox1.ClientSize;
Point P1 = new Point(sz.Width / 2, 0);
Point P2 = new Point(sz.Width / 2, sz.Height);
注意:
// *我扔掉了第一点因为我很懒;当然有办法正确地做到这一点;我想要的只是一种简单的方法来调用交叉方法; - )
// **我们需要保留点数,因此我们使用ToList
方法复制它们!
这是工作: