【C#】GraphicsPath的用法

在 C# 中,GraphicsPath 是 GDI+ 提供的一個非常強大的類,用于創建和操作復雜圖形路徑。它可以用來繪制直線、曲線、多邊形等形狀,并支持判斷點是否在路徑內或路徑的輪廓上。

一、基本概念

GraphicsPath?類功能:

  • 添加各種幾何圖形(線段、矩形、橢圓、多邊形、貝塞爾曲線等)。
  • 支持填充 (Fill) 和描邊 (Draw)。
  • 判斷一個點是否在路徑內部:IsVisible(PointF)
  • 判斷一個點是否在路徑輪廓線上:IsOutlineVisible(PointF, Pen)

二、常用方法和用法示例

1. 創建 GraphicsPath 實例

GraphicsPath path = new GraphicsPath();

2. 添加不同形狀到路徑中

//添加矩形(正方形)
Rectangle rect = new Rectangle(50, 50, 100, 100);
path.AddRectangle(rect);//添加橢圓(圓形)
Rectangle ellipseRect = new Rectangle(50, 50, 100, 100);
path.AddEllipse(ellipseRect);//添加多邊形(三角形為例)
PointF[] trianglePoints = {new PointF(100, 50),new PointF(150, 150),new PointF(50, 150)
};
path.AddPolygon(trianglePoints);//添加線條(線段)
PointF start = new PointF(50, 50);
PointF end = new PointF(150, 150);
path.AddLine(start, end);//添加閉合路徑(例如箭頭)
PointF[] arrowPoints = {new PointF(100, 50),new PointF(150, 100),new PointF(130, 100),new PointF(130, 150),new PointF(70, 150),new PointF(70, 100),new PointF(50, 100),new PointF(100, 50)
};
path.AddPolygon(arrowPoints);
path.CloseFigure(); // 確保閉合

三、判斷鼠標是否在路徑區域內

假設你有一個?MouseMove?或?MouseDown?事件:

private void panel1_MouseMove(object sender, MouseEventArgs e)
{PointF mousePoint = new PointF(e.X, e.Y);if (path.IsVisible(mousePoint)){Console.WriteLine("鼠標在圖形內部");}if (path.IsOutlineVisible(mousePoint, pen)){Console.WriteLine("鼠標在圖形輪廓線上");}
}

其中 pen 是你在繪圖時使用的筆刷對象:

Pen pen = new Pen(Color.Black, 2); // 至少寬度為 2 才容易命中

四、繪制路徑

protected override void OnPaint(PaintEventArgs e)
{base.OnPaint(e);e.Graphics.DrawPath(Pens.Red, path); // 繪制路徑輪廓e.Graphics.FillPath(Brushes.LightBlue, path); // 填充路徑
}

五、判斷鼠標是否在線段或點附近(自定義邏輯)

由于 GraphicsPath 對于線段和點的檢測有限,我們可以自己寫輔助函數來實現更精細的判斷。

判斷鼠標是否在線段附近(比如 5px 寬度內)

public bool IsMouseNearLine(PointF p1, PointF p2, PointF mouse, float tolerance = 5f)
{float distance = DistanceFromPointToLine(p1, p2, mouse);return distance <= tolerance;
}private float DistanceFromPointToLine(PointF a, PointF b, PointF p)
{float length = (float)Math.Sqrt((b.X - a.X) * (b.X - a.X) + (b.Y - a.Y) * (b.Y - a.Y));if (length == 0) return (float)Math.Sqrt((p.X - a.X) * (p.X - a.X) + (p.Y - a.Y) * (p.Y - a.Y));float t = ((p.X - a.X) * (b.X - a.X) + (p.Y - a.Y) * (b.Y - a.Y)) / (length * length);t = Math.Max(0, Math.Min(1, t));float projectionX = a.X + t * (b.X - a.X);float projectionY = a.Y + t * (b.Y - a.Y);return (float)Math.Sqrt((p.X - projectionX) * (p.X - projectionX) + (p.Y - projectionY) * (p.Y - projectionY));
}

六、清理與重置路徑

path.Reset(); // 清空路徑
path.Dispose(); // 釋放資源(記得在不再需要時調用)

七、調試建議

  • 使用?g.DrawPath(Pens.Red, path)?將路徑畫出來,便于調試。
  • 打印路徑的邊界框:path.GetBounds()
  • 鼠標坐標要確保與繪圖坐標一致(考慮縮放、偏移等變換)。

總結

功能方法
添加矩形AddRectangle
添加橢圓AddEllipse
添加多邊形AddPolygon
添加線段AddLine
判斷是否在內部IsVisible(PointF)
判斷是否在輪廓線IsOutlineVisible(PointF, Pen)
獲取包圍盒GetBounds()

?需要注意

在使用 GraphicsPath 進行圖形繪制以及判斷鼠標是否位于特定區域時,有多個方面需要注意,以確保程序的正確性和用戶體驗。以下是一些關鍵點:

1. 坐標系一致性

  • 坐標轉換:確保所有涉及的坐標(如鼠標位置、繪圖位置)都在同一個坐標系統內。如果界面或控件進行了縮放或變換,需要相應地調整這些坐標。
  • 浮點精度問題:由于?GraphicsPath?使用的是浮點數坐標 (PointF),而鼠標事件通常提供整數坐標 (Point),可能需要進行適當的轉換和處理。

2. 路徑閉合

  • 閉合路徑:對于多邊形等形狀,確保路徑是閉合的。可以使用?CloseFigure()?方法來自動閉合當前子路徑。這有助于正確填充和邊界檢測。

3. 筆刷與填充設置

  • Pen 和 Brush 設置:當使用?IsOutlineVisible(PointF, Pen)?檢查點是否在輪廓上時,傳遞給方法的?Pen?對象的寬度會影響結果。同樣,路徑的填充模式(通過?FillMode?屬性設置)也會影響?IsVisible(PointF)?的判斷。

4. 性能考慮

  • 包圍盒檢測:為了提高性能,特別是當處理復雜路徑時,可以在執行精確的?IsVisible?或?IsOutlineVisible?判斷之前,先用簡單的幾何形狀(如矩形)進行粗略的包圍盒檢測。
  • 緩存計算結果:如果某些計算(如路徑邊界框)不會頻繁改變,可以考慮緩存這些結果以減少重復計算。

5. 用戶交互設計

  • 反饋機制:為用戶提供清晰的視覺反饋,例如高亮顯示被選中的元素或改變鼠標指針樣式,可以幫助用戶理解他們的操作效果。
  • 容差范圍:考慮到用戶的鼠標控制精度,適當增加對線段、點等細小圖形的點擊容差范圍,可以提升用戶體驗。

6. 錯誤處理與調試

  • 異常捕獲:在處理圖形繪制和鼠標事件時,加入必要的異常捕獲邏輯,防止程序因意外情況崩潰。
  • 可視化調試:在開發階段,可以通過繪制路徑邊界或臨時更改顏色等方式來驗證路徑的正確性。

遵循上述注意事項,可以幫助你更有效地利用 GraphicsPath 來實現復雜的圖形繪制和交互邏輯,同時確保應用程序的穩定性和良好的用戶體驗。

?

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

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

相關文章

C語言32個關鍵字

文章目錄數據類型1、數據類型&#xff08;12個&#xff09;控制語句2、控制語句關鍵字&#xff08;12個&#xff09;存儲類型3、存儲類型關鍵字&#xff08;4個&#xff09;其他關鍵字4、其他關鍵字&#xff08;4個&#xff09;?一共32個關鍵字分為 數據類型 1、數據類型&am…

粒子濾波|粒子濾波的相關算法理論介紹

在自動控制、導航、目標跟蹤等眾多領域&#xff0c;系統狀態估計是獲取真實狀態的關鍵環節。由于觀測信號常受噪聲干擾&#xff0c;濾波技術成為提取可靠信息的核心手段。本文將圍繞目標跟蹤技術中的濾波算法理論展開&#xff0c;重點解析粒子濾波框架的原理與應用。一、動態系…

Jenkins+Gitee+Docker容器化部署

寫在前文 本文主要是通過Jenkins的maven項目版本GiteeDocker-maven插件來進行部署的&#xff0c;本文沒有使用dockerfile/docker-compose。 本文默認已經安裝了Docker 1、安裝Jenkins Step1、創建文件夾當作映射jenkins的home文件夾 mkdir /app/jenkins Step2、賦權&#xff…

[Meetily后端框架] 多模型-Pydantic AI 代理-統一抽象 | SQLite管理

第5章&#xff1a;人工智能模型交互&#xff08;Pydantic-AI 代理&#xff09; 歡迎回來&#xff01; 在上一章第四章&#xff1a;文字記錄處理邏輯中&#xff0c;我們學習了TranscriptProcessor如何將冗長的會議記錄分解為稱為"塊"的較小片段&#xff0c;因為人工…

利用DeepSeek實現rust調用duckdb動態鏈接庫的duckdb CLI

提示詞&#xff1a;請用rust調用duckdb-rs實現一個duckdb CLI,支持語法突出顯示和計時&#xff0c;還支持命令行管道輸入輸出 Cargo.toml [package] name "duckdb-cli" version "0.1.0" edition "2024"[dependencies] duckdb "1.3.1&qu…

C++,從匯編角度看《虛擬繼承的邪惡》

刷到一篇文章&#xff1a; 作者&#xff1a; 原文&#xff1a;虛擬繼承的邪惡 討論到這樣的一個程序&#xff0c;最終輸出什么&#xff1f;&#xff1f;&#xff1f; 代碼有簡化命名 using namespace std;class A { public:A(int a 0) : v(a) {};int v; };template <type…

多 Agent 強化學習實踐指南(一):CTDE PPO 在合作捕食者-獵物游戲中的應用詳解

我們來詳細講解如何在合作捕食者-獵物游戲中結合 PPO (Proximal Policy Optimization) 算法。我們將聚焦于 CTDE&#xff08;Centralized Training, Decentralized Execution&#xff0c;集中訓練、分散執行&#xff09; 模式&#xff0c;因為這是處理合作多 Agent 任務的常用且…

Web應用文件上傳安全設計指南

引言 在當今的Web應用中&#xff0c;文件上傳功能已成為基礎且必要的服務能力&#xff0c;但不當的設計可能帶來目錄遍歷、代碼注入、服務端資源耗盡等安全風險。本文從威脅模型、安全設計原則、技術實現三個維度&#xff0c;系統闡述安全文件上傳架構的設計要點。 一、威脅模型…

用 React Three Fiber 實現 3D 城市模型的擴散光圈特效

本文介紹了如何使用 React Three Fiber&#xff08;R3F&#xff09;和 Three.js 實現一個從中心向外擴散的光圈特效&#xff08;DiffuseAperture 組件&#xff09;&#xff0c;并將其集成到城市 3D 模型&#xff08;CityModel 組件&#xff09;中。該特效通過動態調整圓柱幾何體…

【牛客刷題】COUNT數字計數

文章目錄 一、題目介紹二、題解思路三、算法實現四、復雜度分析五 、關鍵步驟解析5.1 數字分解5.2 三種情況處理5.2.1 情況1: d < c u r d < cur d<cur(完整周期)5.2.2 情況2: d = c u r d = cur d=cur(混合周期)5.2.3 情況3: d > c u r d > cur d>cu…

AGV穿梭不“迷路”CCLinkIE轉Modbus TCP的銜接技巧

在AGV控制系統集成中&#xff0c;工程師常面臨一個現實難題&#xff1a;如何讓CCLinkIE總線與Modbus TCP設備實現高效通信&#xff1f;這種跨協議的連接需求&#xff0c;往往需要耗費大量時間調試。本文將通過實際案例解析&#xff0c;為制造行業工程師提供可復用的解決方案。【…

【代碼隨想錄】刷題筆記——哈希表篇

目錄 242. 有效的字母異位詞 349. 兩個數組的交集 202. 快樂數 1. 兩數之和 454. 四數相加 II 383. 贖金信 15. 三數之和 18. 四數之和 242. 有效的字母異位詞 思路 代碼 class Solution {public boolean isAnagram(String s, String t) {if (s.length() ! t.length()…

Python爬蟲實戰:研究messytables庫相關技術

1. 引言 在當今數字化時代,互聯網上存在著大量有價值的數據。然而,這些數據通常以不規則的格式存在,尤其是表格數據,可能包含復雜的表頭、合并單元格、不規則布局等問題。傳統的數據處理工具往往難以應對這些挑戰。 網絡爬蟲技術可以幫助我們從網頁上自動提取數據,而 mes…

Vue3的組件通信方式

通信方式適用層級數據流向復雜度Props/Emits父子組件單向/雙向★☆☆v-model父子組件雙向★☆☆Provide/Inject跨層級組件自上而下★★☆事件總線任意組件任意方向★★★Pinia/Vuex全局狀態任意方向★★☆Refs模板引用父子組件父→子★☆☆作用域插槽父子組件子→父★★☆Web W…

創客匠人:大健康創始人IP如何用“社會責任”構建品牌護城河

一、商業與責任的失衡困局部分大健康IP將利潤置于首位&#xff0c;甚至犧牲用戶利益&#xff0c;導致品牌形象脆弱。某保健品公司因夸大宣傳被曝光后&#xff0c;盡管銷量曾達千萬&#xff0c;卻因缺乏社會認同&#xff0c;一夜之間崩塌&#xff0c;證明沒有社會責任支撐的商業…

AI:機器人未來的形態是什么?

機器人未來的形態將受到技術進步、應用場景需求和社會接受度的綜合影響&#xff0c;以下是對未來機器人形態的預測&#xff0c;涵蓋技術趨勢、設計方向和應用場景&#xff1a; 1. 形態多樣化與通用化 人形機器人&#xff08;Humanoid Robots&#xff09;&#xff1a; 趨勢&…

創建 UIKit 項目教程

一、打開 XCode&#xff0c;選擇 iOS 下的 App&#xff0c;然后點 Next二、Interface 選擇 Storyboard&#xff0c;然后點 Next三、刪掉 Main.storyboard四、刪掉 SceneDelegate.swift五、AppDelegate.swift 只保留第一個函數六、在 AppDelegate.swift 文件里的 application 函…

防爬蟲君子協定 Robots.txt 文件

1.什么是robots.txt ? robots.txt是一個位于網站根目錄的文本文件,用于指導搜索引擎爬蟲如何訪問和抓取網站內容。它遵循特定的語法規則,是網站與爬蟲通信的重要工具。當搜索引擎訪問一個網站時,它首先會檢查該網站的根域下是否有一個叫做robots.txt的純文本文件。Robots.…

淺談 Python 中的 yield——生成器對象與函數調用的區別

我們來看這么一個例子&#xff1a; def greeter():name yield "你是誰&#xff1f;"yield f"你好&#xff0c;{name}"g greeter() print(next(g)) # → "你是誰&#xff1f;" print(g.send("張三")) # → "你好&#xf…

云端docker小知識

1、docker的三個關鍵概念image、container、dockerfile2、docker的container3、dockerfile4、docker制作image5、linux&#xff08;ubuntu&#xff09;安裝docker&#xff08;步驟1和4&#xff09;6、docker基本命令docker images 查看全部鏡像docker rmi -f 1e5f3c5b981a 刪除…