三角测量算法

发布于 2024-11-16 04:38:14 字数 484 浏览 2 评论 0原文

我决定创建一个简单的演示,将多边形划分为三角形集。到目前为止,我得到的是:

给出了一个顺序顶点列表(P1),形成多边形边缘(多边形在大多数情况下不是凸的);需要一个三角形集合

循环遍历多边形P1内的所有顶点并找到一个(v),它将满足下一个子句:

  1. 从多边形中删除v并将新的保存到P2< /em> v 的前一个顶点 连接到下一个形成 a 不与任何 P2 相交的线 边

  2. v 不在 P2 内

如果满足这些条件,我们可以将 P1 替换为 (P2 + triangle( prev(v), v, next(v)) )并重复此操作,直到 P1 包含超过 3 个顶点。

那么,问题是:这个算法是否正确?如何使用 C / C++ 以最明显和最简单的方式实现它?

I've decided to create a simple demo, dividing a polygon into triangle set. Here what i've got so far:

A sequential vertex list is given (P1) forming polygon edges (polygon is not convex in most cases); a triangle set is needed

Loop through all the vertices within the polygon P1 and find the one (v), which will satisfy next clauses:

  1. remove v from polygon and save the new one to P2 previous vertex to v
    connected to its next one form a
    line which do not cross any of P2
    edges

  2. v is not inside P2

If these are satisfied, we can replace P1 with (P2 + triangle( prev(v), v, next(v)) ) and repeat this action until P1 contains more than 3 vertices.

So, the questions are: is this algorithm correct and how it could be implemented using C / C++ using the most obvious and simple way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

话少心凉 2024-11-23 04:38:14

我认为您正在描述耳朵修剪方法。该方法的代码位于 http://cs.smith.edu/~orourke/ books/ftp.html ;这是Computational Geometry in C一书中描述的代码。

I think you're describing the ear clipping method. There's code for that method at http://cs.smith.edu/~orourke/books/ftp.html ; it's the code described in the book Computational Geometry in C.

一刻暧昧 2024-11-23 04:38:14

看来我已经完成了这个算法的实现。请某人验证一下。谢谢!

typedef struct Point
{
  float x, y;
};

class MooPolygon
{
    private:
        vector<Point> points;

        int isVertexEar(int n, const vector<Point> &p)
        {
            return (isVertexInsideNewPoly(n, p) && !isEdgeIntersect(n, p));
        }

        int isEdgeIntersect(int n, const vector<Point> &p)
        {
            Point v = p[n];
            vector<Point> a;

            for (size_t i = 0; i < p.size(); i++)
                if (i != n)
                    a.push_back(p[i]);

            int c = 0, cnt = a.size(), prev = (cnt + (n - 1)) % cnt, next = n % cnt;

            Point v1 = a[prev], v2 = a[next];

            for (size_t i = 0, j = cnt - 1; i < cnt; j = i++)
            {
                if (prev == i || prev == j || next == i || next == j)
                    continue;

                Point v4 = a[j], v3 = a[i];

                float denominator = ((v4.y - v3.y) * (v2.x - v1.x)) - ((v4.x - v3.x) * (v2.y - v1.y));

                if (!denominator)
                    continue;

                float ua = (((v4.x - v3.x) * (v1.y - v3.y)) - ((v4.y - v3.y) * (v1.x - v3.x))) / denominator;
                float ub = (((v2.x - v1.x) * (v1.y - v3.y)) - ((v2.y - v1.y) * (v1.x - v3.x))) / denominator;

                //float x = v1.x + (ua * (v2.x - v1.x)), y = v1.y + (ua * (v2.y - v1.y));

                if (ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1)
                {
                    c = 1;
                    break;
                }
            }

            return c;
        }

        int isVertexInsideNewPoly(int n, const vector<Point> &p)
        {
            Point v = p[n];
            vector<Point> a;

            for (size_t i = 0; i < p.size(); i++)
                if (i != n)
                    a.push_back(p[i]);

            int c = 1;

            for (size_t i = 0, j = a.size() - 1; i < a.size(); j = i++) 
            {
                if ((((a[i].y <= v.y) && (v.y < a[j].y)) || ((a[j].y <= v.y) && (v.y < a[i].y))) && (v.x > (a[j].x - a[i].x) * (v.y - a[i].y) / (a[j].y - a[i].y) + a[i].x))
                    c = !c;
            }

            return c;
        }

        float dist(Point a, Point b)
        {
            return sqrt(  ((a.x - b.x) * (a.x - b.x)) + (((a.y - b.y) * (a.y - b.y)))  );
        }

    public:
        void push(const Point &p)
        {
            for (size_t i = 0; i < points.size(); i++)
            {
                if (dist(points[i], p) < 7.f)
                {
                    points.push_back(points[i]);

                    return;
                }
            }

            points.push_back(p);
        }

        void pop()
        {
            if (points.size() > 0)
                points.pop_back();
        }

        void clear()
        {
            points.clear();
        }

        Point v(int index)
        {
            return points[index];
        }

        size_t size()
        {
            return points.size();
        }

        void triangulate()
        {
            vector<Point> a;

            for (size_t i = 0; i < points.size(); i++)
            {
                a.push_back(points[i]);
            }

            points.clear();

            for (size_t t = a.size() - 1, i = 0, j = 1; i < a.size(); t = i++, j = (i + 1) % a.size())
            {
                if (a.size() == 3)
                {
                    points.push_back(a[0]);
                    points.push_back(a[1]);
                    points.push_back(a[2]);

                    break;
                }

                if (isVertexEar(i, a))
                {
                    points.push_back(a[t]);
                    points.push_back(a[i]);
                    points.push_back(a[j]);

                    a.erase(a.begin() + i, a.begin() + i + 1);

                    t = a.size() - 1;
                    i = 0;
                    j = 1;
                }
            }
        }
};

Seems that i'm done with this algorithm implementation. Please, verify it someone. Thanks!

typedef struct Point
{
  float x, y;
};

class MooPolygon
{
    private:
        vector<Point> points;

        int isVertexEar(int n, const vector<Point> &p)
        {
            return (isVertexInsideNewPoly(n, p) && !isEdgeIntersect(n, p));
        }

        int isEdgeIntersect(int n, const vector<Point> &p)
        {
            Point v = p[n];
            vector<Point> a;

            for (size_t i = 0; i < p.size(); i++)
                if (i != n)
                    a.push_back(p[i]);

            int c = 0, cnt = a.size(), prev = (cnt + (n - 1)) % cnt, next = n % cnt;

            Point v1 = a[prev], v2 = a[next];

            for (size_t i = 0, j = cnt - 1; i < cnt; j = i++)
            {
                if (prev == i || prev == j || next == i || next == j)
                    continue;

                Point v4 = a[j], v3 = a[i];

                float denominator = ((v4.y - v3.y) * (v2.x - v1.x)) - ((v4.x - v3.x) * (v2.y - v1.y));

                if (!denominator)
                    continue;

                float ua = (((v4.x - v3.x) * (v1.y - v3.y)) - ((v4.y - v3.y) * (v1.x - v3.x))) / denominator;
                float ub = (((v2.x - v1.x) * (v1.y - v3.y)) - ((v2.y - v1.y) * (v1.x - v3.x))) / denominator;

                //float x = v1.x + (ua * (v2.x - v1.x)), y = v1.y + (ua * (v2.y - v1.y));

                if (ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1)
                {
                    c = 1;
                    break;
                }
            }

            return c;
        }

        int isVertexInsideNewPoly(int n, const vector<Point> &p)
        {
            Point v = p[n];
            vector<Point> a;

            for (size_t i = 0; i < p.size(); i++)
                if (i != n)
                    a.push_back(p[i]);

            int c = 1;

            for (size_t i = 0, j = a.size() - 1; i < a.size(); j = i++) 
            {
                if ((((a[i].y <= v.y) && (v.y < a[j].y)) || ((a[j].y <= v.y) && (v.y < a[i].y))) && (v.x > (a[j].x - a[i].x) * (v.y - a[i].y) / (a[j].y - a[i].y) + a[i].x))
                    c = !c;
            }

            return c;
        }

        float dist(Point a, Point b)
        {
            return sqrt(  ((a.x - b.x) * (a.x - b.x)) + (((a.y - b.y) * (a.y - b.y)))  );
        }

    public:
        void push(const Point &p)
        {
            for (size_t i = 0; i < points.size(); i++)
            {
                if (dist(points[i], p) < 7.f)
                {
                    points.push_back(points[i]);

                    return;
                }
            }

            points.push_back(p);
        }

        void pop()
        {
            if (points.size() > 0)
                points.pop_back();
        }

        void clear()
        {
            points.clear();
        }

        Point v(int index)
        {
            return points[index];
        }

        size_t size()
        {
            return points.size();
        }

        void triangulate()
        {
            vector<Point> a;

            for (size_t i = 0; i < points.size(); i++)
            {
                a.push_back(points[i]);
            }

            points.clear();

            for (size_t t = a.size() - 1, i = 0, j = 1; i < a.size(); t = i++, j = (i + 1) % a.size())
            {
                if (a.size() == 3)
                {
                    points.push_back(a[0]);
                    points.push_back(a[1]);
                    points.push_back(a[2]);

                    break;
                }

                if (isVertexEar(i, a))
                {
                    points.push_back(a[t]);
                    points.push_back(a[i]);
                    points.push_back(a[j]);

                    a.erase(a.begin() + i, a.begin() + i + 1);

                    t = a.size() - 1;
                    i = 0;
                    j = 1;
                }
            }
        }
};
白况 2024-11-23 04:38:14

下面一行代码有错误。该行位于类的 push() 函数的 for 循环中:

points.push_back(points[i]);

您没有传递推送的 Point,而是一个空元素向量本身。我将线路更改为

points.push_back(p);

并且有效。

The code has an error on the line below. The line is in the for loop in the push() function of your class:

points.push_back(points[i]);

You are not passing the pushed Point, but an empty element of the vector itself. I changed the line to

points.push_back(p);

and it worked.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文