modules/aleaFigure/outilsThales.js

import { GVVector } from './elements.js'
import { GVGraphicView } from './GraphicView.js'
import { aleaName } from '../outilsMathjs.js'
import { cross } from 'mathjs'
export class GVAleaThalesConfig extends GVGraphicView {
  classicConfig/** boolean */ = undefined
  k/** number */
  AOB/** boolean */ = false
  OAB/** boolean */ = false
  points/** GVPoint[] */
  constructor (k/** boolean */ = undefined) {
    super(-5, -5, 5, 5)
    this.create(k)
  }

  create (k/** boolean */ = undefined) {
    // Boucle à remplacer par quelque chose de plus efficace
    // Il faut tout simplement créer un objet configuration de Thalès en indiquant le k
    if (k !== undefined) {
      do {
        this.new()
      } while (this.classicConfig !== k)
    } else {
      this.new()
    }
  }

  new () {
    this.geometric = []
    let O/** GVPoint */, A/** GVPoint */, B/** GVPoint */
    if (this.AOB) {
      [O, A, B] = this.addRectPoint() // Trois points non alignés et formant un triangle OAB rectangle en O
    } else if (this.OAB) {
      [A, O, B] = this.addRectPoint() // Trois points non alignés et formant un triangle OAB rectangle en A
    } else {
      [O, A, B] = this.addNotAlignedPoint() // Trois points non alignés
    }
    // M est un point de (OA)
    const M = this.addPointAligned(O, A)[2] // C'est le troisième point de la sortie addPointAligned
    // On ajoute les droites (OB) et (AB) pour ne pas gêner le point M
    const dOB = this.addLine(O, B)
    const dAB = this.addLine(A, B)
    // Exemple d'un vecteur créé à partir de deux points
    const vO = new GVVector(O.x, O.y)
    const vA = new GVVector(A.x, A.y)
    const vB = new GVVector(B.x, B.y)
    const vM = new GVVector(M.x, M.y)
    const vOA = vA.sub(vO)
    const vOB = vB.sub(vO)
    const vOM = vM.sub(vO)
    // On détermine l'orientation de AOB pour la position des labels
    const direct = cross([vOA.x, vOA.y, 0], [vOB.x, vOB.y, 0])[2] > 0
    // On remplace le point M par son symétrique par rapport à O si besoin
    // Mauvaise idée !!
    // Rechercher un point qui corresponde soit par l'aléatoire soir par le barycentre bien choisi
    if (this.classicConfig !== undefined && ((this.classicConfig && vOA.dot(vOM) < 0) || (!this.classicConfig && vOA.dot(vOM) > 0))) {
      // Object.assign(M, this.addHomothetic(O, -1, M)[0])
      this.classicConfig = vOA.dot(vOM) > 0
    } else if (this.classicConfig === undefined) {
      this.classicConfig = vOA.dot(vOM) > 0
    }
    this.k = (vOA.dot(vOM) < 0 ? -1 : 1) * this.distance(O, M) / this.distance(O, A)
    // On crée une parallèle à (AB)
    const dMN = this.addParallelLine(M, dAB)[1] // C'est la seconde parallèle de addParalleleLine
    // On ajoute le point d'intersection de (OA) et (MN)
    const [N] = this.addIntersectLine(dMN, dOB) // C'est un tableau pour prévoir l'intersection de cercles par exemple
    // On commence par nommer les points et les droites
    const aleaNames = aleaName(5) // Nommage aléatoire des points
    // const aleaNames = ['O', 'A', 'B', 'M', 'N'] // Pour le debuggage
    const points = [O, A, B, M, N]
    points.forEach((x, i) => { x.name = aleaNames[i] })
    // On nomme les droites à partir des noms des points
    dAB.name = A.name + B.name // L'ordre des lettres est conservé
    dMN.aleaName(M, N) // L'ordre des lettres est aléatoirisé
    // On positionne les labels des points du mieux possible
    if (this.k < 0) { // À l'extrémités des triangles
      A.labelPoints = [O, A, B]
      B.labelPoints = [O, B, A]
      M.labelPoints = [O, M, N]
      N.labelPoints = [O, N, M]
    } else if (this.k < 1) {
      // ? : http://localhost:8080/mathalea.html?ex=betaThales,s=31,s2=3,s3=1,n=1,cd=1&serie=lvxb&v=ex&z=1
      A.labelPoints = [O, A, B]
      B.labelPoints = [O, B, A]
      M.labelPoints = direct ? [O, M, A] : [A, M, O]
      N.labelPoints = direct ? [B, N, O] : [O, N, B]
    } else {
      A.labelPoints = direct ? [O, A, M] : [M, A, O]
      B.labelPoints = direct ? [N, B, O] : [O, B, N]
      M.labelPoints = [O, M, N]
      N.labelPoints = [O, N, M]
    }
    O.labelPoints = [B, O, M]
    this.geometric = [O, A, B, M, N].map(x => { x.label = true; return x })
    this.points = [O, A, B, M, N].map(x => { x.label = true; return x })
  }

  /**
    * Set dimensions
    * @example
    * this.setDimensions(0.5) - > rectangle half height from the setting xmin, ymin and xmax
    * this.setDimensions(7,5) - > rectangle width=7 and height=5
    * this.setdimensions(0,0,7,6) - > xmin, ymin, xmax, ymax
    * @param args
    */
  setDimensions (...args/** number[] */) {
    switch (args.length) {
      case 1: {
        this.ratio = args[0]
        this.ymax = this.xmax * this.ratio
        this.width = this.xmax - this.xmin
        this.height = this.ymax - this.ymin
        break
      }
      case 2:
      case 3: {
        this.width = args[0]
        this.height = args[1]
        this.xmin = 0
        this.ymin = 0
        this.xmax = this.width
        this.ymax = this.height
        this.ratio = this.height / this.width
        break
      }
      case 4: {
        this.xmin = args[0]
        this.ymin = args[1]
        this.xmax = args[2]
        this.ymax = args[3]
        this.width = this.xmax - this.xmin
        this.height = this.ymax - this.ymin
        this.ratio = this.height / this.width
        break
      }
    }
  }
}