/*
* MathGraph32 Javascript : Software for animating online dynamic mathematics figures
* https://www.mathgraph32.org/
* @Author Yves Biton (yves.biton@sesamath.net)
* @License: GNU AGPLv3 https://www.gnu.org/licenses/agpl-3.0.html
*/
import Outil from './Outil'
import CListeObjets from '../objets/CListeObjets'
import CPrototype from '../objets/CPrototype'
import NatCal from '../types/NatCal'
import NatObj from '../types/NatObjAdd'
import AvertDlg from '../dialogs/AvertDlg'
import ModifConstDlg from '../dialogs/ModifConstDlg'
export default OutilFinirConst
/**
*
* @param {MtgApp} app
* @constructor
* @extends Outil
*/
function OutilFinirConst (app) {
// Attention : Pour cet outil le troisième pramètre est "CreationConst" pour que l'icône de app.outilGestionConst soit
// désactivée quand on désactive l'outil (cet outil n'a pas d'icône)
// Dernier paramètre à false car pas d'icône associée
Outil.call(this, app, 'CreationConst', -1, false, false, false, false)
}
OutilFinirConst.prototype = new Outil()
OutilFinirConst.prototype.select = function () {
let i; let elb; let natureSources; const self = this
const app = this.app
const listePr = app.listePr
const liste1 = new CListeObjets()
const liste2 = new CListeObjets()
// liste1 sera formée de tous les objets sources, objets non graphiques en premier
liste1.ajouteElementsDe(app.listeSrcNG)
liste1.ajouteElementsDe(app.listeSrcG)
// liste2 sera formé de tous les objets finaux
liste2.ajouteElementsDe(app.listeFinNG)
liste2.ajouteElementsDe(app.listeFinG)
// On réordonne la liste de tous les objets finaux
liste2.reordonne(listePr)
if (!this.verifieObjSrcTousUtilises(liste1, liste2)) {
new AvertDlg(app, 'ErrConst', function () {
self.app.activeOutilCapt()
})
return
}
const listeInterm = this.listeIntermediaires(liste1, liste2)
// Comme on permet de désigner comme objet final un point libre qui figurait dans les objets sources,
// Il faut les retirer de la liste des objets sources
for (i = 0; i < liste1.longueur(); i++) {
elb = liste1.get(i)
if (elb.estDeNature(NatObj.NPointBase) && liste2.contains(elb)) {
liste1.removeObj(elb)
i-- // Car l'élément a été retiré de la liste
app.listeSrcG.removeObj(elb)
}
}
// Modification version 3.1.5 : Comme on peut maintenant choisir comme objet final une variable
// à condition qu'elle ait d'abord été choisie dans les objets sources, il faut les retirer
// de la liste des objets sources
let aumoinsUneVariableRetiree = false
for (i = 0; i < liste1.longueur(); i++) {
elb = liste1.get(i)
if (elb.estDeNatureCalcul(NatCal.NVariable) && liste2.contains(elb)) {
liste1.removeObj(elb)
i-- // Car l'élément a été retiré de la liste
app.listeSrcNG.removeObj(elb)
aumoinsUneVariableRetiree = true
}
}
if (app.listeSrcNG.longueur() === 0) natureSources = CPrototype.graph
else {
if (app.listeSrcG.longueur() === 0) natureSources = CPrototype.calc
else natureSources = CPrototype.mixtes
}
if (aumoinsUneVariableRetiree) {
new AvertDlg(app, 'AvConst1', function () {
self.finit(liste1, liste2, listeInterm, natureSources)
})
} else this.finit(liste1, liste2, listeInterm, natureSources)
}
OutilFinirConst.prototype.finit = function (liste1, liste2, listeInterm, natureSources) {
let i; let elb
const liste = new CListeObjets()
const app = this.app
const listePr = app.listePr
// Attention : il ne faut pas réordonner les éléments sources car ceux
// de type calcul doivent être désignés en premier
liste.ajouteElementsDe(listeInterm)
liste.ajouteElementsDe(liste2)
liste.reordonne(listePr) // Important
// On ajoute en tête de liste les éléments de liste1 (sources)
for (i = liste1.longueur() - 1; i >= 0; i--) {
elb = liste1.get(i)
liste.insereElement(elb, 0)
}
const proto = new CPrototype(listePr, natureSources, liste1.longueur(), liste, liste2)
new ModifConstDlg(app, proto, function () {
app.doc.tablePrototypes.push(proto)
app.reInitConst() // Pour réinitialiser la construction en cours
app.activeOutilCapt()
}, function () {
app.activeOutilCapt()
app.reInitConst() // Pour réinitialiser la construction en cours
})
}
/**
* fonction de classe renvoyant true si tous les éléments de la liste listeFinaux dépendent
* bien de au moins un élément de la liste listeSources et false sinon
* @param listeSources
* @param listeFinaux
* @returns {boolean}
*/
OutilFinirConst.prototype.verifieObjSrcTousUtilises = function (listeSources, listeFinaux) {
for (let i = 0; i < listeSources.longueur(); i++) { if (!listeFinaux.depDe(listeSources.get(i))) return false }
return true
}
OutilFinirConst.prototype.listeIntermediaires = function (listeSources, listeFinaux) {
let i; let ind; let elb; let j; let el2
const listePr = this.app.listePr
const listeOb = new CListeObjets()
listeOb.ajouteElementsDe(listeSources)
const liste = new CListeObjets()
const listeVariablesEtCalcConstInterm = new CListeObjets()
// On rajoute à ListeOb les variables qui sont pas des objets sources
// telles qu'il existe des objets dépendant à la fois des objets sources
// et de la variable et chacune des ces variables est rajoutée
// à la liste des objets listo ainsi qu'à la liste des objets intermédiaires
// Même chose avec les calculs intermédiaires contants dont dépend au moins un des objets finaux
for (ind = 0; ind < listePr.longueur(); ind++) {
elb = listePr.get(ind)
if (elb.estDeNatureCalcul(NatCal.NVariable)) {
if (!listeOb.contains(elb)) {
for (j = 0; j < listeFinaux.longueur(); j++) {
el2 = listeFinaux.get(j)
if (el2.depDe(elb) && el2.dependDeAuMoinsUn(listeOb)) {
if (!listeOb.contains(elb)) listeOb.add(elb)
if (!listeVariablesEtCalcConstInterm.contains(elb)) listeVariablesEtCalcConstInterm.add(elb)
}
}
}
} else {
if (elb.estDeNatureCalcul(NatCal.NTtCalcouFoncRouC)) {
if (!listeOb.contains(elb)) {
// CCalcul cal = (CCalcul) elb;
// if (elb.estConstant()) { // Modifié version 6.3.0 pour outil de création de construction
if (elb.estConstantPourConst()) {
for (j = 0; j < listeFinaux.longueur(); j++) {
el2 = listeFinaux.get(j)
if (el2.depDe(elb) && el2.dependDeAuMoinsUn(listeOb)) {
if (!listeOb.contains(elb)) listeOb.add(elb)
if (!listeVariablesEtCalcConstInterm.contains(elb)) listeVariablesEtCalcConstInterm.add(elb)
}
}
}
}
}
}
}
// Il faut vérifier si les variables et calculs constants qui ont été rajoutés à la liste listeVariablesEtCalcConstInterm
// sont bien indipensables.
// C'est nécéssaire car par exemple si un repère a été créé avec comme point J l'image
// d'un autre point par une rotation alors ce repère dépendra de la constante pi mais pourtant
// cette constante n'a pas forcément à faire partie des objets intermédiaires.
// Très important : il ne suffit pas d'aller jusqu'à l'élément qui précède le dernier
// objet final car d'autres objets peuvent suivre entre celui-ci et le dernier
// par exemple en cas de point lié à un bipoint
const der = listeFinaux.get(listeFinaux.longueur() - 1)
const indDernierFinal = listePr.indexOf(der)
for (i = 0; i < indDernierFinal; i++) {
elb = listePr.get(i)
if (
listeVariablesEtCalcConstInterm.contains(elb) ||
(
!listeOb.contains(elb) &&
!listeFinaux.contains(elb) &&
listeFinaux.depDe(elb) &&
// Ligne suivante rajouté version 3.5.1 pour éviter que quand on choisit
// comme objets sources des objets construits à partir d'autres
// certains objets inutiles soient pris dans la liste d'objets intermédiaires
(!(!listeSources.contains(elb) && listeSources.depDe(elb))) &&
elb.estDefiniParObjDs(listeOb)
)
) {
liste.add(elb)
}
}
liste.reordonne(listePr)
return liste
}
OutilFinirConst.prototype.activationValide = function () {
const app = this.app
return app.listeFinNG.longueur() > 0 || app.listeFinG.longueur() > 0
}