zoukankan      html  css  js  c++  java
  • 扫描线--通用多边形填充算法

    扫描线--通用多边形填充算法
    该算法有几个可学习的地方:
    (1)正负1思想
    (2)对边界条件的处理
    (3)数据结构的选择

    code:
    sweep.h

    #ifndef SWEEP_H
    #define SWEEP_H

    struct Edge {
        int nxty;
        int curx;
        int dx, dy; // 所在扫描线的增量
        Edge *nxt;
    };

    //扫描线主算法
    void sweep(int p[][2], int n, void (*setPixel)(int, int));
    #endifsweep.cpp
    #include "sweep.h"
    #include <algorithm>
    using namespace std;

    const int MAXN = 1024;

    int cp[MAXN][2], n;
    inline bool cmp(int i, int j) {
        return cp[i][1] < cp[j][1] || (cp[i][1] == cp[j][1] && cp[i][0] < cp[j][0]);
    }


    Edge * e[MAXN], *h, *ph, *data;
    void insert(int ly, int px, int ind) {
        int y1,y2,y, nxt, pre, flag=0;

        nxt = (ind + 1) % n; pre = (ind - 1 + n) % n;
        y = cp[ind][1]; y1 = cp[nxt][1]; y2 = cp[pre][1];
        if (y1 > y2) swap(y1, y2);
        if (y1 < y && y < y2) {
            //需缩短一个单位
            flag = 1;
        }

        h = e[ly]; ph=NULL;
        while (h) {
            if (h->dy > cp[ind][1] || (h->dy == cp[ind][1] && h->dx > cp[ind][0])) break;
            ph = h;
            h = h->nxt;
        }
        
        data = new Edge;
        data->curx = px; data->nxty = cp[ind][1]; data->dx = cp[ind][0] - px; data->dy = cp[ind][1] - ly; data->nxt = NULL;
        if (flag) data->nxty--;

        if (ph) {    
            data->nxt = ph->nxt;
            ph->nxt = data;
        } else {
            data->nxt = e[ly];
            e[ly] = data;
        }
        

    }

    int ex[MAXN][MAXN], ne[MAXN];
    inline int abs(int a) {
        return a > 0 ? a : -a;
    }
    void makepoint(int line, Edge *h) {
        int dx = h->dx, dy = h->dy, cnt=0;
        int x, y, flag=1;
        if ((h->dx)*(h->dy)<0) flag=0;
        for (y=line, x=h->curx; y<=h->nxty; y++) {
            ex[y][ne[y]++] = x;
            cnt += 2*abs(dx);
            while (cnt>=2*abs(dy)) {
                cnt -= 2*abs(dy);
                if (flag) x++;
                else x--;
            }
        }
    }

    void sweep(int p[][2], int nn, void (*setPixel)(int, int)) {
        //对所有点按y坐标递增排序,y坐标相等的按x坐标递增排序
        n = nn;
        int i, j, k, ind, nxt, pre;
        int *num = new int[n];    //点索引;
        for (i=0; i<n; i++) num[i] = i;
        memcpy(cp, p, sizeof(cp));
        sort(num, num+n, cmp);

        //建立有序边表
        memset(e, 0, sizeof(e));
        for (i=0; i<n; i++) {
            ind = num[i];
            nxt = (ind + 1) % n;
            pre = (ind - 1 + n) % n;
            if (p[nxt][1] > p[ind][1]) insert(p[ind][1], p[ind][0], nxt);
            if (p[pre][1] > p[ind][1]) insert(p[ind][1], p[ind][0], pre);
        }

        //处理active edge list
        memset(ne, 0, sizeof(ne));
        for (i=0; i<MAXN; i++) {
            h = e[i]; ph = NULL;

            while (h) {
                makepoint(i, h);
                h = h->nxt;
            }
            sort(ex[i], ex[i]+ne[i]);
            for (j=0; j<ne[i]; j+=2)
                for (k=ex[i][j]; k<=ex[i][j+1]; k++)
                    setPixel(k,i);
        }

    }sweepline.cpp
    #include <stdlib.h>
    #include <stdio.h>
    #include <GL/glut.h>
    #include "sweep.h"

    void myInit();

    void setPixel(int x, int y);

    void myDisplay();

    int main(int argc, char **argv) {
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
        glutInitWindowSize(640, 480);
        glutInitWindowPosition (100, 150);
        glutCreateWindow("SweepLine");
        glutDisplayFunc(myDisplay);
        myInit();
        glutMainLoop();
        return 0;
    }


    void setPixel(int x, int y) {
        glBegin(GL_POINTS);
        glVertex2i(x, y);
        glEnd();
    }

    void myInit() {
        glClearColor(1.0, 1.0, 1.0, 0.0);
        glColor3f(0.0, 0.0, 0.0);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluOrtho2D(0.0, 640.0, 0.0, 480.0);
    }


    void myDisplay() {
        int i, j;
        glClear(GL_COLOR_BUFFER_BIT);
        int p[5][2];
        p[0][0] = 100; p[0][1] = 300;
        p[1][0] = 200; p[1][1] = 50;
        p[2][0] = 300; p[2][1] = 100;
        p[3][0] = 400; p[3][1] = 0;
        p[4][0] = 350; p[4][1] = 470;
        sweep(p, 5, setPixel);
        glFlush();
    }

    http://zhidao.baidu.com/question/40582214.html
  • 相关阅读:
    Apache开启Rewrite环境
    php 写入和读取序列化的cookie
    discuzx 制作单页面
    php 操作postgresql
    已安装php动态安装pdo_mysql
    PHP 异步调用 后台调用 持续执行 断开连接/浏览器
    ssh配置文件详解
    gdb 调试中No symbol in current context 故障定位
    Linking fails : relocation truncated to fit: R_X86_程序占用内存大于2GB所导致的问题
    谨慎使用单精度/双精度数值类型
  • 原文地址:https://www.cnblogs.com/cutepig/p/1603577.html
Copyright © 2011-2022 走看看