線段與多邊形的關系

轉自周見智

介紹

最近項目中要用到有關幾何(Geometry)方面的知識,程序需要判斷給定的一條線段(Segment)與指定多邊形(Polygon)的位置關系。這種關系分為三種:多邊形包含線段、多邊形與線段相交以及多邊形與線段無關聯。

起初我以為.NET類庫中已經包含此種判定功能的API,比如類似System.Drawing.Region這些類型,后來等到實際要用的時候才發現根本就沒這種“高級”算法。

沒辦法,只能自己去寫代碼實現。后來在stackoverflow(鏈接)上找到了一個解決方案,不過都是源代碼,并沒有詳細的說明。本文參照原作者提供的源碼,進行詳細的說明。如果你只需要最終答案,可以不用閱讀本文所有內容,文章最后會給出判斷源代碼,很簡答使用,就一個方法,代入參數直接調用即可,但如果你想搞清楚怎么回事,那么可以靜下心來看看本文全部內容,雖然比較復雜,但是相信一定會有所收獲的。

?

解決思路

線段與多邊形的關系只有三種:無關聯、相交以及包含。我們可以分以下兩步來進行分析:

  • 判斷線段與多邊形的各條邊是否相交,若是,則線段與多邊形屬于“相交”關系;
  • 如果線段與多邊形的任何邊都不相交,那么我們接著判斷線段的任意一個端點是否在多邊形內部,若是,則整條線段肯定在多邊形內(即“包含”關系);若不是,則整條線段肯定都在多邊形外部(即“無關聯”關系)。

上面兩步看似簡單,實質相當復雜。判斷線段與多邊形各條邊的關系涉及到了“線段與線段關系的判斷”、判斷線段任意一個端點是否在多邊形內部涉及到了“點與線段關系的判斷”,總之,要解決大問題必須先解決一些小問題:

  • 點與線段的關系
  • 線段與線段的關系
  • 點與多邊形的關系

下面依次介紹以上三個小問題的解決方法。

?

問題一:點與線段的關系

點與線段只有兩種關系:

  • 點在線段上
  • 點與線段無關聯

這種判斷方法很簡單,只要我們能確保給定點P的Y坐標在線段AB兩個端點的Y坐標之間(或者點P的X坐標在兩個端點的X坐標之間也行),并且點P與線段AB任意端點間的斜率與AB線段斜率相等即可說明點P在線段AB上。

如上圖,如果Y2<Y<Y1且K==K1,則說明點P在線段AB上;否則,點P與線段AB無關聯。

?

問題二:線段與線段的關系

線段與線段也只有兩種關系:

  • 兩線段相交
  • 兩線段無關聯

這種判斷稍微復雜一些,為了更方便計算,涉及到了“平移”、“旋轉”等操作。給定線段AB和CD,先將兩線段整體平移(注意是整體),讓線段AB的A端點與原點(0,0)重合,接著將兩線段整體旋轉(注意是整體),讓線段AB與X軸的正方向重合。

如上圖,將任意兩線段AB和CD按照“先整體平移,再整體旋轉”的順序操作一遍,最終讓線段AB的A端點與原點(0,0)重合,并讓線段AB與X軸正方向重合。很顯然,任意線段均可以進行以上操作。接下來,再在此基礎上進行判斷就比較簡單了,如果線段CD的兩個端點C和D的Y坐標均大于零(分布在第一、二象限)或者均小于零(分布在第三、四象限),那么AB與CD肯定不相交,換句話說,CD的兩個端點必須一個在X軸上方另一個在X軸下方時,兩條線段才有可能相交。如果線段CD的端點確實是一個在X軸上方一個在X軸下方,接下來再計算直線AB和直線CD(注意這里說的是直線)的交點(這時候兩條直線一定有交點,并且交點在X軸上),這里暫定交點為P,如果P在X軸的負方向上(P.X<0),那么說明線段AB和CD不相交,如果P在X軸正方向但是P的X坐標大于線段AB的長度,那么說明線段AB和CD也不相交,其他情況下,線段AB和CD才屬于“相交”關系。

?

問題三:點與多邊形的關系

點與多邊形有三種關系:

  • 點與多邊形無關聯
  • 點在多邊形上(某條邊上)
  • 點在多邊形內部

判斷點是否在多邊形上需要用到解決問題一的方法,即判斷點與線段的關系。如果點不在多邊形上,那么需要判斷它在多邊形內部還是外部,這個判斷方法說難也不難,說不難也挺難的。事實上,只需要判斷點在多邊形每條邊的左邊還是右邊(注意這里的左邊和右邊定義,見下圖)

如上圖,多邊形ABCDE在右側光源的照射下,它的每條邊(如AB、BC等)都會與Y軸上各自的投影(如A`B`、B`C`等)之間形成一個梯形區域,如ABB`A`、BCC`B`等。我們只需要統計給定點P在這些梯形區域中的次數,若點P在某條邊對應的梯形區域內,那么計數N加1,最后看N是否為偶數,如果N為偶數(包括0),那么說明點P不在多邊形內部;否則,點P在多邊形內部。上圖中P1的計數N==1(只在ABB`A`內部),所以點P1在多邊形ABCDE內部,而點P2的計數N==2(同時在AEE`A`和BCC`B`內部),所以點P2不在多邊形ABCDE內部,同理,點P3的計數N==0,所以它也不在多邊形內部。

?

轉載于:https://www.cnblogs.com/P3nguin/p/9379654.html

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

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

相關文章

shell的交互式和非交互式登錄

工作中經常碰見環境變量加載問題&#xff0c;歸根結底就是配置文件的加載問題。 一般會有四種模式&#xff1a;交互式登陸、非交互式登陸、交互式非登陸、非交互非登陸。 交互式和非交互式對環境變量的加載: -------------------------------------------------- | …

運營商取消話費余額有效期后改收閑置費

摘要&#xff1a;截至昨天&#xff0c;北京的CDMA預付費手機用戶均收到了中國電信北京公司的短信通知。5月初&#xff0c;中國聯通正式取消有月租或有月最低消費的預付費產品的話費有效期。而邱寶昌認為&#xff0c;防止倒號和號碼資源浪費本應是運營商的責任&#xff0c;現在運…

內存柵欄的影響

當我們在使用jvm鎖的時候&#xff0c;一方面是為了減少線程的競爭&#xff0c;另外還有一方面就是保證共享數據的及時可見性。為了保證線程共享變量的可見性&#xff0c;會使用到內存柵欄&#xff0c;jvm設置內存柵欄&#xff0c;并將共享數據及時刷新到主存中保證其他線程可以…

hibernate連接數據庫配置

hibernate連接數據庫配置 1.連接mySql&#xff0c;文件配置如下&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://…

解決,文件上傳到 ftp 服務器,中文出現亂碼問題

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 上傳到 ftp 服務器&#xff0c;中文出現亂碼解決&#xff0c;之前文件名 “ 網關信息 ” 始終不能正確顯示&#xff0c;嘗試了多種編碼…

常用負載均衡策略分析

背景 一般生產環境單機所能承受的QPS壓力為2w左右&#xff0c;過大的壓力會導致服務器爆炸。即便是單機能夠撐住2w QPS&#xff0c;一般也不會這么做&#xff0c;生產環境一般會預留50%的冗余能力&#xff0c;防止QPS因為某個熱門的活動而爆炸。當QPS超過單機所能承受的壓力時&…

cpu id 系列號代碼

1。先看看是那家公司的cpu,有intel的&#xff0c;還有amd的和 cyrix的。全世界只有三家&#xff0c;實際就是兩家。 先讓EAX0&#xff0c;再調用CPUID Inel的CPU將返回: EBX:756E6547H Genu EDX:49656E69H ineI ECX:6C65746EH ntel EBX,EDX,E…

解決- SecureCRT上運行 linux vim 命令中文出現亂碼

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 亂碼如圖&#xff1a; 這個問題是CRT的編碼設置造成的&#xff0c;改一下設置就可以了&#xff1a; 1. 在當前連接上右鍵選擇最后一個 2…

開發一個自己的 CSS 框架(五)

這一期我們繼續完成我們的網格布局 容器類 通過一個 # 占位符&#xff0c;來減少代碼輸出量。 #containerpadding-right: 15pxpadding-left: 15pxmargin-right: automargin-left: auto.containerwidth: 100%extend #containermedia screen and (min-width: $media-size-1)max-w…

mysql event 簡單demo

功能&#xff1a;每3秒刪除b表數據&#xff0c;查詢a表中的5條數據并插入b表。 /* 查看mysql事件狀態 */ show variables like %event_scheduler%;/* 開啟mysql事件 */ SET GLOBAL event_scheduler ON;/* 測試a表*/ CREATE TABLE test_a (id int(11) NOT NULL AUTO_INCREMENT…

linux中操作數據庫的使用命令記錄

1&#xff0c;mysql 查看數據庫表編碼格式&#xff1a; show create table widget; 修改數據庫表編碼格式&#xff1a; alter table widget default character set utf8; 修改數據庫表中某字段的編碼格式&#xff1a; alter table widget change widget_name widget_name varc…

ICC Scenario Definition

現代先進工藝下的后端設計都是在 MCMM 情況下設計的&#xff0c;所謂 MCMM 就是 muti-corner muti-mode&#xff0c;用于芯片的不同工作模式和工作條件。 后端設計過程中&#xff0c;需要保證芯片在所有工作模式和工作條件下都能正常工作&#xff0c;工作模式一般只有幾種&…

別瞎忙活:創業公司的6條時間管理策略

導讀&#xff1a;無數創業者為自己的公司努力拼搏&#xff0c;把一切時間投入到公司建設中。這種724小時的熱情對于創業者本人是必須的&#xff0c;然而對于創業中的團隊來說&#xff0c;更重要的是學會管理時間。倦怠是錯誤時間管理帶來的顯著危害&#xff0c;但最大的危險是因…

JDK8下載|JDK1.8下載可選擇window版和linux版

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 摘要&#xff1a;Oracle甲骨文公司Oracle公司如期發布了Java 8正式版!現在你就可以下載Java 8正式版了&#xff0c;同期發布的還有JDK 8。…

持續集成與持續部署寶典Part 2:創建持續集成流水線

2019獨角獸企業重金招聘Python工程師標準>>> 在本系列文章中&#xff0c;我們將探討在容器時代如何在基于Docker的環境中創建連貫的工作流程和流水線來簡化大規模項目的部署。另外&#xff0c;我們還將詳細介紹如何利用Docker和Rancher自動化處理這些工作流。 在上文…

64 裝飾器函數: 母版 csrf防御機制 cookie

主要內容: 1: 裝飾器函數 a: 原理: 在不改變原函數的代碼和調用方式的情況下, 給函數動態的添加功能 b: 實例: 裝飾器的原理: def yue(tools):print(使用%s約一約 % tools) def wrapper(fn):def inner(*args, **kwargs):print(先準備好錢)fn(*args, **kwargs)return inner yue …

Facebook與Google的互聯網霸主爭奪戰

摘要&#xff1a;谷歌的兩位創始人對搜索情有獨鐘&#xff0c;而沒有看到互聯網發展的大勢。雖然目前Facebook的估值最高為1000億美元&#xff0c;與谷歌近2000億美元的市值還相去甚遠&#xff0c;但是未來很有可能超越谷歌&#xff0c;成為互聯網新一代霸主。谷歌的兩位創始人…

Eclipse將引用了第三方jar包的Java項目打包成jar文件的兩種方法

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 方案一&#xff1a;用Eclipse自帶的Export功能 步驟1&#xff1a;準備主清單文件 “MANIFEST.MF”&#xff0c; 由于是打包引用了第三…

Linux-MySQL基本命令-SQL語句

服務端命令SQL 在數據庫系統中&#xff0c;SQL語句不區分大小寫(建議用大寫) ?SQL語句可單行或多行書寫&#xff0c;以“;”結尾 ?關鍵詞不能跨多行或簡寫 ?用空格和縮進來提高語句的可讀性 ?子句通常位于獨立行&#xff0c;便于編輯&#xff0c;提高可讀性 ?注釋&#x…

webAPI token驗證

ASP.NET WebApi 實現Token驗證 https://www.cnblogs.com/dukang1991/p/5627584.html轉載于:https://www.cnblogs.com/KQNLL/p/9757025.html