objets/CSegment.js

/*
 * 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 NatObj from '../types/NatObj'
import Vect from '../types/Vect'
import { colineairesMemeSens } from '../kernel/kernel'
import CDroite from './CDroite'
import Color from '../types/Color'
import { appartientSegment } from 'src/kernel/kernelVect'

export default CSegment
/**
 * Classe représentant un segment défini par ses deux points extrémités.
 * @constructor
 * @extends CDroite
 * @param {CListeObjets} listeProprietaire  La liste propriétaire de l'objet.
 * @param {CImplementationProto} impProto  null ou la construction propriétaire de l'objet.
 * @param {boolean} estElementFinal  true si l'objet est un objet final de construction
 * @param {Color} couleur  La couleur de l'objet.
 * @param {boolean} masque  true si le nom de l'objet est masqué
 * @param {StyleTrait} style  Le style du tracé.
 * @param {CPt} point1  La première extrémité.
 * @param {CPt} point2  La deuxième extrémité.
 */
function CSegment (listeProprietaire, impProto, estElementFinal, couleur, masque,
  style, point1, point2) {
  if (arguments.length === 0) return // Ajout version 4.9.9.4
  if (arguments.length === 1) CDroite.call(this, listeProprietaire)
  else {
    if (arguments.length === 3) { // Pour objets internes
      CDroite.call(this, arguments[0], null, true, Color.black,
        false, 0, 0, false, '', 16, 0, 0)
      this.point1 = arguments[1]
      this.point2 = arguments[2]
    } else {
      CDroite.call(this, listeProprietaire, impProto, estElementFinal, couleur,
        false, 0, 0, masque, '', 16, style, 0.9)
      this.point1 = point1
      this.point2 = point2
    }
  }
}
CSegment.prototype = new CDroite()
CSegment.prototype.constructor = CSegment
CSegment.prototype.superClass = 'CDroite'
CSegment.prototype.className = 'CSegment'

// A revoir JavaScript
//  public void donneExtremites(CPt pt1, CPt pt2) {
//    point1 = pt1;
//    point2 = pt2;
//  }

CSegment.prototype.getClone = function (listeSource, listeCible) {
  const ind1 = listeSource.indexOf(this.point1)
  const ind2 = listeSource.indexOf(this.point2)
  const ind3 = listeSource.indexOf(this.impProto)
  return new CSegment(listeCible, listeCible.get(ind3, 'CImplementationProto'),
    this.estElementFinal, this.couleur, this.masque, this.style.getClone(),
    listeCible.get(ind1, 'CPt'), listeCible.get(ind2, 'CPt'))
}
CSegment.prototype.setClone = function (ptel) {
  CDroite.prototype.setClone.call(this, ptel)
  this.x1 = ptel.x1
  this.y1 = ptel.y1
  this.x2 = ptel.x2
  this.y2 = ptel.y2
}
CSegment.prototype.ajouteAntecedents = function (liste) {
  liste.add(this.point1)
  liste.add(this.point2)
}
CSegment.prototype.depDe = function (p) {
  if (this.elementTestePourDependDe === p) return this.dependDeElementTeste
  return this.memDep(CDroite.prototype.depDe.call(this, p) ||
    this.point1.depDe(p) || this.point2.depDe(p))
}
CSegment.prototype.dependDePourBoucle = function (p) {
  return (p === this) || this.point1.dependDePourBoucle(p) || this.point2.dependDePourBoucle(p)
}
CSegment.prototype.positionne = function (infoRandom, dimfen) {
  let u1, u2
  this.existe = (this.point1.existe) && (this.point2.existe)
  if (!this.existe) return
  if (arguments.length === 0) { // Spécial segments internes aux objets
    this.point_x = this.point1.x
    this.point_y = this.point1.y
    this.vect.setVecteur(this.point1, this.point2)
    this.xext1 = this.point1.x
    this.yext1 = this.point1.y
    this.xext2 = this.point2.x
    this.yext2 = this.point2.y
    this.x1 = this.xext1
    this.y1 = this.yext1
    this.x2 = this.xext2
    this.y2 = this.yext2
  } else {
    // Ajout version 3.2.0. Utilisé dans appartientA
    this.x1 = this.point1.x
    this.y1 = this.point1.y
    this.x2 = this.point2.x
    this.y2 = this.point2.y

    this.point_x = this.x1
    this.point_y = this.y1
    this.vect.setVecteur(this.point1, this.point2)
    if (this.vect.nul()) {
      this.existe = true
      this.horsFenetre = true
      return
    }
    if (this.point1.dansFenetre && this.point2.dansFenetre) {
      this.xext1 = this.x1
      this.yext1 = this.y1
      this.xext2 = this.x2
      this.yext2 = this.y2
      this.horsFenetre = false
    } else {
      // Au moins un des deux points est hors-fenêtre
      CDroite.prototype.positionne.call(this, infoRandom, dimfen)
      // Si la droite est hors fenetre le segment l'est aussi
      if (this.horsFenetre) return
      if (this.point1.dansFenetre) {
        // point2 n'est pas dans la fenêtre
        u1 = new Vect(this.point1, this.point2)
        u2 = new Vect(this.x1, this.y1, this.xext1, this.yext1)
        if (u2.presqueNul()) {
          this.horsFenetre = true
          return
        }
        if (colineairesMemeSens(u1, u2)) {
          this.xext2 = this.x1
          this.yext2 = this.y1
        } else {
          this.xext1 = this.x1
          this.yext1 = this.y1
        }
      } else {
        if (this.point2.dansFenetre) {
          // point1 n'est pas dans la fenêtre
          u1 = new Vect(this.point2, this.point1)
          u2 = new Vect(this.x2, this.y2, this.xext1, this.yext1)
          if (u2.presqueNul()) {
            this.horsFenetre = true
            return
          }
          if (colineairesMemeSens(u1, u2)) {
            this.xext2 = this.x2
            this.yext2 = this.y2
          } else {
            this.xext1 = this.x2
            this.yext1 = this.y2
          }
        } else {
          // Si les deux points sont hors-fenêtre on regarde si un des points d'intersection
          // de la droite avec le cadre de la fenêtre appartient au segment
          // Il faut les deux tests car un des deux points peut être presque sur le bord
          if (!appartientSegment(this.xext1, this.yext1, this.x1, this.y1, this.x2, this.y2) ||
            !appartientSegment(this.xext2, this.yext2, this.x1, this.y1, this.x2, this.y2)) this.horsFenetre = true
        }
      }
    }
  }
}
CSegment.prototype.abscisseMinimale = function () {
  // Cas d'un segment ayant ses extrémités confondues
  if ((this.vect.x === 0) && (this.vect.y === 0)) return 0
  if (Math.abs(this.vect.x) >= Math.abs(this.vect.y)) { return (this.x1 - this.point_x) / this.vect.x } else { return (this.y1 - this.point_y) / this.vect.y }
}
CSegment.prototype.abscisseMaximale = function () {
  // Cas d'un segment ayant ses extrémités confondues
  if ((this.vect.x === 0) && (this.vect.y === 0)) return 0
  if (Math.abs(this.vect.x) >= Math.abs(this.vect.y)) { return (this.x2 - this.point_x) / this.vect.x } else { return (this.y2 - this.point_y) / this.vect.y }
}
// Ajout version 3.2.0
// Pour ne rien faire lorsque CDroite.positionne appelle positionneNom()
CSegment.prototype.positionneNom = function () {
}
CSegment.prototype.appartientA = function (x, y) {
  if (!this.existe) return false
  else return appartientSegment(x, y, this.x1, this.y1, this.x2, this.y2)
}
CSegment.prototype.confonduAvec = function (p) {
  if (p.className === this.className) {
    return ((this.point1 === p.point1) && (this.point2 === p.point2)) ||
      ((this.point1 === p.point2) && (this.point2 === p.point1))
  } else return false
}
CSegment.prototype.remplacePoint = function (ancienPoint, nouveauPoint) {
  if (this.point1 === ancienPoint) this.point1 = nouveauPoint
  if (this.point2 === ancienPoint) this.point2 = nouveauPoint
}
CSegment.prototype.getNature = function () {
  return NatObj.NSegment
}
CSegment.prototype.read = function (inps, list) {
  CDroite.prototype.read.call(this, inps, list)
  const ind1 = inps.readInt()
  const ind2 = inps.readInt()
  this.point1 = list.get(ind1, 'CPt')
  this.point2 = list.get(ind2, 'CPt')
}
CSegment.prototype.write = function (oups, list) {
  CDroite.prototype.write.call(this, oups, list)
  const ind1 = list.indexOf(this.point1)
  oups.writeInt(ind1)
  const ind2 = list.indexOf(this.point2)
  oups.writeInt(ind2)
}
CSegment.prototype.chaineDesignation = function () {
  return 'desSegment'
}