fonctions.js



// =====================================================================
/**
 * Met à jour la liste des classes d'équivalence dans le menu de sélection de la classe d'équivalence n°1 (dans le cas où l'utilisateur est invité à sélectionner 2 classes d'équivalance).
 * La liste est récupérée dans schema.classes. On ignore la classe qui est présente dans la liste n°2.
 */
update_liste_CE1=function()
{
	//On recupere l'ancienne sélection
	var old=parseInt($("#select_CE1").val());
	//On vide
	$("#select_CE1").empty();
	//On remet...
	for(var i=0; i<SCHEMA.classes.length; i++)
	{
		classe=SCHEMA.classes[i];
		if(!$("#select_CE2 option[value='"+classe.numero()+"']").is(':selected'))//...si c'est pas déjà dans l'autre
		{
			var ajout="<option value=\""+classe.numero()+"\"";
			if(classe.numero()==old)
				ajout+=" selected=\"selected\"";
			ajout+=">"+classe.nom()+"</option>";
			$("#select_CE1").append(ajout);
		}
	}
}


// =====================================================================
/**
 * Met à jour la liste des classes d'équivalence dans le menu de sélection de la classe d'équivalence n°2 (dans le cas où l'utilisateur est invité à sélectionner 2 classes d'équivalance).
 * La liste est récupérée dans schema.classes. On ignore la classe qui est présente dans la liste n°1.
 */
update_liste_CE2 = function()
{
	//On recupere l'ancienne sélection
	var old=parseInt($("#select_CE2").val());
	//On vide
	$("#select_CE2").empty();
	//On remet...
	for(var i=0 ; i< SCHEMA.classes.length; i++)
	{
		classe=SCHEMA.classes[i];
		if(!$("#select_CE1 option[value='"+classe.numero()+"']").is(':selected'))
		{
			var ajout="<option value=\""+classe.numero()+"\"";
			if(classe.numero()==old)
				ajout+=" selected=\"selected\"";
			ajout+=">"+classe.nom()+"</option>";
			$("#select_CE2").append(ajout);
		}
	}
}



// =====================================================================
/**
 * Met à jour la liste des classes d'équivalence dans le menu e sélection de la classe d'équivalence (dans le cas où l'utilisateur est invité à sélectionner 1 seule classe d'équivalance).
 * La liste est récupérée dans schema.classes.
 */
update_liste_CE = function()
{
	//On vide
	$("#select_CE").empty();
	for(var i=0 ; i< SCHEMA.classes.length; i++)
	{
		var classe=SCHEMA.classes[i];
		var ajout="<option value=\""+classe.numero()+"\">"+classe.nom()+"</option>";
		$("#select_CE").append(ajout);
	}
}





// =====================================================================
/**
 * Fonction qui renvoie une référence vers la classe d'équivalence n°i (stoquée dans schema.classe).
 * @param {int} i - Numéro de la classe d'équivalence
 * @return {Classe_Equivalence} Référence vers un objet <Classe_Equivalence>.
*/
getClasse = function(i)
{
	return SCHEMA.classes[Number(i)];
}
// Identique à getClasse, sauf qu'il renvoie direct la référence de la classe 1 dans le menu de sélection
getClasse1 = function()
{
	return getClasse($("#select_CE1").val());
}
// Identique à getClasse, sauf qu'il renvoie direct la référence de la classe 2 dans le menu de sélection
getClasse2 = function()
{
	return getClasse($("#select_CE2").val());
}

// Identique à getClasse, sauf qu'il renvoie direct la référence de la classe 2 dans le menu de sélection
getClasseSelectionnee = function()
{
	return getClasse($("#select_CE").val());
}


// ******************************************************************
/**
 * Fonction qui supprime ce qu'il y a dans l'objet "suiveur" (objet qui suit la souris).
 * À utiliser à chaque nouvelle option cliquer, ou en fin d'action
*/
videSuiveur = function()
{
	for(var i=suiveur.children.length-1; i>1; i--)
		suiveur.removeChildAt(i)
}

// ******************************************************************
/**
 * Fonction qui remet à zéro les actions, et qui vide le curseur suiveur
 * (utile à la fin d'une action, ou pour annuler une action courrante)
*/
resetActions = function()
{
	if(ACTION == "MANIP" && SOUS_ACTION == "TIRE")
	{
		SCHEMA.classes[CLASSE].accroche.autoSupprime();
	}
	
	videSuiveur();
	ACTION="";
	SOUS_ACTION="";
	CLASSE=-1;
	deselectionneToutLeMonde();
	
	$(".menu_tertiaire").css("display","none");//Efface les menus tertiaires
	$(".menu_secondaire .bouton_menu").css("background-color","white");//Vire le bouton en surbrillance
	
	$("#bouton_lancer_simulation img").attr('src','./sources/images/icone_simule.svg');//On remet l'icone "lecture" de la simulation
	$("#info_classe").hide(400); //Cache le menu de séleciton des CE
	
	
	
}


// **********************************************************************
/**
 * Fonction qui remonte les parents jusqu'à trouver la classe d'équivalence
*/
trouveClasse = function(cible)
{
	while(!cible.type || typeof cible.type() == "undefined" || cible.type() != "classe")
		cible = cible.parent;
		
	return cible;
}



// ************************************************
// Fonction qui remplie la zone d'info de la CL
update_info_CE=function(classe)
{
	$("#info_CE_nom").val(classe.nom());
	$("#info_CE_couleur").val(classe.couleur());
	$("#info_CE_bloque").prop("checked",classe.bloque());
	$("#info_CE_schema_visible").prop("checked",classe.schema.visible);
	$("#info_CE_images_visible").prop("checked",classe.images.visible);
	$("#info_CE_annotations_visible").prop("checked",classe.annotations.visible);
}



// ****************************************************
// Calcule l'angle entre deux vecteur V1 et V2 de la forme {x: , y: }
angleEntreVecteurs = function(V1,V2)
{
	return Math.acos((V1.x*V2.x+V1.y* V2.y)/norme(V1)/norme(V2))
}


// *******************************************
// Calcule la norme de V de la forme {x: ,  y: }
norme = function(V)
{
	return Math.sqrt(V.x*V.x+V.y*V.y)
}

// ******************************************************
/** Calcule la dérivée d'une parabole passant par 3 points, au niveau du 3eme point
   @param {Point} A - Point 1 {xA,yA}
   @param {Point} B - Point 2 {xB,yB}
   @param {Point} C - Point 3 {xC,yC}
   @return {je_sais_pas} Je crois que j'ai pas fini la fonction quand je l'ai commandé
 */
deriveGauche3pts = function(A,B,C)
{
	var a = (C.y-A.y)/(C.x-A.x)/(C.x-B.x)-(B.y-A.y)/(B.x-A.x)/(C.x-B.x)
	var b = (B.y-A.y)/(B.x-A.x)-a*(B.x+A.x)
	return 2*a*C.x+b
}

// ******************************************************
/** Affiche_toutes_images en arrière plan
 */
affiche_toutes_images = function()
{
	SCHEMA.classes.forEach(function(classe)
		{
			classe.images.visible = true;
		})
}

// ************************************************************
/** Cache_toutes_images en arrière plan
 */
cache_toutes_images = function()
{
	SCHEMA.classes.forEach(function(classe)
		{
			classe.images.visible = false;
		})
}

// ************************************************************
/** Affiche_tous_schema et symboles cinématiques
 */
affiche_tous_schemas = function()
{
	SCHEMA.classes.forEach(function(classe)
		{
			classe.schema.visible = true;
		})
}

// ************************************************************
/** Cache tous schema et symboles cinématiques.
 */
cache_tous_schemas = function()
{
	SCHEMA.classes.forEach(function(classe)
		{
			classe.schema.visible = false;
		})
}


// *******************************************************
/** Fonction qui update la coloration syntaxique de la console
 */
updateConsoleMiseEnForme = function()
{
	texte = $("#dialog_console .console").text(); // Texte au format brut
	texte = console2HTML(texte);	//Coloration
	$("#dialog_console .console").html(texte);
}

// ************************************************************
/** Fonction qui encode (=met de la coloration syntaxique) le HTML le texte (brut) situé dans la console
 * @param {String} texte - Texte à encoder.
   @return {String} Texte encodé.
 */
console2HTML = function(texte)
{
	// Retour à la ligne
	texte = (texte + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + "<br />" + '$2');
	
	//Commentaires
	texte = texte.replace(/\/\/(.*)/g,'<span class=\"code_commentaire\">//$1</span>');
	
	//commande blanches
	texte = texte.replace(/(new )/g,'<span class=\"code_blanc\">$1</span>');
	
	//commande fonctions de cillon
	texte = texte.replace(/(Classe_Equivalence|ajouteLiaison|ajouteImage)\((.*)\)/g,'<span class="code_fonction_cillon"\>$1(</span>$2<span class="code_fonction_cillon">)</span>');
	
	//commande méthodes de cillon
	texte = texte.replace(/\.(bloque|couleur|dessineLigne|ajouteClasse|pilotee|consignesCinematiques)\((.*)\)/g,'.<span class="code_methode_cillon"\>$1(</span>$2<span class="code_methode_cillon">)</span>');
		
	//commande méthodes str
	//texte = texte.replace(/\"(.*)\"/,'.<span class="code_str"\>\"$1\"</span>');
	//texte = texte.replace(/\'(.*)\'/g,'.<span class="code_str"\>\'$1\'</span>');
		
		
	return texte;
}





/** Fonction qui interprète et exécute la console. Si _reset est à true, le schéma précédent est effacé.
 * @param {Boolean} [_reset=false] - Dit s'il faut effacer le schéma précédent.
 */
execute_console = function(_reset)
{
	if(_reset)
		SCHEMA.reset();
	eval($("#dialog_console .console").text());//Exécution du code source
}




/** Fonction qui calcule le score, c'est à dire si les écarts des liaisons.
Dans le cas idéal, ce score est nul.
* @return {Number} Le score
*/	
getScore = function()
{
	var S=0;
	LISTE_LIAISONS.forEach(function(liaison){
		//S += liaison.L1.getScore();
		S=Math.max(S,liaison.L1.getScore());
	});
	return S;///LISTE_LIAISONS.length;
}


// ************************************************************
/** Fonction qui écrase les paramètres par défaut d'une fonction
 * par les options passées en argument. Les paramètres par défaut (argument 'defaut') est modifié en place.
 * @param {Object} defaut - objet contenant les paramètres par défaut (exemple : {x:0,y:0,....})
 * @param {Object} param - (FACULTATIF) objet contenant les (quelques) paramètres à écraser dans 'defaut' {exemple : {y:12} }
 */
ecraseOptions = function(defaut,param)
{
	if(typeof(param)!="undefined")
	{
		Object.keys(param).forEach(function(key){
			defaut[key] = param[key];
		})
	}
}


// ***************************************************
/** Fonction qui renvoie l'orientation d'un objet createjs par rapport au stage.
 * Utile notament quand un objet est pris dans des containers eux-même tournés.
 * @param {createjs.DisplayObject} _obj - Objet dont on veut connaître la rotation par rapport au stage
 * @return {number} Angle de rotation (en degré, dans le sens horaire)
 */
getGlobalRotation = function(_obj)
{
	var rotation = _obj.rotation ;
	var pointer = _obj
	while(pointer.parent)
	{
		pointer = pointer.parent
		rotation += pointer.rotation
	}
	return rotation;
}

// ***************************************************
/** Fonction qui renvoie l'orientation d'un objet createjs par rapport à un autre objet createjs.
 * Utile notament quand un objet est pris dans des containers eux-même tournés.
 * @param {createjs.DisplayObject} Objet dont on veut connaître la rotation par rapport au stage
 * @return {number} Angle de rotation (en degré, dans le sens horaire)
 */
getLocalToLocalRotation = function(_objSource, _objContexte)
{
	return getGlobalRotation(_objSource)-getGlobalRotation(_objContexte)
}

// ************************************************************
	/** Fonction qui convertit une position (qui peut être locale à une classe d'équivalence, ou n'importe quel objet createjs ou non, qui peut être en, pixel ou en coordonnées locales)
	 * @param {Position} _pos - Object "position".
	 * @param {createjs.DisplayObject} [_contexte_final=SCHEMA] - Objet createjs dans lequel on souhaite calculer les coordonnées.
	 * @param {Boolean} [_uniteSI=true] - false si on souhaite que les coordonnées finale soient exprimées en coordonnées "classique" (en px, y vers le bas, rotation en degré dans le sens horaire). Si true, ce sera en unités dites "SI" (x et y avec l'unité de SCHEMA.unite(), rotation en radian dans le sens trigo).
	 * @return {Position} Object position, par rapport à "schema"
	*/
convertPosition = function(_pos_init, _contexte_final=SCHEMA, _uniteSI=true)
{
	var pos_init = {x:0,y:0,theta:0,contexte:SCHEMA,uniteSI:true}
	// Valeur par defaut
	if(typeof(_pos_init.x) != 'undefined')
		pos_init.x = _pos_init.x;
	if(typeof(_pos_init.y) != 'undefined')
		pos_init.y = _pos_init.y ;
	if(typeof(_pos_init.theta) != 'undefined')
		pos_init.theta = _pos_init.theta ;
	if(typeof(_pos_init.contexte) != 'undefined')
		pos_init.contexte = _pos_init.contexte ;
	if(typeof(_pos_init.uniteSI) != 'undefined')
		pos_init.uniteSI = _pos_init.uniteSI ;
		
		
	// On remet l'angle à l'endroit
	var angle_init = pos_init.theta * (1-1*pos_init.uniteSI-pos_init.uniteSI*1/(Math.PI)*180)
		
	var unite_source = 1 + pos_init.uniteSI*(-1) + pos_init.uniteSI * SCHEMA.unite() ;
	var unite_destination = 1 + _uniteSI*(-1) + _uniteSI * SCHEMA.unite() ;
	var sens_y_source = 1-2*pos_init.uniteSI
	var sens_y_destination = 1-2*_uniteSI

	
	var new_coord = pos_init.contexte.localToLocal(pos_init.x*unite_source ,pos_init.y*unite_source*sens_y_source ,_contexte_final) ; // Conversion en coordonnées px
	
	var newRotation = (angle_init+getLocalToLocalRotation(pos_init.contexte,_contexte_final))*(1-1*_uniteSI-_uniteSI*Math.PI/180) ;
	
	return {x:new_coord.x/unite_destination, y:new_coord.y/unite_destination*sens_y_destination, theta:newRotation, contexte:_contexte_final, uniteSI: _uniteSI} ;
}



// ***************************************************
/** Fonction créneau (utile notamment pour définir des consignes dans des fenetres de temps). renvoie 1 si t appartient à [_deb,_fin[, 0 sinon
 * @param {Numer} t - Temps (en seconde)
   @param {Numer} [_deb=0] Début du créneau
   @param {Number} [_fin=infini] Fin du créneau
 * @return {number} 1 ou 0 si dans le créneau ou non
 */
 creneau = function(t, _deb=0, _fin=Infinity)
 {
 	return Number(t>=_deb && t<_fin);
 }