日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Quartz-2D绘图之路径(Paths)详解

發布時間:2025/4/14 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Quartz-2D绘图之路径(Paths)详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

? 在上篇文章中,我們簡單的理解了繪圖上下文,今天我們來認識一下Quartz-2D中另一個重要的概念,路徑(Paths)。

一、理解路徑

? 路徑定了一個或多個形狀,或是子路徑。一個子路徑可由直,曲,或者同由兩者構成。它可以是開放的,也可以是合的。一個子路徑可以是簡單的形狀,如、矩形、星形;也可以是復的形狀,如山脈的廓或者是涂3-1示了一些我可以建的路徑。左上角的直可以是虛;直也可以是實線。上的路徑是由多條曲線組成的開放路徑。右上角的同心填充了色,但沒有描。左下角的加利福尼州是合路徑,由多曲和直構成,且路徑行填充和描。兩個星形明了填充路徑的兩種方式,我詳細描述。

?

二、建及制路徑

路徑建及路徑制是兩個獨立的工作。首先我們創建路徑。當我需要渲染路徑,我需要使用Quartz制它。正如3-1中所示,我可以選擇對路徑行描,填充路徑,或同時進兩種操作。我可以將其它制到路徑所表示的范內,即對對行裁減。
3-2制了一個路徑,路徑包含兩個子路徑。左的子路徑是一個矩形,右的子路徑是由直和曲線組成的抽象形狀。兩個子路徑都行了填充及描

?

3-3示了多條獨立制的路徑。每個路徑食隨機生成的曲,一些行填充,另一些行了描些路徑都包含在一個形裁減區域內。

?

三、構建塊(Building Block)
子路徑是由直線、弧和曲線構成的。Quartz同樣也提供了簡便的函數用于添加矩形或橢圓等形狀。點也是路徑最基本的構建塊,因為點定義了形狀的起始點與終止點。


點由x, y坐標值定義,用于在用戶空間指定 一個位置。我們可以調用函數CGContextMoveToPoint來為新的子路徑指定起始點。Quartz跟蹤當前點,用于記錄路徑構建過程中最新的位置。例如,如果調用函數CGContextMoveToPoint并設置位置為(10, 10),即將當前點移動到位置(10, 10)。如果在水平位置繪制50個單位長度的直線,則直線的終點為(60, 10),該點變成當前點。直線、弧和曲線總是從當前點開始繪制。
通常我們通過傳遞(x, y)值給Quartz函數來指定一個點。一些函數需要我們傳遞一個CGPoint數據結構,該結構包含兩個浮點值。


直線由兩個端點定義。起始點通常是當前點,所以創建直線時,我們只需要指定終止點。我們使用函數CGContextAddLineToPoint來添加一條直線到子路徑中。
我們可以調用CGContextAddLines函數添加一系列相關的直線到子路徑中。我們傳遞一個點數組給這個函數。第一個點必須是第一條直線的起始點;剩下的點是端點。Quartz從第一個點開始繪制一個新子路徑,然后每兩個相鄰點連接成一條線段。


弧是圓弧段。Quartz提供了兩個函數來創建弧。函數CGContextAddArc從圓中來創建一個曲線段。我們指定一個圓心,半徑和放射角(以弧度為單位)。放射角為2 PI時,創建的是一個圓。圖3-4顯示了多個獨立的路徑。每個路徑飲食一個自動生成的圓;一些是填充的,另一些是描邊的。

函數CGContextAddArcToPoint用于為矩形創建內切弧的場景。Quartz使用我們提供的端點創建兩條正切線。同樣我們需要提供圓的半徑。弧心是兩條半徑的交叉點,每條半徑都與相應的正切線垂直。弧的兩個端點是正切線的正切點,如圖3-5所示。紅色的部分是實際繪制的部分。

下面分別是畫直線和圓弧的代碼

直線:

?

1 // 1. 獲取一個與視圖相關聯的上下文 2 CGContextRef context = UIGraphicsGetCurrentContext(); 3 4 // 2. 構建路徑 5 // 2.1 設置上下文路徑起點 6 CGContextMoveToPoint(context, 85, 85); 7 // 2.2 增加路徑內容…… 8 CGContextAddLineToPoint(context, 150, 150); 9 CGContextAddLineToPoint(context, 250, 50); 10 // 3. 保存上下文狀態 11 // 4. 設置上下文狀態 12 // 4.1 設置邊線顏色 13 CGContextSetRGBStrokeColor(context, 1, 0, 0, 1); 14 // 4.2 設置線寬 15 CGContextSetLineWidth(context, 10); 16 // 4.3 設置線段連接樣式 17 CGContextSetLineJoin(context, kCGLineJoinRound); 18 // 4.4 設置線段收尾樣式 19 CGContextSetLineCap(context, kCGLineCapRound); 20 // 4.5 設置虛線樣式 21 // 4. 繪制路徑 22 CGContextDrawPath(context, kCGPathStroke);

?

圓弧:

// 1. 獲取一個與視圖相關聯的上下文CGContextRef context = UIGraphicsGetCurrentContext();[[UIColor redColor]set];// 2. 添加弧線// 2.1 上下文// 2.2 中心點坐標// 2.3 半徑// 2.4 開始角度,結束角度,角度的單位是“弧度”CGContextAddArc(context, 160, 230, 100, M_PI, -M_PI_2, 0);// 繪制路徑CGContextStrokePath(context);


二次與三次Bezier曲線是代數曲線,可以指定任意的曲線形狀。曲線上的點通過一個應用于起始、終點及一個或多個控制點的多項式計算得出。這種方式定義的形狀是向量圖的基礎。這個公式比將位數組更容易存儲,并且曲線可以在任何分辨下重新創建。
圖3-6顯示了一些路徑的曲線。每條路徑包含一條隨機生成的曲線;一些是填充的,另一些是描邊的。

?

我們使用函數CGContextAddCurveToPoint將Bezier曲線連接到當前點,并傳遞控制點和端點作為參數,如圖3-7所示。兩個控制點的位置決定了曲線的形狀。如果兩個控制點都在兩個端點上面,則曲線向上凸起。如果兩個控制點都在兩個端點下面,則曲線向下凹。如果第二個控制點比第一個控制點離得當前點近,則曲線自交叉,創建了一個回路。

我們也可以調用函數CGContextAddQuadCurveToPoint來創建Bezier,并傳遞端點及一個控制點,如圖3-8所示。控制點決定了曲線彎曲的方向。由于只使用一個控制點,所以無法創建出如三次Bezier曲線一樣多的曲線。例如我們無法創建出交叉的曲線

1 /*畫貝塞爾曲線*/ 2 //二次曲線 3 CGContextMoveToPoint(context, 120, 300);//設置Path的起點 4 CGContextAddQuadCurveToPoint(context,190, 310, 120, 390);//設置貝塞爾曲線的控制點坐標和終點坐標 5 CGContextStrokePath(context); 6 //三次曲線函數 7 CGContextMoveToPoint(context, 200, 300);//設置Path的起點 8 CGContextAddCurveToPoint(context,250, 280, 250, 400, 280, 300);//設置貝塞爾曲線的控制點坐標和控制點坐標終點坐標 9 CGContextStrokePath(context);

?

合路徑
我們可以調用函數CGContextClosePath來閉合曲線。該函數用一條直接來連接當前點與起始點,以使路徑閉合。起始與終點重合的直線、弧和曲線并不自動閉合路徑,我們必須調用CGContextClosePath來閉合路徑。
Quartz的一些函數將路徑的子路徑看成是閉合的。這些函數顯示地添加一條直線來閉合 子路徑,如同調用了CGContextClosePath函數。
在閉合一條子路徑后,如果程序再添加直線、弧或曲線到路徑,Quartz將在閉合的子路徑的起點開始創建一個子路徑。

橢圓
橢圓是一種特殊的圓。橢圓是通過定義兩個焦點,在平面內所有與這兩個焦點的距離之和相等的點所構成的圖形。圖3-9顯示了一些獨立的路徑。每個路徑都包含一個隨機生成的橢圓;一些進行了填充,另一邊進行了描邊。

我們可以調用CGContextAddEllipseInRect函數來添加一個橢圓到當前路徑。我們提供一個矩形來定義一個橢圓。Quartz利用一系列的Bezier曲線來模擬橢圓。橢圓的中心就是矩形的中心。如果矩形的寬與高相等,則橢圓變成了圓,且圓的半徑為矩形寬度的一半。如果矩形的寬與高不相等,則定義了橢圓的長軸與短軸。
添加到路徑中的橢圓開始于一個move-to操作,結束于一個close-subpath操作,所有的移動方向都是順時針。

矩形
我們可以調用CGContextAddRect來添加一個矩形到當前路徑中,并提供一個CGRect結構體(包含矩形的原點及大小)作為參數。
添加到路徑的矩形開始于一個move-to操作,結束于一個close-subpath操作,所有的移動方向都是順時針。
我們也可能調用CGContextAddRects函數來添加一系列的矩形到當前路徑,并傳遞一個CGRect結構體的數組。圖3-10顯示了一些獨立的路徑。每個路徑包含一個隨機生成的矩形;一些進行了填充,另一邊進行了描邊。

?四、創建路徑

當我們需要在一個圖形上下文中構建一個路徑時,我們需要調用CGContextBeginPath來標記Quartz。然后,我們調用函數CGContextMovePoint來設置每一個圖形或子路徑的起始點。在構建起始點后,我們可以添加直線、弧、曲線。記住如下規則:

  • 在開始繪制路徑前,調用函數CGContextBeginPath;
  • 直線、弧、曲線開始于當前點。空路徑沒有當前點;我們必須調用CGContextMoveToPoint來設置第一個子路徑的起始點,或者調用一個便利函數來隱式地完成該任務。
  • 如果要閉合當前子路徑,調用函數CGContextClosePath。隨后路徑將開始一個新的子路徑,即使我們不顯示設置一個新的起始點。
  • 當繪制弧時,Quartz將在當前點與弧的起始點間繪制一條直線。
  • 添加橢圓和矩形的Quartz程序將在路徑中添加新的閉合子路徑。
  • 我們必須調用繪制函數來填充或者描邊一條路徑,因為創建路徑時并不會繪制路徑。

在繪制路徑后,將清空圖形上下文。我們也許想保留路徑,特別是在繪制復雜場景時,我們需要反復使用。基于此,Quartz提供了兩個數據類型來創建可復用路徑—CGPathRef和CGMutablePathRef。我們可以調用函數CGPathCreateMutable來創建可變的CGPath對象,并可向該對象添加直線、弧、曲線和矩形。Quartz提供了一個類似于操作圖形上下文的CGPath的函數集合。這些路徑函數操作CGPath對象,而不是圖形上下文。這些函數包括:

  • CGPathCreateMutable,取代CGContextBeginPath
  • CGPathMoveToPoint,取代CGContextMoveToPoint
  • CGPathAddLineToPoint,取代CGContexAddLineToPoint
  • CGPathAddCurveToPoint,取代CGContexAddCurveToPoint
  • CGPathAddEllipseInRect,取代CGContexAddEllipseInRect
  • CGPathAddArc,取代CGContexAddArc
  • CGPathAddRect,取代CGContexAddRect
  • CGPathCloseSubpath,取代CGContexClosePath

如果想要添加一個路徑到圖形上下文,可以調用CGContextAddPath。路徑將保留在圖形上下文中,直到Quartz繪制它。我們可以調用CGContextAddPath再次添加路徑。

?五、繪制路徑

我們可以繪制填充或描邊的路徑。描邊(Stroke)是繪制路徑的邊框。填充是繪制路徑包含的區域。Quartz提供了函數來填充或描邊路徑。描邊線的屬性(寬度、顏色等),填充色及Quartz用于計算填充區域的方法都是圖形狀態的一部分。

影響描的屬性
我們可以使用表3-1中的屬性來決定如何對路徑進行描邊操作。這邊屬性是圖形上下文的一部分,這意味著我們設置的值將會影響到后續的描邊操作,直到我們個性這些值。

linewidth是線的總寬度,單位是用戶空間單元。
linejoin屬性指定如何繪制線段間的聯接點。Quartz支持表3-2中描述的聯接樣式。

Table 3-2?直線聯接樣式

linecap指定如何繪制直線的端點。Quartz支持表3-3所示的線帽類型。默認的是butt cap。

?

閉合路徑將起始點看作是一個聯接點;起始點同樣也使用選定的直線連接方法進行渲染。如果通過添加一條連接到起始點的直線來閉合路徑,則路徑的兩個端點都使用選定的線帽類型來繪制。
Linedash pattern(虛線模式)允許我們沿著描邊繪制虛線。我們通過在CGContextSetLineDash結構體中指定虛線數組和虛線相位來控制虛線的大小及位置。

CGContextSetLineDash結構如下:

?

1 void CGContextSetLineDash ( 2 CGContextRef ctx, 3 float phase, 4 const float lengths[], 5 size_t count, 6 );

?其中lengths屬性指定了虛線段的長度,該值是在繪制片斷與未繪制片斷之間交替。phase屬性指定虛線模式的起始點。圖3-11顯示了虛線模式:

路徑描的函數
Quartz提供了表3-4中的函數來描邊當前路徑。其中一些是描邊矩形及橢圓的便捷函數。
表3-4 描邊路徑函數

?

函數CGContextStrokeLineSegments等同于如下代碼

1 CGContextBeginPath(context); for(k = 0; k < count; k += 2) { CGContextMoveToPoint(context,s[k].x, s[k].y); CGContextAddLineToPoint(context,s[k+1].x, s[k+1].y);}CGContextStrokePath(context);

當我們調用CGContextStrokeLineSegments時,我們通過點數組來指定線段,并組織成點對的形式。每一對是由線段的起始點與終止點組成。例如,數組的第一個點指定了第一條直線的起始點,第二個點是第一條直線的終點,第三個點是第二條直線的起始點,依此類推。


六、填充路徑
當我們填充當前路徑時,Quartz將路徑包含的每個子路徑都看作是閉合的。然后,使用這些閉合路徑并計算填充的像素。?Quartz有兩種方式來計算填充區域。橢圓和矩形這樣的路徑其區域都很明顯。但是如果路徑是由幾個重疊的部分組成或者路徑包含多個子路徑(如圖3-12所示),我們則有兩種規則來定義填充區域。
默認的規則是非零纏繞數規則(nonzero windingnumber rule)。為了確定一個點是否需要繪制,我們從該點開始繪制一條直線穿過繪圖的邊界。從0開始計數,每次路徑片斷從左到右穿過直線是,計數加1;而從右到左穿過直線時,計數減1。如果結果為0,則不繪制該點,否則繪制。路徑片斷繪制的方向會影響到結果。圖3-13顯示了使用非纏繞數規則對內圓和外圓進行填充的結果。當兩個圓繪制方向相同時,兩個圓都被填充。如果方向相反,則內圓不填充。
我們也可以使用偶數-奇數規則。為了確定一個點是否被繪制,我們從該點開始繪制一條直線穿過繪圖的邊界。計算穿過該直線的路徑片斷的數目。如果是奇數,則繪制該點,如果是偶數,則不繪制該點。路徑片斷繪制的方向不影響結果。如圖3-12所示,無論兩個圓的繪制方向是什么,填充結果都是一樣的。

Quartz提供了表3-5中的函數來填充當前路徑。其中一些是填充矩形及橢圓的便捷函數。
表3-5 填充路徑的函數

?好,說了這么多下面上代碼

1 - (void)drawLine1 2 { 3 // 1. 獲取一個與視圖相關聯的上下文 4 CGContextRef context = UIGraphicsGetCurrentContext(); 5 6 // 2. 創建一個可變路徑 7 // 2.1 創建路徑 8 CGMutablePathRef path = CGPathCreateMutable(); 9 // 2.2 設置路徑起點 10 CGPathMoveToPoint(path, NULL, 50, 50); 11 // 2.3 增加路徑內容…… 12 CGPathAddLineToPoint(path, NULL, 150, 150); 13 CGPathAddLineToPoint(path, NULL, 50, 150); 14 // CGPathAddLineToPoint(path, NULL, 50, 50); 15 // 閉合路徑,關閉路徑,閉合路徑是收尾相連的 16 CGPathCloseSubpath(path); 17 18 // 3. 將路徑添加到上下文; 19 CGContextAddPath(context, path); 20 21 // 4. 設置上下文狀態 22 // 4.1 設置邊線顏色 23 // 顏色數值 = RGB數值 / 255 24 CGContextSetRGBStrokeColor(context, 255.0 / 255.0, 0.0, 0.0 , 1.0); 25 // 4.2 設置填充顏色 26 CGContextSetRGBFillColor(context, 0.0, 0.0, 128.0 / 255.0, 1.0); 27 // 4.3 設置線寬 28 CGContextSetLineWidth(context, 5); 29 // 4.4 設置線段連接樣式 30 CGContextSetLineJoin(context, kCGLineJoinBevel); 31 // 4.5 設置線段首尾樣式 32 CGContextSetLineCap(context, kCGLineCapRound); 33 // 4.6 設置虛線樣式 34 // lengths 設置公有幾條虛線,每條虛線的長度 35 // count 指的是lengths數組的長度 36 CGFloat lengthes[2] = {10.0, 10.0}; 37 CGContextSetLineDash(context, 0, lengthes, 2); 38 // 5. 繪制路徑 39 /** 40 kCGPathStroke 繪制邊線 41 kCGPathFill 填充 42 */ 43 CGContextDrawPath(context, kCGPathFillStroke); 44 // 6. 釋放路徑,不同對象對應著不同的release方法 45 CGPathRelease(path); 46 }

?七、裁剪路徑

當前裁剪區域是從路徑中創建,作為一個遮罩,從而允許遮住我們不想繪制的部分。例如,我們有一個很大的圖片,但只需要顯示其中一小部分,則可以設置裁減區域來顯示我們想顯示的部分。

當我們繪制的時候,Quartz只渲染裁剪區域里面的東西。裁剪區域內的閉合路徑是可見的;而在區域外的部分是不可見的。

當圖形上下文初始創建時,裁減區域包含上下文所有的可繪制區域(例如,PDF上下文的media box)。我們可以通過設置當前路徑來改變裁剪區域,然后使用裁減函數來取代繪制函數。裁剪函數與當前已有的裁剪區域求交集以獲得路徑的填充區域。因此,我們可以求交取得裁減區域,縮小圖片的可視區域,但是不能擴展裁減區域。

裁減區域是圖形狀態的一部分。為了恢復先前的裁減區域,我們可以在裁減前保存圖形狀態,并在裁減繪制后恢復圖形狀態。

?

1 Listing 3-1 Setting up a circular clip area 2 CGContextBeginPath(context); 3 CGContextAddArc(context, w/2, h/2, ((w>h) ? h : w)/2, 0, 2*PI, 0); 4 CGContextClosePath(context); 5 CGContextClip(context);

?

表3-6 裁減圖形上下文的函數

?

轉載于:https://www.cnblogs.com/tmacforever/p/4159163.html

總結

以上是生活随笔為你收集整理的Quartz-2D绘图之路径(Paths)详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。