// Simulation trajectoire d'un robot tondeuse // sur une surface rectangulaire // // (c) Keops 30/10/2014 - Public Domain // // Réalisé par emmanuel.ostenne@ac-lille.fr // // avec ProgLab : http://proglab.fr // et JavascriptEnLigne : http://emmanuel.ostenne.free.fr/mepirem/algo/ // testé aussi sous JSFiddle : http://jsfiddle.net/ // // Le nombre de changements de directions saisie est un minimum // pour le nombre réellement accompli par le bouton Lancer : // l'algorithme se termine toujours par un déplacement solution // donc peut dépasser le minimum visé. // //Sélection automatique de la sortie pour JSGeoDynA, Algo ou ProgLab, JSFiddle if (document.getElementById("jsxbox") !== null) var sortie = document.getElementById("sortiesDiv"); //jsgeodyna else if (document.getElementById("aide") !== null) var sortie = document.getElementById("b"); //algo else var sortie = document.body; //autre : HTML,ProgLab,jsFiddle ... // //Zone de dessin var canvas = sortie.appendChild(document.createElement("canvas")); var context = canvas.getContext("2d"); canvas.width = 300; // Largeur en pixels canvas.height = 200; // hauteur en pixels context.lineWidth = 1; context.strokeStyle = "blue"; context.fillStyle = "red"; // //Affichage infos utilisateur // sortie.appendChild(document.createElement("p")); var label1 = sortie.appendChild(document.createElement("label")); label1.innerHTML = "Total des changements de direction."; // sortie.appendChild(document.createElement("br")); var label3 = sortie.appendChild(document.createElement("label")); label3.innerHTML = "Nombre changements à faire :"; // // saisie du nombre de changements à faire ... var input1 = sortie.appendChild(document.createElement("input")); input1.value = 1; // quand on appuie sur le bouton var btn = document.createElement("input"); btn.setAttribute("name", "bouton1"); btn.setAttribute("value", "Lancer"); btn.setAttribute("type", "button"); var btn1 = sortie.appendChild(btn); // //variables de position var x = 0; var y = 175; //précalcul pour sortie de zone var x1 = 0; var y1 = 0; //déplacement h et v : *100 (cf cos/sin et arrondis) var deltax = 100; var deltay = 0; //angle de rotation en ° : 90 puis aléatoire var angle = 90; //correction aléatoire de la rotation var corr_angle = 0; //coord. de la rotation var p; //drapeau pour arrêter la boucle des calculs/déplacements var stopflag = 0; //compteurs pour les boucles var maxcompteur = 1; var compteur1 = 0; //pour compter les trajest corrects var trajetok = false; //compteur de trajets corrects var compteur2 = 0; // // //dessin des limites de la zone context.beginPath(); context.moveTo(0, 0); context.lineTo(canvas.width / 2, 0); context.lineTo(canvas.width / 2, 50); context.lineTo(canvas.width / 4, 50); context.lineTo(canvas.width / 4, 100); context.lineTo(canvas.width, 100); context.lineTo(canvas.width, canvas.height); context.lineTo(0, canvas.height); context.closePath(); context.stroke(); //point de départ context.fillRect(x - 2, y - 2, 4, 4); // // test si est dans la zone function testPos(a, b) { //canvas est global //return a >= 0 && a <= canvas.width && b >= 0 && b <= canvas.height; return ( ( (a >= 0) && (b >= 0) && (a <= canvas.width / 2) && (b <= 50) ) || ( (a >= 0) && (b >= 50) && (a <= canvas.width /4) && (b <= 100) ) || ( (a >= 0) && (b >= 100) && (a <= canvas.width) && (b<=canvas.height) ) ) } // //rotation des coordonnées suivant l'angle (centre (0,0)) //( cercle trigo et angle en ° ) function rotation(pointX, pointY, angle) { angle = angle * Math.PI / 180; return { x: Math.cos(angle) * pointX - Math.sin(angle) * pointY, y: Math.sin(angle) * pointX + Math.cos(angle) * pointY }; } // //Algo de déplacement / changement de direction function relance() { //on boucle tant que maxcompteur n'est pas atteint/dépassé //après un calcul de trajectoire correct while (stopflag == 0) { //nouvelles coordonnées provisoires si pas d'obstacle x1 = x + deltax / 100; y1 = y + deltay / 100; //si on sort de la zone, if (testPos(x1, y1) == false) { //on recalcule l'angle et la trajectoire // //on recule de 2 positions (2 :choix arbitraire) x1 = x - deltax / 100; y1 = y - 2 * deltay / 100; //angle aléatoire en mutliple de 30° //entre 30° et 330° (0° et 360° exclus) angle = Math.floor((Math.random() * 11 + 1) * 30); //correction aléatoire de l'angle (+-9°) corr_angle = Math.floor(Math.random(19)) - 9; angle = angle + corr_angle; //calcul nouvelle trajectoire p = rotation(deltax, deltay, angle); deltax = p.x; deltay = p.y; //compteur changements de direction compteur1++; //le chemin ne sera peut-être pas bon à la suite trajetok=false } else { //coordonnées provisoires correctes : on roule // //on compte le trajet if(trajetok==false) { trajetok=true; compteur2++; } //on les garde les coordonnées x = x1; y = y1; //nouvelle position dessinées context.fillRect(x, y, 1, 1); //Borne pour donner la possibilité d'arrêt à l'utilisateur //sinon boucle infinie (et/ou JS détecte une boucle "trop" longue) if (compteur1 >= maxcompteur) { //info utilisateur label1.innerHTML = "Il y a eu " + compteur1 + " changements de direction et "+ + compteur2 + " trajets."; //on arrête la boucle stopflag = 1; } } } } // // function bouton_go() { //nouvelle borne à dépasser maxcompteur = Math.max(maxcompteur, compteur1) + parseFloat(input1.value); //on autorise la boucle des calculs stopflag = 0; //c'est parti relance(); } // //L'appui sur le bouton lance ou relance les calculs btn1.onclick = bouton_go; //