以下是Voronoi分割算法的C ++代码示例:

#include <iostream>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;

struct Point {
    double x, y;
    Point(double _x, double _y) : x(_x), y(_y) {}
};

struct Edge {
    Point start, end;
    Edge(Point _s, Point _e) : start(_s), end(_e) {}
};

struct Event {
    double x;
    Point p;
    int type;
    Event(double _x, Point _p, int _t) : x(_x), p(_p), type(_t) {}
    bool operator<(const Event& other) const {
        return x < other.x;
    }
};

struct Site {
    Point p;
    int sitenum;
    Site(double x, double y, int n) : p(x, y), sitenum(n) {}
};

struct SiteCompare {
    bool operator()(const Site& l, const Site& r) const {
        if (l.p.y < r.p.y) return true;
        else if (l.p.y == r.p.y && l.p.x < r.p.x) return true;
        else return false;
    }
};

struct GraphEdge {
    double x1, y1, x2, y2;
    int site1, site2;
    GraphEdge(double _x1, double _y1, double _x2, double _y2, int s1, int s2) : x1(_x1), y1(_y1), x2(_x2), y2(_y2), site1(s1), site2(s2) {}
};

class Voronoi {
private:
    vector<double> site_x, site_y;
    vector<Site> sites;
    priority_queue<Event> eventqueue;
    vector<Edge> edges;
    vector<Point> vertices;
    vector<int> edgecnt;
    double xmin, xmax, ymin, ymax, deltax, deltay;
    int siteidx;
    vector<vector<int>> neighbors;
    vector<bool> processed;
    vector<GraphEdge> graphedges;

    void push_site(double x, double y) {
        site_x.push_back(x);
        site_y.push_back(y);
        siteidx++;
    }

    void read_sites() {
        double x, y;
        while (cin >> x >> y) {
            push_site(x, y);
        }
    }

    void compute_bounding_box() {
        xmin = site_x[0];
        xmax = site_x[0];
        for (int i = 1; i < siteidx; i++) {
            if (site_x[i] < xmin) xmin = site_x[i];
            if (site_x[i] > xmax) xmax = site_x[i];
        }
        deltax = xmax - xmin;

        ymin = site_y[0];
        ymax = site_y[0];
        for (int i = 1; i < siteidx; i++) {
            if (site_y[i] < ymin) ymin = site_y[i];
            if (site_y[i] > ymax) ymax = site_y[i];
        }
        deltay = ymax - ymin;
    }

    void initialize() {
        siteidx = 0;
        read_sites();
        compute_bounding_box();
        int n = site_x.size();
        for (int i = 0; i < n; i++) {
            sites.push_back(Site(site_x[i], site_y[i], i));
        }
        sort(sites.begin(), sites.end(), SiteCompare());
        processed.resize(n, false);
        neighbors.resize(n);
    }

    void insert_event(double x, double y) {
        Point p(x, y);
        eventqueue.emplace(x, p, 0);
    }

    bool circle(Point a, Point b, Point c, double& x, double& y, double& r) {
        double x1 = a.x;
        double y1 = a.y;
        double x2 = b.x;
        double y2 = b.y;
        double x3 = c.x;
        double y3 = c.y;

        double fabsy1y2 = abs(y1 - y2);
        double fabsy2y3 = abs(y2 - y3);

        if (fabsy1y2 < 1e-6 && fabsy2y3 < 1e-6) return false;

        double xc, yc;
        if (fabsy1y2 < 1e-6) {
            double m2 = -((x3 - x2) / (y3 - y2));
            double mx2 = (x2 + x3) / 2.0;
            double my2 = (y2 + y3) / 2.0;
            xc = (x2 + x1) / 2.0;
            yc = m2 * (xc - mx2) + my2;
        }
        else if (fabsy2y3 < 1e-6) {
            double m1 = -((x2 - x1) / (y2 - y1));
            double mx1 = (x1 + x2) / 2.0;
            double my1 = (y1 + y2) / 2.0;
            xc = (x3 + x2) / 2.0;
            yc = m1 * (xc - mx1) + my1;
        }
        else {
            double m1 = -((x2 - x1) / (y2 - y1));
            double m2 = -((x3 - x2) / (y3 - y2));
            double mx1 = (x1 + x2) / 2.0;
            double mx2 = (x2 + x3) / 2.0;
            double my1 = (y1 + y2) / 2.0;
            double my2 = (y2 + y3) / 2.0;
            xc = (m1 * mx1 - m2 * mx2 + my2 - my1) / (m1 - m2);
            yc = m1 * (xc - mx1) + my1;
        }

        x = xc;
        y = yc;
        r = sqrt(pow(x1 - xc, 2) + pow(y1 - yc, 2));
        return true;
    }

    void process_event() {
        while (!eventqueue.empty()) {
            Event e = eventqueue.top();
            if (e.type == 0) {
                insert_site_event(e);
            }
            else {
                insert_circle_event(e);
            }
            eventqueue.pop();
        }
    }

    void insert_site_event(Event e) {
        Site newsite(e.p.x, e.p.y, siteidx++);
        edges.push_back(Edge(newsite.p, newsite.p));
        int ns = sites.size();
        for (int i = 0; i < ns; i++) {
            double dx = newsite.p.x - sites[i].p.x;
            double dy = newsite.p.y - sites[i].p.y;
            double dist = sqrt(dx*dx + dy*dy);
            edges.push_back(Edge(newsite.p, sites[i].p));
            edges.push_back(Edge(sites[i].p, newsite.p));
            if (dist > 0) {
                if (circle(sites[i].p, newsite.p, Point(e.p.x, e.p.y), edges.back().start.x, edges.back().start.y, edges.back().end.x)) {
                    edges.pop_back();
                    edges.pop_back();
                }
            }
        }
        sites.push_back(newsite);
    }

    void insert_circle_event(Event e) {
        int i = e.arc;
        if (i > 0 && i < siteidx - 1) {
            int left = -1, right = -1;
            if (check_circle_event(i, left, right, e.p.x)) {
                Point lp = sites[left].p;
                Point rp = sites[right].p;
                double x, y, r;
                circle(lp, sites[i].p, rp, x, y, r);
                vertices.push_back(Point(x, y));
                eventqueue.emplace(x, Point(x, y), 1);
                edges.push_back(Edge(lp, rp));
                edgecnt.push_back(0);
                int nedges = edges.size();
                graphedges.emplace_back(lp.x, lp.y, rp.x, rp.y, i, -1);
                for (int j = 0; j < nedges - 1; j++) {
                    if ((edges[j].start == edges.back().start && edges[j].end == edges.back().end) ||
                        (edges[j].start == edges.back().end && edges[j].end == edges.back().start)) {
                        edgecnt[j]++;
                        edgecnt.back()++;
                        graphedges.back().site2 = j / 2;
                        graphedges[j / 2].site2 = i;
                    }
                }
            }
        }
    }

    bool check_circle_event(int i, int& left, int& right, double& x) {
        int n = sites.size();
        left = i - 1;
        right = i + 1;
        bool ileft = false, iright = false;
        double xleft, xright;
        while (left >= 0 && processed[left] == false) {
            double a = intersection_point(i, left);
            if (a > x) {
                xleft = a;
                ileft = true;
                break;
            }
            left--;
        }
        if (left < 0) {
            xleft = xmin;
        }
        while (right < n && processed[right] == false) {
            double a = intersection_point(i, right);
            if (a > x) {
                xright = a;
                iright = true;
                break;
            }
            right++;
        }
        if (right == n) {
            xright = xmax;
        }
        if (ileft && iright) {
            x = (xleft + xright) / 2;
            return true;
        }
        return false;
    }

    double intersection_point(int i, int j) {
        Site si = sites[i];
        Site sj = sites[j];
        double yi = si.p.y;
        double yj = sj.p.y;
        double xi = si.p.x;
        double xj = sj.p.x;
        double slopei = (xj - xi) / (yi - yj);
        double slopej = (xi - xj) / (yj - yi);
        double x = (si.p.x + sj.p.x + slopei*si.p.y - slopej*sj.p.y) / (slopei - slopej);
        return x;
    }

    void finish_edges() {
        int n = edges.size();
        for (int i = 0; i < n; i++) {
            if (edgecnt[i] == 1) {
                edges[i].end = vertices.size() > 0 ? vertices.back() : Point(NAN, NAN);
                vertices.push_back(Point(NAN, NAN));
            }
        }
    }

    void build_graph() {
        int nedges = edges.size();
        for (int i = 0; i < nedges; i++) {
            if (!isnan(edges[i].end.x)) {
                int s1 = edges[i].start.sitenum;
                int s2 = edges[i].end.sitenum;
                graphedges.emplace_back(edges[i].start.x, edges[i].start.y, edges[i].end.x, edges[i].end.y, s1, s2);
                neighbors[s1].push_back(graphedges.size() - 1);
                graphedges.emplace_back(edges[i].end.x, edges[i].end.y, edges[i].start.x, edges[i].start.y, s2, s1);
                neighbors[s2].push_back(graphedges.size() - 1);
            }
        }
    }

public:
    Voronoi() {}

    void compute() {
        initialize();
        insert_event(xmin - deltax, ymin - deltay);
        insert_event(xmin - deltax, ymax + deltay);
        insert_event(xmax + deltax, ymin - deltay);
        insert_event(xmax + deltax, ymax + deltay);
        process_event();
        finish_edges();
        build_graph();
    }

    vector<Point> get_vertices() {
        return vertices;
    }

    vector<GraphEdge> get_edges() {
        return graphedges;
    }

    vector<vector<int>> get_neighbors() {
        return neighbors;
    }
};

int main() {
    Voronoi v;
    v.compute();
    return 0;
}
``
Voronoi 分割算法c++代码

原文地址: https://www.cveoy.top/t/topic/emNP 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录