日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Lisp-Stat翻译 —— 第九章 统计绘图窗体

發布時間:2025/3/8 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Lisp-Stat翻译 —— 第九章 统计绘图窗体 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

第九章 統計繪圖窗體

????除了前幾章略述的繪圖窗體原型提供的基本繪圖工具之外,Lisp-Stat里的統計繪圖還需要用來管理數據和將那些數據轉換成屏幕上的圖形的工具集。這些工具由繪圖原型graph-proto提供。更多的專業繪圖工具,比如直方圖和散點圖矩陣,它們都是基于繼承自graph-proto的原型。本章的第一節描述了繪圖原型,第二節略述了更加專用的原型,下一章將展示那些描述如何從這些原型來開發新的繪圖工具類型的例子。

9.1 繪圖原型

????graph-proto原型實現了一個散點圖,該散點圖用來表示在m維空間中的點和線的二維視圖。該視圖是這樣構造的,首先對數據進行中心化和尺度化,然后使用線性變換,比如旋轉變換,最后產生該變換的圖形里的維度的兩個維度的一個散點圖。該原型的:resize和:redraw方法可以保證:當窗體出現或改變大小時,圖形可以得到合適的重畫。鼠標點擊和移動方法支持以下語法:即在第2.5節描述的在選擇模式和刷模式里使用的繪圖方式。該原型也提供了一個基本的菜單用來與圖形交互。

? ? 為了給出該原型提供的機制的詳細的說明,本節使用一個圖形來檢測5.6.2節引入的stack loss數據。

9.1.1 構造一個新的圖形

????graph-proto原型繼承自graph-window-proto原型,graph-proto的:isnew方法需要一個參數,即表示將被視圖化的那個空間的維度的整型值m。stack loss數據由4個變量組成,氣流(Air)、溫度(Temp)、濃度(Conc)和氨損耗(Loss)。視圖化這些數據的圖形可以這樣構造:

> (setf w (send graph-proto :new 4)) #<Object: 141e7e8, prototype = GRAPH-PROTO> 圖形里的變量數目可以使用:num-variables消息來獲取: > (send w :num-variables) 4 但是,一個圖形創建,該值就不能改變。

? ? 圖形包含為每個維度描述的標簽字符串,這些字符串可以使用:variable-label消息來設置和獲取。初始情況下,這些字符串是空值:

> (send w :variable-label 0) "" 可以通過使用一個字符串作為其第二個參數的方式來改變它的值: > (send w :variable-label 0 "Air") "Air" 這個消息的方法是矢量化的。表示三個維度的標簽可以通過下式指定: > (send w :variable-label '(1 2 3) (list "Temp." "Conc" "Loss")) ("Temp." "Conc" "Loss") 現在我們可以獲得這4個變量了: > (send w :variable-label '(0 1 2 3)) ("Air" "Temp." "Conc" "Loss") ? ? :graph-proto原型的:isnew方法可以接受graph-window-proto原型的:isnew方法能夠接受的所有關鍵字參數。此外,:variable-label關鍵字可用來指定一個m維度的初始化變量標簽字符串。還有一個關鍵字:scale-type將在接下來的9.1.3節里描述。

9.1.2 增加數據可坐標軸

點數據

????一個圖形里可以包含兩類數據:點數據和線數據。點由m維空間里的坐標和一些附加信息組成,這些附加信息比如像用來繪制點的顏色和符號。初始情況下,圖形里不包含點數據:

> (send w :num-points) 0 點數據可以使用:add-points消息來添加,該消息的方法需要一個參數:一個m維的列表,表示將要添加的點的坐標值。下邊的表達式將stack loss數據添加到圖形里: > (def air '(80 80 75 62 62 62 62 62 58 58 58 58 58 58 50 50 50 50 50 56 70)) AIR > (def temp '(27 27 25 24 22 23 24 24 23 18 18 17 18 19 18 18 19 19 29 29 29)) TEMP > (def conc '(89 88 90 87 87 87 93 93 87 80 89 88 82 93 89 86 72 79 80 82 91)) CONC > (def loss '(42 37 37 28 18 18 19 20 15 14 14 13 11 12 8 7 8 8 9 15 15)) LOSS > (send w :add-points (list air temp conc loss)) NIL 數據集里有21個點: > (send w :num-points) 21 :add-points方法會在屏幕上繪制了新的點,除非提供了值為nil的:draw關鍵字。該方法也允許使用:point-label關鍵字的標簽字符串列表。

? ? 盡管現在該圖形包含這些數據,在它的窗體上不會顯示任何點。原因是這些數據點在初始情況下,當做在每一個變量的單位間隔組成的一個數據范圍。為了調整圖形視圖化的范圍以適應這些數據,你可以向圖形發送:adjust-to-data消息,你可以使用下邊的表達式發送該消息:

> (send w :adjust-to-data) NIL 或者也可以從圖形的菜單里選擇Rescale Plot菜單項。這個消息的方法將調整圖形視圖化的數據范圍以精確地適應對應的數據的范圍跨度。發送該消息之后,圖形應該顯示了一個散點圖,該散點圖表示出數據集中前兩個變量。結果圖形如圖9.1所示。

? ? 當向一個圖形里加入新點的時候,每一個點都會分給一個默認的符號、顏色和標簽,對于第一個點:

> (send w :point-symbol 0) DISK > (send w :point-color 0) NIL > (send w :point-label 0) "0"

圖9.1 stack loss數據集中氣流與溫度變量圖示

????默認符號是一個叫disk的符號。默認顏色是nil,意思是改點使用當前繪圖窗體的顏色來繪制。默認標簽是該點索引的字符串形式。通過向這些消息傳遞第二個參數來為這些屬性指定新值。符號應該取自plot-symbol-symbols函數返回的列表。顏色值應該是nil或者由color-symbols返回的列表的一個值。:point-symbol, :point-color和:point-label消息的方法是矢量化的,因此將所有21個點的符號設置到diamond變量里。這三個消息都不會引起圖形重畫;為了看到屏幕上改變的影響,你不得不向圖形發送一個重畫命令。

? ? 每個點還有一個狀態值,該值可以使用:point-stat消息來設置和獲取。該狀態值可以是invisible, normal, hilited和selected這四個符號中的一個。點數據狀態用做鏈接機制的一部分,它將在9.1.5節詳細描述。

? ? :point-coordinate消息可以用來為某一特定點獲取和設置單一變量坐標的值。該消息的方法需要兩個參數:變量的索引和點數據的索引。因此,第一次觀察到的氣流、溫度、濃度和氨損耗的值是:

> (send w :point-coordinate 0 0) 80.0 > (send w :point-coordinate 1 0) 27.0 > (send w :point-coordinate 2 0) 89.0 > (send w :point-coordinate 3 0) 42.0 :point-coordinate消息的方法也是矢量化的。新的坐標值可以以第三個參數的形式來指定。在強調一次,提供新值的時候,方法不會重畫圖形。

練習 9.1
略。

線數據

????線數據表示從處在m維空間里叫做linestart的點位開始,每個起點都包含額外的信息(比如在繪制線段時使用的寬度和線型信息),還有用來作為線段終點的另一個linestart的索引,nil的下標表示該linestart僅用作在其它地方凱斯的線段的終點。環形定義是是運行的:這不會帶來什么問題,因為繪圖路徑斤通過linestart集合一次。

? ? 當創建一個圖形的時候,它沒有linestart:

> (send w :num-lines) 0

? ? stack loss數據事實上是隨著時間收集到的。通過繪制一條從第一個觀察點到第二個觀察點、從第二個到第三個觀察點等等的直線的方式,來表示時間關系,這可能是很有用的。:add-line消息可以增加這樣一個線段序列,它的方法需要一個參數,一個針對linestart的坐標的m維列表的列表。因此,下式將針對stack loss數據向我們的圖形里添加連在一起的線段序列。這些線數據有助于說明,在數據集的前10個觀測量里,氣流和溫度是下降的。

> (send w :add-lines (list air temp conc loss)) NIL

? ? :add-lines消息的方法還允許使用:type關鍵字來提供線型,這時直線會會自導圖形上,除非使用了值為nil的:draw關鍵字。

? ? 每一個linestart都有一個寬度、類型和顏色,用來從一個linestart繪制到下一個linestart。對于第一個linestart,對應第一個數據點:

> (send w :linestart-width 0) 1 > (send w :linestart-type 0) SOLID > (send w :linestart-color 0) NIL

該方法也是矢量化的,通過提供一個新值作為第二個參數它可以被用來改變linestart屬性的值,數值的改變不會引起任何繪圖行為的發生。

? ? 每個linestart都包含序列里下一個linestart的索引,在繪圖中用來作為一個線段的終點,:add-lines方法將這些linestart連接成序列,因此:

> (send w :linestart-next 0) 1 > (send w :linestart-next 1) 2 序列里的最后一個linestart沒有關于下一個linestart的索引: > (send w :linestart-next 20) NIL 可以通過在線段的開始處為linestart設置下一個線段的值為nil,來移除一個線段。例如: > (send w :linestart-next 7 nil) NIL 上式移除了點號索引為7和8的點之間的線段,為了使該改變可見,你可以向圖形發送:redraw消息。

? ? 就想點一樣,你也可以獲取和改變linestart的坐標。第一個linestart的前兩個坐標值可以這樣給出(對應氣流和溫度變量):

> (send w :linestart-coordinate 0 0) 80.0 > (send w :linestart-coordinate 1 0) 27.0 :linestart-coordinate消息的方法是矢量化的,可以用來改變坐標的值。如果坐標改變了,圖形不會重畫。

練習 9.2

略。

坐標軸和當前變量

????由graph-proto原型實現的散點圖,使用:x-axis和:y-axis消息,可以用來表示x和y坐標軸。不提供參數,這些消息返回當前坐標軸的狀態。例如:

> (send w :x-axis) (NIL NIL 0) 列表的三個元素表示該坐標軸是否正處于顯示狀態,是否有標簽,它使用的刻度的數目。發送一個值為t的參數將重畫帶坐標軸的圖形。默認地,不使用標簽,使用4為刻度: > (send w :x-axis t) (T NIL 4) 你可以使用可選的第二、三個參數,來指定一個替代的選項。:y-axis方法是相同的。當坐標軸狀態改變時,這兩個方法都向圖形發送:resize和:redraw消息,除非使用了值為nil的:draw關鍵字。為了使用該關鍵字,你需要給出所有這3個可選參數。在加入x、y坐標軸之后,我們的圖形如圖9.2所示。

圖9.2 stack loss數據集中氣流和溫度變量的x坐標與y坐標圖形,連續觀測量由直線相連

? ? :adjust-to-data方法會將被一個圖形視圖化的數據范圍設置到數據范圍,該方法通常不會產生一個效果很好的坐標軸標簽。你也可以使用:range消息為每個變量獲取和改變數據范圍。對于氣流和溫度變量:

> (send w :range 0) (50.0 80.0) > (send w :range 1) (17.0 29.0) 結果列表的元素表示該數據范圍的高低邊界。為了改變一個變量的數據范圍,你需要使用兩個附加值,新的高低邊界。 > (send w :range 1 15 30) (15.0 30.0) 上式將溫度變量的數據范圍設置到區間[15, 30]之間。當數據范圍改變的時候,圖形將重畫,除非使用了值為nil的:draw關鍵字。:range消息的方法是矢量化的。

? ? get-nice-range函數可用來幫助找到數據范圍和刻度的一個好的組合。該函數帶3個參數,區間的高、低邊界端點和刻度值的整型數值。它返回一個3值列表,表示包含原始區間的區間端點,和接近指定數值得刻度的數值。新值應該產生合理的坐標軸。例如,對于大約有4刻度值的溫度變量的數據范圍來說:

> (get-nice-range 17 27 4) (16.0 28.0 7) 對于這個變量推薦的設置范圍是[16, 28],表達式如下: > (send w :range 1 16 28) (16.0 28.0) 將y軸設置為使用7作為刻度值: > (send w :y-axis t t 7) (T T 7) 結果坐標軸標記為16, 18, 20, ..., 28.

? ? 到目前為止,我們的圖形只顯示了我們的4變量數據集的前兩個。:current-variables消息可用來設置獲取構造該圖形的兩個當前變量。默認的情況是顯示前兩個變量:

> (send w :current-variables) (0 1) 下邊的表達式命令圖形切換到使用其它兩個變量。該方法向圖像發送:redraw消息,除非使用了值為nil的:draw關鍵字。

練習9.3

略。

清除繪圖數據

????圖形里當前的數據可以使用:clear, :clear-points和:clear-lines消息來清除。:clear-points消息移除內部數據,并將點數設為0,該消息會重畫圖形,除非使用了值為nil的:draw關鍵字。用來清除linestart數據的:clear-lines消息是相同的。:clear消息會將點數據和線數據一并移除。

? ? 這些消息對于動畫是非常有用的,即顯示在圖形里的快速變化的數據動畫。鑒于之后第9.1.6節里描述的重畫方法使用了雙緩沖技術,該技術會產生一個平滑的動畫效果。

9.1.3 縮放與變換

????graph-proto原型最主要的特征就是其允許對數據進行線性變換的能力,尤其是旋轉變換。變換過程可以分解為兩個階段。第一階段由數據的中心化和縮放組成;第二階段由對已經中心化和縮放過的詩句使用一個變化矩陣組成。然后,將顯示一個散點圖,即該變換的結果的坐標中的兩個數據。

縮放和中心化

????縮放和中心化階段引入了一個新的坐標系統,即縮放坐標系。作為對比,原來指定數據的那個坐標系叫做真實坐標系。可以使用人造的縮放體系,但是有兩個叫定縮放和變縮放的標準的縮放體系對大多數情況來說是足夠用了。這些縮放類型可以通過使用:adjust-to-data方法和:scale-type方法來實現。在處理之前,我們可以私用下邊兩個表達式將坐標軸從圖形中移除:

> (send w :x-axis nil) (NIL NIL 4) > (send w :y-axis nil) (NIL NIL 4) 對于變換后的數據來說,坐標軸是沒有意義的。

????當構造一個新的圖形時,它的縮放類型是nil:

> (send w :scale-type) NIL 這意味著沒有進行中心化和縮放,每個維度內的視圖范圍設置成真實坐標系的對應維度里的數據范圍。縮放坐標系里的數據范圍可以通過使用:scale-range消息來獲取: > (send w :range 0) (50.0 80.0)> (send w :scaled-range 0) (50.0 80.0) 因為在初始情況下沒有進行縮放,縮放過的和真實的數據范圍是相等的。

? ? 為了檢測這個新的縮放類型,我們可以通過將我們的圖形的縮放類型設置為variable符號來檢測,表達式如下:

> (send w :scale-type 'variable) VARIABLE :scale-type消息的方法將發送:adjust-to-data消息,并重畫圖形,除非使用了值為nil的:draw關鍵字。對于一個使用變化的縮放的圖形,:adjust-to-data方法為每個變量在數據范圍的中心位置進行中心化,在將每個中心化后的變量縮放到[-1, 1]區間上,最后將縮放后的數據范圍設置到[-sqrt(m), sqrt(m)]區間。這將確保數據進行旋轉之后都在縮放范圍之內。在將縮放類型設置成variable之后,圖形的第一個維度的數據范圍和縮放后的數據范圍如下: > (send w :range 0) (34.99999999999999 95.0) > (send w :scaled-range 0) (-2.0 2.0) ? ? 當變量在可比較的尺度內無法量度的時候,可變縮放是合適的。如果變量在可比較的尺度上是可以量度的,通過在每個維度上使用相同的比例系數,我們可能想要在數據內保持一定的角度,這在固定縮放策略里是一體的。如果尺度類型設置為符號fixed,那么:adjust-to-data方法將在數據區間的中間進行數據的中心化,并為每個維度選擇縮放系數為1,然后為每個變量設置其縮放后的區間,該數值為數據中心化的數據最大范圍的sqrt(m)倍。

? ? 如果可變縮放和固定縮放體系都不能勝任你的需求,你可以通過定義一個新的:adjudt-to-data方法來定義你自己的縮放體系。該方法可以使用:scale-range方法來設置一個新的縮放范圍,再使用:center和:scale消息來設置或者獲取中心和縮放系數。對于我們的圖形,因為是可變縮放,第一個變量的縮放系數和中心是:

> (send w :scale 0) 15.0 > (send w :center 0) 65.0 當使用:scaled-range消息設置縮放范圍時,原始坐標系內的數據范圍可會調整以適應該變化。:scale, :center和:scaled-range等消息是矢量化的。當使用該方法設置新值時,將會重畫圖形,除非使用了值為nil的:draw關鍵字。

? ? 對于定義自定義的縮放體系來說另一個重要的消息是:visible-range消息。該消息的方法接受維度索引作為參數,返回在那個維度里所有可見的點數據和linestart的數據范圍。例如,對于圖形里的第一維度:

> (send w :visible-range 0) (50.0 80.0) ? ? 一個圖形的初始縮放類型可以這樣指定——在graph-proto原型的:isnew方法里指定:scale-type關鍵字。

練習 9.4
略。

變換

????在選定一個縮放體系之后,比如說可變縮放,現在我們可以使用變換了。初始情況下,是沒有變換的:

> (send w :transformation) NIL 我們可以通過向:transformation消息傳遞一個參數,對數據中的每一個點和linestart使用一個轉換矩陣。浙江轉換每一個數據點,這些數據點被視為一個列向量,通過在該列向量左側乘一個變換矩陣完成變換。除非使用了值為nil的:draw關鍵字,否則在給定一個新的變換時:transformation方法將重畫該圖形。舉個例子,如果這樣給定當前變量: > (send w :current-variables) (0 1)

那么我們可以使用下邊這個表達式使用一個旋轉變換,該變換使用濃度變量代替氣流變量,氨損失代替溫度。

> (send w :transformation'#2A((0 0 -1 0)(0 0 0 -1)(1 0 0 0)(0 1 0 0))) #2A((0 0 -1 0) (0 0 0 -1) (1 0 0 0) (0 1 0 0)) 下式將返回一個未變換狀態的圖形: > (send w :transformation nil) NIL ? ? 對于變換的使用,一些其它方法也是可用的。為了更容易理解原始圖形中的溫度相對于氣流的點數據,與變換后圖形中的氨損失相對于濃度的點數據,這兩種點數據之間的對應關系,從第一個圖形平滑地旋轉到第二個圖形時有用的。這樣的從第一個散點圖到另一個散點圖的旋轉叫做圖形差值。通過將變換矩陣設置成一系列不同的中間旋轉變換,你可以執行這個旋轉。另一個方法就是使用:apply-transformation消息。該消息的方法接受一個增加的變換矩陣,然后通過使用該增加的變換左乘當前變換來構造一個新的圖形變換。默認地,該方法重畫圖形。因為該重畫使用緩沖區,下式將花費10個步驟將原始圖形平滑地旋轉成為變換后的圖形: > (let* ((c (cos (/ pi 20)))(s (sin (/ pi 20)))(m (+ (* c (identity-matrix 4))(* s '#2A((0 0 -1 0)(0 0 0 -1)(1 0 0 0)(0 1 0 0))))))(dotimes (i 10) (send w :apply-transformation m))) NIL 旋轉后的圖形數據

? ? :rotate-2消息可用來使用一個由兩個變量索引定義的平面的二維旋轉變換。該消息需要一個旋轉角度作為第三個參數。例如,下式將當前已經變換后的數據的0維到2維的數據旋轉pi/20角度。通過在你的圖形里將變換重設為nil,我們可以再表達式里使用:rotate-2消息,目的是將溫度對氣流圖形平滑地變換為氨損失對濃度圖形。每步都由兩個二維旋轉組成。圖形僅在第二次旋轉之后重畫。

? ? 可以對:transformation和:apply-transformation方法傳遞一個維度k<m的方陣作為參數。這種情況下改變換將作用到當前數據空間的前k維上。這對于一些原型來說是很有用的,比如說繼承自graph-proto原型的histogram原型。還可以向:apply-transformation消息里傳遞一個與矩陣參數相同維度的序列,這里的矩陣參數是帶;basis關鍵字的。該序列應該包含nil和非nil元素。該變換系統會忽略基里值為nil的對應位置處旋轉矩陣的元素。該特性允許低維旋轉變換可以在高維圖形里有效地使用。

練習 9.5
略。

獲取轉換后的數據

????graph-proto原型提供了用來獲取轉換后的點數據和linestart坐標數據當前值的消息。例如,第一個轉換后的點數據和linestart數據可以這樣給出:

> (send w :point-transformed-coordinate 0 0) -0.6190476190476191 > (send w :point-transformed-coordinate 1 0) -1.0000000000000002 和 > (send w :linestart-transformed-coordinate 0 0) -0.6190476190476191 > (send w :linestart-transformed-coordinate 1 0) -1.0000000000000002

9.1.4 鼠標事件和鼠標模式

????graph-proto原型的:do-click和:do-motion方法是用來支持這樣的語法的——即使圖形可以在不同的鼠標模式里。新的模式可以添加進來,你可以通過使用一個由Mouse Mode菜單項產生的對話框,或者向圖形發送一個消息,在幾個可用模式之間進行切換。鼠標模式可以使用一個Lisp符號來區別。每個鼠標模式都有一個標簽字符串,用在用來切換模式的那個對話框里,還有一個光標用來提供當前模式、自身點擊和行為動作的可視化暗示。為了自定義一個圖形和一個新的原型,通常不需要覆蓋:do-click和:do-motion方法。添加新的鼠標模式或者覆蓋由標準鼠標模式使用的消息是足夠的。

增加新的鼠標模式

????初始情況下,一個圖形由兩個鼠標模式,選擇模式和刷模式。:mouse-modes返回區別可用模式的符號列表:

> (send w :mouse-modes) (SELECTING BRUSHING) ? ? :add-mouse-mode消息添加一個新的鼠標模式,或者重定義一個現有的模式。該消息需要一個參數,即鼠標模式符號,還接受一些關鍵字參數。這些關鍵字包括用來指定標簽字符串的:title,用來指定光標符號的:cusor。:click和:motion關鍵字可以用來指定消息選擇器,當圖形在新的模式里的時候該消息選擇器用來處理點擊和動作事件。

? ? 舉個例子,我們可以向圖形里添加一個新的模式,該圖形僅展示在窗體上點擊的鼠標的坐標。該模式可以這樣添加:

> (send w :add-mouse-mode 'show-coordinates:title "Show Coordinates":click :do-show-coordinates:cursor 'finger) SHOW-COORDINATES 添加了這個模式之后,該圖形就有3個可用的模式了: > (send w :mouse-modes) (SELECTING BRUSHING SHOW-COORDINATES) 當圖形處于show-coordinate模式的時候,光標設成了finger(手指形)。當在該模式里點擊鼠標時,圖形將向:do-click消息發送:do-show-coordinates消息,該消息帶4個參數。因為沒有指定動作,動作事件將被忽略。

? ? 在使用該新模式之前,我們需要定義:do-show-coordinates方法。為了避免重畫圖形,我們可以使用XOR繪圖,在按鈕按下的時候繪制一個表示點擊位置的字符串。當按鈕釋放的時候,我們可以再次繪制字符串以移除字符串映像:

> (defmeth w :do-show-coordinates (x y m1 m2)(let ((s (format nil "~s" (list x y)))(mode (send self :draw-mode)))(send self :draw-mode 'xor)(send self :draw-string s x y)(send self :while-button-down #'(lambda (x y) nil))(send self :draw-string s x y)(send self :draw-mode mode))) :DO-SHOW-COORDINATES :while-button-down動作僅僅是等待鼠標按鈕彈起。

? ? 現在我們使用圖形菜單提供的對話框切換到新的模式,或者向圖形發送一個參數為模型符號的:mouse-mode消息,向圖形發送一個不帶參數的:mouse-mode消息將返回當前模式的符號:

> (send w :mouse-mode 'show-coordinates) SHOW-COORDINATES > (send w :mouse-mode) SHOW-COORDINATES

? ? 我們可以展示縮放后的坐標系統里的當前變量的當前坐標,而不是展示鼠標點擊處的圖上坐標。:canvas-to-scaled消息帶兩個整型參數——代表畫布上的一個點,返回兩個實數——代表縮放后坐標系統的兩個當前變量的對應的點:

> (send w :canvas-to-scaled 100 150) (-0.4 -0.3904382470119522) :canvas-to-real消息試圖轉換回是坐標系,但是它僅在圖形變換為nil時才合適地工作。為了允許你在顯示畫布、縮放和真實坐標系,我們可以定義一個:do-show-coordinates消息來檢查修飾符,在點擊時同時按下shift時顯示實坐標,在alt使用時顯示縮放坐標。如果沒有按下這些擴展修飾符,它僅顯示圖上坐標: > (defmeth w :do-show-coordinates (x y m1 m2)(let* ((xy (cond (m1 (send self :canvas-to-real x y))(m2 (send self :canvas-to-scaled x y))(t (list x y))))(s (format nil "~s" xy))(mode (send self :draw-mode)))(send self :draw-mode 'xor)(send self :draw-string s x y)(send self :while-button-down #'(lambda (x y) nil))(send self :draw-string s x y)(send self :draw-mode mode))) :DO-SHOW-COORDINATES ? ? :scaled-to-canvas和:real-to-canvas消息帶兩個實數參數,表示縮放坐標或實數坐標系中當前變量的坐標,然后返回響應畫布坐標的列表。

? ? 為了助于開發新的鼠標模式,一些其它的消息也是可用的。為了說明這些消息中的一些,我們可以構造一些鼠標模式,用于當鼠標在某點附近點擊和按下的時候通過在附近放置一個標簽來標示該點。對于使所有高亮的或選中的點顯示它們的標簽這一標準選項,我們提供的方法是對其的替代物。首先,我們可以通過使用以下表達式移除定義的模式:

(send w :delete-mouse-mode 'show-coordinates) 該操作不會移除與模式有聯系的鼠標點擊或者動作消息。該消息需要每個圖形至少有一個鼠標模式。其次,為了識別各點,我們可以制定一個新模式: (send w :add-mouse-mode 'identify:title "Identify":click :do-identify:cursor 'finger) 為了確定一次點擊足夠接近一個點,新模式的點擊方法需要設置一個容差值。每個圖形都保持一個容差值范圍,該范圍可以通過:click-range消息設置或獲取。該消息返回一個兩個整型數的列表,用像素表示的該容差值的寬度和高度。默認范圍如下: > (send w :click-range) (4 4) 該范圍被標準selection模式采用,當鼠標點擊的時候用來確定選擇的點。可以通過發送帶兩個整型參數的消息來指定一個新的點擊范圍,這兩個整型參數是新范圍的寬度和高度。

? ? 使用范圍和鼠標點擊位置的坐標,我們可以下個圖形發送:points-in-rect消息來獲取落在指定矩形區域內的影響的所有點的索引列表。例如:

(send w :points-in-rect 100 150 10 15) 然后,返回位于左上角坐標為(100, 150),寬10像素,高15像素的矩形區域內的影像的所有點的索引列表。如果該該區域內沒有點數據,返回nil。

? ? 使用這兩個詳細,我們的:do-identify消息可以定義成下面的樣子:

> (defmeth w :do-identify (x y m1 m2)(let* ((cr (send self :click-range))(p (first (send self :points-in-rect(- x (round (/ (first cr) 2)))(- y (round (/ (second cr) 2)))(first cr)(second cr)))))(if p(let ((mode (send self :draw-mode))(label (send self :point-label p)))(send self :draw-mode 'xor)(send self :draw-string label x y)(send self :while-button-down #'(lambda (x y) nil))(send self :draw-string label x y)(send self :draw-mode mode)))))

:points-in-rect消息使用中心點為鼠標點擊處的矩形,這里的點擊位置的寬度和高度與點擊范圍內指定的值相等。函數first返回由:points-in-rect消息返回的列表的第一個索引,如果列表為空則返回nil。因此,如果在點擊處附近的發現一個點,變量p是一個整數,如果沒有這樣的一個點,變量p就是nil。

? ? 為了說明另一個消息:drag-point,我們可以通過在圖形里移動數據點來定義一個鼠標模式,用來編輯我們的數據。我們可以這樣設置新的模式:

(send w :add-mouse-mode 'point-moving:title "Point Moving":cursor 'hand:click :do-point-moving) 在圖形里,:drag-point消息用來拖動一個點,該消息帶兩個參數,鼠標點擊的圖上坐標和檢測某點是否接近點擊位置。如果存在這樣的點,將在窗體周圍拖拽出一個灰色的長方形直到鼠標按鍵釋放。在此期間,該點的坐標將改變同時圖形重畫,除非使用了一個值為nil的:draw關鍵字。新的坐標將使用上邊提到的變換消息來計算。對于一個轉換后的圖形,;drag-point消息試圖移動與當前變量相關的平面上的點,并保持正交分量不變。如果變換是正交的,這才會正確地起作用。:drag-point消息的方法返回被拖動的點的索引,如果沒有這樣的足夠接近點擊處的點將返回nil。使用:drag-point,我們可以這樣為:do-point-moving消息定義一個方法: (defmeth w :do-point-moving (x y m1 m2)(let ((p (send self :drag-point x y)))(if p (format t "Point ~d has been moved.~%" p)))) 練習 9.6
略。

標準鼠標模式

????初始情況下,由graph-proto原型構造的圖形包括兩個模式:selecting模式和brushing模式。selecting模式使用arrow光標,僅需要一個點擊方法:do-select-click;brushing模式使用brush光標,它的點擊消息和動作消息是:do-brush-click和:do-brush-motion。

? ? 針對selecting和brushing模式的點擊和動作手勢是被用來設計基本的用戶接口以針對這些鼠標模式。實際的選擇和高亮操作是通過兩個其它消息實現的,:unselect-all-points和:adjust-points-in-rect。:unselect-all-points消息不帶參數。:adjust-points-in-rect消息需要5個參數,前4個參數矩形的整型坐標值,左上角的兩個坐標值,還有矩形的寬和高。第5個參數是點狀態符號selected或hilited中的的一個。當發生一個點擊事件時,該圖形處于selecting模式,:do-select-click方法以下邊的方式使用這些消息:

  • 如果點擊操作不包括擴展修飾器(即shift或alt鍵),:unselect-all-points消息發向任意當前選中點集中未被選中的點。
  • 然后,:adjust-points-in-rect消息被發送,其作用范圍是以點擊點為中心的,由當前點擊范圍指定的寬和高的矩形區域的坐標范圍。第5個參數是selected。這個消息的方法應該會選擇指定矩形范圍內的所有可視點。
  • 當鼠標按鍵按下時,一個角固定在鼠標點擊處的虛線矩形將拖拽出來并覆蓋圖形。當鼠標按鍵釋放時,一個帶有最終矩形坐標和符號selected作為參數的:adjust-points-in-rect消息將被發送出去。

? ? 當圖形處于brushing模式時,:do-brush-click方法首先取消對所有點的選擇操作,除非給定了擴展修飾符;然后,該方法將發送一個以當前刷坐標和符號'selected為參數的:adjust-points-in-rect消息。每次鼠標按下并移動的時候,它都會持續發送該消息。:do-brush-motion方法將發送參數為當前刷坐標和符號hilited為參數的消息。當第5個參數是hilited時,該消息的方法有望高亮矩形區域內所有可見的點,然后將矩形外高亮的點取消高亮效果。

? ? 當前刷的位置和大小可以使用:brush消息來獲取。刷由4個整數指定:右下角的畫布坐標x、y,連接鼠標的角,還有刷的寬度和高度。通過發送一個帶四個整數參數(即新坐標)的:brush消息,可以指定新刷的坐標;:resize-brush消息提供了一個對話框來交互地設置新刷的大小,該消息可以通過使用圖形菜單里的Resize Brush菜單項來發送給該圖形。

? ? 使用:unselect-all-points和:adjust-points-in-rectx消息的協議允許開發新的圖形,而不用修改刷模式或選擇模式方法自身。例如,在彩色顯示器的系統上,我們可以為這兩個消息修改這些方法,以確保選中的點著紅色,未選中的點著繪圖色。在發送下邊這條消息以確保使用彩色繪圖之后,

(send w :use-color t) 我們可以這樣為:unselect-all-points定義消息:

(defmeth w :unselect-all-points ()(send self :point-color (iseq (send self :num-points)) nil)(call-next-method)) 該方法將所有點的顏色設置為nil,然后調用從graph-proto原型繼承來的方法。新的:adjust-points-in-rect方法可以這樣定義:

(defmeth w :adjust-points-in-rect (x y w h s)(if (eq s 'selected)(let ((p (send self :points-in-rect x y w h)))(if p (send self :point-color p 'red))))(call-next-method x y w h s)) 變量p包含指定的矩形區域內的點的索引列表,如果該列表不是nil的則金發送:point-color消息。

9.1.5 連接

????圖形里的點可能處于一些不同的狀態,selecting和brushing操作提供了一種容易的方式來改變圖形里點的狀態。為了瀏覽數據集的一些視圖之間的關系,Lisp-Stat繪圖系統允許圖形之間的互連操作。當兩個或更多圖形連接到一起時,系統將試圖保證連接在一起的圖形里的點狀態時相同的。

? ? 默認的Lisp-Stat連接系統基于一個松散的聯合模型,在這個模型里,被連接到一起的不同圖形的點通過他們的索引值彼此關聯。因此,在一個圖形里選擇索引值為3的點,同時也會選中與該圖形連接的圖形里索引值同為3的點。在不存在點的其它屬性匹配的意義下,這個聯合是松散的。在連接的圖形中的點可以有不同的標簽、顏色或者符號。其它的連接模式也是可能的,其中一個可替換的連接模式將在10.6節里說明。

確定哪些圖形可以連接

????確定哪些圖形可以連接到其它圖形上的系統依賴:linked和:links兩個消息。當向圖形發送:links消息時,如果該圖形沒有被連接則返回nil;如果該圖形被連接了,它應該返回一個列表,該類表包含所有連接到該圖形的接收了該消息的其它圖形,圖形自身可能是該列表的一個元素。:linked消息可以以不帶參數的形式發送,用來確定該圖形是否已經被連接,如果已經被連接了,返回t;否則,返回nil。該消息可以接受一個可選參數,該參數為t就是連接該圖形,該參數為nil就是解開連接。

? ? graph-proto原型的:links和linked方法將維護一個包含已連接圖形的單列表,該列表由被連接的圖形的:links消息返回,該列表也可以通過使用linked-plots函數好獲取,當某個圖形被連接時,該圖形的點的狀態傳遞到其它被連接的圖形,就像由:links消息返回的結果確定的一樣。

? ? 因為被連接圖形的確認完全基于這兩個消息,定義一個可代替的策略是相當簡單的。例如,如果我們想確保所有與stack loss data相關的圖形都與另一個數據相連而不是與所有的圖形都相連,我們可以這樣設置一個stack loss圖形的列表:

(setf *stack-plots* nil) 然后,給予每個stack圖形它們自己的:links和:linked方法,它們這樣定義:

(defmeth w :links ()(if (member self *stack-plots*) *stack-plots*))(defmeth w :linked (&optional (link nil set))(when set(setf *stack-plots*(if link(cons self *stack-plots*)(remove self *stack-plots*)))(call-next-method))) 避免為每個新圖形添加這些方法的一個方式是定義一個獨立的stack loss圖形原型。

點狀態和連接

????圖形里的每個點都是四種狀態中的一種,對應的符號為invisible, normal, hilited和selected。graph-proto繪圖方法可以繪制高亮的點和由點的符號的高亮版本選中的點。處于正常狀態的點使用正常符號來繪制,處于invisible狀態的點不被繪制。點的狀態可以通過:point-state消息來確定和繪制。對于處于stack loss數據圖形里的第一個點:

> (send w :point-state 0) NORMAL :point-state消息的方法是矢量化的,所以它可以用來確定圖形里的所有點的狀態,方法如下: > (send w :point-state (iseq 21)) (NORMAL NORMAL NORMAL NORMAL ...) ? ? 為了改變點的狀態,可以向:point-state消息的第二個參數賦值為一個新狀態,下邊的表達式將第一個點的狀態改為selected。當圖形里的一個點的狀態發生了改變,在所有被連接的圖形了對應的點的狀態也會發生改變。另外,會向每個圖形發送一個帶一個參數的:adjust-screen-point方法,該參數是想要改變的那個點的索引值。該方法負責改變屏幕上點的影像。

? ? :adjust-screen-point方法采取的動作即取決于改點的新狀態也取決于改點的上一個狀態。當發送:adjust-screen-point消息的時候,:point-state消息返回的值將表達新的狀態,點的上一個狀態可以通過向:last-point-state消息發送一個參數來獲取,該參數是改點的索引值。

? ? 為了在所有連接在一起的圖形該處最佳的對應關系,:adjust-screen-ponit方法試圖盡可能快地重畫點數據,以表達它們之間的任何狀態變化。對于有些狀態改變來說,這是相當簡單的。如果點的狀態在normal, hilited和selected這些值之間變化的話,那么:adjust-screen-point方法將使用上一章引入的:replace-symbol方法來改變屏幕上顯示的符號。不幸的是,如果點的新狀態是不可見的,不重畫圖形而從屏幕上清晰地移除改點是很困難的。由于每次將一點設置成不可見狀態都要進行重畫操作是很浪費的,所以:adjust-screen-point方法采取了一個間接的方法:它向圖形發送一個標識位來指示是否需要調整以適合窗體,:needs-adjusting消息用來設置和獲取這個標識位的值。在將一個點的狀態設置為不可見后,該標識位的值為t:

> (send w :needs-adjusting) NIL> (send w :point-state 0 'invisible) INVISIBLE> (send w :needs-adjusting) T 在方便的時候,也可以向圖形發送:adjust-screen消息,如果需要的話,該消息的方法將檢查該標志位、重設它,然后重畫圖形。因此,在將一個點的狀態設置為不可見之后,在對所有需要改變狀態的點進行調整之后,:adjust-points-in-rect方法將向所有連接的圖形發送:adjust-screen消息。

? ? 作為這些想法的一個簡單的展示,我們可以為我們的圖形定義一個新的:adjust-screen-point方法,該方法將所有高亮的點和選中的點設置為紅色,然后將所有未高亮的點設置為nil:

> (defmeth w :adjust-screen-point (i)(let* ((state (send self :point-state i))(color (if (member state '(selected hilited)) 'red)))(send self :point-color i color))(call-next-method i)) 該方法與早先我們使用的那個為:adjust-points-in-rect方法修改的方法有些不同,之前的方法,僅當在圖形自身內部的點的狀態被刷模式或選擇模式改變的時候才會著色;而現在的方法可以確保即使是在被連接的圖形里由刷模式或選擇模式改變狀態的點,其顏色也會調整。

練習 9.7
略。

高級狀態消息

????對于獲取和改變點的狀態,還有一些其它消息是可用的。:point-showing, :point-hilited和:point-selected消息需要一個點的索引做參數,然后返回t或nil來分別指示點的狀態是否是可見的、高亮的或被選中的;對這些消息的第二個參數賦值為t或nil,將會對其狀態做合適的改變。這3個方法都是矢量化的,這3個方法在返回之前都會發送:adjust-screen消息。

? ? :selection消息返回當前被選中的所有點的列表,如果向該消息傳遞一個索引列表作為它的可選參數的話,該消息將取消所有選中的點,然后選中參數列表里指定的所有可見的點,他在返回前將發送:adjust-screen消息。:points-selected消息的方法與:selection方法是等效的;:points-hilited和:points-showing的方法也是相同的。

? ? :erase-selection方法將所有當前選中的點的狀態改變成不可見狀態,:show-all-points方法將所有點的狀態改為正常狀態;:focus-on-selection方法將所有未選中的方法設置為不可見狀態。這3個方法在返回之前都發送:adjust-screen消息。

? ? 這里有兩個有用的謂詞消息是可用的。:any-points-selected-p消息的方法在圖形里任何一個點被選中時都返回t,否則返回nil。:all-points-showing-p消息在所有點都是可見狀態小返回t,任意一個點為不可見狀態則返回nil。

9.1.6 窗體布局、縮放和重畫

縮放方法

????graph-proto原型的:resize方法基于一定的假設,該假設是關于圖形的布局的。圖形的內容,點數據與線數據的影像被限制在一個叫做內容矩形的矩形里。如果圖形里包含坐標軸,它們將立即在內容矩形的外部被畫出來。由內容和坐標軸組成的整個圖形被一個邊緣包裹起來,這個邊緣被用來束縛圖形,像標準旋轉圖形的旋轉控制,這個邊緣沿著窗體的畫布的左側、上側、右側和下側都有一個固定的像素數的留白。當該圖形變換大小的時候,:resize消息會保持邊緣不變,然后內容矩形的大小以填充畫布的剩余部分。內容矩形的精確的大小和形狀依賴于該空間是否需要x和y坐標軸,坐標軸是否擁有標簽,內容矩形是否保持固定的方位比例。對于一個固定的方位比例,內容多邊形是這樣的一個最大矩形,它是能裝下邊緣的并為坐標軸留下空間的那個最大正方形。如果該圖形允許方位比例改變,內容多邊形將是滿足這個限制的最大的矩形。圖9.3針對一個帶有坐標軸和固定方位比例的圖形的邊緣和內容矩形。

圖9.3?帶有坐標軸和固定方位比例的圖形的邊緣和內容矩形

內容矩形可以通過使用:content-rect消息來設置和獲取。不適用參數的話,該消息將返回內容矩形的坐標的列表(比如說一個包含左上角兩個坐標值、寬度和高度的列表):

> (send w :content-rect) (0 0 250 251) 如果該消息使用四個參數來調用的話,它將會把內容矩形設置成指定的坐標。

? ? 圖形的邊緣可以使用:margin消息來設置和獲取。不適用參數調用,該消息返回一個四個整型數表示的列表,代表邊緣距離畫布的上側、頂側、右側和下側的距離的像素值。初始情況下,一個從graph-proto原型創建的圖形的邊緣,其值都是0:

> (send w :margin) (0 0 0 0) 為了設置一個新的邊緣,可以給:margin消息賦予4個參數。

? ? 圖形的方位比例可以使用:fixed-aspect消息確定和設置,對于固定的方位比例該結果是一個非空值,對于一個可變的方位比例該結果返回nil。對于我們的例子,方位比例初始情況下是可變的:

> (send w :fixed-aspect) NIL 為了改變方位比例,你可以向該消息發送一個nil和一個非空的參數,以下表達式給予我們的圖形一個固定的方位比例。

? ? 如果使用:margin, :fixed-aspect, x-axis 或 :y-axis消息,布局特征的任意一個發生改變的話,那么這些消息的方法將向圖形發送:resize和:redraw消息,除非:draw關鍵字被賦予了值為nil的參數。

? ? 在返回之前,:resize方法將向圖形發送:redraw-overlays消息,這里的疊置(Overlays)將在9.1.7節里描述,它提供方便的方法來實現圖形控制,比如對旋轉圖形的旋轉控制。

重畫方法

????繪圖原型的重畫方法:redraw將重畫過程打斷成幾個階段。首先,它發送:redraw-backgroud消息,該消息的方法將擦除畫布,然后當前圖形設置需要的所有坐標軸。下一步,:redraw消息向圖形發送:redraw-overlays消息。最后,向圖形發送:redraw-content消息,該消息對應的方法負責點數據和線數據自身。:redraw, :redraw-content和:redraw-backgroud消息對應的方法都使用了緩沖區。

? ? 將背景繪制與內容繪制分離的原因是,繪制坐標軸和疊置操作可能很耗時,并且僅有內容改變時這是不需要的。結果,像:adjust-screen和:rotate-2這樣的消息對應的方法僅需要向圖形發送:redraw-content消息以改變圖形的內容。

? ? 開發新圖形時,很少要覆蓋:graph-proto的:redraw方法,通常寫一個新的:redraw-content方法就最夠了。

下層消息

????為了有助于繪圖方法,graph-proto原型轉換系統保持將待轉換的點數據和線數據坐標的整型版本(即轉換后的坐標數據為整型值)。整型數的范圍,即所謂的畫布范圍,與每個變量都有關系。該系統將被變換坐標值從被縮放的比例縮放到畫布的比例。那么如果一個變量的范圍是從0到200,那么在-1.0到1.0范圍內坐標值為0.5的坐標對應的畫布坐標是150。

? ? 變量的畫布范圍可以使用:canvas-range消息進行獲取和設置。對于我們的事例圖形里的第一個變量,它的范圍就是:

> (send w :canvas-range 0) (0 232)

對于當前變量的第一個,:resize方法將畫布范圍設置為從0到內容矩形寬度這樣的范圍,對于所有其它變量來說,該范圍被設置到從0到內容多邊形高度這一范圍中。

? ? 點數據和直線中的點數據的畫布坐標可以使用:point-canvas-coordinate和:linestart-canvas-coordinate消息來獲取。這些消息可以向我們在上邊介紹的其它的坐標消息一樣來使用。第一個點的前兩個變量的畫布坐標可以這樣獲取:

> (send w :point-canvas-coordinate 0 0) 80> (send w :point-canvas-coordinate 1 0) 58 ????繪圖系統還會使用一個在內容矩形里的叫做內容原點的點,該原點可以使用:content-origin消息來設置和獲取: > (send w :content-origin) (9 250) :resize方法將該原點放置在內容矩形的左上角稍低點的位置。:redraw-content方法使用畫布坐標作為偏移量。

? ? 在這個上下文里使用的一個終極消息是:content-variables,該消息對應的方法與:current-variables方法等價,除非在這樣的情況下——當該變量變化時它沒有重畫圖形。

9.1.7 圖形疊置

????疊置可以被視為一張透明的紙,這張紙在內容繪制之前放置在圖形的背景上,這些紙保持一定的順序,并從下向上繪制。為了不被圖形的內容覆蓋,疊置層通常只在圖形的邊緣里繪制。

? ? 圖形疊置的一個關鍵的特性是它們的攔截或者說是過濾鼠標點擊的能力。graph-proto原型的:do-click方法允許每個疊置層,從頂層逐層向下,來接收或者傳遞一個鼠標點擊事件。如果該點擊事件未被任何疊置層接收,那么它僅能傳遞到當前鼠標模式上。該特性使使用疊置層來實現簡單的圖形控制成為可能,比如讓某個圖形執行特殊的動作。對于旋轉圖形的旋轉操作就是以疊置層實現的。

? ? 圖形疊置層是一個對象,它繼承自graph-overlay-proto原型。通過向圖形發送帶一個參數的:add-overlay消息(該參數是疊置層對象)來向一個圖形里添加疊置層。該操作將新的疊置層置于所有其它疊置層之上;通過向圖形發送帶一個參數的:delete-overlay消息來移除疊置層(該參數是要移除的疊置層對象)。

? ? 當圖形放縮的時候,:resize方法在返回之前向圖形發送:resize-overlays消息,該消息對應的方法向圖形里的每個疊置層發送:resize消息。當圖形重畫時,:redraw方法向圖形發送:redraw-overlays消息,該消息對應的方法向每個疊置層發送:redraw消息,從最底層的疊置層開始一直向上直到疊置堆棧的最頂端。

? ? graph-proto :do-click方法向疊置層發送:do-click消息,該消息帶它接受到的一些參數,該過程從最上邊的疊置層開始,持續穿過其它疊置層,直到返回一個非nil值作為點擊的結果。如果所有的疊置層對點擊動作的反應都返回nil,那么對于當前的鼠標模式該click事件將被傳遞給click方法。

? ? 舉個例子,我們可以向我們的氨氣損耗數據圖形里添加一個疊置層,那個圖形包含一個按鈕的和一個跟著一個標簽的正方形。當在正方形里發生點擊事件時,圖形將接受指令運行一個平滑差值算法,該算法從溫度對氣流的圖形到氨氣損失到濃度的圖形。為了避免圖形縮放中需要重新定位按鈕,我們可以將它放置在圖形的左上角位置。

> (let ((h (+ (send w :text-ascent) (send w :text-descent))))(send w :margin 0 (round (* 1.5 h)) 0 0)) ? ? 上式設置了圖形上邊距,目的是為窗體的字體里的一行文本留下足夠的空間。通過向疊置層原型發送:new-message消息,我們可以構造疊置層對象: > (setf interp-overlay (send graph-overlay-proto :new))

接下來,我們可以給予該疊置層一個槽,用來容納描述按鈕容器和標簽字符串的位置的信息。

> (let* ((ascent (send w :text-ascent))(x ascent)(y (round (* 1.5 ascent)))(box ascent))(send interp-overlay :add-slot 'location(list x y box (round (+ x (* 1.5 box)))))) 然后,我們可以為該槽定義一個讀取方法: > (defmeth interp-overlay :location () (slot-value 'location)) ? ? 現在可以定義該疊置層的:redraw方法來獲取位置信息,這里使用:location消息,然后在指定位置繪制一個盒子容器和一個標簽: > (defmeth interp-overlay :redraw ()(let* ((loc (send self :location))(x (first loc))(y (second loc))(box (third loc))(string-x (fourth loc))(graph (send self :graph)))(send graph :frame-rect x (- y box) box box)(send graph :draw-string "Interpolate" string-x y))) 該方法向疊置層發送了:graph消息,目的是某圖形是否含有某疊置層。當某疊置層安裝到一個圖形以后,該疊置層系統將確保該消息返回合適的結果。

? ? :do-click消息將返回nil,除非點擊落在按鈕的盒子容器的內部;如果點擊發生在盒子容器里,該方法將向圖形發送:interpolate消息然后返回t,進一步確保點擊事件沒有被做進一步處理:

> (defmeth interp-overlay :do-click (x y m1 m2)(let* ((loc (send self :location))(box (third loc))(left (first loc))(top (- (second loc) box))(right (+ left box))(botton (+ top box))(graph (send self :graph)))(when (and (< left x right) (< top y bottom))(send graph :interpolate)t))) 為了完成這個例子,我們需要為我們的圖形定義一個:interpolate方法。可以基于9.1.3節的平滑旋轉循環,做一個簡單的定義,例如:

圖 9.4 疊置層里帶差值按鈕的煙霧損失數據圖形

> (defmeth w :interpolate ()(send self :transformation nil)(dotimes (i 10)(send self :rotate-2 0 2 (/pi 20) :draw nil)(send self :rotate-2 1 3 (/ pi 20)))) 最后,通過使用下式將疊置層安裝到我們的圖形里: > (send w :add-overlay interp-overlay) 結果見圖9.4,圖形內容部分發生的點擊像以前一樣被處理了,但是在按鈕里的點擊引起圖形運行了差值算法。

? ? 待使用疊置層試驗之后,我們可以使用以下表達式來移除該疊置層:

> (send w :delete-overlay interp-overlay) 練習9.8

練習9.9

練習9.10

9.1.8 菜單和菜單項

????graph-proto原型的:isnew方法可以通過向圖形對象發送:new-menu消息來添加一個菜單,該消息對應的方法按順序向對象發送:menu-title和:menu-template消息。:menu-title消息返回一個標題字符串:

> (send w :menu-title) "Plot" 在構建新的圖形菜單的時候,該消息可以用來安裝一個新的菜單標題,在給予一個新的原型一個更合適的菜單標題上,這是非常有用的。

? ? :menu-template方法預期會返回一個列表,該列表用來構建菜單項,該列表可以包含菜單項對象,這些菜單項對象可以簡單地安裝在菜單里,或者也可能包含一些用來指定標準菜單項的符號。該消息的graph-proto原型對應的方法返回一個符號列表:

> (send w :menu-templates) (LINK SHOWING-LABELS MOUSE REIZE-BRUSH ...)
  • :new-ment方法為這些符號里的每個符號都構造了一個合適的菜單。下邊的符號可以用來指定標準菜單項:
  • color——發送:set-sselection-color消息,該消息會顯示一個對話框,用來改變選中的點的顏色。
  • dash——一個處于不可用狀態的分隔符。
  • focus-on-selection——發送:focus-on-selection消息。
  • link——使用:linked消息切換圖形的鏈接。
  • mouse——發送:choose-mouse-mode消息,該消息顯示一個對話框,用來改變鼠標模式。
  • option——向圖形發送:set-options消息,該消息顯示一個對話框,用來設置一些選項。
  • redraw——發送:redraw消息。
  • erase-selection——發送:erase-selection消息。
  • rescale——發送:adjust-to-data消息。
  • save-image——發送:ask-save-image消息,該消息顯示一個對話框,用來將圖像保存成文件。
  • selection——發送:selection-dialog消息。
  • show-all——發送:show-all-points消息。
  • show-labels——使用:showing-labels消息切換顯示標簽。
  • symbol——發送:set-selection-symbol消息,該消息顯示一個對話框,用來改變選中的點的符號。

這些菜單項的一些使用:any-points-selected-p或者:all-points-showing-p來確定他們是否處于可用狀態(使能)。

? ? :new-menu消息還可以被賦予一個可替代的標題字符串參數,該參數用來代替:menu-title消息的結果。菜單項的可選列表可以通過使用:items關鍵字來使用,該列表可以包含上邊列出的符號中的任意多個,目的是指定標準菜單項。例如:

> (send w :new-menu "Stack Loss" :items '(link dash rescale)) 該表達式賦予stack loss圖形一個菜單,它僅包括link項和rescale項,中間用一條直線分開。可替代的方法就是去定義一個新的:menu-template方法,然后發送:new-menu不帶:items關鍵字的消息給它。對于開發一個新的原型是很有用的。

9.1.9 雜項消息

????還有一些其它消息在graph-proto原型里是可用的。:showing-labels消息用于設置和獲取標簽選項的狀態,如果該值為非nil值,繪圖方法將把它放置于高點的選中的點數據附近。

? ? 有些方法是專為2維圖形設計的。add-function消息接受一個帶一個實數參數的函數,代表一個區間的高低界限的兩個實數,還有一個指定一定數量點數據的關鍵字參數。該消息對應的方法構造了一個網格,并在該網格上計算函數,然后將對應的線集合添加到圖形上。它也接受關鍵字參數:color和:type,用來指定顏色和線型。該圖形將被設置:redraw-content消息,除非使用了參數為nil的:draw關鍵字。
? ? 對于線性函數,:abline消息帶兩個參數,一個截矩和一個斜率,然后將該直線加到圖形上。該獨立變量的范圍就是x軸的當前范圍。
? ? :adjust-depth-cuing消息主要由旋轉圖形來使用,但是它也可以被其它圖形使用,它將整數維的索引作為參數,對于那些維度使用畫布坐標(它們被視為超出屏幕的坐標),目的是為圖形里的點數據和線數據使用深度標識。通過將點數據的符號改變為符號dot1,dot2,dot3和dot4中的一個,該點數據是深度標識的。符號dot1是為離視點最遠的點使用的,dot4用于里視點最近的點。通過改變線的寬度也可以達到顯得深度標識效果。

9.2 一些標準繪圖原型

????第二章里介紹的那5個標準圖形類型,它們是使用從graph-proto原型繼承來的原型構造的。盡管這些圖形在外觀上相差很大,但是它們僅需要向graph-proto提供的原型,覆蓋和增加少量的方法。

9.2.1 散點圖

????基礎散點圖原型scatterplot-proto用于構造一類圖形,即由plot-points和plot-lines函數構造的圖形。它至少需要二個維度的數據。針對:add-points和:add-lines消息的二維散點圖,允許這樣指定新數據——使用兩個分離的列表代替所需的列表的列表。那樣的話,如果s是一個二維散點圖,x和y是等長度的數值型列表,那么下邊的兩個語句是等價的:

> (send s :add-points x y) > (send s :add-points (list x y)) ? ? 如果圖形的尺度類型是nil的話,:adjust-to-data方法向圖形里添加一個坐標軸,它還會將坐標范圍設置到坐標軸上產生好看的坐標刻度。

9.2.2 散點圖矩陣

????散點圖矩陣原型scatmat-proto至少需要2個維度的數據,它使用一個固定的長寬比例,它的內容的原點坐標在內容矩形的左下角,每個變量在畫布上的范圍設置在一定范圍內——子圖的列的左右范圍,從原點開始量度。通過修改:do-click和:do-motion方法,將內容變量設置為包含光標的那個子圖的索引上,這個操作允許很多繼承它的方法可以不經修改就正常工作。

? ? 與:add-lines, :add-points, :adjust-screen-point和:redraw-content消息相對的方法,通過修改它們可以讓矩陣里的所有子圖形合適地繪制。如果圖形的尺度類型是nil,默認地,:redraw-content方法還可以在對角圖里繪制變量標簽和界限。

9.2.3 旋轉圖形

????由spin-plot函數產生的,用來旋轉圖形的原型就是spin-proto,該原型至少需要三個維度的數據,它使用一個固定的橫寬比數據,其默認的尺度類型是variable。:content-variables方法使用3個內容變量索引,前兩個以常規方式使用,第三個變量是深度提示變量的索引。:resize方法將內容的原點放置于內容矩形的中間。

? ? :redraw-content方法在進行標準內容重畫之前調整深度提示。如果圖形要顯示坐標軸,坐標軸可以通過調用:redraw-content方法來重畫,該方法可以通過向圖形對象發送:draw-axes消息來構造。如果尺度類型為nil,:adjust-to-data方法將調整圖形的范圍,以確保所有的點在圍繞原點所做的旋轉過程中均是可見的。:depth-cuing和:showing-axes消息可以用來確定一個圖形時使用深度提示還是顯示坐標軸。通過發送一個值為nil或非nil的參數,這兩個消息可用來圖形對應的狀態。

? ? 旋轉圖形下邊的控件可以以一個疊置層的形式實現,該疊置層由:isnew方法加入。這些按鈕將旋轉的類型設置為pitching、rolling或yawing,調整角度符號,然后在鼠標按下時發送:rotate消息,:do-idle方法也發送該消息。旋轉圖形里的當前角度可以通過使用:angle消息來設置和獲取。角度以度計量。旋轉類型可以通過使用:rotation-type消息設置和獲取,它的值可能是符號pitching, rolling或者yawing中的一個,也可能是一個以漸進式旋轉來使用的旋轉矩陣。如果旋轉類型是一個符號,:rotate方法使用:rotate-2方法(使用合適的變量和角度作為其參數);如果該類型是一個矩陣,:rotate使用:apply-transformation。

? ? 除了添加控件疊置層,針對該原型:isnew方法將圖形的橫寬比設置為固定值,并為疊置層設置一個合適的邊緣。

? ? 針對旋轉圖形原型的:add-function方法是為三維圖形設計的,它需要一些參數:一個兩個參數(x軸限值和y軸限值)的函數,和四個實數數值。:abcplane消息有三個實數參數a,b和c,然后增加線段來顯示函數f(x,y)=a+bx+cy的一段。

9.2.4 直方圖

????直方圖原型是histogram-proto,直方圖在一個m+1維的圖形里顯示m維的點數據,剩余的維度用于圖形的y坐標,第一個維度被扔掉,作為直方圖來顯示,例如,下邊的表達式針對stack loss 數據構造了一個直方圖:

> (setf hs (histogram (list air temp conc loss))) 該直方圖變量的數量是5: > (send hs :num-variables) 5 內容變量是: > (send hs :content-variables) (0 4) 那么,初始情況下該圖形顯示的是數據集里第一個變量——氣流的直方圖。如果對圖形hs使用了變換,它將顯示轉換后的數據的第一維度數據的直方圖。例如,在為們為圖形的尺度類型設置為variable之后: > (send hs :scale-type 'variable) 下邊的表達式將在10步之內旋轉成溫度變量的直方圖。

? ? 對于一維數據的直方圖,可以給予:add-points方法一個數值序列而不是一個數值序列的列表;對于一個m維數據的直方圖,:add-points方法需要一個m個序列的列表。那么stack loss數據可以使用下式來安裝:

> (send hs :add-points (list air temp conc loss)) ? ? :add-lines消息相對應的方法(它也可能用于向一個直方圖里添加一個密度線),它需要一個包含m+1個序列的列表。最后一個序列用來作為y坐標軸。例如,如果hp是一個一維的降水量數據的直方圖(該數據在第2.2.1節里),它可以這樣構造: > (setf hp (histogram precipitation)) 那么下邊的表達式將一個正常濃度的圖形添加到直方圖里。

? ? 因為:transfomation和:apply-transformation消息相對應的方法可以接受一個維度低于圖形維度矩陣,你也可以使用相同維度的變換作為直方圖里的點數據。

? ? 針對:adjust-screen, :adjust-screen-point, :redraw-content和:adjust-points-in-rect這些消息,直方圖原型提供了它自己的方法。如果尺度類型為nil,:adjust-to-data犯法增加一個x軸,該方法也會重新計算直方圖里的矩形條塊,與:clear-points和:resize相對應的方法也會修改以適應這些矩形條塊。

? ? 有兩個消息提供了對這些矩形條塊的信息訪問能力。:bin-count消息返回每一個矩形條塊的數量的列表;不帶參數的:num-bins消息返回當前用到的矩形條塊的數量,如果給它傳遞一個正整數來調用的話,它將矩形條塊的數量給位指定的數量,當指定了一個行的矩形條塊的數量的時候,同時向圖形對象發送:redraw消息,除非關鍵字參數:draw接受了值為nil的參數。

9.2.5 名稱列表

????最后一個標準繪圖原型是name-list-proto,它的目的是提供一個點標簽的可連接的列表,它不適用任何數值數據。

? ? 名稱列表可以使用一個維度數m=0的數字來構造。該原型的:add-points方法可以接受一個數值來指定添加的點的數量,用來替代坐標值列表的列表。例如,針對stack loss數據的名稱列表可以這樣構造:

> (setf n (send name-list-proto :new 0)) 擁有21個標簽的集合和以使用下式來添加: > (send n :add-points 21) ? ? :add-lines方法被重定義,目的是不要做任何事,因為名稱列表不需要顯示線數據。:adjust-screen, :adjust-screen-point, :redraw-content和:adjust-points-in-rect方法也會被重定義。:isnew方法名稱列表擁有一個垂直滾動條。

轉載于:https://my.oschina.net/u/1011760/blog/359393

總結

以上是生活随笔為你收集整理的Lisp-Stat翻译 —— 第九章 统计绘图窗体的全部內容,希望文章能夠幫你解決所遇到的問題。

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

日韩欧美在线中文字幕 | 久久久91精品国产一区二区精品 | 一区二区三区电影在线播 | 蜜臀一区二区三区精品免费视频 | 香蕉网址| 免费精品在线观看 | 日本中文字幕在线电影 | 最新中文字幕视频 | 丁香五婷 | 九九在线精品视频 | 国精产品满18岁在线 | 五月天,com| 2018亚洲男人天堂 | 亚洲亚洲精品在线观看 | 国产精品免费视频网站 | 国偷自产中文字幕亚洲手机在线 | 99视频国产精品 | 国产精品99久久久久久宅男 | 一区二区不卡在线观看 | 免费观看一区二区 | 狠狠色狠狠色综合日日92 | 国产精品一区二区三区久久 | 欧美不卡视频在线 | 97在线观看视频 | 国产a级片免费观看 | 久久久精品 一区二区三区 国产99视频在线观看 | www.色婷婷.com | 黄色成人在线网站 | 精品久久久久久亚洲综合网 | 免费黄a | 九草视频在线观看 | av超碰免费在线 | 91看片淫黄大片一级在线观看 | 日韩一区二区免费视频 | 中文字幕在线字幕中文 | 久久精品亚洲综合专区 | adc在线观看| 天天操天天射天天 | 中文字幕日韩伦理 | 国产一级免费电影 | 五月天综合色激情 | 成年人黄色av | 亚洲精品美女在线观看 | 99精品在线视频观看 | 精品在线二区 | 欧美国产日韩一区二区三区 | 激情网站网址 | 免费看黄在线观看 | 久久草草影视免费网 | av888.com| 91丨九色丨蝌蚪丨对白 | 超碰大片 | 综合精品久久 | av在线等| 国产亚洲精品久久19p | 99久久日韩精品免费热麻豆美女 | 六月激情丁香 | 欧洲精品亚洲精品 | 狠狠色丁香婷婷综合橹88 | 亚洲一区二区视频在线播放 | 91中文在线视频 | 黄网站免费大全入口 | 欧美极度另类 | 成人av免费| 日本女人的性生活视频 | 九九热在线观看视频 | 国产精品一区在线观看你懂的 | 久久一区二区三区超碰国产精品 | 精品国产91亚洲一区二区三区www | 狠狠色狠狠色综合日日92 | 国产精品国产亚洲精品看不卡 | 97在线观看免费高清 | 婷婷av网 | 久久综合激情 | www.成人精品 | 国产精品专区h在线观看 | 亚洲热视频 | 97国产超碰 | 久久免费国产精品1 | 玖玖在线视频观看 | 久艹视频免费观看 | 午夜久久久影院 | 日韩精品亚洲专区在线观看 | 久久成视频 | 欧美色图一区 | 久草在线视频中文 | 四虎成人免费影院 | 在线观看精品一区 | free. 性欧美.com | 国产日韩欧美综合在线 | 亚洲人毛片 | 国产生活一级片 | 在线观看av大片 | 亚州av成人 | 久久国产精品视频 | 免费看的黄网站 | 日韩精品欧美一区 | 日韩视频一区二区 | 啪嗒啪嗒免费观看完整版 | 伊人五月天 | 中文字幕在线免费 | 久久97精品 | 99久久www| 国产精品密入口果冻 | 国产美女永久免费 | 91色在线观看 | 日本在线观看中文字幕 | 天堂va欧美va亚洲va老司机 | 日韩黄色在线观看 | 久草成人在线 | 人人舔人人 | 欧美淫aaa免费观看 日韩激情免费视频 | 国产麻豆精品久久 | 日日夜夜天天久久 | 亚洲中字幕 | 亚洲精品国产精品国自 | 日韩av一区二区在线播放 | 91日韩在线播放 | 九九精品久久久 | 国产精品福利在线观看 | 国产一区二区免费在线观看 | 日韩在线不卡 | 99精品视频99 | 久草在线视频免费资源观看 | 狠狠狠狠狠狠操 | 精品日韩视频 | 中文字幕免费看 | 91视频午夜 | 亚洲四虎| 精品国模一区二区 | 99精彩视频| 摸bbb搡bbb搡bbbb | 亚洲精品啊啊啊 | 97在线视频免费播放 | 久久综合九色综合网站 | 在线视频日韩精品 | 黄色1级毛片 | 久久久精品网 | 国产.精品.日韩.另类.中文.在线.播放 | 日韩理论视频 | 成人网页在线免费观看 | 中文在线最新版天堂 | 国产成人精品一二三区 | 婷婷伊人五月 | 国内精品久久久久久久久久久久 | 中文有码在线 | 天天色播 | 欧美另类视频 | 国产最新91| 日韩亚洲国产中文字幕 | 久久精品久久精品久久 | 日韩3区| 99久久精品免费视频 | 亚洲欧美视频在线观看 | 国产私拍在线 | 人人爽人人爽人人爽学生一级 | 亚州精品天堂中文字幕 | 国产99久久久久 | 韩国精品在线观看 | 国产美腿白丝袜足在线av | 欧美日韩高清在线一区 | 国产精品久久久久免费a∨ 欧美一级性生活片 | 高清av在线免费观看 | 国产黄色片在线 | 伊人手机在线 | 亚洲 欧美变态 另类 综合 | 精品久久久久久一区二区里番 | 在线观看免费高清视频大全追剧 | 黄色国产在线观看 | 玖草影院 | 亚洲一区二区三区在线看 | 青青草华人在线视频 | 成人欧美一区二区三区在线观看 | 国产精品人成电影在线观看 | 亚洲做受高潮欧美裸体 | 成年人毛片在线观看 | 婷婷六月天丁香 | 天堂网av在线 | 欧美污在线观看 | 精品 一区 在线 | 国产黄色精品网站 | 国产中文字幕av | 米奇狠狠狠888 | 国产精品久久久久久久久久三级 | 香蕉视频在线观看免费 | 国产69久久 | 中文字幕在线人 | 97人人看 | 亚洲第一av在线 | 在线一区电影 | 亚洲精品美女久久 | 国产手机视频 | av免费在线观看1 | 久久久精品国产一区二区电影四季 | 六月丁香综合网 | 欧美精品久久久久久久亚洲调教 | 精品资源在线 | 热久久这里只有精品 | 精品爱爱| 天天色天天搞 | 欧美在线aaa| 91亚洲精品国偷拍自产在线观看 | 久久国产精品99久久久久久进口 | 天天爱天天射天天干天天 | 91亚色免费视频 | 国产在线一区二区三区播放 | 免费av片在线 | 在线免费观看视频 | 亚洲精品久久在线 | 免费色视频在线 | 久久久久在线 | 欧美成人在线网站 | 免费色黄 | 成人在线视频一区 | 五月婷婷视频在线观看 | 欧美一级日韩三级 | 欧美a免费 | 在线小视频国产 | 欧美专区日韩专区 | 精油按摩av | 一级特黄aaa大片在线观看 | 9在线观看免费 | 国产成视频在线观看 | 国产欧美精品一区二区三区四区 | av在线网站观看 | 亚洲国产免费网站 | 久久y | 国产精品视频观看 | 久久刺激视频 | 欧美极品久久 | 日韩电影一区二区三区在线观看 | 一区二区三区日韩精品 | 久久久久久网址 | 久久精品影视 | 久久婷婷综合激情 | 四虎www| 99热国内精品 | 久久精品久久久久电影 | 色悠悠久久综合 | 天天操天天射天天操 | 一区二区三区视频网站 | 一区二区三区日韩视频在线观看 | 精品国产成人av在线免 | 探花视频在线观看+在线播放 | 亚洲精品色视频 | 毛片网免费 | 人人添人人澡人人澡人人人爽 | 超碰97av在线 | 亚洲va欧美va人人爽春色影视 | 国产无限资源在线观看 | 久久韩国免费视频 | 国产免费激情久久 | 深爱五月激情五月 | 99色在线观看视频 | 国产黄在线播放 | 在线观看麻豆av | 少妇视频一区 | 国产精品一区二区久久精品爱涩 | 九九热中文字幕 | 中文字幕人成乱码在线观看 | 天天碰天天操 | 中文字幕在线观看播放 | 最新国产精品视频 | 精品美女视频 | 欧美成人xxx | 久久综合婷婷国产二区高清 | 久久亚洲私人国产精品va | 三级黄色在线观看 | 中文字幕在线国产 | 日批网站在线观看 | 久久久国产精品一区二区中文 | 欧亚日韩精品一区二区在线 | 免费看高清毛片 | 成人久久毛片 | 国产资源中文字幕 | 人人插人人澡 | 婷婷在线综合 | 一区在线免费观看 | 久久黄色影院 | 99久久这里有精品 | 日韩欧美一区二区在线 | 五月激情在线 | 韩日精品在线观看 | 免费看的视频 | 久久国产精品99久久久久 | 国产成人精品一区二区三区网站观看 | 少妇精69xxtheporn | 在线看片a | 国产一区欧美日韩 | 麻豆高清免费国产一区 | 国产99久久久精品 | 天天射天天爱天天干 | 久久99亚洲精品久久久久 | 五月婷婷深开心 | 中文永久免费观看 | 精品久久久久久一区二区里番 | 亚洲国产欧美在线看片xxoo | 国产成人精品在线 | 国产一级片久久 | 久久国产精品一国产精品 | 日韩精品视频在线免费观看 | 成人影片在线免费观看 | 中文字幕免费高 | 天天超碰 | 在线电影91| 久久超碰97| 国产精品自产拍在线观看 | 日韩电影中文字幕在线 | 久久国产三级 | 永久免费看av | 超级碰碰免费视频 | 99国产情侣在线播放 | 亚州黄色一级 | 福利区在线观看 | 99 视频 高清 | 久久tv视频| 亚洲成人av影片 | 六月激情久久 | 免费 在线 中文 日本 | 97精品国产97久久久久久免费 | av先锋中文字幕 | 91丨九色丨蝌蚪丨老版 | 韩国一区二区三区视频 | 99国产在线观看 | 国产香蕉97碰碰碰视频在线观看 | 久久亚洲美女 | 蜜臀av在线一区二区三区 | 成年人国产视频 | 国产精品12 | 在线看的av网站 | 亚洲激情网站免费观看 | 免费在线视频一区二区 | 狠狠干婷婷色 | 成年人免费在线播放 | 国产美女免费观看 | 色综合久久88色综合天天 | 色综合久久88色综合天天人守婷 | 日韩精品视频第一页 | 激情文学综合丁香 | 国产区在线视频 | 中文视频在线看 | 国产一级免费播放 | 欧美激情片在线观看 | 婷婷色婷婷 | av黄色大片 | 国产一区二区电影在线观看 | 久久久久久毛片精品免费不卡 | 精油按摩av | 亚洲无吗视频在线 | 国产丝袜 | 97国产在线播放 | 欧美视频日韩 | 午夜久久影院 | 亚洲九九爱| 欧美久久久久久久久中文字幕 | 日韩xxxx视频 | 欧美十八| 久久精品9 | 97精品一区 | 91资源在线视频 | 国产精品久久久久永久免费 | 天天曰天天曰 | 日韩v在线 | 婷婷色狠狠 | 蜜臀aⅴ国产精品久久久国产 | 成人国产精品免费观看 | 日韩一区精品 | 国产精品 欧美 日韩 | 黄色app网站在线观看 | 六月婷操 | 久久久国产影视 | 日韩精品一区二区免费视频 | 伊人中文网 | 久久手机在线视频 | 亚一亚二国产专区 | 日韩中文字幕免费视频 | 久久狠狠一本精品综合网 | 久久在线免费观看 | 99久久久久久国产精品 | 99在线精品观看 | 日韩一区二区三区在线观看 | 97视频精品 | 高清免费av在线 | 欧美日韩在线免费观看视频 | 亚洲劲爆av | 色偷偷人人澡久久超碰69 | 久久亚洲日本 | 五月天av在线 | 免费观看的黄色 | 国产欧美日韩精品一区二区免费 | 欧美日韩免费在线视频 | 久久精品2 | 99产精品成人啪免费网站 | av电影一区二区三区 | 婷婷丁香狠狠爱 | 免费在线观看视频一区 | 奇米导航 | 国产三级在线播放 | 国产精品美女久久久久久久 | 91人人射| 日本高清xxxx | 色在线视频| 成人免费在线播放视频 | 日韩av快播电影网 | 特级毛片aaa| www.香蕉视频 | 丁香国产视频 | 最近中文字幕完整视频高清1 | 国产精品免费不 | 美女性爽视频国产免费app | 国产无套视频 | 天天综合网久久综合网 | 亚洲欧洲精品一区二区精品久久久 | 欧美一级高清片 | 超碰免费97 | 欧美精品国产精品 | 国产成人三级在线 | 亚洲aⅴ在线观看 | 欧美精品二 | 国产麻豆精品95视频 | 国产精品久久久久一区二区国产 | 天天综合色网 | 国产精品色在线 | 狠狠色丁香久久婷婷综合五月 | 五月开心综合 | 中文字幕日韩精品有码视频 | 久久国产精品99久久久久久进口 | 国产一区二区三区久久久 | 色开心 | 国产精品自在欧美一区 | 不卡的av电影在线观看 | 午夜婷婷综合 | 免费看色网站 | 91精品在线播放 | 97国产在线观看 | 国产精品福利午夜在线观看 | 精品国产福利在线 | 国内精品99 | 国产精品少妇 | 中日韩在线视频 | 日韩黄色在线电影 | 久青草国产在线 | 国产视频在线观看一区二区 | 亚洲网站在线 | 一区二区三区不卡在线 | 波多野结依在线观看 | 国产高清一区二区 | 成人a视频在线观看 | 亚洲精品久久久久久中文传媒 | 中文字幕色婷婷在线视频 | 六月丁香综合 | 日韩精品一区二区三区在线播放 | 精品一区精品二区 | 一区二区三区手机在线观看 | 黄色毛片大全 | 国产精品免费一区二区 | 日本爽妇网 | 在线观看免费观看在线91 | 亚洲国产伊人 | 狠狠撸电影 | 国产精品第十页 | 国产精品99视频 | 91人人澡人人爽人人精品 | 99久久久精品 | 九九九热精品免费视频观看网站 | 激情亚洲综合在线 | 黄色视屏在线免费观看 | 日韩午夜在线观看 | 久久玖| 亚洲最大的av网站 | 中文字幕欧美三区 | 久久涩涩网站 | 不卡av电影在线 | 精品国产乱码久久久久久天美 | 亚洲最新在线 | 奇米777777 | 少妇性色午夜淫片aaaze | 成人久久影院 | 午夜91在线| 精品久久1 | 91爱爱免费观看 | 91精品免费 | 国内视频在线 | 亚洲免费a | 91在线视频观看免费 | 久久激情综合 | 色婷婷久久久综合中文字幕 | 久久人人插 | 久久99精品久久久久久 | 日韩在线观看的 | 亚洲在线色 | 日p视频在线观看 | 6699私人影院 | 久草在线视频精品 | 99性视频| 国产精品久久久999 国产91九色视频 | 一区二区三区av在线 | 狠狠操导航 | 国产一级视频在线 | www.香蕉视频在线观看 | 永久免费看av | 国产亚洲精品女人久久久久久 | 91喷水| 国产欧美日韩视频 | 探花在线观看 | 国产中文a | 在线观看国产一区 | 日韩精品一区二区在线观看 | 四虎成人精品在永久免费 | 国产精品免费在线观看视频 | 日韩系列 | 色婷婷综合久久久久中文字幕1 | 十八岁以下禁止观看的1000个网站 | av网站免费在线 | 精品亚洲网 | 在线观看 亚洲 | 国产一区免费在线 | 国产在线免费 | 91激情在线视频 | 一区二区三区在线免费观看视频 | 国产成人综合图片 | 日韩av片无码一区二区不卡电影 | 五月的婷婷| 中文字幕999 | 高清不卡免费视频 | 中文字幕在线播放视频 | 欧美性精品 | 国产精品小视频网站 | 在线观看黄色大片 | 三级黄色片在线观看 | 久热精品国产 | 免费高清无人区完整版 | 欧美怡红院视频 | 日韩r级在线 | 日韩电影中文字幕在线 | 中文字幕久久亚洲 | 免费电影播放 | 区一区二区三区中文字幕 | 欧美一区日韩精品 | 精品国产一区二区在线 | 丁香久久久 | 91麻豆精品国产91久久久久久 | 亚洲成人第一区 | av线上看| 色综合久久五月 | 99久久精品免费 | 婷婷丁香激情五月 | www.久久久 | 国产日韩精品欧美 | 久久久精品免费观看 | 婷婷综合电影 | 国内精品在线观看视频 | 天天操夜操视频 | av免费福利 | 蜜臀av性久久久久蜜臀aⅴ涩爱 | 国产精品久久视频 | 精品美女视频 | 亚洲精品视频在线免费播放 | 午夜精品福利在线 | 伊人日日干 | 久久国产精品一区二区三区 | 久久草网站 | 欧美亚洲国产一卡 | 国产精品久久久久久久久久久不卡 | 国产在线播放一区二区 | 91视频链接 | 国产精品一区二区在线免费观看 | 黄色成人91| 色丁香色婷婷 | 婷婷色在线观看 | 美女网站视频色 | 国产午夜三级一区二区三 | 天天干婷婷 | 98福利在线 | 在线国产视频 | 欧美日韩国产区 | 午夜精品久久久久久久久久久 | 在线视频app | 丰满少妇一级 | 精品国模一区二区 | 日韩黄色免费在线观看 | 成人福利在线播放 | 粉嫩高清一区二区三区 | 亚洲国产精品成人女人久久 | 欧美韩日在线 | 亚洲资源在线观看 | 依人成人综合网 | 亚洲黄色一级大片 | 最近字幕在线观看第一季 | 日韩网站在线观看 | 成年人免费看片 | 国产高清在线观看 | 天天爱天天操天天爽 | 久久精品影片 | 97成人精品区在线播放 | 婷婷五天天在线视频 | 日日碰夜夜爽 | 日韩av不卡在线播放 | 婷婷色综合网 | 日韩欧美电影 | 欧美精品亚洲二区 | 久久久影院一区二区三区 | 免费一级黄色 | 黄色毛片在线观看 | 欧美成年人在线观看 | 精品国模一区二区三区 | 国产一区免费观看 | 成人毛片一区二区三区 | 波多在线视频 | 亚洲视频专区在线 | 久久欧美综合 | 最新极品jizzhd欧美 | 欧美国产日韩久久 | 欧美成人xxxxx | 91精品婷婷国产综合久久蝌蚪 | 久久综合久久久 | 国产精品永久免费视频 | 超碰人人射 | 综合在线亚洲 | 国产最顶级的黄色片在线免费观看 | 91.dizhi永久地址最新 | 天堂久色| 国产视频2 | 一区二区三区中文字幕在线观看 | 又黄又刺激又爽的视频 | 又色又爽又黄高潮的免费视频 | 日韩在线播放av | 玖玖爱免费视频 | 成人天堂网 | 亚洲网站在线 | 欧美日韩一二三四区 | 成年人免费在线播放 | 在线观看久久久久久 | 国产精品美女久久久久久2018 | 国产999免费视频 | 日韩高清精品免费观看 | 18久久久久久 | 亚洲综合色视频 | 成人久久久久久久久久 | 999国内精品永久免费视频 | 新版资源中文在线观看 | 丁香婷婷综合五月 | 欧美在线不卡一区 | 久久精品99国产精品酒店日本 | 国产99久久精品一区二区永久免费 | 一区二区三区免费看 | 久在线观看视频 | 久久一区国产 | 亚洲成人资源网 | 色久天 | 亚洲精品一区二区三区新线路 | ,久久福利影视 | 亚洲国产精品传媒在线观看 | 黄色网在线免费观看 | 国产一区高清在线观看 | 国产涩图 | 日日夜夜综合 | 久久精品视频在线观看免费 | 日韩欧美精品在线观看 | 国产精品久久久久高潮 | 久久人人97超碰精品888 | 在线播放 一区 | 91精品国产自产在线观看永久 | 日韩免费网站 | 日韩中文在线视频 | 久久精品一二三区白丝高潮 | 日韩精品视频在线观看免费 | 国产一线在线 | 国产高清在线永久 | bbb搡bbb爽爽爽 | 久久五月天综合 | 97视频免费在线观看 | 成人一级在线观看 | 999热视频 | 久久黄色网 | 久艹视频在线观看 | 午夜12点| 91免费日韩 | 九热精品| 久久成人国产精品 | av中文字幕在线观看网站 | 久久综合久久综合久久综合 | 婷婷久久综合网 | 中文字幕在线视频一区二区 | 成人av免费电影 | 国产成人精品综合久久久 | 亚州国产精品久久久 | 国产高清在线观看 | 亚洲午夜久久久综合37日本 | 国产精品18久久久久久不卡孕妇 | 色综合网在线 | 国产精品入口麻豆www | 国产精品对白一区二区三区 | 成人午夜片av在线看 | 九九热视频在线 | 国产精品 美女 | 亚洲国产视频在线 | 毛片黄色一级 | 97操操操 | 久草精品在线播放 | 激情网五月婷婷 | 丁香婷婷综合五月 | 国产精品女同一区二区三区久久夜 | av一区在线 | 国产在线自| 久久99精品久久久久久三级 | 国产精品嫩草影院9 | 天天操综 | 五月天激情视频在线观看 | 蜜桃视频在线视频 | 国产高清在线看 | 99久久精品免费看国产麻豆 | 久久精品视频一 | 亚州av免费 | 欧美日韩不卡一区二区三区 | 91亚洲精品久久久中文字幕 | 天天干,天天草 | 国产麻豆剧果冻传媒视频播放量 | 黄色一级大片在线观看 | 成年人网站免费观看 | 亚洲视频在线看 | 中文字幕av免费在线观看 | 97人人模人人爽人人少妇 | 欧美久久久影院 | 日韩午夜在线观看 | 天天操天天射天天添 | 成人精品视频久久久久 | www.91成人 | 丁香花中文在线免费观看 | 久久黄视频 | 中文字幕影视 | 免费日韩av电影 | 日韩高清免费观看 | 国产精品一区二区在线 | 亚洲久久视频 | 中文字幕在线播放av | 久久欧美综合 | 久久综合视频网 | 欧美日韩一区二区三区在线免费观看 | 亚洲精品影视在线观看 | 99久久夜色精品国产亚洲 | 色偷偷88欧美精品久久久 | 午夜.dj高清免费观看视频 | 亚洲国产成人在线观看 | 日韩网站免费观看 | 日韩免费在线视频观看 | 亚洲免费视频观看 | 婷婷六月综合亚洲 | 一级黄色片在线 | 在线 欧美 日韩 | 蜜臀久久99精品久久久久久网站 | 亚洲免费小视频 | 欧美极度另类性三渗透 | 国产黄色片免费观看 | 欧美作爱视频 | 亚洲视频在线看 | 亚洲色综合 | 国模视频一区二区三区 | 日本少妇视频 | 国产最新网站 | 成人av在线直播 | 欧美国产不卡 | 国产高清在线永久 | 国产999精品久久久久久 | 亚洲欧洲一区二区在线观看 | 成人丝袜 | av网在线观看| 国产98色在线 | 日韩 | 国内外成人免费在线视频 | 国产专区视频在线 | 久久久久国 | 91精品久久久久久综合五月天 | 色视频网站免费观看 | 欧美日韩99| www.夜夜骑.com| 日韩伦理片hd | 亚洲欧美综合精品久久成人 | av福利第一导航 | av成人免费观看 | 国产日本高清 | 午夜久久久影院 | 久久av影院 | 色综合久久综合网 | 国产精品国产三级国产aⅴ无密码 | 国产精品久免费的黄网站 | 最近中文字幕免费 | 成人午夜剧场在线观看 | 手机av电影在线 | 久久精品三 | 91一区二区三区久久久久国产乱 | 国产视频一区精品 | 天天干,狠狠干 | 亚洲婷久久 | 国产成人av| 91日韩在线播放 | 五月婷婷综合激情网 | 日韩在线高清 | 亚洲狠狠婷婷综合久久久 | 99久久精品国产一区 | 97国产精品视频 | 狠狠狠狠狠狠操 | 国产亚洲免费的视频看 | 久久久久久高潮国产精品视 | 中文字幕a∨在线乱码免费看 | 99精品一级欧美片免费播放 | 波多野结衣小视频 | 精品产品国产在线不卡 | 久久小视频 | 91视视频在线直接观看在线看网页在线看 | 国产精品无av码在线观看 | 欧美地下肉体性派对 | av字幕在线 | 亚洲欧美怡红院 | 最近中文字幕第一页 | 5月丁香婷婷综合 | 麻豆视频在线看 | 国产午夜精品一区二区三区四区 | 91九色蝌蚪国产 | 亚洲在线观看av | 亚洲最大av在线播放 | 国产精品99久久久久久宅男 | 亚洲高清在线视频 | 五月天中文字幕mv在线 | 久久看片 | 婷婷久久一区 | 国产精品人人做人人爽人人添 | 久热电影 | 一区二区三区免费在线观看视频 | 亚洲国产成人在线 | 伊人伊成久久人综合网站 | 999在线精品 | 国产成人资源 | 日韩在线电影一区二区 | 99精品久久99久久久久 | 97在线观看| 一本一本久久a久久精品牛牛影视 | 激情校园亚洲 | 免费网站黄 | 日韩大片在线免费观看 | 免费在线色 | 另类老妇性bbwbbw高清 | 射久久| 亚洲 中文字幕av | 有码视频在线观看 | 国语精品视频 | 国产日韩精品一区二区三区 | 精品国产大片 | 最近中文字幕在线 | 久久一区二区三区国产精品 | 午夜私人影院 | 欧美高清视频不卡网 | 日韩av免费一区二区 | 天天摸天天舔 | 黄av免费在线观看 | 亚洲精品在线视频网站 | 一级黄色免费网站 | 国产老熟| 在线观看完整版免费 | 成年人国产视频 | www.午夜色.com | 在线观看你懂的网站 | 9797在线看片亚洲精品 | 日日干夜夜干 | 国产一区二区精品久久 | 国产精品mv | 日本三级在线观看中文字 | 在线中文字幕观看 | 欧美一级久久 | 四虎免费在线观看 | 国产在线精品区 | 久草在线免费资源 | 99国产精品免费网站 | 色亚洲激情 | 免费在线激情电影 | 欧美一级片 | 一级片色播影院 | 午夜精品电影一区二区在线 | 日韩黄在线观看 | 国产精品永久久久久久久久久 | 欧美国产日韩在线观看 | 亚洲最新在线视频 | 久精品在线 | 国内精品在线看 | 国产香蕉久久 | 亚洲va男人天堂 | 国产精品美女免费视频 | 精品毛片久久久久久 | 国产偷国产偷亚洲清高 | 四虎8848免费高清在线观看 | 日韩av免费在线电影 | 天天干天天综合 | 欧美了一区在线观看 | 国产在线观看一 | 久久久高清 | 热99久久精品 | 人人爱人人做人人爽 | 国产 日韩 中文字幕 | av电影免费在线 | 黄色大全在线观看 | 久久一区二区三区超碰国产精品 | 97av色| 成人一级影视 | 二区在线播放 | 色免费在线 | 视频二区在线 | 国产在线理论片 | 久久精品国产久精国产 | 在线观看视频在线 | 一区二区三区久久 | www.啪啪.com | 日韩在线字幕 | 免费看国产精品 | 亚洲少妇xxxx | 干亚洲少妇 | 欧美一区二区在线免费观看 | 99在线观看| 中文字幕永久在线 | 人人爽人人爽人人爽学生一级 | 久久高清免费视频 | 久久国产网站 | 热久久免费国产视频 | 97碰在线 | 一区二区三区 亚洲 | 国产精品专区在线观看 | 中文字幕在线视频网站 | www.黄色在线 | av免费试看 | 久草网视频在线观看 | 激情综合亚洲 | 国产精品高潮呻吟久久av无 | av一级久久 | 亚洲精品午夜视频 | 亚洲性少妇性猛交wwww乱大交 | 久久久久福利视频 | 岛国av在线不卡 | 在线国产日本 | 成人免费网站在线观看 | 欧美日韩视频观看 | 久草在线观看 | 人人澡超碰碰97碰碰碰软件 | 人人爱人人做人人爽 | 久久综合九色综合欧美就去吻 | 亚洲国产午夜精品 | 久久se视频 | 一本一道波多野毛片中文在线 | 精品国偷自产国产一区 | 国产麻豆剧传媒免费观看 | 亚洲精品乱码久久 | 中文字幕电影在线 | 亚洲日本激情 | 韩国精品福利一区二区三区 | 欧美国产日韩一区二区三区 | 欧美黑人性猛交 | 91最新在线视频 | 久久免费国产电影 | 日韩,中文字幕 | 麻豆国产露脸在线观看 | 四虎精品成人免费网站 | 五月婷在线观看 | 玖玖爱在线观看 | 天天干天天做天天操 | 欧美人zozo| 在线免费视频一区 | 国内精品久久久久影院一蜜桃 | 成人黄色大片 | 91在线看 | 婷婷亚洲综合 | 国产精品久久网站 | 国产一级二级在线播放 | 欧美激情精品久久久久久变态 | 91精品国产欧美一区二区成人 | 天海冀一区二区三区 | 中文字幕一区二区在线观看 | 亚洲欧洲精品视频 | 天天激情在线 | 中文字幕在线观看的网站 | 一区二区三区四区免费视频 | 日本成人中文字幕在线观看 | 美女视频一区二区 | 在线蜜桃视频 | 久久久久久久亚洲精品 | 国偷自产视频一区二区久 | 国产亚洲成av片在线观看 | 91精品视频在线播放 | 在线国产视频 | 九色精品 | 婷婷色视频 | 99久久综合狠狠综合久久 | www.狠狠操.com | 免费看十八岁美女 | av在观看| 亚洲日本va中文字幕 | 国产视频久久久 | 国产精品乱看 | 午夜影院一级片 | 在线观看国产福利片 | 日本精品xxxx | 日韩色区 |