/*
* 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 NatArc from '../types/NatArc'
import Vect from '../types/Vect'
import { mesurePrincipale, zeroAngle } from '../kernel/kernel'
import CArcDeCercleAncetre from './CArcDeCercleAncetre'
import CValeurAngle from './CValeurAngle'
export default CArcDeCercle
/**
* Classe représentant un petit arc de cercle.
* Il peut être défini de deux façons :
* Par l'origine, un point donnant le début de l'ar et un point donnant la direction de la fin de l'arc.
* Ou par l'origine, un point donnant le début de l'arc et la valeur de l'angle au centre.
* @constructor
* @extends CArcDeCercleAncetre
* @param {CListeObjets} listeProprietaire La liste propriétaire.
* @param {CImplementationProto} impProto null ou la construction propriétaire.
* @param {boolean} estElementFinal true si élément final de construction.
* @param {Color} couleur
* @param {boolean} masque true si l'objet est masqué.
* @param {StyleTrait} style le style de tracé.
* @param {CPt} o Le centre de l'arc.
* @param {CPt} a Le point donnant le début de l'arc.
* @param {CPt} pointFinArc Le point donnant la fin de l'arc.
* Si null c'est que l'arc est défini par son angle au centre.
* @param {CValeurAngle} angleAuCentre L'angle au centre (si pointFinArc est null)
* @returns {CArcDeCercle}
*/
function CArcDeCercle (listeProprietaire, impProto, estElementFinal, couleur, masque,
style, o, a, pointFinArc, angleAuCentre) {
if (arguments.length === 0) return // Ajout version 4.9.9.4
if (arguments.length === 1) CArcDeCercleAncetre.call(this, listeProprietaire)
else {
CArcDeCercleAncetre.call(this, listeProprietaire, impProto, estElementFinal, couleur,
masque, style)
this.o = o
this.a = a
this.pointFinArc = pointFinArc
this.angleAuCentre = angleAuCentre
}
}
CArcDeCercle.prototype = new CArcDeCercleAncetre()
CArcDeCercle.prototype.constructor = CArcDeCercle
CArcDeCercle.prototype.superClass = 'CArcDeCercleAncetre'
CArcDeCercle.prototype.className = 'CArcDeCercle'
CArcDeCercle.prototype.setClone = function (ptel) {
CArcDeCercleAncetre.prototype.setClone.call(this, ptel)
this.ang1 = ptel.ang1
this.ang2 = ptel.ang2
this.valeurAngleAuCentre = ptel.valeurAngleAuCentre
}
CArcDeCercle.prototype.getClone = function (listeSource, listeCible) {
const ind1 = listeSource.indexOf(this.o)
const ind2 = listeSource.indexOf(this.a)
let ptFinArc = null
let angleAuCentreClone
if (this.pointFinArc === null) { angleAuCentreClone = this.angleAuCentre.getClone(listeSource, listeCible) } else {
const ind3 = listeSource.indexOf(this.pointFinArc)
ptFinArc = listeCible.get(ind3, 'CPt')
angleAuCentreClone = null
}
const ind4 = listeSource.indexOf(this.impProto)
return new CArcDeCercle(listeCible, listeCible.get(ind4, 'CImplementationProto'),
this.estElementFinal, this.couleur, this.masque, this.style.getClone(), listeCible.get(ind1, 'CPt'),
listeCible.get(ind2, 'CPt'), ptFinArc, angleAuCentreClone)
}
CArcDeCercle.prototype.positionne = function (infoRandom, dimfen) {
let u
if (this.pointFinArc === null) {
this.angleAuCentre.positionne(infoRandom, dimfen)
this.existe = this.o?.existe && this.a?.existe && this.angleAuCentre.existe
if (!this.existe) return
this.valeurAngleAuCentre = this.angleAuCentre.rendValeurRadian()
if (zeroAngle(this.valeurAngleAuCentre)) {
this.existe = false
return
}
u = new Vect(this.o, this.a)
this.rayon = u.norme()
this.centreX = this.o.x
this.centreY = this.o.y
this.origine_x = this.a.x
this.origine_y = this.a.y
this.ang1 = u.angleRad()
this.ang2 = this.ang1 + this.valeurAngleAuCentre
if (this.ang2 < 0) this.ang2 = this.ang2 + 2 * Math.PI
if (this.ang2 >= 2 * Math.PI) this.ang2 = this.ang2 - 2 * Math.PI
} else {
this.existe = this.o.existe && this.a.existe && this.pointFinArc.existe
if (!this.existe) return
u = new Vect(this.o, this.a)
this.rayon = u.norme()
this.centreX = this.o.x
this.centreY = this.o.y
this.origine_x = this.a.x
this.origine_y = this.a.y
this.ang1 = u.angleRad()
const v = new Vect(this.o, this.pointFinArc)
this.ang2 = v.angleRad()
this.valeurAngleAuCentre = mesurePrincipale(this.ang2 - this.ang1)
if (zeroAngle(this.valeurAngleAuCentre)) {
this.existe = false
return
}
}
CArcDeCercleAncetre.prototype.positionne.call(this, infoRandom, dimfen)
}
// Ajout version 6.3.0
CArcDeCercle.prototype.positionneFull = function (infoRandom, dimfen) {
if (this.pointFinArc === null) this.angleAuCentre.dejaPositionne = false
this.positionne(infoRandom, dimfen)
}
CArcDeCercle.prototype.confonduAvec = function (p) {
if (p.className === this.className) {
if (this.pointFinArc === null) { return (this.o === p.o) && (this.a === p.a) && this.angleAuCentre.confonduAvec(p.angleAuCentre) } else { return (this.o === p.o) && (this.a === p.a) && (this.pointFinArc === p.pointFinArc) }
} else return false
}
CArcDeCercle.prototype.ajouteAntecedents = function (liste) {
liste.add(this.o)
liste.add(this.a)
if (this.pointFinArc !== null) liste.add(this.pointFinArc)
}
CArcDeCercle.prototype.depDe = function (p) {
if (this.elementTestePourDependDe === p) return this.dependDeElementTeste
if (this.pointFinArc === null) {
return this.memDep(CArcDeCercleAncetre.prototype.depDe.call(this, p) ||
this.o.depDe(p) || this.a.depDe(p) || this.angleAuCentre.depDe(p))
} else {
return this.memDep(CArcDeCercleAncetre.prototype.depDe.call(this, p) ||
this.o.depDe(p) || this.a.depDe(p) || this.pointFinArc.depDe(p))
}
}
CArcDeCercle.prototype.dependDePourBoucle = function (p) {
if (this.pointFinArc === null) {
return (p === this) || this.o.dependDePourBoucle(p) ||
this.a.dependDePourBoucle(p) || this.angleAuCentre.dependDePourBoucle(p)
} else {
return (p === this) || this.o.dependDePourBoucle(p) ||
this.a.dependDePourBoucle(p) || this.pointFinArc.dependDePourBoucle(p)
}
}
/**
* Spécial JavaScript
* Renvoie le path pour définir le svg element associé.
*/
CArcDeCercle.prototype.path = function () {
const u = new Vect(this.centreX, this.centreY, this.origine_x, this.origine_y)
const v = new Vect()
u.tourne(this.valeurAngleAuCentre, v)
const xf = this.centreX + v.x
const yf = this.centreY + v.y
const sweepflag = (this.valeurAngleAuCentre < 0) ? '1 ' : '0 '
return 'M ' + this.origine_x.toString() + ' ' + this.origine_y + 'A' + this.rayon + ',' +
this.rayon + ' 0 0 ' + sweepflag + xf.toString() + ',' + yf.toString()
}
CArcDeCercle.prototype.surArc = function (xt, yt) {
let ang1aux, ang2aux, dif, d
const w = new Vect(this.centreX, this.centreY, xt, yt)
const ang = w.angleRad()
if (zeroAngle(Math.abs(this.valeurAngleAuCentre) - Math.PI)) {
if (zeroAngle(ang - this.ang1)) return true
if (this.valeurAngleAuCentre > 0) { // Cas d'un petit arc tracé dans le sens direct
if (this.ang1 <= Math.PI) return ((ang >= this.ang1) && (ang <= this.ang1 + Math.PI)) || zeroAngle(ang - this.ang1 - Math.PI)
else return (ang >= this.ang1) || (ang <= this.ang1 - Math.PI) || zeroAngle(ang - this.ang1 + Math.PI)
} else {
if (this.ang1 <= Math.PI) return (ang >= this.ang1 + Math.PI) || (ang <= this.ang1) || zeroAngle(ang - this.ang1 - Math.PI)
else return ((ang <= this.ang1) && (ang >= this.ang1 - Math.PI)) || zeroAngle(ang - this.ang1 + Math.PI)
}
} else {
ang1aux = this.ang1
ang2aux = this.ang2
// On ordonne ang1Aux et ang2Aux dans l'ordre croissant
if (ang1aux > ang2aux) {
d = ang2aux
ang2aux = ang1aux
ang1aux = d
}
if (zeroAngle(ang - ang1aux) || zeroAngle(ang - ang2aux)) return true
dif = ang2aux - ang1aux
if (dif < Math.PI) return (ang >= ang1aux) && (ang <= ang2aux)
else return (ang <= ang1aux) || (ang >= ang2aux)
}
}
/**
* Fonction servant à positionner un point lié à un arc de cercle.
* Renvoie un nombre compris entre 0 et 1.
* @param {number} ang La valeur testée.
* @returns {number}
*/
CArcDeCercle.prototype.abscisseCurviligne = function (ang) {
let difang
if (this.valeurAngleAuCentre === 0) return 0
difang = Math.abs(ang - this.ang1)
if (difang > Math.PI) difang = 2 * Math.PI - difang
return difang / Math.abs(this.valeurAngleAuCentre)
}
CArcDeCercle.prototype.abscisseMinimale = function () {
return 0
}
CArcDeCercle.prototype.abscisseMaximale = function () {
return 1
}
/**
* Renvoie la nature de l'arc.
* @returns {NatArc}
*/
CArcDeCercle.prototype.natureArc = function () {
return NatArc.PetitArc
}
CArcDeCercle.prototype.remplacePoint = function (ancienPoint, nouveauPoint) {
if (this.o === ancienPoint) this.o = nouveauPoint
if (this.a === ancienPoint) this.a = nouveauPoint
if (this.pointFinArc === ancienPoint) this.pointFinArc = nouveauPoint
}
CArcDeCercle.prototype.read = function (inps, list) {
CArcDeCercleAncetre.prototype.read.call(this, inps, list)
this.angleAuCentre = null
const ind1 = inps.readInt()
const ind2 = inps.readInt()
this.o = list.get(ind1, 'CPt')
this.a = list.get(ind2, 'CPt')
this.pointFinArc = null
const ind3 = inps.readInt()
if (ind3 === -1) {
this.angleAuCentre = new CValeurAngle()
this.angleAuCentre.read(inps, list)
} else this.pointFinArc = list.get(ind3, 'CPt')
}
CArcDeCercle.prototype.write = function (oups, list) {
CArcDeCercleAncetre.prototype.write.call(this, oups, list)
const ind1 = list.indexOf(this.o)
oups.writeInt(ind1)
const ind2 = list.indexOf(this.a)
oups.writeInt(ind2)
let ind3
if (this.pointFinArc === null) ind3 = -1
else ind3 = list.indexOf(this.pointFinArc)
oups.writeInt(ind3)
if (this.pointFinArc === null) this.angleAuCentre.write(oups, list)
}