PortaleOrdiniGruppo/PortalStudio/visualquery/treedrawfile/mixedTree.js
2025-03-24 15:28:26 +01:00

482 lines
24 KiB
JavaScript
Raw Permalink Blame History

/*
Dipendenze:
NodoGrafico
RaphaelAdapter
Eredita:
alberoBase
Descrizione:
algoritmo per la creazione di un albero misto ovvero meta' viene disegnato verso il basso e meta' verso destra
Metodi:
aggiustaLivelloVerticale <---- senza this.
aggiustaLivelloOrizzontale <---- senza this.
sistemaLivelli
ottimizzaSpazio
ottimizzaSpazioSinistra
ottimizzaSpazioDestra
creaFigli
calcoloNodiPerLivello <---- senza this.
creaRadice
Membri:
this.inheritFrom. Riferimento alla superclasse
*/
/* exported albertoMisto */
function albertoMisto() {
//chiamata al costruttore della super classe alberoBase
this.inheritFrom = alberoBase;
this.inheritFrom();
var _treeObj,_firstIndex;
var index=0;
/*
la funzione aumenta la coordinata y dei nodi del valore contenuto in "differenza"
Dopo aver aumentato la coordinata y di un livello controlla che il livello sottostante non sia troppo vicino, nel caso aumenta coordinata y anche del livello sottostante
profondita, livello del nodo N.B. La radice e' a profondita' -1
differenza, l'aumento della coordinata y dei nodi richiesta
nodiCreati, array con tutti i nodi creati
*/
var aggiustaLivelloVerticale = function (profondita, differenza, nodiCreati) {
if(differenza <= 0) {
return;
}
for(var i = 0; i < nodiCreati[profondita].length; ++i) {
nodiCreati[profondita][i].setY(nodiCreati[profondita][i].getPuntoY() + differenza);
}
if(nodiCreati[profondita+1]) { //se c'e' un livello successivo
differenza = nodiCreati[profondita][0].getPuntoY() + 1.6*nodiCreati[profondita][0].getAltezza() - nodiCreati[profondita+1][0].getPuntoY();
if(differenza > 0) { //il livello sottostante e' distante meno di 0.6*altezza del nodo
aggiustaLivelloVerticale(profondita + 1, differenza, nodiCreati);
}
}
}
/*
la funzione aumenta la coordinata x dei nodi del valore contenuto in "differenza"
Dopo aver aumentato la coordinata x di un livello controlla che il livello sottostante non sia troppo vicino, nel caso aumenta la coordinata x anche del livello a destra
profondita, livello del nodo N.B. La radice e' a profondita' -1
differenza, l'aumento della coordinata x dei nodi richiesta
nodiCreati, array con tutti i nodi creati
*/
var aggiustaLivelloOrizzontale = function (profondita, differenza, nodiCreati) {
if(differenza <= 0) {
return;
}
for(var i = 0; i < nodiCreati[profondita].length; ++i) {
nodiCreati[profondita][i].setX(nodiCreati[profondita][i].getPuntoX() + differenza);
}
if(nodiCreati[profondita+1]) { //se c'e' un livello successivo
differenza = nodiCreati[profondita][0].getPuntoX() + 1.6*nodiCreati[profondita][0].getLarghezza() - nodiCreati[profondita+1][0].getPuntoX();
if(differenza > 0) { //il livello sottostante e' distante meno dello 0.6*Larghezza del nodo
aggiustaLivelloOrizzontale(profondita + 1, differenza, nodiCreati);
}
}
}
/*
la funzione aggiusta l'altezza dei due sottoalberi, facendo in modo che nessuno dei due "sfori" nell'area dell'altro
nodiSinistra, i nodi grafici della parte sinistra
nodiDestra, i nodi grafici della parte destra
angle, utilizzato per separare in due l'area di disegno
profondita, livello dell'albero in cui si sta lavorando. N.B. La radice e' a profondita' -1
*/
this.sistemaLivelli = function(nodiSinistra, nodiDestra, angle, profondita) {
if(nodiSinistra) {
var nodoSinistroPiuADestra = nodiSinistra[profondita][nodiSinistra[profondita].length - 1];
//calcolo la distanza dall'origine che dovrebbe rispettare il livello del sottoalbero se l'altro sottoalbero fosse pieno
var altezzaSinistro = (nodoSinistroPiuADestra.getPuntoX()+nodoSinistroPiuADestra.getLarghezza()+this._spazioStandard)/Math.cos(angle)*Math.sin(angle);
aggiustaLivelloVerticale(profondita, Math.round(altezzaSinistro - nodoSinistroPiuADestra.getPuntoY()), nodiSinistra);
}
if(nodiDestra) {
var nodoDestroPiuInBasso = nodiDestra[profondita][nodiDestra[profondita].length - 1];
var larghezzaDestro = (nodoDestroPiuInBasso.getPuntoY()+nodoDestroPiuInBasso.getAltezza())/Math.cos(Math.PI/2 - angle)*Math.sin(Math.PI/2 - angle);
aggiustaLivelloOrizzontale(profondita, Math.round(larghezzaDestro - nodoDestroPiuInBasso.getPuntoX()+this._spazioStandard), nodiDestra);
}
if(nodiSinistra && nodiDestra && nodiSinistra[profondita+1] && nodiDestra[profondita+1]) {
this.sistemaLivelli(nodiSinistra, nodiDestra, angle, profondita+1);
}
else if(nodiSinistra && nodiSinistra[profondita+1]) {
this.sistemaLivelli(nodiSinistra, null, angle, profondita+1);
}
else if(nodiDestra && nodiDestra[profondita+1]) {
this.sistemaLivelli(null, nodiDestra, angle, profondita+1);
}
}
/*
Ottimizza lo spazio occupato dall'albero, permettendo ai singoli livelli di "sforare" nell'area dell'altro sottoalbero se possibile.
La funzione considera dei due livelli quali dei due e' pi<70> lontano dal livello precedente e cerca di spostare quello pi<70> distante
*/
this.ottimizzaSpazio = function(nodiSinistra, nodiDestra, profondita) {
var nodoSinistroPiuADestra = nodiSinistra[profondita][nodiSinistra[profondita].length - 1];
var nodoDestroPiuInBasso = nodiDestra[profondita][nodiDestra[profondita].length - 1];
var padreSinistro = nodoSinistroPiuADestra.getPadre();
var diffAltezzaSinistro = padreSinistro.getPuntoY() + 1.6*padreSinistro.getAltezza() - nodoSinistroPiuADestra.getPuntoY();
var padreDestro = nodoDestroPiuInBasso.getPadre();
var diffLarghezzaDestro = padreDestro.getPuntoX() + 1.6*padreDestro.getLarghezza() - nodoDestroPiuInBasso.getPuntoX();
var i, controllatoCriticita;
if(diffAltezzaSinistro < 0 || diffLarghezzaDestro < 0 ){ // ha senso cercare di ottimizzare spazio
if(diffAltezzaSinistro <= diffLarghezzaDestro) { //sposto il livello pi<70> distante dal padre
//calcolo la nuova altezza del livello
var newPuntoY = nodoSinistroPiuADestra.getPuntoY() + diffAltezzaSinistro; //come minimo l'altezza puo' essere
i = 0;
controllatoCriticita = false;
while(i < nodiDestra.length && !controllatoCriticita) {
//un nodo del sottoalbero destro puo' sovrapporsi se la propria coordinata x e' inferiore alla coordinata x del nodo sinistro pi<70> la sua larghezza e lo spazio
if(nodiDestra[i][nodiDestra[i].length - 1].getPuntoX() < nodoSinistroPiuADestra.getPuntoX() + nodoSinistroPiuADestra.getLarghezza() + this._spazioStandard) {
//calcolo l'altezza del lvello del nodo
var altezzaLivelloDestro = nodiDestra[i][nodiDestra[i].length - 1].getPuntoY() + nodiDestra[i][nodiDestra[i].length - 1].getAltezza() + this._spazioStandard*2; // spazio per 2 per distanziare
if( altezzaLivelloDestro > newPuntoY ) {
newPuntoY = altezzaLivelloDestro;
}
if(newPuntoY>= nodoSinistroPiuADestra.getPuntoY()) {
controllatoCriticita = true;
}
++i;
}
else { //non ci sono altri livelli del sottoalbero destro che si possono sovrapporre
controllatoCriticita = true;
}
}
if(newPuntoY < nodoSinistroPiuADestra.getPuntoY()) {
for(i = 0; i < nodiSinistra[profondita].length; ++i) {
nodiSinistra[profondita][i].setY(newPuntoY);
}
}
}
else {
//calcolo la nuova larghezza del livello
var newPuntoX = nodoDestroPiuInBasso.getPuntoX() + diffLarghezzaDestro;
i = 0;
controllatoCriticita = false;
while(i < nodiSinistra.length && !controllatoCriticita) {
//un nodo del sottoalbero sinistro puo' sovrapporsi se la propria coordinata y e' inferiore alla coordinata y del nodo destro pi<70> l'altezza del nodo e lo spazio
if(nodiSinistra[i][nodiSinistra[i].length - 1].getPuntoY() < nodoDestroPiuInBasso.getPuntoY() + nodoDestroPiuInBasso.getAltezza() + this._spazioStandard) {
//calcolo la larghezza del lvello del nodo
var larghezzaLivelloSinistro = nodiSinistra[i][nodiSinistra[i].length - 1].getPuntoX() + nodiSinistra[i][nodiSinistra[i].length - 1].getLarghezza() + this._spazioStandard*2; //spazio per 2 per distanziare
if( larghezzaLivelloSinistro > newPuntoX ) {
newPuntoX = larghezzaLivelloSinistro;
}
if(newPuntoX >= nodoDestroPiuInBasso.getPuntoX()) {
controllatoCriticita = true;
}
++i;
}
else { //non ci sono altri livelli del sottoalbero destro che si possono sovrapporre
controllatoCriticita = true;
}
}
if(newPuntoX < nodoDestroPiuInBasso.getPuntoX()) {
for(i = 0; i < nodiDestra[profondita].length; ++i) {
nodiDestra[profondita][i].setX(newPuntoX);
}
}
}
}
if(nodiSinistra[profondita+1] && nodiDestra[profondita+1]) { //non ottimizzo i livelli se uno dei due sottoalberi non ha il livello successivo
this.ottimizzaSpazio(nodiSinistra, nodiDestra, profondita+1);
}
else if(nodiSinistra[profondita+1] && !nodiDestra[profondita+1]) { //il sottoalbero sinistro e' pi<70> profondo
this.ottimizzaSpazioSinistra(nodiSinistra, nodiDestra, profondita+1);
}
else if(!nodiSinistra[profondita+1] && nodiDestra[profondita+1]) { //il sottoalbero destro e' pi<70> profondo
this.ottimizzaSpazioDestra(nodiSinistra, nodiDestra, profondita+1);
}
}
/*
Versione della funzione precedente che cerca di ottimizzare solo il lato sinistro
*/
this.ottimizzaSpazioSinistra = function(nodiSinistra, nodiDestra, profondita) {
var nodoSinistroPiuADestra = nodiSinistra[profondita][nodiSinistra[profondita].length - 1];
var padreSinistro = nodoSinistroPiuADestra.getPadre();
var diffAltezzaSinistro = padreSinistro.getPuntoY() + 1.6*padreSinistro.getAltezza() - nodoSinistroPiuADestra.getPuntoY();
if(diffAltezzaSinistro < 0){ // ha senso cercare di ottimizzare spazio
//calcolo la nuova altezza del livello
var newPuntoY = nodoSinistroPiuADestra.getPuntoY() + diffAltezzaSinistro; //come minimo l'altezza puo' essere
var i = 0;
var controllatoCriticita = false;
while(i < nodiDestra.length && !controllatoCriticita) {
//un nodo del sottoalbero destro puo' sovrapporsi se la propria coordinata x e' inferiore alla coordinata x del nodo sinistro pi<70> la sua larghezza e lo spazio
if(nodiDestra[i][nodiDestra[i].length - 1].getPuntoX() < nodoSinistroPiuADestra.getPuntoX() + nodoSinistroPiuADestra.getLarghezza() + this._spazioStandard) {
//calcolo l'altezza del lvello del nodo
var altezzaLivelloDestro = nodiDestra[i][nodiDestra[i].length - 1].getPuntoY() + nodiDestra[i][nodiDestra[i].length - 1].getAltezza() + this._spazioStandard*2; // spazio per 2 per distanziare
if( altezzaLivelloDestro > newPuntoY ) {
newPuntoY = altezzaLivelloDestro;
}
if(newPuntoY>= nodoSinistroPiuADestra.getPuntoY()) {
controllatoCriticita = true;
}
++i;
}
else { //non ci sono altri livelli del sottoalbero destro che si possono sovrapporre
controllatoCriticita = true;
}
}
if(newPuntoY < nodoSinistroPiuADestra.getPuntoY()) {
for(i = 0; i < nodiSinistra[profondita].length; ++i) {
nodiSinistra[profondita][i].setY(newPuntoY);
}
}
}
if(nodiSinistra[profondita+1]) {
this.ottimizzaSpazioSinistra(nodiSinistra, nodiDestra, profondita+1);
}
}
/*
Versione della funzione precedente che cerca di ottimizzare solo il lato destro
*/
this.ottimizzaSpazioDestra = function(nodiSinistra, nodiDestra, profondita) {
var nodoDestroPiuInBasso = nodiDestra[profondita][nodiDestra[profondita].length - 1];
var padreDestro = nodoDestroPiuInBasso.getPadre();
var diffLarghezzaDestro = padreDestro.getPuntoX() + 1.6*padreDestro.getLarghezza() - nodoDestroPiuInBasso.getPuntoX();
//calcolo la nuova larghezza del livello
var newPuntoX = nodoDestroPiuInBasso.getPuntoX() + diffLarghezzaDestro;
var i = 0;
var controllatoCriticita = false;
while(i < nodiSinistra.length && !controllatoCriticita) {
//un nodo del sottoalbero sinistro puo' sovrapporsi se la propria coordinata y e' inferiore alla coordinata y del nodo destro pi<70> l'altezza del nodo e lo spazio
if(nodiSinistra[i][nodiSinistra[i].length - 1].getPuntoY() < nodoDestroPiuInBasso.getPuntoY() + nodoDestroPiuInBasso.getAltezza() + this._spazioStandard) {
//calcolo la larghezza del lvello del nodo
var larghezzaLivelloSinistro = nodiSinistra[i][nodiSinistra[i].length - 1].getPuntoX() + nodiSinistra[i][nodiSinistra[i].length - 1].getLarghezza() + this._spazioStandard*2; //spazio per 2 per distanziare
if( larghezzaLivelloSinistro > newPuntoX ) {
newPuntoX = larghezzaLivelloSinistro;
}
if(newPuntoX >= nodoDestroPiuInBasso.getPuntoX()) {
controllatoCriticita = true;
}
++i;
}
else { //non ci sono altri livelli del sottoalbero destro che si possono sovrapporre
controllatoCriticita = true;
}
}
if(newPuntoX < nodoDestroPiuInBasso.getPuntoX()) {
for(i = 0; i < nodiDestra[profondita].length; ++i) {
nodiDestra[profondita][i].setX(newPuntoX);
}
}
if(nodiDestra[profondita+1]) { //il sottoalbero destro e' pi<70> profondo
this.ottimizzaSpazioDestra(nodiSinistra, nodiDestra, profondita+1);
}
}
/*
Disegna un albero con i nodi pi<70> a sinistra incolonnati o pi<70> a destra allineati
nodiPerLivello e' un array che contiene il numero di nodi di ogni livello
profondita, a che profondita si e' N.B. La radice e' a profondita' -1
figli, sono i nodi da disegnare, sono dati in formato JSON
padre e' il padre dei figli ed e' di tipo NodoGrafico
canvas e' l'oggetto di tipo RaphaelAdapter da passare agli oggetti di tipo nodoGrafico
offset, e' la coordinata minima x a cui si puo' disegnare un nodo di quel livello. all'ultima iterazione diventa lo spazio occupato in x dal livello
nodiCreati, array con i riferimenti a tutti i nodi creati. N.B. Non sarebbe indispensabile, ma senza quando si tratta di "correggere" la profondita' dei vari livelli la complessita' algoritmica aumenta troppo.
tipo: se verticale o orizzontale,
dimspostamento: la dimensione con cui devo spostare lungo lo stesso livello
return: lo spazio occupato sull'asse per il disegno da tutti i nodi di quel livello
*/
this.creaFigli = function (nodiPerLivello, profondita, figli, padre, canvas, offset, nodiCreati, tipo, dimSpostamento) {
var coord;
if(tipo == "verticale") {
coord = padre.getPuntoY() + padre.getAltezza()*1.6; //altezza standard successivamente verra' sistemata
}
else {
coord = padre.getPuntoX() + padre.getLarghezza()*1.6; //larghezza standard successivamente verra' sistemata
}
var noFigliBrother = false; // viene messa a false se il nodo non ha figli, all'iterazione successiva il fratello destro controlla se il fratello sinistro non ha figli.
var dueopiuFigliFratello = false; //memorizzo se il fratello ha due o pi<70> figli, il primo nodo del sottoalbero non puo' spostarsi quindi false
var spostatoBrother = false; //viene messo a true se il nodo viene spostato, all'iterazione successiva il nodo controllera' se il fratello sinistro e' stato spostato
for(var i=0; i < figli.length; ++i) {
//creo un array con tutte le proprieta' e rimuovo quelle non-extra, quindi figli e colore
var arrKeyProp = this.rimuoviNonInformazioni(figli[i]);
//creo un array con i valori delle proprieta non eliminate
var arrValueProp = [];
for(var j = 0; j < arrKeyProp.length; ++j) {
arrValueProp.push(figli[i][arrKeyProp[j]]);
}
if(dueopiuFigliFratello && !(figli[i].figli && figli[i].figli.length > 0)) { //il fratello ha due o pi<70> figli e questo nodo non ha figli, posso spostarlo di una grandezza pari alla grandezza del nodo
offset = offset - (dimSpostamento + this._spazioStandard);
spostatoBrother = true;
} else if(!dueopiuFigliFratello && !(figli[i].figli && figli[i].figli.length > 0)) { //non e' andato nel ramo if non perch<63> il nodo non abbia figli, ma perch<63> il fratello non ha 2 o pi<70> figli
spostatoBrother = false;
}
//creo nodo
nodiCreati[profondita].push(new NodoGrafico());
index++;
//la differenza tra le due chiamate e' che l'offset e' passato come punto x nel primo caso e punto y nel secondo
if(tipo == "verticale") {
nodiCreati[profondita][nodiCreati[profondita].length - 1].init(figli[i].nome, figli[i].color, arrValueProp, arrKeyProp, offset, coord, this._lunghezzaNodoStandard, this._altezzaNodoStandard, canvas, padre,index+_firstIndex);
}
else {
nodiCreati[profondita][nodiCreati[profondita].length - 1].init(figli[i].nome, figli[i].color, arrValueProp, arrKeyProp, coord, offset, this._lunghezzaNodoStandard, this._altezzaNodoStandard, canvas, padre,index+_firstIndex);
}
padre.addFiglio(nodiCreati[profondita][nodiCreati[profondita].length -1]);
//ho disegnato un nodo di questo livello
--nodiPerLivello[profondita];
if(figli[i].figli && figli[i].figli.length > 0 && !_treeObj[index+_firstIndex].hiddenChild) {
/*ramo if: il fratello non aveva figli, c'e' pi<70> spazio per un nodo che ha pi<70> di due figli, inoltre il fratello non e' stato spostato e quindi lo spazio c'e' */
if(figli[i].figli.length > 1 && noFigliBrother == true && spostatoBrother == false) {
dueopiuFigliFratello = true;
//chiamate ricorsive, disegno prima i figli del fratello
if(nodiPerLivello[profondita] == 0) { //se e' l'ultimo nodo del livello non sommo lo spazio occupato dai figli, ma solo del nodo
this.creaFigli(nodiPerLivello, profondita + 1, figli[i].figli, nodiCreati[profondita][nodiCreati[profondita].length - 1], canvas, offset - (dimSpostamento + this._spazioStandard), nodiCreati, tipo, dimSpostamento);
offset += dimSpostamento + this._spazioStandard;
}
else {
//lo spazio occupato dal proprio sottoalbero e' >= dello spazio occupato dal nodo
offset = this.creaFigli(nodiPerLivello, profondita + 1, figli[i].figli, nodiCreati[profondita][nodiCreati[profondita].length - 1], canvas, offset - (dimSpostamento + this._spazioStandard), nodiCreati, tipo, dimSpostamento);
}
}
else {
//stabilisco solo se ho uno o pi<70> figli, ma per l'invocazione ricorsiva i parametri non cambiano.
if(figli[i].figli.length > 1){
dueopiuFigliFratello = true;
}
else {
dueopiuFigliFratello = false;
}
if(nodiPerLivello[profondita] == 0) { //se e' l'ultimo nodo del livello non considero lo spazio occupato dai figli, ma solo del nodo
this.creaFigli(nodiPerLivello, profondita + 1, figli[i].figli, nodiCreati[profondita][nodiCreati[profondita].length - 1], canvas, offset, nodiCreati, tipo, dimSpostamento);
offset += dimSpostamento + this._spazioStandard;;
}
else {
//lo spazio occupato dal proprio sottoalbero e' >= dello spazio occupato dal nodo
offset = this.creaFigli(nodiPerLivello, profondita + 1, figli[i].figli, nodiCreati[profondita][nodiCreati[profondita].length - 1], canvas, offset, nodiCreati, tipo, dimSpostamento);
}
}
noFigliBrother = false; //il nodo in questione ha dei figli
spostatoBrother = false; //un nodo con figli non puo' essere spostato
}
else if (figli[i].figli && figli[i].figli.length > 0 && _treeObj[index+_firstIndex].hiddenChild){
noFigliBrother=false;
offset += dimSpostamento + this._spazioStandard;
nodiCreati[profondita][nodiCreati[profondita].length - 1].addIconShowChild();
index+=_treeObj[index+_firstIndex].allChild;
}
else { //non ci sono figli
noFigliBrother = true; //non ha figli
dueopiuFigliFratello = false; // non ha due figli
offset += dimSpostamento + this._spazioStandard;
}
}
return offset;
}
/*
funzione ricorsiva che restituisce un array dove ogni elemento e' il numero di nodi di profondita' i del sottoalbero N.B. La radice e' a profondita' -1
nodi sono i figli di un certo nodo.
*/
var calcoloNodiPerLivello = function (nodi) {
var nodiPerLivello = [];
nodiPerLivello.push(nodi.length); //numero di nodi a profondita' 1
for(var i = 0; i < nodi.length; ++i) {
//chiamata ricorsiva
if(nodi[i].figli != undefined && nodi[i].figli != null) {
var numbSubTree = calcoloNodiPerLivello(nodi[i].figli);
for(var j = 0; j < numbSubTree.length; ++j) {
//se e' il ritorno di una chiamata ricorsiva che restituisce un array di lunghezza + 1 > lunghezza di nodiPerLivello inizializzo
if(isNaN(nodiPerLivello[1+j])) {
nodiPerLivello[1+j] = 0;
}
//in ogni chiamata l'unico valore da non alterare e' il primo. Per cui cio' che restituisce il figlio va messo dopo. Se ci sono pi<70> figli i valori vanno sommati.
nodiPerLivello[1+j] += numbSubTree[j];
}
}
}
return nodiPerLivello;
}
/*primo step qui creo la radice e divido a meta' l'albero. e chiamo le due funzioni che disegnano la parte sinistra e poi la parte destra
Json, contiene i dati
canvas, l'oggetto di tipo RaphaelAdapter da passare alle istanze di NodoGrafico
*/
var _padre;
this.creaRadice = function(Json, canvas, lunghezza, altezza, spazioTraNodi,treeObj,firstIndex) {
if(!Json) { //json vuoto
return;
}
_treeObj=treeObj;
_firstIndex=firstIndex;
var arrKeyProp = this.rimuoviNonInformazioni(Json);
//creo un array con i valori delle proprieta non eliminate
var arrValueProp = [];
var i;
for(i = 0; i < arrKeyProp.length; ++i) {
arrValueProp.push(Json[arrKeyProp[i]]);
}
this._padre = new NodoGrafico();
this._padre.init(Json.nome, Json.color, arrValueProp, arrKeyProp, 10, 10, lunghezza, altezza, canvas, null,_firstIndex);
if (_firstIndex!=0)
this._padre.addIconShowAncestors();
if(!Json.figli) { //non ci sono figli
return;
}
this._lunghezzaNodoStandard = lunghezza;
this._altezzaNodoStandard = altezza;
this._spazioStandard = spazioTraNodi;
//numero di nodi che disegno a sinistra
var metaSinistra = Math.ceil(Json.figli.length / 2); //arrotondo sempre all'intero superiore, si puo' utilizzare anche round, ma cos<6F> e' esplicito
var nodiJsonMeta = [];
for(i = 0; i < metaSinistra; ++i ) {
nodiJsonMeta.push(Json.figli[i]);
}
var nodePerLevel = calcoloNodiPerLivello(nodiJsonMeta);
//allNodeLeft conterra' tutti i nodi grafici creati a sinistra, array bidemnsionale, il primo indice corrisponde alla profondita' meno uno dei nodi, ad es un nodo di profondita' uno sara' sull'indice zero
var allNodeLeft = [];
for(i = 0; i < nodePerLevel.length; ++i) {
allNodeLeft.push(new Array());
}
this.creaFigli(nodePerLevel, 0, nodiJsonMeta, this._padre, canvas, this._padre.getPuntoX(), allNodeLeft, "verticale", this._lunghezzaNodoStandard);
if(Json.figli.length > 1) { //non ho nodi a destra
//tutta la parte sinistra e' creata, si passa a quella destra
nodiJsonMeta = [];
for(i = metaSinistra; i < Json.figli.length; ++i ) {
nodiJsonMeta.push(Json.figli[i]);
}
nodePerLevel = [];
nodePerLevel = calcoloNodiPerLivello(nodiJsonMeta);
//allNode conterra' tutti i nodi grafici creati, array bidemnsionale, il primo indice corrisponde alla profondita' meno uno dei nodi, ad es un nodo di profondita' uno sara' sull'indice zero
var allNodeRight = [];
for(i = 0; i < nodePerLevel.length; ++i) {
allNodeRight.push(new Array());
}
this.creaFigli(nodePerLevel, 0, nodiJsonMeta, this._padre, canvas, this._padre.getPuntoY(), allNodeRight, "orizzontale", this._altezzaNodoStandard);
//angolo necessario per separare correttamente in due il canvas. e' l'arccoseno della lunghezza di un nodo diviso dall'ipotenusa dell'ipotetico triangolo dove la lunghezza e' il cateto maggiore
var angleIpotenusaBase = Math.acos(this._lunghezzaNodoStandard/Math.sqrt(this._lunghezzaNodoStandard*this._lunghezzaNodoStandard + this._altezzaNodoStandard*this._altezzaNodoStandard));
//sistemo l'altezza dei vari livelli solo se entrambi i rami dell'albero sono stati creati
this.sistemaLivelli(allNodeLeft, allNodeRight, angleIpotenusaBase, 0);
this.ottimizzaSpazio(allNodeLeft, allNodeRight, 0);
}
//sistemo la dimensione del canvas se non supporta SVG
if(!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")) {
canvas.resizeCanvas(this._padre.getLarghezzaSubTree() + 5 ,this._padre.getAltezzaSubTree() + 5);
}
_padre=this._padre;
}
this.getSize=function(){
return [_padre.getLarghezzaSubTree()-5,this._padre.getAltezzaSubTree()-5];
}
this.getPosizione=function(){
return [_padre.getPuntoX(),_padre.getPuntoY()];
}
}