国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【W(wǎng)eiler-Atherton算法】 計算機圖形學多邊形裁剪算法

這篇具有很好參考價值的文章主要介紹了【W(wǎng)eiler-Atherton算法】 計算機圖形學多邊形裁剪算法。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。


源代碼: https://github.com/ricar0/Weiler-Atherton-Alogrithm/tree/master

什么是多邊形裁剪

通常來說就是利用多邊形來裁剪多邊形的一種方法,一般情況下是利用矩形來裁剪凹凸多邊形

  1. 凸多邊形
    【W(wǎng)eiler-Atherton算法】 計算機圖形學多邊形裁剪算法
  2. 凹多邊形
    【W(wǎng)eiler-Atherton算法】 計算機圖形學多邊形裁剪算法
    上面紅色劃線部分就是裁剪出的部分

前置知識

  1. OPENGL基礎(chǔ)語法
    基本上就是一些畫線和畫多邊形的操作,難度較低
  2. 求兩直線交點
    較為基礎(chǔ)的數(shù)學知識
  3. 求一個點是否落在多邊形內(nèi)/外
    計算幾何知識
  4. Weiler-Atherton多邊形裁剪算法

這里著重介紹Weiler-Atherton算法,其余不懂的可以先學會再看。

算法步驟

  1. 首先繪制兩個相交的多邊形
  2. 對于多邊形1,我們從一個點出發(fā),將所有經(jīng)過的點(包含交點)存入新的數(shù)組中,對于多邊形2也是同理
  3. 對兩個新數(shù)組中的相同點進行點對映射
  4. 開始對裁剪多邊形1進行遍歷,從任意點出發(fā),如果改點將從多邊形2的內(nèi)部穿越到外部,我們改變遍歷點的對象,從多邊形2開始遍歷,依次類推…
  5. 直到當前點被遍歷過,那么之前肯定形成了一個回路,我們將當前回路繪制出來就是裁剪出的多邊形。
  6. 一直重復(fù)4和5操作,直到所有點都被遍歷

接下來結(jié)合圖片解釋一下

【W(wǎng)eiler-Atherton算法】 計算機圖形學多邊形裁剪算法
對于如下這個圖,我們利用矩形裁剪凹多邊形。
首先從E點出發(fā),判斷E到J是否為出點,發(fā)現(xiàn)不是。遍歷到J點,判斷JF是否是出點,發(fā)現(xiàn)是,這時候改變遍歷的對象,通過映射關(guān)系從K點開始。判斷發(fā)現(xiàn)KC又是出點,因此再次改變遍歷對象,遍歷多邊形到E,發(fā)現(xiàn)J已經(jīng)被遍歷過,這時直接繪制出JKE…

程序框圖

【W(wǎng)eiler-Atherton算法】 計算機圖形學多邊形裁剪算法

代碼實現(xiàn)

建立窗口以及自動調(diào)整大小

void reshape(int w, int h) {
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60.0, (GLfloat)w / (GLfloat)h, 0.1, 100000.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0, 0, 25, 0, 0, -1, 0, 1, 0);
}
int main(int argc,char** argv) {
    glutInit(&argc, const_cast<char**>(argv));
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    // 初始化窗口
    glutInitWindowSize(500, 500);
    glutInitWindowPosition(100, 100);
    glutCreateWindow(argv[0]);
    init();
    glutReshapeFunc(reshape);
    glutDisplayFunc(display);

    glutMainLoop();
}


建立點和線

struct Point2d {
    double x, y;
    bool operator < (const Point2d &rhs) const {
        if (x==rhs.x) return y < rhs.y;
        return x < rhs.x;
    }
};
struct Line{
    Point2d start;
    Point2d end;
};

求兩條線段交點的模板,如果不存在返回-inf

inline Point2d Vector(Point2d a, Point2d b) {  //向量ab
    return{ b.x - a.x, b.y - a.y };
}
double dis2(Point2d a, Point2d b) {          //兩點間的距離的平方
    return (b.x - a.x)*(b.x - a.x) + (b.y - a.y)*(b.y - a.y);
}
double cross(Point2d A, Point2d B, Point2d P) {  //向量的外積
    Point2d AB = Vector(A,B);
    Point2d AP = Vector(A,P);
    return AB.x*AP.y - AB.y*AP.x;
}
double dot(Point2d A, Point2d B, Point2d P) {     //向量的內(nèi)積
    Point2d AB = Vector(A,B);
    Point2d AP = Vector(A,P);
    return AB.x*AP.x + AB.y*AP.y;
}
int dir(Point2d A, Point2d B, Point2d P) {    //點與線段方位判定
    if (cross(A, B, P) > 0)  return -1;
    else if (cross(A, B, P)<0) return 1;
    else if (dot(A, B, P) < 0) return -2;
    else if (dot(A, B, P) >= 0)
    {
        if (dis2(A, B) < dis2(A, P)) return 2;
        else return 0;
    }
    return 0;
}
double disLine(Point2d A, Point2d B, Point2d P) {   //點P到直線AB的距離
    return fabs(cross(A, B, P)) / sqrt(dis2(A, B));
}
Point2d intersection(Line u, Line v) {
    Point2d A1 = u.start;
    Point2d A2 = u.end;
    Point2d B1 = v.start;
    Point2d B2 = v.end;
    if (dir(A1, A2, B1)*dir(A1, A2, B2) <= 0 && dir(B1, B2, A1)*dir(B1, B2, A2) <= 0) {//判斷有無交點
        double t = disLine(A1, A2, B1) / (disLine(A1, A2, B1) + disLine(A1, A2, B2));
        Point2d B1B2 = Vector(B1, B2);
        Point2d inter = { B1.x + B1B2.x*t, B1.y + B1B2.y*t };
        return {inter.x, inter.y};
    } else {
        return {-inf, -inf};
    }
}

求兩點距離,用于排序

double dis(Point2d point1, Point2d point2) {
    return sqrt((point1.x-point2.x)*(point1.x-point2.x) + (point1.y-point2.y)*(point1.y-point2.y));
}

判斷點是否落在多邊形內(nèi),這里加了個誤差0.001

bool isPointInsidePoly(Point2d P,const vector<Point2d>& polyVertices) {
    std::size_t vertCount = polyVertices.size();
    if (vertCount < 2)
        return false;
    Point2d tmp = P;
    for (int l = 0; l < 2; l++) {
        for (int r = 0; r < 2; r++) {
            P = tmp;
            if (l % 2) P.x += 0.001;
            else P.x -= 0.001;
            if (r % 2) P.y += 0.001;
            else P.y -= 0.001;
            bool inside = false;
            for (unsigned i = 1; i <= vertCount; ++i) {
                const Point2d &A = polyVertices[i - 1];
                const Point2d &B = polyVertices[i % vertCount];
                if ((B.y <= P.y && P.y < A.y) || (A.y <= P.y && P.y < B.y)) {
                    double t = (P.x - B.x) * (A.y - B.y) - (A.x - B.x) * (P.y - B.y);
                    if (A.y < B.y)
                        t = -t;
                    if (t < 0)
                        inside = !inside;
                }
            }
            if (inside) return inside;
        }
    }
    return false;
}

求交點以及重新放入數(shù)組

void getIntersections() {//求出所有交點以及按照順序存放在新數(shù)組中
    int len1 = poly1.size();//求出new1
    for (int i = 0; i < len1; i++) {
        new1.push_back(poly1[i]);
        vector<Point2d> tmp;
        for (auto it2 : p2) {
            Point2d p = intersection({{poly1[i].x, poly1[i].y},{poly1[(i+1)%len1].x, poly1[(i+1)%len1].y}}, it2);
            if (p.x != -inf && p.y != -inf) tmp.push_back({p.x, p.y});
        }
        sort(tmp.begin(), tmp.end(), [&](Point2d p1, Point2d p2){
            return dis(p1, poly1[i]) < dis(p2, poly1[i]);
        });
        for (auto it : tmp) new1.push_back(it);
    }

    int len2 = poly2.size();//求出new2
    for (int i = 0; i < len2; i++) {
        new2.push_back(poly2[i]);
        vector<Point2d> tmp;
        for (auto it2 : p1) {
            Point2d p = intersection({{poly2[i].x, poly2[i].y},{poly2[(i+1)%len2].x, poly2[(i+1)%len2].y}}, it2);
            if (p.x != -inf && p.y != -inf) tmp.push_back({p.x, p.y});
        }
        sort(tmp.begin(), tmp.end(), [&](Point2d p1, Point2d p2){
            return dis(p1, poly2[i]) < dis(p2, poly2[i]);
        });
        for (auto it : tmp) new2.push_back(it);
    }
    for (int i = 0; i < new1.size(); i++) {//映射關(guān)系,給定eps為誤差范圍
        for (int j = 0; j < new2.size(); j++) {
            if (fabs(new1[i].x-new2[j].x)<eps&&fabs(new1[i].y-new2[j].y)<eps) {
                pos1[i] = j;
                pos2[j] = i;
            }
        }
    }
    work();
}

繪制兩個多邊形以及初始化操作

void prework() {
    p1.clear();
    p2.clear();
    new1.clear();
    new2.clear();
    vis1.clear();
    vis2.clear();
    pos1.clear();
    pos2.clear();
}
void display() {
    prework();//初始化
    glClear(GL_COLOR_BUFFER_BIT);
    glBegin(GL_LINES);
    glColor3f(1.0, 1.0, 1.0);
    int len1 = poly1.size();//繪制多邊形
    for (int i = 0; i < len1; i++) {
        glVertex2f(poly1[i].x, poly1[i].y);
        glVertex2f(poly1[(i+1)%len1].x, poly1[(i+1)%len1].y);
        p1.push_back({{poly1[i].x, poly1[i].y}, {poly1[(i+1)%len1].x, poly1[(i+1)%len1].y}});
    }
    int len2 = poly2.size();
    for (int i = 0; i < len2; i++) {
        glVertex2f(poly2[i].x, poly2[i].y);
        glVertex2f(poly2[(i+1)%len2].x, poly2[(i+1)%len2].y);
        p2.push_back({{poly2[i].x, poly2[i].y}, {poly2[(i+1)%len2].x, poly2[(i+1)%len2].y}});
    }
    getIntersections();
    glEnd();
    glFlush();
}

最核心的代碼,遍歷兩個多邊形

void work() {
    vector<Point2d> now;//當前選擇到的點
    int len1 = new1.size();
    int len2 = new2.size();
    for (int i = 0; i < new1.size(); i++) {//new1 第一個新多邊形 new2第一個新多邊形
        if (vis1[i]) continue;
        int ch = 1, nowpos = i;
        while (1) {
            if (ch == 1) {//遍歷第一個多邊形
                if (isPointInsidePoly(new1[nowpos], poly2)) now.push_back(new1[nowpos]);
                if (vis1[nowpos]) {//如果該點遍歷過
                    glBegin(GL_LINES);
                    glColor3f(1, 0, 0);
                    for (int j = 0; j < now.size(); j++) {//繪制交多邊形
                        glVertex2f(now[j].x, now[j].y);
                        glVertex2f(now[(j+1)%now.size()].x, now[(j+1)%now.size()].y);
                    }
                    now.clear();
                    glEnd();
                    glFlush();
                    break;
                }
                vis1[nowpos] = true;//給當前經(jīng)歷點打上標記
                if (isPointInsidePoly(new1[nowpos], poly2) && !isPointInsidePoly(new1[(nowpos+1)%len1], poly2)) {//判斷是否為出點
                    ch = 2;
                    nowpos = pos1[nowpos];
                    nowpos = (nowpos + 1) % len2;
                } else {
                    nowpos = (nowpos + 1) % len1;
                }
            } else {//遍歷第二個多邊形
                if (isPointInsidePoly(new2[nowpos], poly1)) now.push_back(new2[nowpos]);
                if (vis2[nowpos]) {//如果該點遍歷過
                    glBegin(GL_LINES);
                    glColor3f(1, 0, 0);
                    for (int j = 0; j < now.size(); j++) {//繪制交多邊形
                        glVertex2f(now[j].x, now[j].y);
                        glVertex2f(now[(j+1)%now.size()].x, now[(j+1)%now.size()].y);
                    }
                    now.clear();
                    glEnd();
                    glFlush();
                    break;
                }
                vis2[nowpos] = true;//給當前點打上標記
                if (isPointInsidePoly(new2[nowpos], poly1) && !isPointInsidePoly(new2[(nowpos+1)%len2], poly1)) {//判斷是否為出點
                    ch = 1;
                    nowpos = pos2[nowpos];
                    nowpos = (nowpos + 1) % len1;
                } else {
                    nowpos = (nowpos + 1) % len2;
                }
            }
        }
    }
}

這里存入需要繪制的兩個多邊形,按順序存文章來源地址http://www.zghlxwxcb.cn/news/detail-405774.html

void init() {
    poly1.clear();
    poly2.clear();
//    poly1.push_back({-5, -5});
//    poly1.push_back({-5, 5});
//    poly1.push_back({5, 5});
//    poly1.push_back({5, -5});
//
//    poly2.push_back({-7, 0});
//    poly2.push_back({0, 7});
//    poly2.push_back({7, 0});
//    poly2.push_back({0, -7});

//    poly1.push_back({0, -6});
//    poly1.push_back({-3, -3});
//    poly1.push_back({0, 3});
//    poly1.push_back({3, 0});
//
//    poly2.push_back({0, -3});
//    poly2.push_back({-3, 3});
//    poly2.push_back({0, 6});
//    poly2.push_back({3, 3});

//    poly1.push_back({-8, -6});
//    poly1.push_back({-8,  6});
//    poly1.push_back({8, 6});
//    poly1.push_back({8, -6});
//
//    poly2.push_back({-2, 10});
//    poly2.push_back({12, -6});
//    poly2.push_back({-2, 2});
//    poly2.push_back({-12, -6});

    poly2.push_back({-6, -3});
    poly2.push_back({-6,  3});
    poly2.push_back({6, 3});
    poly2.push_back({6, -3});

    poly1.push_back({-1.98, 0.91});
    poly1.push_back({4, 6});
    poly1.push_back({12, 6});
    poly1.push_back({4, -2});
    poly1.push_back({8, 4.7});
    glClearColor(0.0, 0.3, 0.7, 0.0);
    glShadeModel(GL_SMOOTH);
}

到了這里,關(guān)于【W(wǎng)eiler-Atherton算法】 計算機圖形學多邊形裁剪算法的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 計算機博弈算法(Adversarial Search)

    計算機博弈算法(Adversarial Search)

    人機博弈是人工智能的重要分支,人們在這一領(lǐng)域探索的過程中產(chǎn)生了大量的研究成果,而 極小化極大算法(minimax) 是其中最基礎(chǔ)的算法,它由Shannon在1950年正式提出。 Alpha-beta剪枝 的本質(zhì)就是一種基于極小化極大算法的改進方法。Knuth等人在1975年優(yōu)化了算法,提出了 負極大

    2024年02月04日
    瀏覽(22)
  • 圖像處理與計算機視覺算法

    圖像處理與計算機視覺算法是實現(xiàn)對圖像和視頻內(nèi)容分析、理解和操作的一系列技術(shù)。這些算法可以分為多個類別,包括但不限于以下幾個主要方面: 預(yù)處理 : 像素操作:灰度化、二值化、直方圖均衡化等,用于改善圖像的對比度和亮度分布。 去噪:高斯濾波、中值濾波、

    2024年02月22日
    瀏覽(21)
  • 計算機算法設(shè)計與分析期末復(fù)習

    計算機算法設(shè)計與分析期末復(fù)習

    以下是我的部分算法筆記,希望可以給復(fù)習的小伙伴們參考一下: 題目: 一切合法的輸入數(shù)據(jù)都能得出滿足要求的結(jié)果,包括典型的、苛刻的輸入數(shù)據(jù)也能夠得出滿足要求的結(jié)果。這個含義對應(yīng)算法的(正確性) 算法要對異常情況進行適當?shù)奶幚?,就是算法的(健壯性?/p>

    2024年02月13日
    瀏覽(19)
  • 計算機操作系統(tǒng)——頁面置換算法

    計算機操作系統(tǒng)——頁面置換算法

    聲明 :本篇博客參考書籍《計算機操作系統(tǒng)》(西安電子科技大學出版社) 首先說說影響頁面換進換出的效率的幾個因素: (1)頁面置換算法。該因素是影響頁面換進換出效率的重要因素。一個好的頁面置換算法可以使進程在運行過程中具有較低的缺頁率,從而減少頁面換

    2024年02月07日
    瀏覽(35)
  • 計算機畢業(yè)分享(含算法) opencv圖像增強算法系統(tǒng)

    計算機畢業(yè)分享(含算法) opencv圖像增強算法系統(tǒng)

    今天學長向大家分享一個畢業(yè)設(shè)計項目 畢業(yè)設(shè)計 opencv圖像增強算法系統(tǒng) 項目運行效果: 畢業(yè)設(shè)計 基于機器視覺的圖像增強 項目獲取: https://gitee.com/sinonfin/algorithm-sharing 直方圖均衡化是通過調(diào)整圖像的灰階分布,使得在0~255灰階上的分布更加均衡,提高了圖像的對比度,達

    2024年01月18日
    瀏覽(41)
  • 計算機導論07-算法和數(shù)據(jù)結(jié)構(gòu)

    計算機導論07-算法和數(shù)據(jù)結(jié)構(gòu)

    算法是 為使用計算機解決問題而制定的運算序列,是解決實際問題的方法及步驟 ;在計算機科學中,算法研究應(yīng)用計算機程序處理問題的方法及其實現(xiàn)流程,是計算機問題解決方案的完整描述, 它是計算機科學的核心研究對象之一。 算法的概念 一般認為,算法(algorithm)

    2024年01月20日
    瀏覽(26)
  • 計算機視覺&多模態(tài)算法實習面試記錄

    計算機視覺&多模態(tài)算法實習面試記錄

    一面(12.20) 自我介紹:第一次面有點瓢嘴 介紹科研項目 如何使用的CLIP Open-vocab和zero-shot 介紹比賽項目——多模態(tài)行車數(shù)據(jù)視頻 介紹任務(wù)是什么 自定義數(shù)據(jù)集? Yolo v8 介紹CLIP: 對比學習訓練:一個batch的N張圖片和文本進行對比;首先分別進行編碼-再投影到相同特征維度

    2024年03月25日
    瀏覽(32)
  • 計算機視覺--距離變換算法的實戰(zhàn)應(yīng)用

    計算機視覺--距離變換算法的實戰(zhàn)應(yīng)用

    前言: Hello大家好,我是Dream。 計算機視覺CV是人工智能一個非常重要的領(lǐng)域 。 在本次的距離變換任務(wù)中,我們將使用 D4距離度量方法 來對圖像進行處理。通過這次實驗,我們可以更好地理解距離度量在計算機視覺中的應(yīng)用。希望大家對計算機視覺和圖像處理有了更深入的

    2024年02月15日
    瀏覽(25)
  • 計算機競賽 - 基于機器視覺的圖像拼接算法

    計算機競賽 - 基于機器視覺的圖像拼接算法

    圖像拼接在實際的應(yīng)用場景很廣,比如無人機航拍,遙感圖像等等,圖像拼接是進一步做圖像理解基礎(chǔ)步驟,拼接效果的好壞直接影響接下來的工作,所以一個好的圖像拼接算法非常重要。 再舉一個身邊的例子吧,你用你的手機對某一場景拍照,但是你沒有辦法一次將所有你

    2024年02月13日
    瀏覽(25)
  • 計算機視覺中各種歸一化算法

    計算機視覺中各種歸一化算法

    歸一化算法是對激活函數(shù)的輸入進行歸一化 將feature map shape設(shè)為[N,C,H,W],其中N表示batch size,C表示通道數(shù),H、W分別表示特征圖的高度、寬度 在batch上,對N、H、W做歸一化,保留通道C的維度。對較小的batch size效果不好,BN適用于固定深度的前向神經(jīng)網(wǎng)絡(luò),如CNN,不適用于RNN;

    2024年04月16日
    瀏覽(18)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包