【翻譯】Leapmotion-python開發官方文檔(7)

觸摸仿真

LeapMotion的通用接口提供了一些功能使你能夠在你的應用中實現觸摸仿真。觸摸仿真相關功能可以在Pointable類中找到。

概覽

LeapMotion定義了一個自適應觸摸面使你能夠用來與你程序中的2D部件進行交互。這個平面大概是與x-y平面平行(譯者注:應該是z-y吧?),但是與用戶手及手指位置相適應。當用戶向前觸動手指或工具,LeapMotion會回饋pointable(即移動的手指或工具)是在接近還是觸摸此虛擬界面。LeapMotion反饋兩個值代表觸摸:觸摸區域和與觸摸平面的距離。

虛擬觸摸平面
觸摸區域用於識別是否有一個Pointable對象懸停在觸摸屏面附近、穿透觸摸平面還是與平面距離過遠(或者運動方向與觸摸平面所在的方向相反)。這些區域包括“懸停(區)”、“觸摸(區)”、“無觸摸(區)”。觸摸區之間的轉換總滯後於觸摸距離的變化。這個滯後適用於避免誤識別和頻繁轉換。如果你在程序中使用觸摸交互,你可能不需要經常考慮觸摸區域。
觸摸距離只有當一個Pointable對象處在懸停區或者觸摸區時纔是有效的。這個距離已經被歸一化了,屬於[+1,-1]。當一個Pointable對象第一次進入懸停區域,其觸摸距離是+1.0同時離觸摸界面越近,距離越小(向零減小)。當Pointable對象接觸到觸摸平面,距離爲0.當Pointable再在觸摸區間中深入,距離會無限接近-1.
你可以基於懸停區間和觸摸區間值來決定何時更新UI部件。你可以基於與觸摸平面的接近程度利用觸摸距離進一步的修飾UI部件。比如,當有手指處於控制時,你可以將對應的UI部件標亮表明其處於受控狀態,同時基於觸摸距離改變光標,來向用戶提供反饋——其離觸摸控制界面的距離。
除了標準位置,作爲觸摸仿真的一部分,LeapMotion接口還爲Pointable對象提供了穩定位置。LeapMotion軟件使用一個能夠平滑和減慢運動的自適應濾波器使位置變得穩定以便使用戶更容易與屏幕的小區域進行互動(比如按鈕和鏈接)。當運動變得很慢時,平滑會更劇烈,使得用戶更容易能集中在一個點上進行觸摸操作。

獲得觸摸區間

觸摸空間由Pointable類的touchZone屬性反饋。這些觸摸區間用枚舉類型進行識別,其定義如下:
NONE——pointable對象離觸摸平面過遠或者運動方向爲用戶的後方。
HOVERING——pointable對象的尖端進入懸停區間,但是不被識別爲觸摸。
TOUCHING——pointbale對象穿過觸摸平面。
接下來的代碼段展示瞭如何訪問最前端的手指的觸摸區間
zone = pointable.touch_zone

獲取觸摸距離

觸摸距離可以通過Pointable類的touchDistance屬性訪問。這個距離介於+1與-1之間。這個距離並不代表物理量,只反應此Pointable對象與觸摸平面的接近程度。

接下來的代碼段展示瞭如何獲得最前端手指的觸摸距離:

distance = pointable.touch_distance

獲得一個Pointable對象的穩定位置

穩定位置可以通過訪問Pointable類的stabilizedTipPosition來獲得。這個位置是以LeapMotion座標系統爲參考系的。
接下來的代碼段展示瞭如何獲得最前端手指的穩定距離:
frame = controller.frame()
pointable = frame.pointables.frontmost
stabilizedPosition = pointable.stabilized_tip_position

從LeapMotion座標系統嚮應用程序的座標系統轉換

當使用觸摸仿真時,你必須瞭解如何從LeapMotion的座標空間轉換到你程序的顯示窗口空間。爲了使轉換更容易,LeapMotion接口提供了InteractionBox類。這個InteractionBox代表了一個處於LeapMotion視野中的線性空間。這個類提供了歸一化位置座標的函數,你可以歸一化位置座標然後根據你程序中窗口的尺寸進行縮放,從而將座標點變換到程序座標空間中。
比如,如果你有一個窗口,windowWidth和windowHeight分別代表窗口的寬和高,你可以使用下列代碼得到一個觸摸點的2D座標:
frame = controller.frame()
finger = frame.fingers.frontmost
stabilizedPosition = finger.stabilized_tip_position

interactionBox = controller.frame().interaction_box
normalizedPosition = interactionBox.normalize_point(stabilizedPosition)
x = normalizedPosition.x * windowWidth
y = windowHeight - normalizedPosition.y * windowHeight

觸摸點的例子

接下來的例子使用觸摸仿真接口,在程序窗口中顯示所有檢測到的Pointable對象的位置。這個例子使用觸摸區間改變每個點的顏色,使用觸摸距離改變每個點的透明度。穩定的尖端位置通過使用Interactionbox類將其轉換到程序窗口空間。
from Tkinter import Frame, Canvas, YES, BOTH
import Leap

class TouchPointListener(Leap.Listener):
    def on_init(self, controller):
        print "Initialized"

    def on_connect(self, controller):
        print "Connected"

    def on_frame(self, controller):
        self.paintCanvas.delete("all")
        frame = controller.frame()

        interactionBox = frame.interaction_box
        
        for pointable in frame.pointables:
            normalizedPosition = interactionBox.normalize_point(pointable.tip_position)
            if(pointable.touch_distance > 0 and pointable.touch_zone != Leap.Pointable.ZONE_NONE):
                color = self.rgb_to_hex((0, 255 - 255 * pointable.touch_distance, 0))
                
            elif(pointable.touch_distance <= 0):
                color = self.rgb_to_hex((-255 * pointable.touch_distance, 0, 0))
                #color = self.rgb_to_hex((255,0,0))
                
            else:
                color = self.rgb_to_hex((0,0,200))
                
            self.draw(normalizedPosition.x * 800, 600 - normalizedPosition.y * 600, 40, 40, color)

    def draw(self, x, y, width, height, color):
        self.paintCanvas.create_oval( x, y, x + width, y + height, fill = color, outline = "")

    def set_canvas(self, canvas):
        self.paintCanvas = canvas
        
    def rgb_to_hex(self, rgb):
        return '#%02x%02x%02x' % rgb

class PaintBox(Frame):

    def __init__( self ):
        Frame.__init__( self )
        self.leap = Leap.Controller()
        self.painter = TouchPointListener()
        self.leap.add_listener(self.painter)
        self.pack( expand = YES, fill = BOTH )
        self.master.title( "Touch Points" )
        self.master.geometry( "800x600" )
      
        # create Canvas component
        self.paintCanvas = Canvas( self, width = "800", height = "600" )
        self.paintCanvas.pack()
        self.painter.set_canvas(self.paintCanvas)

def main():
    PaintBox().mainloop()

if __name__ == "__main__":
    main()
這個例子使用了Tkinter模塊,但是與LeapMotion相關的代碼可以用於所有的Python項目。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章