Sei sulla pagina 1di 11

GRAFICA IN JAVA PER DISEGNARE FIGURE GEOMETRICHE Domenico Saccà

1. Utilizzo dell’oggetto “graphics”

Nel package System personalizzato per il corso è disponibile l’oggetto graphics che include alcuni

metodi elementari di grafica. A tale scopo viene automa ticamente messo a disposizione un pannello (cioè una specie di terminale grafico) in cui vengono visualizzate le operazioni di grafica - il pannello abilitato sia nel caso che il programma venga lanciato come una classica applicazione Java sia nel caso

di esecuzione come applet.

Il pannello è un rettangolo suddiviso in un numero prefissato di punti (chiamati pixel). Esso può essere considerato una matrice di pixel con ( dim Y +1) righe e ( dim X +1) colonne – la numerazione parte da 0. Le coordinate dei quattr o vertici del pannello sono:

(0, 0) – vertice in alto a sinistra

(0, dimY ) – vertice in basso a sinistra

( dimX , 0) – vertice in alto a destra

( dimX , dimY ) – vertice in basso a destra.

I comandi per conoscere le dimensioni del pannello sono:

System.graphic s.getDimX () : r estituisce la larghezza ( width ) totale dell area grafica (in pixel) come intero

System.graphics.getDimY () : r estituisce l ’a ltezza ( height ) totale dell area grafica (in pixel) come intero.

Si noti che nel caso il programma sia lanciato com e applicazione Java, la dimensione del pannello è

prefissata (ma può essere modificata in corso di utilizzo) mentre nel caso sia lanciata come applet essa dipende dallo spazio indicato nella pagina html per l’applet:

<applet code=" nomeClasse .class" archive=" nomeClasse .jar" height="500" width="800">

Ne ll’esempio dimY è 500 pixel e dimX è 800 pixel.

Il comando per disegnare una linea tra due punti del pannello è il seguente:

System.graphics.drawLine ( int x1 , int y1 , int x2 , int y2 ) : d isegna il segmento che unisce i punti di coordinate ( x1 , y1 ) ed ( x2 , y2 ).

La linea viene disegnata con il colore corrente. All’inizio del programma il colore corrente è quello di

default (tipicamente il nero). E’ possibile rendere corrente un colore diverso tramite il comando:

System.graphics.setColor ( Color c ol ) : viene reso corrente il colore col .

Per utilizzare questo metodo occorre importare il package java.awt.Color . Il parametro cc può assumere uno dei seguenti valori: Color.BLACK (nero) , Color.BLUE (blu) , Color.CYAN (ciano) , Color.DARK_GRAY (grigio scuro) , Color.G RAY (grigio) , Color.LIGHT_GRAY (grigio chiaro) , Color.GREEN (verde) , Color.MAGENTA (magenta) , Color.ORANGE (arancio) , Color.PINK (rosa) , Color.RED (rosso) , Color.WHITE (bianco) , Color.YELLOW (giallo) .

Questa porzione di codice disegna in nero i 4 lati d el pannello, poi in blu le due mediane ed, infine, in rosso le due diagonali:

import java.awt.Color; import system.Scanner; import system.SystemApplet; import system.System; public class Prova_graphics extends SystemApplet { public static void main(String[] args) { int dimX = System.graphics.getDimX();

int dimY = System.graphics.getDimY(); System.graphics.setColor(Color.black); System.graphics.drawLine(0, 0, 0, dimY); // lato verticale a sinistra System.graphics.drawLine(dimX, 0, dimX, dimY); // lato verticale a destra System.graphics.drawLine(0, 0, dimX, 0); // lato orizzontale in alto System.graphics.drawLine(0, dimY, dimX, dimY); // lato orizzontale in basso System.graphics.setColor(Color.blue); System.graphics.drawLine(dimX/2, 0, dimX/2, dimY); // mediana orizzontale System.graphics.drawLine(0, dimY/2, dimX, dimY/2); // mediana verticale System.graphics.setColor(Color.red);

System.graphics.drawLine(0, 0, dimX, dimY); // diagonale dall’alto verso il basso System.graphics.drawLine(dimX, 0, 0, dimY); // diagonale dal basso verso l’alto

}

}

Per ripulire il pannello, va utilizzato il comando:

System.graphics. clear ( ) .

E’ possibile scrivere stringhe di testo con il comando:

System.graphics.drawS tring ( String str, int x, int y ): scriv e la stringa str in orizzontale a partire dal punto di coordinate (x , y ).

E’ possibile disegnare rettangoli, eventualmente colorati, con i comandi:

System.graphics.drawRoundRect ( int x, int y, int width, int height, int arcWidth, int arcHeight):

disegna il rettangolo di base width e altezza height il cui vertice superiore sinistro è posto nel punto di coordinate ( x,y ) . I parametri arcWidth e arcHeight possono essere utilizzati per arrotondare gli angoli (porre a 0 questi due parametri per non arrotondare gli angoli).

System.graphics.fillRoundRect ( int x, int y, int width, int height, int arcWidth, int arcHeight):

disegna un rettangolo con le caratteristiche del comando precedente e lo colora utilizzando il colore corrente.

Sono disponibili ulteriori com andi per disegnare ellissi, cerchi, archi, spezzate e poligoni. Per dettagli consultare la guida all’uso del package System .

2 . Disegno di una parabola

Vogliamo disegnare una parabola descritta dall’equazione Y = a X 2 + b X + c cioè con asse parallela

a ll’asse Y. Ricordiamo che il vertice della parabola è ( - b/2a; – (b 2 - 4ac)/4a ) e la concavità è rivolta

verso l’alto se a > 0 e verso il basso se a < 0. Ad esempio la parabola Y = X 2 – X – 6 ha la concavità rivolta verso l’alto in quanto a = 1 > 0

< 0. Ad esempio la parabola Y = X 2 – X – 6 ha la

ment re la parabola Y = – 2X 2 +3 ha concavità rivolta verso il basso:

Y = – 2X 2 +3 ha concavità rivolta verso il basso: Il metodo main consiste

Il metodo main consiste nella lettura dei dati della parabola, nella scrittura dei suoi dati (vertice e intersezioni con gli assi) e una sessione interattiva in cui viene chiesto se si vuole disegnare la parabola e, in caso positivo, in quale range dell’asse X. Il main è il seguente:

public static void main(String[] args) { System.out.println("Disegno di una parabola y = ax^2+bx+c");

// lettura parametri a, b e c della parabola letturaParabola(); // scrittura vertice e intersezione della parabola con gli assi scritturaParabola(); // sessione interattiva per il disegno della parabola

System.out.print("Vuoi disegnare la parabola [s/n]?"); char comando = Character.toUpperCase(reader.nextChar()); boolean inizio = true; while ( comando == 'S' ) { if (inizio ) { dimX = System.graphics.getDimX(); dimY = System.graphics.getDimY();

// vectorY memorizza un valore di Y per ogni punto di X

vectorY = new double[dimX+1];

}

inizio = false;

// Lettura area di disegno: Xmin e Xmax letturaRangeX (); discretizzaPuntiParabola(); disegnaAssi(); disegnaParabola();

System.out.print("Disegno di altra porzione della parabola [s/n]?"); comando = Character.toUpperCase(reader.nextChar());

}

System.out.println("bye");

}

Come si vede, il metodo è molto astratto in quanto fa un utilizzo ampio di metodi – la sua lettura è immediata in quanto i dettagli implementativi sono rinviati alla scr ittura dei vari metodi. Inoltre sono utilizzate le seguenti variabili statiche: dimX, dimY e vectorY . Va precisato l’uso della variabile booleana inizio : essa serve per dimensionare solo la prima volta vectorY .

Mostriamo ora la scrittura dei metodi lettur aParabola e scritturaParabola .

static void letturaParabola() { do {

System.out.println("Inserisci a: ");

a = reader.nextDouble();

System.out.println("Inserisci b: ");

b = reader.nextDouble();

System.out.println("Inserisci c: ");

c = reader.nextDouble();

if ( a== 0 && b==0) System.out.println("Errore: a e b entrambi 0");

} while ( a == 0 && b == 0 );

}

static void scritturaParabola() { double D = b*b-4*a*c; // discriminante

if ( a!=0 ) { // parabola non degenere

System.out.println("Coordinate del Vertice"); System.out.print("X = " + -b/(2*a)); System.out.println("; Y = " + -D/(4*a));

if

(

D > 0

) {

System.out.println("2 intersezioni con asse X"); double rD = Math.sqrt(D); // radice quadrata del discriminante double x1 = (-b-rD)/(2*a), x2 = (-b+rD)/(2*a); System.out.print("X1 = " + x1 ); System.out.println("; X2 = " + x2 );

}

else if ( D < 0 ) System.out.println("Nessuna intersezione con asse X"); else {

System.out.println("1 intersezione con asse X"); System.out.print("X = " + (-b/(2*a)) );

}

}

else {

 

System.out.println("Parabola degenere: retta");

System.out.println("Intersezione con asse X"); System.out.println("X = " + (-c/b) );

}

System.out.println("Intersezione con asse Y"); System.out.println("Y = " + c );

}

I tuoi metodi fanno entrambi utilizzo delle variabili di tipo double a, b, c : esse vengono dichiarate di tipo statico in modo che possano essere condivise. Decidiamo di dichiarare di tipo statico anche “reader”, che viene utilizzato anche dal metodo letturaRangeX che legge l’intervallo delle X in cui disegnare la parabola:

static void letturaRangeX ( ) { System.out.println("Lettura area di disegno: Xmin e Xmax"); do {

System.out.println("Inserisci Xmin: "); rangeX[0] = reader.nextDouble(); System.out.println("Inserisci Xmax: "); rangeX[1] = reader.nextDouble(); if ( rangeX[1]<= rangeX[0]) System.out.println("Errore: Xmax <= Xmin");

} while ( rangeX[1] <= rangeX[0] );

}

L’array rangeX , che memorizza gli estremi dell’intervallo di disegno, è definito come variabile statica in quanto condiviso da altri metodi, tra cui discretizzaPuntiParabola :

static void discretizzaPuntiParabola() { scaleFactorX = ( rangeX[1] - rangeX[0])/dimX;

vectorY[0]=getOrdinata(rangeX[0]);

vectorY[dimX]=getOrdinata(rangeX[1]);

for (int i=1; i < dimX; i++ )

vectorY[i]=getOrdinata(rangeX[0]+scaleFactorX*i);

rangeY[0]=trovaMinimo(vectorY);

rangeY[1]=trovaMassimo(vectorY);

scaleFactorY = ( rangeY[1] - rangeY[0])/dimY; // il vertice viene leggermente spostato dal bordo

if ( a > 0 ) // concavità verso l’alto

rangeY[0] -= 10*scaleFactorY;

else

if ( a < 0 ) // concavità verso il basso

rangeY[1] += 10*scaleFactorY;

// se a != 0 viene ricalcolato il fattore di scala

if ( a != 0 ) scaleFactorY = ( rangeY[1] - rangeY[0])/dimY;

}

Il metodo innanzitutto acquisisce il numero di punti dimX disponibili per il disegno nella direzione X e il numero dim Y nella direzione Y – come avevamo già scritto, queste variabili sono dichiarate statiche. Viene quindi calcolato il fattore di scala in direzione X in modo che il rangeX da disegnare sia discretizzato nei dimX punti a disposizione. In corrispondenza con ciascuno di tali punti X viene memorizzato il valore del corrispondente Y (ordinata) sulla base dell’equazione della parabola – le ordinate sono memorizzate su un apposito vettore statico vectorY con tanti elementi quanti sono i punti di scretizzati nella dimensione X. Viene quindi calcolato il fattore di scala per la direzione Y sulla base del valore minimo e massimo delle ordinate – tale fattore viene un po’ spostato per evitare di dover schiacciare il vertici sul bordo del disegno. I metodi trovaMassimo e trovaMinimo sono semplici metodi per cercare rispettivamente massimo e minimo in un vettore – visto il loro carattere di metodi standard, abbiamo preferito non fare uso in essi di variabili statiche:

static double trovaMinimo ( double [] V ) { double minimo = V[0]; for ( int i = 1; i < V.length; i++ )

}

if (

V[i] < minimo ) minimo = V[i];

return minimo;

static double trovaMassimo ( double [] V ) { double massimo = V[0]; for ( int i = 1; i < V.length; i++ )

}

if (

V[i] > massimo ) massimo = V[i];

return massimo;

Per ottimizzare il codice avremmo anche potuto utilizzare un unico metodo che calcolo minimo e massimo contemporaneamente:

static double[] trovaMinimoMassimo ( double [] V ) { double [] minMax = new double[2]; minMax[0] = minMax[1] = V[0]; for ( int i = 1; i < V.length; i++ )

if (

V[i] < minMax[0] ) minMax[0] = V[i];

else

}

if ( V[i] > minMax[\] ) minMax[1] = V[i];

return minMax;

Le seguenti due istruzioni in discretizzaPuntiParabola:

rangeY[0]=trovaMinimo(vectorY);

rangeY[1]=trovaMassimo(vectorY);

vanno allora sostituite dalla seguente unica istruzione:

rangeY=trovaMinimoMassimo(vectorY);

Il metodo getOrdinata utilizza un parametro form ale per passare l’ascissa in corrispondenza della quale calcolare l’ordinata e le variabili statiche che memorizzano i coefficienti dell’equazione della parabola:

public static double getOrdinata (double ascissa) { return a*ascissa*ascissa+b*ascissa+c;

}

Il metodo disegna assi valuta se all’interno del range X, dato in input, e del range Y calcolato, ricadono gli assi X e Y e, nel caso, li disegna.

public static void disegnaAssi() { System.graphics.clear(); System.graphics.setColor(Color.black);

// Asse Y

if ( rangeX[0] <= 0 && rangeX[1]>=0 ) System.graphics.drawLine(getPuntoAscissa(0), 0, getPuntoAscissa(0), dimY);

// Asse X

if ( rangeY[0] <= 0 && rangeY[1]>=0 ) System.graphics.drawLine(0, getPuntoOrdinata(0), dimX, getPuntoOrdinata(0));

}

Per il disegno dei due assi, va individuata la posizione dell’origine tramite opportuna scalatura delle ascisse con il metodo getPuntoAscissa e delle ordinate con il metodo getPuntoOrdinata (poiché le ordinate vanno dall’alto verso il basso, esse vanno ribaltate sottraendole a dimY in modo da riportarle dal basso verso l’alto) :

public static int getPuntoOrdinata ( double v ) { return dimY - (int) Math.round((v-rangeY[0])/scaleFactorY);

}

public static int getPuntoAscissa ( double v ) { return (int) Math.round((v-rangeX[0])/scaleFactorX);

}

Il disegno della parabola è effettuato dal metodo disegnaParabola che non fa altro che raccordare con delle linee tutti i dimX punti della parabola, equamente intervallati sulle ascisse, tramite o pportuna scalatura delle ordinate con il metodo getPuntoOrdinata :

public static void disegnaParabola( ) { System.graphics.setColor(Color.red);

for(int i=0;i< dimX-1;i++){ System.graphics.drawLine(i, getPuntoOrdinata(vectorY[i]), i+1,

}

}

getPuntoOrdinata(vectorY[i+1]));

Per concludere, presentiamo di seguito la classe Parabola che contiene le variabili statiche e i metodi (che per brevità non vengono riportati nuovamente ):

public class Parabola {

// variabili globali statiche (visibili da tutti i metodi) static int dimX, dimY; // numero di punti nelle due direzioni static double a, b, c; // coefficienti dell'equazione della parabola // range (valori min e max) nella direzione X

static double [] rangeX = new double[2];

// range (valori min e max) nella direzione Y

static double [] rangeY = new double[2]; static double scaleFactorX, scaleFactorY; // fattori di scala nelle 2 direzioni

static double [] vectorY; // valori di Y per ogni punto X del range

static Scanner reader = new Scanner(System.in);

// seguono le definizioni di tutti i metodi

}

3 . Applicazione del disegno di una parabola: diagrammi dei momenti e dei tagli in una trave poggiata con carico distribuito

Consideriamo una trave di una certa lunghezza L (misurata in m etri) poggiata ai due estremi su appositi appoggi A e B non solidali con essa (ad esempio un ponticello poggiato sopra due sponde laterali) su cui grava un carico distribuito q , misurato in kg / m.

su cui grava un carico distribuito q , misurato in kg / m. La trave scarica

La trave scarica sui due appoggi A e B una forza totale verso il basso Q pari a q * L . Pertanto essa dovrà essere equilibrata da due forze verso l’alto agli appoggi Va e Vb , cioè Va + Vb = q * L . Considerata la simmetria Va = Vb = q * L / 2 . La trave ai due estremi è quindi sollecitata da una forza verticale chiamata taglio mentre non esiste alcun momento (cioè sollecitazione a rotazione) in quanto la trave non è incastrata agli estremi ma è libera di ruotare (e quindi non subisce alcun momento).

E’ interessante conoscere le sollecitazioni (taglio e momento) su ogni sezione della trave, ad esempio

ad una qualsiasi distanza x dall’estremo A. Separiamo i due pezzi di trave "tagliati " dalla sezione a distanza x , e applichiamo ad esse le azioni che

si scambiavano quando erano unite. Esse sono: una forza parallela alla sezione, che viene detta taglio e

indicata con T , una forza perpendicolare alla sezione, che viene detto sforzo normale ed indicato con

N e da un momento flettente che viene indicato con M.

Ovviamente, gli sforzi che il tratto di destra eserci ta sul tratto di trave di

Ovviamente, gli sforzi che il tratto di destra eserci ta sul tratto di trave di sinistra sono uguali e contrari agli sforzi che il tratto di sinistra esercita su quello di destra (azioni mutue). Per calcolare tali azioni, vanno scritte le 3 equazioni di equilibrio: equilibrio alla traslazione verticale, equil ibrio alla traslazione orizzontale ed equilibrio alla rotazione, ovviamente, possiamo scrivere tali equazioni di equilibrio, dopo avere calcolato le reazioni vincolari Va e Vb . Assumendo che non ci sia sollecitazione orizzontale (cioè la trave non è solle citata alla traslazione orizzontale), dobbiamo scrivere due equazioni di equilibrio: traslazione verticale e rotazione. Considerando il tratto di sinistra della trave di lunghezza x, abbiamo le seguenti equazioni:

EQUAZIONE DEL TAGLIO:

T (x) = Va q * x , cioè alla distanza x dall’appoggio A, vi è una spinta verso il basso che deve controbilanciare, insieme alla porzione di carico distribuito q sulla tratta x , la forza verso l’alto Va . Poiché Va = q * L / 2 , l’equazione del taglio diventa:

T (x) = – q * x + q * L / 2 Tale equazione rappresenta una retta che nell’intervallo [0, L] costituisce il diagramma dei tagli sulla trave. Tale diagramma ha il seguente formato:

tagli sulla trave. Tale diagramma ha il seguente formato: All’estremo A, il taglio ha valore q

All’estremo A, il taglio ha valore q * L / 2 , convenzionalmente di segno positivo; a metà trave il taglio è 0; all’estremo B ha valore q * L / 2 . Dato un qualsiasi x nell’intervallo [0, L], è possibile calcolare il valore del taglio tramite il diagramma.

EQUAZIONE DEL MOMENTO :

M (x) = Va * x q * x * x / 2, cioè alla distanza x dall’appoggio A, vi è una rotazione causata dalla forza in A moltiplicata per il braccio x , spinta verso il basso che deve controbilanciare, insieme al momento generato dalla porzione di carico distribuito q sulla tratta x , il momento generato dalla forza Va moltiplicat a per il braccio x . Si noti che il momento generato dal carico distribuito va calcolato sostituendo il carico distribuito con un carico concentrato q * x posto alla distanza x / 2. Poiché Va = q * L / 2 , l’equazione del momento diventa:

M (x) = – ( q /2 ) x 2 + ( q * L / 2 ) x Tale equazione rappresenta una parabola che nell’intervallo [0, L] costituisce il diagramma dei momenti sulla trave. Tale diagramma ha il seguente formato:

Ai due estremi A e B, il momento è nullo; esso ha il valore massimo

Ai due estremi A e B, il momento è nullo; esso ha il valore massimo di q * L 2 / 8 al centro della trave (cioè per x = L / 2 ), convenzionalmente di segno positivo; a metà trave il taglio è 0; all’estremo B ha valore q * L / 2 . Dato un qualsiasi x nell’intervallo [0, L], è possibile calcolare il valore del momento tramite il diagram ma.

Passiamo ora a presentare un programma che chiede in input la dimensione L della trave (in metri) e il carico distribuito q (in kg / m), calcola le reazioni Va e V b , l’equazione della parabola dei momenti, quella della retta dei tagli, disegna i diagr ammi dei momenti e dei tagli e poi chiede interattivamente se calcolare le sollecitazioni in qualche punto x della trave – per ogni valore introdotto, vengono restituiti i valori del momento e del taglio e viene tracciata sui diagramma la posizione di x .

Il metodo main è il seguente:

public static void main(String[] args) { System.out.println("Diagrammi dei momenti e tagli di una trave poggiata");

// lettura lunghezza e carico distribuito della trave letturaTrave(); // scrittura reazioni agli appoggi, momento massimo e // equazioni di taglio e momento scritturaMomentoTaglio();

dimX = System.graphics.getDimX(); dimY = System.graphics.getDimY();

vectorY_M = new double[dimX+1]; // un valore del momento per ogni X vectorY_T = new double[dimX+1]; // un valore del taglio per ogni X // disegno dei diagrammi dei momenti e dei tagli

System.graphics.clear();

disegnaTrave(); discretizzaPuntiMomentiTagli(); disegnaMomento(); disegnaAsseTaglio(); disegnaTaglio(); // sessione interattiva per il calcolo del momento e taglio in un punto

System.out.print("Momento e taglio in un punto [s/n]?"); char comando = Character.toUpperCase(reader.nextChar()); boolean inizio=true; while ( comando == 'S' ) { if ( !inizio ) { System.graphics.clear();

disegnaTrave();

discretizzaPuntiMomentiTagli();

disegnaMomento();

disegnaAsseTaglio();

disegnaTaglio();

};

inizio=false;

double x = leggiAscissaPunto(); calcolaMomentoTaglioPunto(x); disegnaAssePunto(x);

System.out.print("Momento e taglio in un altro punto [s/n]?");

comando = Character.toUpperCase(reader.nextChar());

};

System.out.println("bye");

}

La variabile booleana inizio serve per evitare di ridisegnare i di agrammi all’inizio; successivamente

vanno ridisegnati per rimuovere la traccia della sezione x disegnata al passo precedente. Lo schema del programma è molto simile a quello del disegno di una parabola. In questo caso

dobbiamo disegnare sia una parabola che una retta contemporaneamente – pertanto dividiamo l’area

di disegno in due parti: in alto il diagramma dei momenti e in basso quello dei tagli. Si noti che,

essendo la retta un caso degenere della parabola, possiamo riutilizzare lo stesso codice. Abbiam o però bisogno di due vettori in cui memorizzare le ordinate della parabola e quelle della retta: vectorY_M e vectorY_T . Lasciamo allo studente il compito di scrivere i metodi e la classe, che comunque è riportata sul sito del corso.

4 . Disegno di una ip erbole

Vogliamo disegnare una iperbole con asintoti paralleli agli assi e con centro di simmetria traslato rispetto all’origine degli assi, descritta dall’equazione Y = (aX+b)/(cX+d) con c 0 e a × d b × c. Il centro di simmetria ha coordinate ( - b/a, b/d ).

In figura la rappresentazione grafica di una iperbole con centro di simmetria (2,2):

grafica di una iperbole con centro di simmetria (2,2): Il metodo main consiste nella lettura dei

Il metodo main consiste nella lettura dei dati dell’iperbole, nella scrittura dei suoi dati (centro di simmetria dove si intersecano i due asintoti e le intersezioni con gli assi) e una sessione interattiva in cui viene chiesto se si vuole disegnare la parabola e, in caso positivo, in quale range dell’asse X. Il main è il seguente:

public static void main(String[] args) { System.out.println("Disegno di una iperbole y = (ax+b)/(cx+d)");

// lettura parametri a, b, c, d dell'iperbole

letturaIperbole();

// scrittura centro simmetria e intersezione dell'iperbole con gli assi

scritturaIperbole();

// sessione interattiva per il disegno della parabola

System.out.print("Vuoi disegnare l'iperbole [s/n]?"); char comando = Character.toUpperCase(reader.nextChar()); while ( comando == 'S' ) {

// Lettura area di disegno: Xmin e Xmax

letturaRangeX (); discretizzaPuntiIperbole();

disegnaAssi();

Lasciamo allo studente il compito di scrivere i metodi e la classe, che comunque è riportata sul sito del corso. E’ importante sottolineare che in prossimità dell’asintoto verticale le ordinate dell’iperbole diventano estremamente elevati in valore assoluto, per cui la operazioni di scalatura potrebbero schiacciare sull’asse X i valori delle altre ordinate. Per ridurre questo inconveniente, nel caso che un valore di X disti dall’asintoto verticale meno di metà del passo di discretizzazione, esso viene distanziato a metà del passo. Tale tecnica è implementata dal seguente metodo

public static double getOrdinata (double ascissa)

{

if ( ascissa <= X_CS && ascissa > X_CS-deltaX/2) ascissa = ascissa -deltaX/2;

else

if ( ascissa > X_CS && ascissa < X_CS+deltaX/2) ascissa = ascissa +deltaX/2; return (a*ascissa+b)/(c*ascissa+d);

}

L ’ asintoto verticale passa per i l punto con ascissa X_CS. Se l ’ ascissa x per cui va calcolata l’ ordinata è molto vicino all ’ asintoto, essa va spostata a sinistra o a destra per mantenerla lontana dall’ assintoto di almeno mezzo passo.