Leap Motion翻譯系列文章http://52coding.com/leap-motion-official-doc-translation
觸摸模擬
Leap Motion的API提供了在你的應用中可以進行模擬的資訊。觸摸資訊是通過尖端類提供的。
概述
Leap 定義了一個自適應的觸摸平面,你可以將它與你應用中的二維元素美妙的結合在一起。這個平面粗糙的旋轉到與x-y平面平行,但是根據使用者的手指和手的位置動態調整。但使用者的手或者工具從前方到達平面,Leap會報告尖端物體是接近還是觸碰到這個虛擬平面。API通過2個值彙報與平面相關的資訊:觸摸平面地帶和到觸摸平面的距離。
:虛擬觸摸平面
觸摸地帶是識別Leap Motion軟體是否把尖端當作懸浮在觸摸平面,是穿透觸摸平面還是相對於螢幕較遠(或者指向錯誤的方向)。地帶包含“懸浮”、“觸摸”和“無”。觸摸地帶的轉換根據觸摸距離變換有一定滯後。這個滯後用於避免突然和反覆的變換。如果你在應用中使用這個觸摸互動,你可能不需要經常考慮地帶。
只有當尖端在懸浮和觸摸地帶,觸摸距離才是有效。這個距離是歸一到[-1,+1]的數值。當一個尖端物體第一次進入懸浮地帶,此時觸摸距離為+1,而當距離不斷減少到0,意味著尖端物體接近觸摸平面。但尖端物體穿入平面,距離變為0。因為尖端物體繼續往觸摸地帶推進,距離不斷靠近但不會超過-1(永遠趨向於-1)。
你可以使用地帶數值,根據懸浮還是觸摸來決定何時更新介面元素。你還可以使用距離,根據是否靠近平面進一步改變介面元素[一個粗,一個細]。例如,當手指在控制體上並且在懸浮地帶,你可以讓控制體高亮顯示,並且依據使用者到底多接近控制體的距離,改變游標形態。
作為觸摸模擬API的一部分,Leap Motion為尖端物體,提供了一個額外的相對於標準座標的穩定座標。Leap Motion軟體使用自適應濾波器來穩定這個位置,可以平滑和降低運動,最終使得它在螢幕上小地區內(例如按鈕和連結)更容易地與使用者互動。但運動緩慢是凹凸貼圖也越強,這樣使用者可以調整距離並且更容易的觸碰到特定的點[這個效果很贊,和人們在現實世界操作一樣]。
擷取觸摸地帶
觸摸地帶通過尖端類的touchZone屬性描述。這些地帶都是使用枚舉類型標識的,一共有下面三個狀態:
#NONE --- 尖端距離觸控螢幕幕太遠,大於考慮它觸摸的距離。又或者它指向反方向的使用者(也就是物體預設在使用者正面前,使用者手指著自己是一種不合適的操作)
#HOVERING --- 尖端物體的頂端已經到達懸浮地帶,但不被認為觸摸。
#TOUCHING --- 尖端到達了虛擬平面內。
下面的程式碼片段說明如何取回最前面手指的地帶標識:
Leap::Frame frame = leap.frame(); Leap::Pointable pointable = frame.pointables().frontmost(); Leap::Pointable::Zone zone = pointable.touchZone();
擷取觸摸距離
觸摸距離是通過尖端類的touchDistance屬性描述的。這個距離範圍是+1到-1,對應了手指移向和穿過虛擬觸摸平面。這個距離沒有物理意義,但卻是Leap Motion軟體認為的到底有多靠近觸碰。
下面的程式碼片段說明如何取出最前端手指的觸摸距離:
Leap::Frame frame = leap.frame(); Leap::Pointable pointable = frame.pointables().frontmost(); float distance = pointable.touchDistance();
擷取尖端的穩定座標
穩定座標是尖端類的stabilizedTipPosition屬性描述的。這個位置根據標準Leap Motion座標系統參照得出的,但是具有一個上下文相關大量資料的濾波器,所以很穩定。
下面的程式碼片段描述了如何得到最前端手指的穩定位置:
Leap::Frame frame = leap.frame(); Leap::Pointable pointable = frame.pointables().frontmost(); Leap::Vector stabilizedPosition = pointable.stabilizedTipPosition();
從Leap Motion座標系轉換到應用座標系
但使用觸摸模擬時,你必須把Leap Motion的座標空間轉化到應用的螢幕空間。為了使得這個操作更簡單,Leap Motion的API提供了一個互動箱子類[互動盒子類](IneractionBox)。這個互動箱子類描述Leap Motion視野中的線性物體運動。這個類提供了一個把物體範圍中的座標歸一化到[0,1]範圍內。你可以歸一化一個距離,並且根據應用尺寸,把結果座標進行縮放,來擷取一個在應用中的座標。
例如,如果你在用戶端區域中有個具有windowWidth和windowHeight兩個度量的視窗,你可以使用以下代碼,取得在視窗中觸摸點的二維像素座標:
Leap::Frame frame = leap.frame(); Leap::Finger finger = frame.fingers().frontmost(); Leap::Vector stabilizedPosition = finger.stabilizedTipPosition(); Leap::InteractionBox iBox = leap.frame().interactionBox(); Leap::Vector normalizedPosition = iBox.normalizePoint(stabilizedPosition); float x = normalizedPosition.x * windowWidth; float y = windowHeight - normalizedPosition.y * windowHeight;
觸點例子
下面的例子使用觸摸模擬的API,來顯示所有在應用視窗下,檢測到的尖端物體。這個例子使用了觸摸地帶來設定點的顏色,使用觸摸距離來設定alpha數值。使用了互動盒子類爸穩定的頂點位置被映射到應用視窗中。
:觸摸點例子
#include "cinder/app/AppNative.h"#include "cinder/gl/gl.h"#include "Leap.h"#include "LeapMath.h"using namespace ci;using namespace ci::app;using namespace std;class TouchPointsApp : public AppNative { public: void setup(); void draw(); private: int windowWidth = 800; int windowHeight = 800; Leap::Controller leap;};void TouchPointsApp::setup(){ this->setWindowSize(windowWidth, windowHeight); this->setFrameRate(120); gl::enableAlphaBlending();}void TouchPointsApp::draw(){ gl::clear( Color( .97, .93, .79 ) ); Leap::PointableList pointables = leap.frame().pointables(); Leap::InteractionBox iBox = leap.frame().interactionBox(); for( int p = 0; p < pointables.count(); p++ ) { Leap::Pointable pointable = pointables[p]; Leap::Vector normalizedPosition = iBox.normalizePoint(pointable.stabilizedTipPosition()); float x = normalizedPosition.x * windowWidth; float y = windowHeight - normalizedPosition.y * windowHeight; if(pointable.touchDistance() > 0 && pointable.touchZone() != Leap::Pointable::Zone::ZONE_NONE) { gl::color(0, 1, 0, 1 - pointable.touchDistance()); } else if(pointable.touchDistance() <= 0) { gl::color(1, 0, 0, -pointable.touchDistance()); } else { gl::color(0, 0, 1, .05); } gl::drawSolidCircle(Vec2f(x,y), 40); }}CINDER_APP_NATIVE( TouchPointsApp, RendererGl )
這個例子使用了Cinder庫來建立用於繪畫的應用視窗。[例子這麼簡單,怎麼玩運行啊]