/*
* 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 NatObj from '../types/NatObj'
import NatCal from '../types/NatCal'
import { getStr } from '../kernel/kernel'
import CCalcul from '../objets/CCalcul'
import CImplementationProto from '../objets/CImplementationProto'
import CMesureX from '../objets/CMesureX'
import CourbeAvecTanDlg from '../dialogs/CourbeAvecTanDlg'
import CourbeAvecTanCoefDlg from '../dialogs/CourbeAvecTanCoefDlg'
import CMesureY from 'src/objets/CMesureY'
import CValeur from 'src/objets/CValeur'
import CResultatValeur from 'src/objets/CResultatValeur'
import CMatrice from 'src/objets/CMatrice'
export default OutilCourbeAvecTan
/**
*
* @param {MtgApp} app
* @constructor
* @extends Outil
*/
function OutilCourbeAvecTan (app) {
Outil.call(this, app, 'CourbeAvecTan', 32986, true)
}
OutilCourbeAvecTan.prototype = new Outil()
OutilCourbeAvecTan.prototype.select = function () {
Outil.prototype.select.call(this)
const self = this
new CourbeAvecTanDlg(this.app, function (nbPoints, rep, bpoly, nbPointsCourbe) {
self.suite(nbPoints, rep, bpoly, nbPointsCourbe)
}, function () { self.app.activeOutilCapt() })
}
/**
* Une fois que la boîte de dialogue demandant le repère et le nombre de points a été validé, cette fonction
* est appelée avec le nombre de points demandés nbPoints et le repère rep en paramètres
* @param {number} nbPoints le nombre de points (de 2 à 10)
* @param {CRepere} rep le repère choisi
* @param {boolean} bpoly true si on doit utiliser une fonction polynôme unique. Dans ce cas
* @param {number} nbPointsCourbe le nombre de points de la courbe finale
* on utilise un calcul polynomial au lieu de raccorder des sgements de fonctions polynômes du
* troisème degré
*/
OutilCourbeAvecTan.prototype.suite = function (nbPoints, rep, bpoly, nbPointsCourbe) {
this.nbPoints = nbPoints
this.rep = rep
this.bpoly = bpoly
this.nbPointsCourbe = nbPointsCourbe
const app = this.app
const list = app.listePr
// On crée maintenant nbPoints calculs qui contiendront les coefficients directeurs souhaités pour les tangentes
this.coef = []
// On crée un tableau qui contiendra des pointeurs sur les points cliqués qui n'étaient pas nommés
this.ptsSansNom = []
for (let i = 0; i < nbPoints; i++) {
this.coef[i] = new CCalcul(list, null, false, list.genereNomPourCalcul('mt', true), '0')
app.ajouteElement(this.coef[i])
}
// Maintenant on va attendre que l'utilisateur ait cliqué sur nnPoints
this.nbPtsCliques = 0 // Ce nombre augmentera à chaque fois qu'on clique sur un point
this.points = [] // Ce tableau contiendra des pointeurs sur les points cliqués
app.outilPointageActif = app.outilPointageCre
app.outilPointageActif.aDesigner = NatObj.NTtPoint
app.outilPointageActif.reset()
app.indication(getStr('indCourTan1') + '1' + getStr('indCourTan2'), '', true)
}
OutilCourbeAvecTan.prototype.traiteObjetDesigne = function (elg) {
const self = this
const app = this.app
const list = app.listePr
const nbPoints = this.nbPoints
let j; let k; let w
this.nbPtsCliques++
this.points.push(elg)
this.ajouteClignotementDe(elg)
this.excluDeDesignation(elg)
if (this.nbPtsCliques === 1) this.resetClignotement()
// Si tous les points cont été désignés, on implémente la construction correspondant au nombre de points
// puis on ouvre une boîte de dialogue permetteant de modifier les coefficients
if (this.nbPtsCliques >= nbPoints) {
const indImplementation = list.longueur()
// On réordonne les points par ordre d'abscisse croissante
// On affecte des noms aux points qui n'étaient pas nommés en les mémorisant de façon à supprimer le nom
// si on abandonne l'outil lors de la boîte de dialogue de choix des coefficients
const abs = []
for (j = 0; j < nbPoints; j++) {
abs[j] = new CMesureX(list, null, false, '', this.rep, this.points[j])
abs[j].positionne()
}
for (j = 0; j < nbPoints - 1; j++) {
for (k = j + 1; k < nbPoints; k++) {
if (abs[k].abscisse < abs[j].abscisse) {
w = abs[k]
abs[k] = abs[j]
abs[j] = w
w = this.points[k]
this.points[k] = this.points[j]
this.points[j] = w
}
}
}
// Dans le cas où l'utilisateur annulerait on prépare un array this.ptsSansNom
for (j = 0; j < nbPoints; j++) {
if (this.points[j].nom === '') {
this.ptsSansNom.push(this.points[j])
this.points[j].nom = list.genereNomPourPoint()
this.points[j].updateName(app.svg, true)
}
}
// Suivant le choix d'utiliser une seule fonction polynomiale ou non on utilise
// une macro construction différente
let impProto
if (this.bpoly) {
const proto = app.docConsAv.getPrototype('PolyParPtTan')
// On crée des mesures d'abscisses de tous les points cliqués
// On crée des mesures d'abscisses et d'ordonnées pour chacun des points créés
const tabmesabs = []
const tabmesord = []
for (let i = 0; i < nbPoints; i++) {
const pt = this.points[i]
if (pt.nom === '') {
pt.donneNom(list.genereNomPourPointOuDroite('M', true))
pt.nomMasque = true
}
const mesabs = new CMesureX(list, null, false,
list.genereNomPourCalcul('mesx', true), this.rep, this.points[i])
tabmesabs.push(mesabs)
const mesord = new CMesureY(list, null, false,
list.genereNomPourCalcul('mesy', true), this.rep, this.points[i])
tabmesord.push(mesord)
app.ajouteElement(mesabs)
app.ajouteElement(mesord)
}
// On crée une matrice de deux colonnes formées des coordonnées mesurées
// On crée une matrice de deux colonnes formées des mesures d'abscisses en première colonne
// et d'ordonnées en deuxième
const tabVal = []
for (let i = 0; i < nbPoints; i++) {
const lig = []
for (let j = 0; j < 2; j++) {
lig.push(new CValeur(list, new CResultatValeur(list, tabmesabs[i])))
lig.push(new CValeur(list, new CResultatValeur(list, tabmesord[i])))
}
tabVal.push(lig)
}
const mat = new CMatrice(list, null, false, list.genereNomPourCalcul('matCoord', true),
nbPoints, 2, tabVal)
app.ajouteElement(mat)
// On crée une matrice colonne contenant des CResultatValeur des calculs créés pour contenir les coefficients
// directeurs des tangentes
const tabValCoeff = []
for (let i = 0; i < nbPoints; i++) {
const lig = []
tabValCoeff.push(lig)
lig.push(new CValeur(list, new CResultatValeur(list, this.coef[i])))
}
const matcoef = new CMatrice(list, null, false, list.genereNomPourCalcul('matCoef', true),
nbPoints, 1, tabValCoeff)
app.ajouteElement(matcoef)
proto.get(0).elementAssocie = mat
proto.get(1).elementAssocie = matcoef
impProto = new CImplementationProto(list, proto)
impProto.implemente(app.dimf, proto)
impProto.nomProto = getStr('CourbeAvecTan')
// La construction produit comme objets finaux une matrice colonne formée des coefficients
// du polynôme et une fonction
// Il faut en plus rajouter la courbe de cette fonction
// Dernier paramètre false car pas de gestion auto des discontinuités
app.ajouteCourbeSurR(this.rep, list.get(list.longueur() - 1),
list.genereNomPourPointOuDroite('x', true),
list.genereNomPourCalcul('x', true),
list.genereNomPourCalcul('y', true),
this.nbPointsCourbe, true, true, false)
} else {
const proto = app.docConsAv.getPrototype('CourbeAvecTgte' + nbPoints)
proto.get(0).elementAssocie = this.rep
for (j = 0; j < nbPoints; j++) proto.get(j + 1).elementAssocie = this.coef[j]
for (j = 0; j < nbPoints; j++) proto.get(j + nbPoints + 1).elementAssocie = this.points[j]
impProto = new CImplementationProto(list, proto)
impProto.implemente(app.dimf, proto)
impProto.nomProto = getStr('CourbeAvecTan')
const lieu = impProto.premierFinal(NatObj.NLieu)
lieu.infoLieu.nombreDePoints = this.nbPointsCourbe
lieu.donneCouleur(app.getCouleur())
lieu.donneStyle(app.getStyleTrait())
}
const indImpProto = list.indexOf(impProto)
list.positionne(false, app.dimf)
list.setReady4MathJax()
list.afficheTout(indImpProto, app.svgFigure, true, app.doc.couleurFond)
new CourbeAvecTanCoefDlg(this.app, this.coef, this.points, list.longueur() - 1,
function () {
self.annuleClignotement()
app.outilCourbeAvecTan.saveFig()
// Ligne suivnat à appeler dès qu'on crée des objets en implémentant une macro construction
if (app.estExercice) app.listePourConst = app.listePourConstruction()
app.activeOutilCapt()
}, function () {
self.annuleClignotement()
// Il faut enlever les noms des points qui avaient été nommés
for (j = 0; j < self.ptsSansNom.length; j++) {
self.ptsSansNom[j].nom = ''
self.ptsSansNom[j].updateName(app.svgFigure, true)
}
// Il faut détruire tout ce qui avait été rajouté
list.removegElements(app.svgFigure, this.interm, indImpProto)
app.detruitDerniersElements(list.longueur() - indImplementation + self.nbPoints)
app.activeOutilCapt()
})
} else app.indication(getStr('indCourTan1') + String(this.nbPtsCliques + 1) + getStr('indCourTan2'), '', true)
}
OutilCourbeAvecTan.prototype.activationValide = function () {
const list = this.app.listePr
return (list.nombreObjetsCalcul(NatCal.NRepere) > 0) && (list.nombreObjetsParNatureVisibles(NatObj.NTtPoint) > 2)
}