清華計算幾何-ConvexHull(凸包)-求極點InTriangle/ToLeft Test

ConvexHull(凸包)

凸包是什么

凸包是計算幾何一個非常基礎核心的概念。我理解的凸包就是給定一個點集合, 最外圍的點的包圍體就是凸包。如下所示:

極點(ExtremityPoint)

給定的點集合中, 如果一個點存在一條直線, 讓其他所有點都在于該直線的同一側, 則該點為極點。

非極點

和極點性質相反, 經過該點任一直線都無法做到讓其他所有點位于同一側

凸集合

給定一個點集合S = [P1, P2...Pn], 給每個點分配一個權重rx,? 滿足條件:

[1]rx >= 0 &&rx <= 1,?

[2]r1 + r2 +? ...... rn = 1.0

由 P = r1 * P1 + ..... + Pn * rn 計算公式,? 得到新的點集合,成為S的凸組合.

我理解的是點S構成的凸包內部的點集合就是凸組合。

凸相關

給定一個點集合S, 加入一個點A后,凸組合沒變化的,就稱點A和點集合S是凸相關的。

換一個說法就是, 點A包含在集合S里的凸組合里。

比如給定點S = {1, 4}, 點2或者點3和集合S是凸相關。

凸無關

給定一個點集合S, 加入一個點A后,凸組合發生變化,?就稱點A和點集合S是凸無關。

對于點集合S(1, 2, 3), 點4是凸無關.

給定點集合求極點

分解問題

極點滿足: 不在點集合構成的所有三角形內部的點, 則為極點。反之為非極點。

偽代碼實現

算法復雜度為O(n4)

算法實現

In-Trianle-Test

In-Trianle-Test: 判斷一個點是否在一個三角形內.

如果點S在三角形三條邊的同一側, 則在三角形內. 分解為三次ToLeft測試,即點和三角形的三條邊的測試.

ToLeft測試

ToLeft測試就是用于判斷點是否在一條邊的左側.

叉積面積正負來判斷左側 or 右側

(CCW 的時候ToLeft 世界左側返回True,?CW的時候ToLeft 世界左側返回False)

代碼實現

給定點集合

代碼實現

#include <iostream>
#include <vector>using namespace std;struct Point
{float x;float y;
};float Area2(const Point& inPointA, const Point& inPointB, const Point& inPointC)
{float value =inPointA.x * inPointB.y - inPointA.y * inPointB.x+ inPointB.x * inPointC.y - inPointB.y * inPointC.x+ inPointC.x * inPointA.y - inPointC.y * inPointA.x;return value;
}bool IsLeftTest(const Point& inPointA, const Point& inPointB, const Point& inPointC)
{return Area2(inPointA, inPointB, inPointC) > 0;
}bool IsInTrianle(const Point& inPoint, const Point& triangleA, const Point& triangleB, const Point& triangleC)
{bool bLeftA = IsLeftTest(triangleA, triangleB, inPoint);bool bLeftB = IsLeftTest(triangleB, triangleC, inPoint);bool bLeftC = IsLeftTest(triangleC, triangleA, inPoint);return (bLeftA == bLeftB) && (bLeftB == bLeftC);
}void GetConvexPointSet(const vector<Point>& inPoints, vector<Point>& outPoints)
{int pointNum = inPoints.size();vector<bool> extrmeFlags;extrmeFlags.resize(pointNum);for (int index = 0; index < pointNum; index++){extrmeFlags[index] = true;}// O(n4)for (int idxA = 0; idxA < pointNum; idxA++){for (int idxB = idxA + 1; idxB < pointNum; idxB++){for (int idxC = idxB + 1; idxC < pointNum; idxC++){for (int s = 0; s < pointNum; s++){if (s == idxA || s == idxB || s == idxC || !extrmeFlags[s])continue;if (IsInTrianle(inPoints[s], inPoints[idxA], inPoints[idxB], inPoints[idxC])){extrmeFlags[s] = false;}}}}}for (int index = 0; index < pointNum; index++){if (extrmeFlags[index]){outPoints.push_back(inPoints[index]);}}}int main()
{std::cout << "Hello World!\n";// point set contructvector<Point> inPoints ={{0, 0},{-1, -1},{5, 2},{4, 5},{3, 3},{-1, 3},{2, 2},{-3, 2},};vector<Point> outPoints;GetConvexPointSet(inPoints, outPoints);for (int index = 0; index < outPoints.size(); index++){printf("(%f, %f)\n", outPoints[index].x, outPoints[index].y);}}
運行結果

很顯然漏掉了 (-1, -1, -1, -1)

原因是(-1, -1), (0, 0) (2, 2), (3, 3)四點共線導致ToLeft測試失效,誤認為也在三角形內部。所以得改進檢測算法。

改進In-Trianle-Test

在進行In-Trianle-Test的時候先判斷是否四點共線, 然后在進行ToLeftTest

bool IsInTrianle(const Point& inPoint, const Point& triangleA, const Point& triangleB, const Point& triangleC)
{float a_area2 = Area2(triangleA, triangleB, inPoint);float b_area2 = Area2(triangleB, triangleC, inPoint);float c_area2 = Area2(triangleC, triangleA, inPoint);if (a_area2 == 0 && b_area2 == 0 && c_area2 == 0)return false;bool bLeftA = a_area2 > 0;bool bLeftB = b_area2 > 0;bool bLeftC = c_area2 > 0;// 取決于CCW/CWreturn (bLeftA == bLeftB) && (bLeftB == bLeftC);
}
運行結果

參考資料

[1]清華計算幾何?P1-P12

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/45084.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/45084.shtml
英文地址,請注明出處:http://en.pswp.cn/web/45084.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何理解electron 的預加載腳本

在 Electron 應用中,預加載腳本(Preload Script)是一個非常重要的概念,它允許你在渲染進程(web 頁面)和主進程之間創建一個安全的橋梁。預加載腳本運行在 Node.js 環境中,但位于渲染進程的一個單獨的上下文中,這意味著它可以訪問 Node.js 的 API,但無法直接訪問 DOM。…

JavaScript進階(7) ----構造函數和原型對象

目錄 構造函數 prototype 定義&#xff1a; 使用場景&#xff1a; constructor 使用場景&#xff1a; 原型proto 原型鏈 定義 特點 instanceof 運算符 原型繼承的基本概念 在JavaScript中&#xff0c;構造函數和原型是面向對象編程的核心概念&#xff0c;它們共同構…

海康工業相機驅動

1.新建基于對話框的MFC程序&#xff0c;界面布局如下 2.修改控件ID&#xff0c;為控件綁定變量 3.創建全局變量&#xff0c;構造函數中初始化變量&#xff0c;初始化對話框界面&#xff0c;補齊各控件按鈕響應函數 全文程序如下&#xff1a; // MFC_GrabimageDlg.h : 頭文件 /…

【動態規劃Ⅰ】斐波那契、爬樓梯、楊輝三角

動態規劃—斐波那契系列 什么是動態規劃斐波那契數組相關題目509. 斐波那契數 Easy1137. 第 N 個泰波那契數 Easy 楊輝三角118. 楊輝三角 Easy 爬樓梯相關題目70. 爬樓梯 Easy746. 使用最小花費爬樓梯 Easy 什么是動態規劃 動態規劃是一種通過將原問題分解為相對簡單的子問題來…

linux下解壓命令

在Linux下&#xff0c;解壓縮文件通常涉及多種命令&#xff0c;具體取決于文件的壓縮格式。以下是一些常用的解壓縮命令&#xff1a; tar.gz / .tgz 如果文件擴展名為 .tar.gz 或 .tgz&#xff0c;你可以使用 tar 命令來解壓縮&#xff1a; tar -xzf filename.tar.gz這里的 -x …

近期幾首小詩匯總-生活~卷

生活 為生活飄零&#xff0c;風雨都不阻 路見盲人艱&#xff0c;為她心點燈 賀中科大家長論壇成立十五周年 科學家園有喜賀 園外丑漢翹望中 曾一學子入我科 正育科二盼長大 憧憬也能入此家 與科學家論短長 園外翹首聽高論 發現有隙入此壇 竟然也能注冊成 入園瀏覽惶然立 此貼…

系統架構的基礎:定義、原則與發展歷程

目錄 1. 系統架構的定義 2. 系統架構的基本組成部分 2.1 架構層次 2.2 架構視圖 2.3 架構原則 3. 系統架構的發展歷程 3.1 初期階段:單體架構(Monolithic Architecture) 3.2 面向對象和組件化階段 3.3 客戶端-服務器架構(Client-Server Architecture) 3.4 三層架…

在 Linux 上使用 lspci 命令查看 PCI 總線硬件設備信息

lspci 命令用于顯示 Linux 系統上的設備和驅動程序 當在個人電腦或服務器上運行 Linux 時&#xff0c;有時需要識別該系統中的硬件。lspci 命令用于顯示連接到 PCI 總線的所有設備&#xff0c;從而滿足上述需求。該命令由 pciutils 包提供&#xff0c;可用于各種基于 Linux 和…

JAVA中的回溯算法解空間樹,八皇后問題以及騎士游歷問題超詳解

1.回溯算法的概念 回溯算法顧名思義就是有回溯的算法 回溯算法實際上一個類似枚舉的搜索嘗試過程&#xff0c;主要是在搜索嘗試過程中尋找問題的解&#xff0c;當發現已不滿足求解條件時&#xff0c;就“回溯”返回&#xff0c;嘗試別的路徑。回溯法是一種選優搜索法&#xff…

E12.【C語言】練習:求兩個數的最大公約數

1.枚舉 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main() {int a 0;int b 0;int tmp 0;scanf("%d %d", &a, &b);if (a < b){for (int i1; i < a; i){if (0a% i && 0b%i)tmp i;}}if (a>b){for (int i 1; i <…

[線性RNN系列] Mamba: S4史詩級升級

前言 iclr24終于可以在openreview上看預印本了 這篇&#xff08;可能是顛覆之作&#xff09;文風一眼c re組出品&#xff1b;效果實在太驚艷了&#xff0c;實驗相當完善&#xff0c;忍不住寫一篇解讀分享分享。 TL;DR &#xff08;overview&#xff09; Structured State-Sp…

Nginx 日志統計分析命令

統計訪問量最多的IP地址&#xff1a; awk {print $1} /path/to/nginx/access.log | sort | uniq -c | sort -nr | head -n 10統計不同狀態碼的出現次數&#xff1a; awk {print $9} /path/to/nginx/access.log | sort | uniq -c | sort -nr統計訪問量最多的URL&#xff1a; awk…

SQL Server端口配置指南

SQL Server是微軟推出的關系型數據庫管理系統&#xff0c;它支持多種操作系統平臺。默認情況下&#xff0c;SQL Server使用TCP/IP協議的1433端口進行通信。然而&#xff0c;出于安全或其他考慮&#xff0c;我們可能需要更改SQL Server實例的默認端口。本文將指導你如何更改SQL …

利率債與信用債的區別及其與債券型基金的關系

利率債與信用債的定義及其區別 定義 利率債&#xff1a; 定義&#xff1a;利率債是指由主權或類主權主體&#xff08;如中華人民共和國財政部、國家開發銀行等&#xff09;發行的債券。這些債券通常被認為沒有信用風險&#xff0c;因為它們由國家信用背書。特點&#xff1a;由…

【Python】 深入了解 Python 字典的 | 更新操作

我白天是個 搞笑廢物 表演不在乎 夜晚變成 憂傷怪物 撕扯著孤獨 我曾經是個 感性動物 小心地感觸 現在變成 無關人物 &#x1f3b5; 張碧晨/王赫野《何物》 Python 3.9 引入了一種新的字典更新操作&#xff0c;即使用 | 運算符合并字典。這種方式不僅簡潔…

xshell公鑰免密登錄

設備&#xff1a;一臺linux系統機器&#xff0c;一臺windows系統機器 軟件&#xff1a;xshell 要求&#xff1a;公鑰免密登錄 一、生成公鑰、私鑰 1、打開shell &#xff1b; 點擊工具 &#xff1b; 新建用戶生成密鑰向導 2、生成密鑰參數 密鑰類型&#xff1a;RS…

element ui ts table重置排序

#日常# 今天帶的實習生&#xff0c;在遇到開發過程中&#xff0c;遇到了element ui table 每次查詢的時候都需要重置排序方式&#xff0c;而且多個排序是由前端排序。 <el-table :data"tableData" ref"restTable"> </<el-table> <script…

bi項目筆記

1.bi是什么 bi項目就是商業智能系統&#xff0c;也就是數據可視畫、報表可視化系統&#xff0c;如下圖的就是bi項目了 2.技術棧

Linux rsync文件同步工具

scp的不足 1. 性能問題 單線程傳輸 SCP只使用單線程進行傳輸&#xff0c;這意味著在傳輸大文件或大量小文件時&#xff0c;其傳輸速度和效率可能不如其他多線程工具。 無法壓縮數據傳輸 SCP不支持內置的壓縮機制&#xff0c;這在傳輸大文件時會導致帶寬使用效率較低。 2.…

我花了5年時間訓練自己這種能力,希望你也能成功

人生最重要的能力是日拱一卒&#xff0c;即每天做一點點對自己有利的事并持續足夠長的時間。作者之前急于求成&#xff0c;減肥失敗。同事通過每月改進一件小事成功減肥且知識儲備豐富。作者受啟發后&#xff0c;通過走樓梯、換代糖等小改變&#xff0c;用 4 年減了 40 斤&…