server.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. const express = require('express');
  2. const { Bundle, Client } = require('node-osc');
  3. const path = require('path');
  4. const bodyParser = require('body-parser');
  5. const app = express();
  6. const oscClient = new Client('127.0.0.1', 3333);
  7. let alive = [];
  8. let fseq;
  9. function getHypotenuse(touch1, touch2) {
  10. var x = Math.abs(touch1.x - touch2.x);
  11. var y = Math.abs(touch1.y - touch2.y);
  12. return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
  13. }
  14. const server = require('http').Server(app);
  15. app.use(bodyParser.json());
  16. app.use(bodyParser.urlencoded({extended:true}));
  17. app.use(express.static('./frontend/assets'));
  18. app.get('/', function (req, res) {
  19. res.sendFile('./frontend/index.html', { root: path.resolve(__dirname + '/..') })
  20. });
  21. app.post('/json', function (req, res) {
  22. if (req.body.debug) {
  23. //console.log(req.body);
  24. }
  25. let oscBundle;
  26. if (req.body.event === 'touchend') {
  27. fseq = fseq ? fseq + 1 : 1;
  28. const aliveMessage = [ '/tuio/2Dcur', 'alive' ].concat(alive);
  29. oscBundle = new Bundle(
  30. [ '/tuio/2Dcur', 'source', `tangibles${req.body.section.toString()}@127.0.0.1` ],
  31. aliveMessage,
  32. [ '/tuio/2Dcur', 'fseq', fseq ],
  33. [
  34. '/tuio/2Dcur',
  35. 'del',
  36. req.body.changedTouches[0].identifier
  37. ]
  38. );
  39. oscClient.send(oscBundle, () => {
  40. const index = alive.indexOf(req.body.changedTouches[0].identifier);
  41. alive.splice(index, 1);
  42. if (alive.length === 0) {
  43. oscBundle = new Bundle(
  44. [ '/tuio/2Dcur', 'source', `tangibles${req.body.section.toString()}@127.0.0.1` ],
  45. [ '/tuio/2Dcur', 'alive' ],
  46. [ '/tuio/2Dcur', 'fseq', fseq ]
  47. );
  48. oscClient.send(oscBundle, () => {
  49. res.status(200).json(JSON.stringify(req.body));
  50. fseq = 0;
  51. });
  52. } else {
  53. res.status(200).send();
  54. }
  55. });
  56. } else {
  57. if (req.body.changedTouches && req.body.changedTouches.length && req.body.changedTouches.length > 0) {
  58. fseq = fseq ? fseq + 1 : 1;
  59. const touches = Object.keys(req.body.changedTouches);
  60. const aliveMessage = [ '/tuio/2Dcur', 'alive' ].concat(alive);
  61. touches.forEach(touch => {
  62. const id = req.body.changedTouches[touch].identifier;
  63. if (!alive.includes(id)) {
  64. alive.push(id);
  65. aliveMessage.push(id);
  66. }
  67. });
  68. /* Listage de tous les points */
  69. const dots = [];
  70. touches.forEach(function(touch) {
  71. dots.push({
  72. id: req.body.changedTouches[touch].identifier,
  73. x: req.body.changedTouches[touch].clientX,
  74. y: req.body.changedTouches[touch].clientY
  75. });
  76. });
  77. // console.log(dots, dots.length);
  78. /* Listage des segments */
  79. const segments = [];
  80. if (dots.length > 2) {
  81. for (var i = 0; i < dots.length; i++) {
  82. for (var j = 0; j < dots.length; j++) {
  83. if (j !== i) {
  84. /* on vérifie que le segment n'est pas déjà listé */
  85. const alreadyExists = segments.find(segment => {
  86. return segment.identifiers.includes(i) && segment.identifiers.includes(j);
  87. });
  88. /* on calcule la taille du segment (l'hypoténuse) */
  89. var hyp = getHypotenuse(dots[i], dots[j]);
  90. /* on garde uniquement les segments inférieurs à 550px
  91. * cette valeur devra être une variable de configuration */
  92. if (!alreadyExists && hyp <= 550) {
  93. segments.push({
  94. identifiers: [i, j],
  95. x1: dots[i].x,
  96. x2: dots[j].x,
  97. y1: dots[i].y,
  98. y2: dots[j].y,
  99. hyp
  100. });
  101. }
  102. }
  103. }
  104. }
  105. }
  106. // console.log(segments, segments.length);
  107. /* Listage des triangles */
  108. var triangles = [];
  109. /* on boucle sur les segments */
  110. segments.forEach((segment) => {
  111. const dot1 = segment.identifiers[0];
  112. const dot2 = segment.identifiers[1];
  113. /* on vérifie que le triangle n'est pas déjà listé */
  114. const alreadyExists = triangles.find(triangle => {
  115. return triangle.includes(dot1) && triangle.includes(dot2);
  116. });
  117. if (!alreadyExists) {
  118. /* on cherche les segments qui contiennent un des 2 points du segment actuel
  119. * ex: si le segment actuel est AB, on cherche un segment contenant A (pour AC) et un autre contenant B (pour BC) */
  120. const found1 = segments.findIndex(seg => {
  121. return (seg.identifiers.includes(dot1) && !seg.identifiers.includes(dot2));
  122. });
  123. const found2 = segments.findIndex(seg => {
  124. return (seg.identifiers.includes(dot2) && !seg.identifiers.includes(dot1));
  125. });
  126. /* si on trouve bien les 2 segments (AC et BC), on peut créer un triangle */
  127. if (found1 !== -1 && found2 !== -1) {
  128. /* on devine quel est le 3ème point du triangle par rapport au segment actuel (le point C par rapport au segment AB) */
  129. const dot3 = segments[found1].identifiers.find(identifier => {
  130. return identifier !== dot1 && identifier !== dot2;
  131. });
  132. triangles.push([dot1, dot2, dot3]);
  133. }
  134. }
  135. });
  136. // console.log(triangles, triangles.length);
  137. /* Définition de l'apex */
  138. triangles.forEach(triangle => {
  139. /* on récupère les 3 côtés (segments) du triangle */
  140. const segment1 = segments.find(segment => {
  141. return segment.identifiers.includes(triangle[0]) && segment.identifiers.includes(triangle[1]);
  142. });
  143. const segment2 = segments.find(segment => {
  144. return segment.identifiers.includes(triangle[1]) && segment.identifiers.includes(triangle[2]);
  145. });
  146. const segment3 = segments.find(segment => {
  147. return segment.identifiers.includes(triangle[0]) && segment.identifiers.includes(triangle[2]);
  148. });
  149. /* on trouve quel côté est le plus court
  150. * NOTE: dans notre cas, l'apex sera toujours le point opposé au plus petit côté
  151. * cette méthode n'est pas généralisable à d'autres projets */
  152. const smallestSegment = [segment1, segment2, segment3].reduce(function(prev, current) {
  153. return (prev.hyp < current.hyp) ? prev : current
  154. });
  155. /* on déduit quel point du triangle est l'apex */
  156. const apexDot = triangle.find(dot => {
  157. return dot !== smallestSegment.identifiers[0] && dot !== smallestSegment.identifiers[1];
  158. });
  159. console.log(apexDot);
  160. /* Reste à faire:
  161. * trouver la valeur de l'angle de l'apex (théorème des cosinus)
  162. * trouver le "centre" du triangle (via les orthocentres ou médianes??)
  163. * déduire l'orientation du triangle
  164. */
  165. });
  166. oscBundle = new Bundle(
  167. [ '/tuio/2Dcur', 'source', `tangibles${req.body.section.toString()}@127.0.0.1` ],
  168. aliveMessage,
  169. [ '/tuio/2Dcur', 'fseq', fseq ]
  170. );
  171. touches.forEach(touch => {
  172. oscBundle.append(
  173. [
  174. '/tuio/2Dcur',
  175. 'set',
  176. req.body.changedTouches[touch].identifier,
  177. req.body.changedTouches[touch].clientX / req.body.screenW,
  178. req.body.changedTouches[touch].clientY / req.body.screenH,
  179. 0.0,
  180. 0.0
  181. ]
  182. );
  183. });
  184. oscClient.send(oscBundle, () => {
  185. res.status(200).json(JSON.stringify(req.body));
  186. });
  187. } else {
  188. res.status(400).send();
  189. }
  190. }
  191. });
  192. server.listen(5001, function () {
  193. console.log('Votre app est disponible sur localhost:5001 !')
  194. });