Comparing version 1.4.0 to 1.5.0
20
index.js
@@ -1,6 +0,6 @@ | ||
/* | ||
*/ | ||
exports.Transform = require('./lib/Transform') | ||
exports.estimateI = require('./lib/estimateI') | ||
exports.estimateL = require('./lib/estimateL') | ||
exports.estimateX = require('./lib/estimateX') | ||
exports.estimateY = require('./lib/estimateY') | ||
exports.estimateT = require('./lib/estimateT') | ||
@@ -61,3 +61,3 @@ exports.estimateS = require('./lib/estimateS') | ||
// string. One of the following: | ||
// 'I', 'T', 'S', 'R', 'TS', 'TR', 'SR', 'TSR' | ||
// 'I', 'L', 'X', 'Y', 'T', 'S', 'R', 'TS', 'TR', 'SR', 'TSR' | ||
// domain | ||
@@ -68,9 +68,13 @@ // array of 2d arrays | ||
// pivot | ||
// optional 2d array, does nothing for translation estimators | ||
// An optional 2d array for 'S', 'R', and 'SR'. An angle for 'L'. | ||
// | ||
var name = 'estimate' + type.toUpperCase() | ||
if (exports.hasOwnProperty(name)) { | ||
try { | ||
return exports[name](domain, range, pivot) | ||
} // else | ||
throw new Error('Unknown estimator type: ' + type) | ||
} catch (e) { | ||
if (typeof exports[name] !== 'function') { | ||
throw new Error('Unknown estimator type: ' + type) | ||
} | ||
throw e | ||
} | ||
} |
@@ -108,2 +108,24 @@ | ||
proto.toString = function () { | ||
// Return a string of CSS transform-function data type. | ||
// | ||
// Together with nudged.createFromString(...), this method allows | ||
// serialization to and from strings. | ||
// | ||
// NOTE When JavaScript converts numbers to strings, the string might | ||
// end up using the scientific notation (e.g. 1e-12). Not all browsers | ||
// support scientific notation in CSS. We have experienced problems | ||
// with Safari and Opera. Therefore toString must prevent the scientific | ||
// notation here and convert to fixed number of decimal places. | ||
// | ||
// See also: https://stackoverflow.com/q/1685680/638546 | ||
// | ||
var a = this.s.toFixed(8) | ||
var b = this.r.toFixed(8) | ||
var c = (-this.r).toFixed(8) // Unnecessary? Maybe '-' + b? | ||
var x = this.tx.toFixed(8) | ||
var y = this.ty.toFixed(8) | ||
return 'matrix(' + a + ',' + b + ',' + c + ',' + a + ',' + x + ',' + y + ')' | ||
} | ||
// Methods that return new points | ||
@@ -110,0 +132,0 @@ |
// generated by genversion | ||
module.exports = '1.4.0' | ||
module.exports = '1.5.0' |
{ | ||
"name": "nudged", | ||
"version": "1.4.0", | ||
"version": "1.5.0", | ||
"description": "Affine transformation estimator e.g. for multi-touch gestures and calibration", | ||
@@ -39,3 +39,3 @@ "keywords": [ | ||
"should": "^13.2.0", | ||
"standard": "^10.0.3" | ||
"standard": "^14.3.4" | ||
}, | ||
@@ -42,0 +42,0 @@ "scripts": { |
150
README.md
@@ -6,46 +6,31 @@ # nudged | ||
**A JavaScript lib** to efficiently estimate translation, scale, and/or rotation between two sets of 2D points. We have found it to be useful in **graphics, user interfaces, multi-touch recognition, and eye tracker calibration**. In general, you can apply *nudged* in any situation where you want to move a number of points based on a few sample points and optionally one fixed pivot point. See the image below for visual explanation. | ||
*Nudged* is **a JavaScript module** to efficiently estimate translation, scale, and/or rotation between two sets of 2D points. It has already been applied to **user interfaces, multi-touch recognition, geography, and eye tracker calibration**. | ||
<img src="https://rawgit.com/axelpale/nudged/master/doc/figure-pointset.png" alt="Example transformation" width="500"/> | ||
### Table of contents | ||
_**Figure**: Left: You have a set of points. Center: you known where three of them should be moved. Right: With *nudged*, based on the initial position of the three points and their target positions, you can estimate a transformation that nicely transforms all the rest of the points._ | ||
- [Introduction](#introduction) | ||
- [Installation](#installation) | ||
- [Usage](#usage) | ||
- [Example apps](#example-apps) | ||
- [API](#api) | ||
- [For developers](#for-developers) | ||
- [Acknowledgments](#acknowledgments) | ||
- [Versioning](#versioning) | ||
- [Licence](#licence) | ||
**Mathematically speaking**, *nudged* is a set of optimal least squares estimators for nonreflective similarity transformation matrices. Such transformations are [affine transformations](https://en.wikipedia.org/wiki/Affine_transformation) with translation, rotation, and/or uniform scaling, and without reflection or shearing. The estimation has time complexity of O(*n*), where *n* is the cardinality (size) of the point sets. In other words, *nudged* solves a 2D to 2D point set registration problem (alias [Procrustes superimposition](https://en.wikipedia.org/wiki/Procrustes_analysis)) in linear time. The algorithms and their efficiency are thoroughly described in a **M.Sc. thesis** [Advanced algorithms for manipulating 2D objects on touch screens](http://URN.fi/URN:NBN:fi:tty-201605264186). | ||
**The development has been supported** by [Infant Cognition Laboratory](http://www.uta.fi/med/icl/index.html) at [University of Tampere](http://www.uta.fi/en/) where it is used to correct eye tracking data. | ||
## Introduction | ||
Available also [in Python](https://pypi.python.org/pypi/nudged). | ||
In general, you can apply Nudged in any situation where you want to capture a 2D transformation based on a movement of any number of control points. There are different See the image below for available types of transforms Nudged can estimate. | ||
<img src="doc/transformation-types.jpg" alt="Types of transformation estimators"/><br> | ||
_**Image**: Available types of transformation estimators. Each estimator has an abbreviated name, for example 'SR'. The black-white dots and connecting arrows represent movement of two control points. Given the control points, Nudged estimates a transformation. The image pairs represent the effect of the resulting transformation. To emphasize the effect, the control points and the initial image positions are kept the same for each type._ | ||
**Mathematically speaking**, Nudged is a set of optimal [least squares estimators](https://en.wikipedia.org/wiki/Least_squares) for nonreflective similarity transformation matrices. Such transformations are [affine transformations](https://en.wikipedia.org/wiki/Affine_transformation) with translation, rotation, and/or uniform scaling, and without reflection or shearing. The estimation has [time complexity](https://en.wikipedia.org/wiki/Time_complexity) of O(*n*), where *n* is the cardinality (size) of the point sets. In other words, Nudged solves a 2D to 2D point set registration problem (alias [Procrustes superimposition](https://en.wikipedia.org/wiki/Procrustes_analysis)) in [linear time](https://en.wikipedia.org/wiki/Time_complexity#Linear_time). The algorithms and their efficiency are thoroughly described in a **M.Sc. thesis** [Advanced algorithms for manipulating 2D objects on touch screens](http://URN.fi/URN:NBN:fi:tty-201605264186). | ||
## Example apps | ||
**The development has been supported** by [Infant Cognition Laboratory](https://www.tuni.fi/en/research/infant-cognition) at [Tampere University](https://www.tuni.fi/en/) where Nudged is used to correct eye tracking data. Yet, the main motivation for Nudged comes from [Tapspace](https://github.com/taataa/tapspace), a zoomable user interface library where smooth and fast scaling by touch is crucial. | ||
To get a grip, play with the following demos. | ||
### Multitouch transformation with N fingers | ||
## Installation | ||
[<img src="https://rawgit.com/axelpale/nudged/master/examples/nudged-gesture/screenshot.jpg" alt="Four hands transforming the image simultaneously" width="600"/>](https://rawgit.com/axelpale/nudged/master/examples/nudged-gesture/index.html) | ||
The [**touch gesture demo**](https://rawgit.com/axelpale/nudged/master/examples/nudged-gesture/index.html) takes the common pinch-zoom and rotate gestures a step further. Many multitouch apps allow you to scale and rotate with two fingers. However, usually the additional fingers are ignored. But what if one wants to use, say, both hands and all the fingers on a huge touchscreen? | ||
For reference, the [**typical gesture demo**](https://rawgit.com/axelpale/nudged/master/examples/typical-gesture/index.html) implements similar demo with the popular [Hammer.js](http://hammerjs.github.io/) touch gesture library. As you can experience, only the first two pointers are regarded for scaling and rotation. | ||
### Point set editor | ||
[<img src="https://rawgit.com/axelpale/nudged/master/examples/nudged-editor/screenshot.png" alt="Nudged editor screenshot" width="600"/>](https://rawgit.com/axelpale/nudged/master/examples/nudged-editor/index.html) | ||
The [**editor demo**](https://rawgit.com/axelpale/nudged/master/examples/nudged-editor/index.html) allows you to add domain and range points on a surface and explore how the points affect the transformation. | ||
### Tokyo metro map viewer | ||
[<img src="https://rawgit.com/axelpale/nudged/master/examples/nudged-map/screenshot.png" alt="A screenshot of Nudged map viewer example" width="600"/>](https://rawgit.com/axelpale/nudged/master/examples/nudged-map/index.html) | ||
In this [map viewer demo](https://rawgit.com/axelpale/nudged/master/examples/nudged-map/index.html), nudged is used to recognize multi-touch gestures to scale, rotate, and translate [a large image](https://commons.wikimedia.org/wiki/File:Tokyo_metro_map.png) on HTML5 canvas. | ||
## Install | ||
With [npm](https://www.npmjs.com/package/nudged): | ||
@@ -55,2 +40,3 @@ | ||
Available also [in Python](https://pypi.python.org/pypi/nudged). | ||
@@ -98,3 +84,2 @@ | ||
### Using pivoted transformations | ||
@@ -123,6 +108,30 @@ | ||
## Example apps | ||
The following demo applications give an example how nudged can be used in web. | ||
### Multitouch transformation with N fingers | ||
[<img src="https://rawgit.com/axelpale/nudged/master/examples/nudged-gesture/screenshot.jpg" alt="Four hands transforming the image simultaneously" width="600"/>](https://rawgit.com/axelpale/nudged/master/examples/nudged-gesture/index.html) | ||
The [**touch gesture demo**](https://rawgit.com/axelpale/nudged/master/examples/nudged-gesture/index.html) takes the common pinch-zoom and rotate gestures a step further. Many multitouch apps allow you to scale and rotate with two fingers. However, usually the additional fingers are ignored. But what if one wants to use, say, both hands and all the fingers on a huge touchscreen? | ||
For reference, the [**typical gesture demo**](https://rawgit.com/axelpale/nudged/master/examples/typical-gesture/index.html) implements similar demo with the popular [Hammer.js](http://hammerjs.github.io/) touch gesture library. As you can experience, only the first two pointers are regarded for scaling and rotation. | ||
### Point set editor | ||
[<img src="https://rawgit.com/axelpale/nudged/master/examples/nudged-editor/screenshot.png" alt="Nudged editor screenshot" width="600"/>](https://rawgit.com/axelpale/nudged/master/examples/nudged-editor/index.html) | ||
The [**editor demo**](https://rawgit.com/axelpale/nudged/master/examples/nudged-editor/index.html) allows you to add domain and range points on a surface and explore how the points affect the transformation. | ||
### Tokyo metro map viewer | ||
[<img src="https://rawgit.com/axelpale/nudged/master/examples/nudged-map/screenshot.png" alt="A screenshot of Nudged map viewer example" width="600"/>](https://rawgit.com/axelpale/nudged/master/examples/nudged-map/index.html) | ||
In this [map viewer demo](https://rawgit.com/axelpale/nudged/master/examples/nudged-map/index.html), nudged is used to recognize multi-touch gestures to scale, rotate, and translate [a large image](https://commons.wikimedia.org/wiki/File:Tokyo_metro_map.png) on HTML5 canvas. | ||
## API | ||
Nudged API provides a class for nonreflective similarity transformations and 7 types of estimators, one for each combination of translation, scaling, and rotation. The ones without translation allow an optional fixed point. | ||
Nudged API provides a class `Transform` to represent a nonreflective similarity transformation matrix and multiple functions to estimate such transformations from sets of points. | ||
@@ -161,3 +170,2 @@ ### nudged.create(scale, rotation, translationX, translationY) | ||
### nudged.createFromArray(arr) | ||
@@ -173,11 +181,25 @@ | ||
### nudged.estimate(type, domain, range, pivot?) | ||
### nudged.estimate(type, domain, range, param?) | ||
Compute an optimal affine transformation from the *domain* to *range* points. The *type* of transformation is any combination of translation `T`, scaling `S`, and rotation `R`, in this order. A special type `I` returns always the identity transformation. Transformations without translation (`S`, `R`, `SR`) allow an optional fixed *pivot* point. | ||
Compute an optimal affine transformation from *domain* to *range* points. The *type* of transformation determines the freedom of the transformation to be estimated. | ||
**Available types** | ||
- `I`: Identity transform. Whatever the points, returns always the identity transformation. | ||
- `L`: Translation along line. Takes additional *angle* parameter in radians. Direction of the angle is from positive x-axis towards positive y-axis. | ||
- `X`: Horizontal translation. Equivalent to `L` with angle 0. | ||
- `Y`: Vertical translation. Equivalent to `L` with angle ±PI/2. | ||
- `T`: Free translation. | ||
- `S`: Scaling about a fixed *pivot* point. | ||
- `R`: Rotation around a fixed *pivot* point. | ||
- `TS`: Free translation with scaling. | ||
- `TR`: Free translation with rotation. | ||
- `SR`: Scaling and rotation around a fixed *pivot* point. | ||
- `TSR`: Free translation with both scaling and rotation. | ||
**Parameters:** | ||
- *type*: string, freedom of the transformation. Types available: `'I'`, `'T'`, `'S'`, `'R'`, `'TS'`, `'TR'`, `'SR'`, `'TSR'` | ||
- *domain*: array of [x,y] points | ||
- *range*: array of [x,y] points | ||
- *pivot*: optional [x,y] point. Defaults to the origin [0,0] with types `'S'`, `'R'`, and `'SR'`. | ||
- *type*: string. The freedom of the transformation. Must be one of the following: `'I'`, `'L'`, `'X'`, `'Y'`, `'T'`, `'S'`, `'R'`, `'TS'`, `'TR'`, `'SR'`, `'TSR'` | ||
- *domain*: array of [x,y] points. The source point set. | ||
- *range*: array of [x,y] points. The target point set. | ||
- *param*: For types `S`, `R`, and `SR` this is an optional `[x,y]` pivot point that defaults to the origin `[0,0]`. For type `L` this is an angle in radians so that angle PI/2 (90 deg) is towards positive y-axis. | ||
@@ -188,5 +210,8 @@ The *domain* and *range* should have equal length. Different lengths are allowed but additional points in the longer array are ignored. | ||
You can also call the estimators directly: | ||
You can also call the estimators directly for slightly enhanced performance: | ||
- `nudged.estimateI()` | ||
- `nudged.estimateL(domain, range, angle)` | ||
- `nudged.estimateX(domain, range)` | ||
- `nudged.estimateY(domain, range)` | ||
- `nudged.estimateT(domain, range)` | ||
@@ -210,3 +235,2 @@ - `nudged.estimateS(domain, range, pivot)` | ||
### nudged.version | ||
@@ -219,3 +243,2 @@ | ||
### nudged.Transform(s, r, tx, ty) | ||
@@ -377,3 +400,2 @@ | ||
## For developers | ||
@@ -393,16 +415,13 @@ | ||
Release: | ||
Git workflow: | ||
- Create a feature branch: `$ git branch feature-name` | ||
- When feature finished, merge: | ||
- `$ git checkout master` | ||
- `$ git merge feature-name` | ||
- `$ git push` | ||
- Delete the feature branch. | ||
- Bump version in package.json, `npm run gv`, and run tests. | ||
- Build examples `npm run build:examples` | ||
- Create release branch. See [tutorial](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow). | ||
- `$ git checkout -b release-7.7.7 development` | ||
- Update the [badge urls](http://shields.io/) in README. | ||
- Update the rawgit urls in README: | ||
- Replace 'nudged/development' with 'nudged/master' | ||
- Commit: `$ git commit -a -m "Clean release 7.7.7"` | ||
- Merge (see the tutorial link above): | ||
- `$ git checkout master` | ||
- `$ git merge release-7.7.7` | ||
- `$ git push` | ||
- Commit: `$ git commit -a -m "Release 7.7.7"` | ||
- Create [tag](https://git-scm.com/book/en/v2/Git-Basics-Tagging): | ||
@@ -413,12 +432,13 @@ - `$ git tag -a 7.7.7 -m "v7.7.7 Superb Name"` | ||
- `$ npm publish` | ||
- Return to development to avoid accidental master commits | ||
- `$ git checkout development` | ||
## Thanks | ||
## Acknowledgments | ||
- [Infant Cognition Laboratory at University of Tampere](http://www.uta.fi/med/icl/index.html) for funding. | ||
- [3D Media Group at Tampere University of Technology](http://www.tut.fi/en/about-tut/departments/signal-processing/research/3d-media/) for testing devices. | ||
We want to thank: | ||
- [Tampere University of Technology](https://www.tuni.fi/en) and [Adj. Prof. Ossi Nykänen](https://www.researchgate.net/scientific-contributions/Ossi-Nykaenen-69896506) for guidance on the [M.Sc. thesis on Nudged](http://URN.fi/URN:NBN:fi:tty-201605264186). | ||
- [Infant Cognition Laboratory at University of Tampere](https://www.tuni.fi/en/research/infant-cognition) and [Adj. Prof. Jukka Leppänen](https://scholar.google.fi/citations?user=dNRRUIsAAAAJ) for funding and support in research. | ||
- [3D Media Group at Tampere University of Technology](https://www.tuni.fi/en/research/3d-media-group), [M.Sc. Olli Suominen](https://tutcris.tut.fi/portal/en/persons/olli-suominen(8d7b7ce4-1468-4621-9a6e-d307f644c9bb).html), and [Assoc. Prof. Atanas Gotchev](https://tutcris.tut.fi/portal/en/persons/atanas-gotchev(3b4a825b-941b-484e-b046-cd09bde1cd31).html) for providing touch-screen devices for testing. | ||
- Tanja for math photos. | ||
- Vilkku, Xiao, and Krista for fingers. | ||
- Vilkku, Xiao, and Krista for finger photos. | ||
@@ -432,4 +452,4 @@ | ||
## License | ||
## Licence | ||
[MIT License](../blob/master/LICENSE) | ||
[MIT Licence](../blob/master/LICENSE) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
42314
17
680
443