4 Commits c803646fdc ... 9fe8240303

Author SHA1 Message Date
  bdestombes 9fe8240303 WIP: draw triangles 3 years ago
  bdestombes 52882fb274 chore: merge master 3 years ago
  bdestombes 89d9a88b10 feat: log handling 3 years ago
  bdestombes d1d0908497 feat: add configurable timer to emitter 3 years ago
3 changed files with 260 additions and 161 deletions
  1. 63 65
      backend/server.js
  2. 31 2
      frontend/assets/config.json
  3. 166 94
      frontend/index.html

+ 63 - 65
backend/server.js

@@ -50,8 +50,11 @@ app.get('/receiver/json', function (req, res) {
 
 receiverIo.sockets.on('connection', (socket) =>{
 	console.log(`Connecté au client ${socket.id}`);
+
 	const dgramCallback = function (buf) {
-		// console.log(oscParser.decode(buf));
+		if (config.app.debugLog.backend.receiver.oscDatagram) {
+			console.log(oscParser.decode(buf));
+		}
 		socket.emit('osc', oscParser.decode(buf));
 	};
 
@@ -158,69 +161,83 @@ function getOrientation(dotTrio, topIndex) {
 	 //return length ;
 }
 
+let currentOscBundle = null;
+let hasPending = false;
+
+const sendBundle = () => {
+	if (hasPending) {
+		emitterOscClient.send(currentOscBundle, () => {
+			hasPending = false;
+		});
+	}
+	setTimeout(() => {
+		sendBundle();
+	}, config.app.timerRefresh);
+};
+sendBundle();
+
 app.post('/emitter/json', function (req, res) {
-	if (req.body.debug) {
-		//console.log(req.body);
+	if (config.app.debug && config.app.debugLog.backend.emitter.httpRequest) {
+		console.log('### Emitter POST request ###');
 	}
 	let oscBundle;
-	if (req.body.event === 'touchend') {
+	if (req.body.type === 'touchend') {
 		fseq = fseq ? fseq + 1 : 1;
 
 		const aliveMessage = [ '/tuio/2Dcur', 'alive' ].concat(alive);
-		oscBundle = new Bundle(
+		currentOscBundle = new Bundle(
 			[ '/tuio/2Dcur', 'source', `tangibles${req.body.section.toString()}@127.0.0.1` ],
 			aliveMessage,
 			[ '/tuio/2Dcur', 'fseq', fseq ],
 			[
 				'/tuio/2Dcur',
 				'del',
-				req.body.changedTouches[0].identifier
+				req.body.touches[0].identifier
 			]
 		);
-		emitterOscClient.send(oscBundle, () => {
-			const index = alive.indexOf(req.body.changedTouches[0].identifier);
+		emitterOscClient.send(currentOscBundle, () => {
+			const index = alive.indexOf(req.body.touches[0].identifier);
 			alive.splice(index, 1);
 			if (alive.length === 0) {
-				oscBundle = new Bundle(
+				currentOscBundle = new Bundle(
 					[ '/tuio/2Dcur', 'source', `tangibles${req.body.section.toString()}@127.0.0.1` ],
 					[ '/tuio/2Dcur', 'alive' ],
 					[ '/tuio/2Dcur', 'fseq', fseq ]
 				);
-				emitterOscClient.send(oscBundle, () => {
+				emitterOscClient.send(currentOscBundle, () => {
 					res.status(200).send();
 					fseq = 0;
+					hasPending = false;
 				});
 			} else {
 				res.status(200).send();
 			}
 		});
 	} else {
-		if (req.body.changedTouches && req.body.changedTouches.length && req.body.changedTouches.length > 0) {
+		if (req.body.touches && req.body.touches.length && req.body.touches.length > 0) {
 			fseq = fseq ? fseq + 1 : 1;
-			const touches = Object.keys(req.body.changedTouches);
+			const touches = Object.keys(req.body.touches);
 			const aliveMessage = [ '/tuio/2Dcur', 'alive' ].concat(alive);
 			touches.forEach(touch => {
-				const id = req.body.changedTouches[touch].identifier;
+				const id = req.body.touches[touch].identifier;
 				if (!alive.includes(id)) {
 					alive.push(id);
 					aliveMessage.push(id);
 				}
 			});
 
-
-
-
-
 			/* Listage de tous les points */
 			const dots = [];
 			touches.forEach(function(touch) {
 				dots.push({
-					id: req.body.changedTouches[touch].identifier,
-					x: req.body.changedTouches[touch].clientX,
-					y: req.body.changedTouches[touch].clientY
+					id: req.body.touches[touch].identifier,
+					x: req.body.touches[touch].clientX,
+					y: req.body.touches[touch].clientY
 				});
 			});
-			// console.log(dots, dots.length);
+			if (config.app.debug && config.app.debugLog.backend.emitter.dots) {
+				console.log('-- dots --', dots);
+			}
 
 			/* Listage des segments */
 			const segments = [];
@@ -250,7 +267,9 @@ app.post('/emitter/json', function (req, res) {
 					}
 				}
 			}
-			// console.log(segments, segments.length);
+			if (config.app.debug && config.app.debugLog.backend.emitter.segments) {
+				console.log('-- segments --', segments);
+			}
 
 			/* Listage des triangles */
 			const triangles = [];
@@ -281,14 +300,15 @@ app.post('/emitter/json', function (req, res) {
 					}
 				}
 			});
-			 console.log(triangles, triangles.length);
+			if (config.app.debug && config.app.debugLog.backend.emitter.triangles) {
+				console.log('-- triangles --', triangles);
+			}
 
-			//MOD TITI
-			//objet pour stocker les informations des triangles identifiés (points, centre, apexAngle, orientation, indice apex, width, height)
+			/* objet pour stocker les informations des triangles identifiés (points, centre, apexAngle, orientation, indice apex, width, height) */
 
 			objTriangle = {} ;
 
-			/* Définition de l'apex */
+			/* Définition de l'apex, de la position du centre et de l'orientation */
 			triangles.forEach(triangle => {
 				objTriangle.dots = [];
 				objTriangle.dots[0] = dots[triangle[0]];
@@ -303,35 +323,11 @@ app.post('/emitter/json', function (req, res) {
 
 				objTriangle.angleApex = getAngleApex(objTriangle.dots, objTriangle.apex) ;
 				objTriangle.orientation = getOrientation(objTriangle.dots, objTriangle.apex) ;
-				// /* on récupère les 3 côtés (segments) du triangle */
-				// const segment1 = segments.find(segment => {
-				// 	return segment.identifiers.includes(triangle[0]) && segment.identifiers.includes(triangle[1]);
-				// });
-				// const segment2 = segments.find(segment => {
-				// 	return segment.identifiers.includes(triangle[1]) && segment.identifiers.includes(triangle[2]);
-				// });
-				// const segment3 = segments.find(segment => {
-				// 	return segment.identifiers.includes(triangle[0]) && segment.identifiers.includes(triangle[2]);
-				// });
-				// /* on trouve quel côté est le plus court
-				//  * NOTE: dans notre cas, l'apex sera toujours le point opposé au plus petit côté
-				//  * cette méthode n'est pas généralisable à d'autres projets */
-				// const smallestSegment = [segment1, segment2, segment3].reduce(function(prev, current) {
-				// 	return (prev.hyp < current.hyp) ? prev : current
-				// });
-
-				// /* on déduit quel point du triangle est l'apex */
-				// const apexDot = triangle.find(dot => {
-				// 	return dot !== smallestSegment.identifiers[0] && dot !== smallestSegment.identifiers[1];
-				// });
-				console.log(objTriangle.apex);
-				console.log('centerPos : ' + objTriangle.center + ' orientation : ' + objTriangle.orientation);
-
-				/* Reste à faire:
-				 * trouver la valeur de l'angle de l'apex (théorème des cosinus)
-				 * trouver le "centre" du triangle (via les orthocentres ou médianes??)
-				 * déduire l'orientation du triangle
-				 */
+
+				if (req.body.debug) {
+					console.log('-- apex --', objTriangle.apex);
+					console.log('centerPos : ' + objTriangle.center + ' orientation : ' + objTriangle.orientation);
+				}
 			});
 
 
@@ -392,24 +388,26 @@ app.post('/emitter/json', function (req, res) {
 			// 		[
 			// 			'/tuio/2Dcur',
 			// 			'set',
-			// 			req.body.changedTouches[touch].identifier,
-			// 			req.body.changedTouches[touch].clientX / req.body.screenW,
-			// 			req.body.changedTouches[touch].clientY / req.body.screenH,
+			// 			req.body.touches[touch].identifier,
+			// 			req.body.touches[touch].clientX / req.body.screenW,
+			// 			req.body.touches[touch].clientY / req.body.screenH,
 			// 			0.0,
 			// 			0.0
 			// 		]
 			// 	);
 			// });
-			oscBundle = new Bundle ;
-			oscBundle.append([ '/tuio/2Dobj', 'alive', 1 ]);
+			currentOscBundle = new Bundle ;
+			currentOscBundle.append([ '/tuio/2Dobj', 'alive', 1 ]);
 			if (objTriangle.dots != undefined) {
-				oscBundle.append([
+				currentOscBundle.append([
 					'/tuio/2Dobj',
 					'set',
 					1,
 					1,
 					objTriangle.center[0],
 					objTriangle.center[1],
+					// objTriangle.center[0] / req.body.screenW,
+					// objTriangle.center[1] / req.body.screenH,
 					objTriangle.orientation,
 					0.0,
 					0.0,
@@ -418,10 +416,10 @@ app.post('/emitter/json', function (req, res) {
 					0.0
 				]);
 			}
-			oscBundle.append([ '/tuio/2Dobj', 'fseq', fseq ]);
-			emitterOscClient.send(oscBundle, () => {
-				res.status(200).send();
-			});
+
+			currentOscBundle.append(['/tuio/2Dobj', 'fseq', fseq]);
+			hasPending = true;
+			res.status(200).send();
 		} else {
 			res.status(400).send();
 		}

+ 31 - 2
frontend/assets/config.json

@@ -1,10 +1,39 @@
 {
 	"app": {
-		"debug": 0,
 		"oscUdpPort": 3333,
 		"httpPort": 5000,
 		"timerRefresh": 50,
-		"maxDistanceBetweenPoints": 750
+		"maxDistanceBetweenPoints": 750,
+		"debug": true,
+		"debugLog": {
+			"backend": {
+				"emitter": {
+					"httpRequest": false,
+					"dots": false,
+					"segments": true,
+					"triangles": false
+				},
+				"receiver": {
+					"oscDatagram": false
+				}
+			},
+			"frontend": {
+				"emitter": {
+					"screen": true,
+					"events": false
+				},
+				"receiver": {
+					"onAddTuioCursor": false,
+					"onUpdateTuioCursor": false,
+					"onRemoveTuioCursor": false,
+					"onAddTuioObject": false,
+					"onUpdateTuioObject": true,
+					"onRemoveTuioObject": false,
+					"onRefresh": false
+				}
+			}
+		},
+		"debugDisplay": true
 	},
 	"triangles": []
 }

+ 166 - 94
frontend/index.html

@@ -7,7 +7,15 @@
 
 		<style>
 			body {
+				width: 100%;
+				height: 100%;
 				margin: 0;
+				background-color: #EEEEEE;
+			}
+			#box {
+				width: 100%;
+				height: 100%;
+				border: 1px solid red;
 			}
 			.tuioCursor {
 				background: #111;
@@ -29,172 +37,236 @@
 		</style>
 	</head>
 
-	<body style="height: 100%;">
-		<div id="box" style="width: 100%; height: 100%; background-color: #EEEEEE;"></div>
-		<script src="/jquery-1.7.2.js"></script>
+	<body>
+
+		<!--<div id="box"></div>-->
+		<canvas id="box"></canvas>
+
+		<!--<script src="/jquery-1.7.2.js"></script>-->
 		<script src="/lodash.js"></script>
 		<script src="/socket.io/socket.io.js"></script>
 		<script src="/tuio.js"></script>
 		<script>
-			/* -------
-			 * EMITTER
-			 * -------
-			 */
-			const box = document.getElementById('box');
-
-			const urlParams = new URLSearchParams(window.location.search);
-			const sectionParam = urlParams.get('section');
-			const section = sectionParam ? parseInt(sectionParam, 10) : 100;
-			const debugParams = urlParams.get('debug');
-			const debug = debugParams ? true : false;
-			if (debug) {
-				console.log('--- Debug activated ---');
-				console.log(`Section: ${section.toString()}`);
-			}
+			let config = {};
+			const getConfig = () => {
+				return fetch('/config.json');
+			};
+
+			getConfig().then(response => {
+				return response.json();
+			}).then(data => {
+				config = data;
+
+				const urlParams = new URLSearchParams(window.location.search);
+				const sectionParam = urlParams.get('section');
+				const section = sectionParam ? parseInt(sectionParam, 10) : 100;
+
+				if (config.app.debug) {
+					console.log('### Frontend debug activated ###');
+				}
 
-			const eventHandler = (evt, type) => {
-				if (debug) {
-					console.log(evt);
+				const screenW = window.innerWidth;
+				const screenH = window.innerHeight;
+
+				if (config.app.debug && config.app.debugLog.frontend.emitter.screen) {
+					console.log(`-- Screen width: ${screenW} --`);
+					console.log(`-- Screen height: ${screenH} --`);
 				}
 
-				const touches = [];
-				for (var i = 0; i < evt.changedTouches.length; i++) {
-					touches[i] = {
-						clientX: evt.changedTouches[i].clientX,
-						clientY: evt.changedTouches[i].clientY,
-						force: evt.changedTouches[i].force,
-						identifier: ((evt.changedTouches[i].identifier + 1) % 100) + section,
-						pageX: evt.changedTouches[i].pageX,
-						pageY: evt.changedTouches[i].pageY,
-						radiusX: evt.changedTouches[i].radiusX,
-						radiusY: evt.changedTouches[i].radiusY,
-						rotationAngle: evt.changedTouches[i].rotationAngle,
-						screenX: evt.changedTouches[i].screenX,
-						screenY: evt.changedTouches[i].screenY
+				/* -------
+				 * EMITTER
+				 * -------
+				 */
+				const box = document.getElementById('box');
+
+				const eventHandler = (evt, type) => {
+					const touches = [];
+					for (var i = 0; i < evt.changedTouches.length; i++) {
+						touches[i] = {
+							clientX: evt.changedTouches[i].clientX,
+							clientY: evt.changedTouches[i].clientY,
+							force: evt.changedTouches[i].force,
+							identifier: ((evt.changedTouches[i].identifier + 1) % 100) + section,
+							pageX: evt.changedTouches[i].pageX,
+							pageY: evt.changedTouches[i].pageY,
+							radiusX: evt.changedTouches[i].radiusX,
+							radiusY: evt.changedTouches[i].radiusY,
+							rotationAngle: evt.changedTouches[i].rotationAngle,
+							screenX: evt.changedTouches[i].screenX,
+							screenY: evt.changedTouches[i].screenY
+						};
 					};
+
+					if (config.app.debug && config.app.debugLog.frontend.emitter.events) {
+						console.log(`-- Event: ${type} --`, touches);
+					}
+
+					if (config.app.debug && config.app.debugDisplay) {
+						box.innerHTML = evt.touches.length;
+					}
+
+					fetch(`http://localhost:${config.app.httpPort}/emitter/json`, {
+						method: 'POST',
+						mode: 'cors',
+						cache: 'no-cache',
+						credentials: 'same-origin',
+						headers: {
+							'Content-Type': 'application/json'
+						},
+						redirect: 'follow',
+						referrerPolicy: 'no-referrer',
+						body: JSON.stringify({
+							type,
+							section,
+							screenW,
+							screenH,
+							touches
+						})
+					});
+					evt.preventDefault();
 				};
-				box.innerHTML = evt.touches.length;
-				fetch('http://localhost:5000/emitter/json', {
-					method: 'POST',
-					mode: 'cors',
-					cache: 'no-cache',
-					credentials: 'same-origin',
-					headers: {
-						'Content-Type': 'application/json'
-					},
-					redirect: 'follow',
-					referrerPolicy: 'no-referrer',
-					body: JSON.stringify({
-						event: type,
-						debug,
-						section,
-						screenW: $(document).width(),
-						screenH: $(document).height(),
-						changedTouches: touches
-					})
-				});
-				evt.preventDefault();
-			};
 
-			box.addEventListener('touchstart', (evt) => {
-				return eventHandler(evt, 'touchstart');
-			});
+				box.addEventListener('touchstart', (evt) => {
+					return eventHandler(evt, 'touchstart');
+				});
 
-			box.addEventListener('touchmove', (evt) => {
-				return eventHandler(evt, 'touchmove');
-			});
+				box.addEventListener('touchmove', (evt) => {
+					return eventHandler(evt, 'touchmove');
+				});
 
-			box.addEventListener('touchend', (evt) => {
-				return eventHandler(evt, 'touchend');
-			});
+				box.addEventListener('touchend', (evt) => {
+					return eventHandler(evt, 'touchend');
+				});
 
-			if (!(typeof box.ontouchstart != 'undefined')) {
-				box.style.border = '1px solid red';
-			}
+				/* --------
+				 * RECEIVER
+				 * --------
+				 */
 
+				const canvas = document.getElementById('box');
+				context = canvas.getContext('2d');
 
-			/* --------
-			 * RECEIVER
-			 * --------
-			 */
+				const drawTriangle = (a, b, c) => {
+					console.log(context, Math.round(a.x), Math.round(a.y), Math.round(b.x), Math.round(b.y), Math.round(c.x), Math.round(c.y));
 
-			$(function() {
-				const urlParams = new URLSearchParams(window.location.search);
-				const debugParams = urlParams.get('debug');
-				const debug = debugParams ? true : false;
-				if (debug) {
-						console.log('--- Debug activated ---');
-				}
-				var dotGroups = [];
-				var client = new Tuio.Client({
-						host: 'http://localhost:5000'
-				}),
-				screenW = $(document).width(),
-				screenH = $(document).height()
+					const path = new Path2D();
+					path.moveTo(Math.round(a.x), Math.round(a.y));
+					path.lineTo(Math.round(b.x), Math.round(b.y));
+					path.lineTo(Math.round(c.x), Math.round(c.y));
+					context.fill(path);
+				};
+				const client = new Tuio.Client({
+					host: `http://localhost:${config.app.httpPort}`
+				});
 
-				cursors = {},
-				objects = {},
+				const cursors = {};
+				const objects = {};
 
 				onConnect = function() {
-					if (debug) {
-						console.log('connected');
+					if (config.app.debug) {
+						console.log('connected to web-socket');
 					}
 				},
 
 				onAddTuioCursor = function(addCursor) {
+					/*
 					var $addCursor = $('<div class="tuioCursor"></div>');
 					$('body').append($addCursor);
 					cursors[addCursor.getCursorId()] = $addCursor;
+					*/
 					onUpdateTuioCursor(addCursor);
+					if (config.app.debug && config.app.debugLog.frontend.receiver.onAddTuioCursor) {
+						console.log('addTuioCursor', addCursor);
+					}
 				},
 
 				onUpdateTuioCursor = function(updateCursor) {
+					/*
 					var $updateCursor = cursors[updateCursor.getCursorId()];
 					$updateCursor.css({
 						left: updateCursor.getScreenX(screenW),
 						top: updateCursor.getScreenY(screenH)
 					});
+					*/
+					if (config.app.debug && config.app.debugLog.frontend.receiver.onUpdateTuioCursor) {
+						console.log('updateTuioCursor', updateCursor);
+					}
 				},
 
 				onRemoveTuioCursor = function(removeCursor) {
+					/*
 					var $removeCursor = cursors[removeCursor.getCursorId()];
 					$removeCursor.remove();
 					delete[removeCursor.getCursorId()];
+					*/
+					if (config.app.debug && config.app.debugLog.frontend.receiver.onRemoveTuioCursor) {
+						console.log('removeTuioCursor', removeCursor);
+					}
 				},
 
 				onAddTuioObject = function(addObject) {
+					/*
 					var $addObject = $('<div class="tuioObj"></div>');
 					$('body').append($addObject);
 					objects[addObject.symbolID] = $addObject;
+					*/
+
 					onUpdateTuioObject(addObject);
-					if (debug) {
+					if (config.app.debug && config.app.debugLog.frontend.receiver.onAddTuioObject) {
 						console.log('addTuioObject', addObject);
 					}
 				},
 
 				onUpdateTuioObject = function(updateObject) {
+					/*
 					var $updateObject = objects[updateObject.symbolID];
 					$updateObject.css({
 						left: updateObject.getScreenX(screenW),
 						top: updateObject.getScreenY(screenH),
 						rotate : updateObject.getAngleDegrees()
 					});
-					if (debug) {
+					*/
+
+					const apexAngle = 35;
+					const mediatrice = 300;
+
+					if (config.app.debugDisplay) {
+						const x = updateObject.xPos;
+						const y = updateObject.yPos;
+
+						const apex = {
+							x: Math.cos(updateObject.angle * Math.PI / 180) * (mediatrice / 2) + x,
+							y: Math.sin(updateObject.angle * Math.PI / 180) * (mediatrice / 2) + y
+						};
+						const b = {
+							x: Math.cos((apexAngle / 2) * Math.PI / 180) * (mediatrice / 2) + apex.x,
+							y: Math.sin((apexAngle / 2) * Math.PI / 180) * (mediatrice / 2) + apex.y
+						};
+						const c = {
+							x: Math.cos((-1 * apexAngle / 2) * Math.PI / 180) * (mediatrice / 2) + apex.x,
+							y: Math.sin((-1 * apexAngle / 2) * Math.PI / 180) * (mediatrice / 2) + apex.y
+						};
+						drawTriangle(apex, b, c);
+					}
+
+					if (config.app.debug && config.app.debugLog.frontend.receiver.onUpdateTuioObject) {
 						console.log('updateTuioObject', updateObject);
 					}
 				},
 
 				onRemoveTuioObject = function(removeObject) {
+					/*
 					var $removeObject = objects[removeObject.symbolID];
 					$removeObject.remove();
 					delete[removeObject.symbolID];
-					if (debug) {
+					*/
+					if (config.app.debug && config.app.debugLog.frontend.receiver.onRemoveTuioObject) {
 						console.log('removeTuioObject', removeObject);
 					}
 				},
 
 				onRefresh = function(time) {
-					if (debug) {
+					if (config.app.debug && config.app.debugLog.frontend.receiver.onRefresh) {
 						console.log('refresh', time);
 					}
 				};