曲线和直线的组合多边形

时间:2017-06-20 12:24:10

标签: c# winforms

沿着纵坐标有一条曲线和一条直线,我需要在直线的左右两侧获得闭合的多边形点,这是由于直线与曲线的交点而形成的。

我将说明:enter image description here

在图中有一条曲线和一条直线,封闭的多边形相对于直线形成在左右两侧,我需要得到不同的列表。

对任务的共同理解的插图。颜色是为了清晰起见,有必要分别为左右两种情况获得两个多边形列表。

你能用gdi实现吗?

1 个答案:

答案 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方法复制它们!

这是工作:

enter image description here