1 | var Pointable = require('./pointable'),
|
2 | Bone = require('./bone')
|
3 | , Dialog = require('./dialog')
|
4 | , _ = require('underscore');
|
5 |
|
6 | /**
|
7 | * Constructs a Finger object.
|
8 | *
|
9 | * An uninitialized finger is considered invalid.
|
10 | * Get valid Finger objects from a Frame or a Hand object.
|
11 | *
|
12 | * @class Finger
|
13 | * @memberof Leap
|
14 | * @classdesc
|
15 | * The Finger class reports the physical characteristics of a finger.
|
16 | *
|
17 | * Both fingers and tools are classified as Pointable objects. Use the
|
18 | * Pointable.tool property to determine whether a Pointable object represents a
|
19 | * tool or finger. The Leap classifies a detected entity as a tool when it is
|
20 | * thinner, straighter, and longer than a typical finger.
|
21 | *
|
22 | * Note that Finger objects can be invalid, which means that they do not
|
23 | * contain valid tracking data and do not correspond to a physical entity.
|
24 | * Invalid Finger objects can be the result of asking for a Finger object
|
25 | * using an ID from an earlier frame when no Finger objects with that ID
|
26 | * exist in the current frame. A Finger object created from the Finger
|
27 | * constructor is also invalid. Test for validity with the Pointable.valid
|
28 | * property.
|
29 | */
|
30 | var Finger = module.exports = function(data) {
|
31 | Pointable.call(this, data); // use pointable as super-constructor
|
32 |
|
33 | /**
|
34 | * The position of the distal interphalangeal joint of the finger.
|
35 | * This joint is closest to the tip.
|
36 | *
|
37 | * The distal interphalangeal joint is located between the most extreme segment
|
38 | * of the finger (the distal phalanx) and the middle segment (the medial
|
39 | * phalanx).
|
40 | *
|
41 | * @member dipPosition
|
42 | * @type {number[]}
|
43 | * @memberof Leap.Finger.prototype
|
44 | */
|
45 | this.dipPosition = data.dipPosition;
|
46 |
|
47 | /**
|
48 | * The position of the proximal interphalangeal joint of the finger. This joint is the middle
|
49 | * joint of a finger.
|
50 | *
|
51 | * The proximal interphalangeal joint is located between the two finger segments
|
52 | * closest to the hand (the proximal and the medial phalanges). On a thumb,
|
53 | * which lacks an medial phalanx, this joint index identifies the knuckle joint
|
54 | * between the proximal phalanx and the metacarpal bone.
|
55 | *
|
56 | * @member pipPosition
|
57 | * @type {number[]}
|
58 | * @memberof Leap.Finger.prototype
|
59 | */
|
60 | this.pipPosition = data.pipPosition;
|
61 |
|
62 | /**
|
63 | * The position of the metacarpopophalangeal joint, or knuckle, of the finger.
|
64 | *
|
65 | * The metacarpopophalangeal joint is located at the base of a finger between
|
66 | * the metacarpal bone and the first phalanx. The common name for this joint is
|
67 | * the knuckle.
|
68 | *
|
69 | * On a thumb, which has one less phalanx than a finger, this joint index
|
70 | * identifies the thumb joint near the base of the hand, between the carpal
|
71 | * and metacarpal bones.
|
72 | *
|
73 | * @member mcpPosition
|
74 | * @type {number[]}
|
75 | * @memberof Leap.Finger.prototype
|
76 | */
|
77 | this.mcpPosition = data.mcpPosition;
|
78 |
|
79 | /**
|
80 | * The position of the Carpometacarpal joint
|
81 | *
|
82 | * This is at the distal end of the wrist, and has no common name.
|
83 | *
|
84 | */
|
85 | this.carpPosition = data.carpPosition;
|
86 |
|
87 | /**
|
88 | * Whether or not this finger is in an extended posture.
|
89 | *
|
90 | * A finger is considered extended if it is extended straight from the hand as if
|
91 | * pointing. A finger is not extended when it is bent down and curled towards the
|
92 | * palm.
|
93 | * @member extended
|
94 | * @type {Boolean}
|
95 | * @memberof Leap.Finger.prototype
|
96 | */
|
97 | this.extended = data.extended;
|
98 |
|
99 | /**
|
100 | * An integer code for the name of this finger.
|
101 | *
|
102 | * * 0 -- thumb
|
103 | * * 1 -- index finger
|
104 | * * 2 -- middle finger
|
105 | * * 3 -- ring finger
|
106 | * * 4 -- pinky
|
107 | *
|
108 | * @member type
|
109 | * @type {number}
|
110 | * @memberof Leap.Finger.prototype
|
111 | */
|
112 | this.type = data.type;
|
113 |
|
114 | this.finger = true;
|
115 |
|
116 | /**
|
117 | * The joint positions of this finger as an array in the order base to tip.
|
118 | *
|
119 | * @member positions
|
120 | * @type {array[]}
|
121 | * @memberof Leap.Finger.prototype
|
122 | */
|
123 | this.positions = [this.carpPosition, this.mcpPosition, this.pipPosition, this.dipPosition, this.tipPosition];
|
124 |
|
125 | if (data.bases){
|
126 | this.addBones(data);
|
127 | } else {
|
128 | Dialog.warnBones();
|
129 | }
|
130 |
|
131 | };
|
132 |
|
133 | _.extend(Finger.prototype, Pointable.prototype);
|
134 |
|
135 |
|
136 | Finger.prototype.addBones = function(data){
|
137 | /**
|
138 | * Four bones per finger, from wrist outwards:
|
139 | * metacarpal, proximal, medial, and distal.
|
140 | *
|
141 | * See http://en.wikipedia.org/wiki/Interphalangeal_articulations_of_hand
|
142 | */
|
143 | this.metacarpal = new Bone(this, {
|
144 | type: 0,
|
145 | width: this.width,
|
146 | prevJoint: this.carpPosition,
|
147 | nextJoint: this.mcpPosition,
|
148 | basis: data.bases[0]
|
149 | });
|
150 |
|
151 | this.proximal = new Bone(this, {
|
152 | type: 1,
|
153 | width: this.width,
|
154 | prevJoint: this.mcpPosition,
|
155 | nextJoint: this.pipPosition,
|
156 | basis: data.bases[1]
|
157 | });
|
158 |
|
159 | this.medial = new Bone(this, {
|
160 | type: 2,
|
161 | width: this.width,
|
162 | prevJoint: this.pipPosition,
|
163 | nextJoint: this.dipPosition,
|
164 | basis: data.bases[2]
|
165 | });
|
166 |
|
167 | /**
|
168 | * Note that the `distal.nextJoint` position is slightly different from the `finger.tipPosition`.
|
169 | * The former is at the very end of the bone, where the latter is the center of a sphere positioned at
|
170 | * the tip of the finger. The btipPosition "bone tip position" is a few mm closer to the wrist than
|
171 | * the tipPosition.
|
172 | * @type {Bone}
|
173 | */
|
174 | this.distal = new Bone(this, {
|
175 | type: 3,
|
176 | width: this.width,
|
177 | prevJoint: this.dipPosition,
|
178 | nextJoint: data.btipPosition,
|
179 | basis: data.bases[3]
|
180 | });
|
181 |
|
182 | this.bones = [this.metacarpal, this.proximal, this.medial, this.distal];
|
183 | };
|
184 |
|
185 | Finger.prototype.toString = function() {
|
186 | return "Finger [ id:" + this.id + " " + this.length + "mmx | width:" + this.width + "mm | direction:" + this.direction + ' ]';
|
187 | };
|
188 |
|
189 | Finger.Invalid = { valid: false };
|