Avatar billede sion Nybegynder
15. april 2003 - 14:25 Der er 5 kommentarer og
1 løsning

Skalering

Jeg sidder og kokser over et problem ved et eksamensprojekt i programmering (HTX). Mit projekt består af en java-applet der skal kunne tegne en graf ud fra en række givne koordinatsæt. Disse koordinatsæt læses fra den html-fil som appletten kaldes fra. Mit problem er det at jeg skal have skaleret koordinatsættene så de passer indenfor appletten. Hvis appletten f.eks. er 500 pixels i bredden nytter det jo ikke noget at et punkt på grafen bliver placeret i x = 700.
Derfor har jeg sammenkogt følgende metoder til udregning af nye koordinatsæt i forhold til applettens størrelse:

int Xpos[] = {50,100,200,300,400,500,600,700,800,900,1000};
int Ypos[] = {15,30,70,130,150,170,190,230,140,100,70};

Ypos = GraphFunc.SkaleYakse(Ypos,getHeight());
Xpos = GraphFunc.SkaleXakse(Xpos, getWidth());

g.drawPolyline(Xpos,Ypos,Xpos.length);

       
/* Fra classen GraphFunc.java */
public class GraphFunc {
   
  public static int FindMax(int GrafArray[]) {
    int Max = GrafArray[0];
    for (int Taeller = 0; Taeller < GrafArray.length; Taeller++) {
      if (GrafArray[Taeller] > Max) {
          Max = GrafArray[Taeller];
      }
    }
    return Max;
  }
 
  public static int FindMin(int GrafArray[]) {
    int Min = GrafArray[0];
    for (int Taeller = 0; Taeller < GrafArray.length; Taeller++) {
      if (GrafArray[Taeller] < Min) {
          Min = GrafArray[Taeller];
      }
    }
    return Min;
  }
 
  public static int[] SkaleXakse(int GrafArray[], int MaxX) {
    int ArrayMax = FindMax(GrafArray);
    int SkaleringsForhold = MaxX / ArrayMax;
   
    for (int Taeller = 0; Taeller < GrafArray.length; Taeller++) {
      GrafArray[Taeller] = GrafArray[Taeller] * (MaxX / ArrayMax);//SkaleringsForhold;
    }
    return GrafArray;
  }
 
  public static int[] SkaleYakse(int GrafArray[], int MaxY) {
    int ArrayMax = FindMax(GrafArray);
    int SkaleringsForhold = MaxY / ArrayMax;
   
    for (int Taeller = 0; Taeller < GrafArray.length; Taeller++) {
      GrafArray[Taeller] = MaxY-(GrafArray[Taeller] * (MaxY / ArrayMax));//SkaleringsForhold);
    }
    return GrafArray;
  }
 
}

...men det fungere ikke helt ordentligt. Nogle gange bliver grafen for lav og nogle gange for smal. Jeg tror måske det skyldes min brug at int-variablen - dette skyldes at jeg benytter drawPolyline til at tegne grafen med, og den håndtere kun int-værdier.
Jeg har sat "Skaleringsforhold" i kommentar, da det er en int. I stedet ganges en double nu direkte på en int uden at resultere i fejl og det burde give en gyldig int-værdi, men det kan godt være at fejlen ligger her.
Mit spørgsmål lyder: Har jeg lavet en fejl, og hvis ja, hvor består den så i? ...eller: Hvordan kan jeg lave en skaleringsmetode der virker?
-Sion

PS. I må undskylde hvis det er et simpelt spørgsmå, men jeg er ikke så sej til Java...
Avatar billede conrad Nybegynder
15. april 2003 - 17:40 #1
Umiddelbart vil jeg mene at din skalering er OK. Grunden til at din graf bliver for lav eller for smal kan være at du skalerer  X og Y akse uafhængigt af hinanden. Hvis du vil skalere så grafen bare bliver "formindsket" så skal du bruge samme skaleringsforhold på begge akser.  Jeg gætter på at dit maxX og MaxY giver de max værdier du kan tegne. Prøv at kalde

SkaleXakse(int GrafArray[], Math.min(xMax,yMax))
SkaleYakse(int GrafArray[], Math.min(xMax,yMax))
Avatar billede sion Nybegynder
15. april 2003 - 17:46 #2
Jeg har ikke kunne få dit foreslag til at virke, men det gør ikke noget at akserne bliver skaleret uafhængigt af hinanden, tallene i array'ene skal bare skaleres så de alle ligger indenfor applettens højde og bredde. Jeg har forsøgt at bruge "scale"-metoden i stedet, men så bliver grafikken bare "streched" eller trukket ud så det passer med skaleringen...
Avatar billede conrad Nybegynder
15. april 2003 - 18:30 #3
prøv lige med

Ypos = GraphFunc.SkaleYakse(Ypos,Math.min(getHeight(),getWidth())  );
Xpos = GraphFunc.SkaleXakse(Xpos, Math.min(getHeight(),getWidth()));
Avatar billede conrad Nybegynder
15. april 2003 - 18:53 #4
fik lige kigget lidt mere på det. Du er selv inde på problemet omkring double.

Jeg vil foreslå du arbejder med doubles som her :
/* Fra classen GraphFunc.java */
public class GraphFunc {
   
  public static double FindMax(double GrafArray[]) {
    double Max = GrafArray[0];
    for (int Taeller = 0; Taeller < GrafArray.length; Taeller++) {
      if (GrafArray[Taeller] > Max) {
          Max = GrafArray[Taeller];
      }
    }
    return Max;
  }
 
  public static double FindMin(double GrafArray[]) {
    double Min = GrafArray[0];
    for (int Taeller = 0; Taeller < GrafArray.length; Taeller++) {
      if (GrafArray[Taeller] < Min) {
          Min = GrafArray[Taeller];
      }
    }
    return Min;
  }
 
  public static double[] SkaleXakse(double GrafArray[], double MaxX) {
    double ArrayMax = FindMax(GrafArray);
    double SkaleringsForhold = MaxX / ArrayMax;
   
    for (int Taeller = 0; Taeller < GrafArray.length; Taeller++) {
      GrafArray[Taeller] = GrafArray[Taeller] * (MaxX / ArrayMax);//SkaleringsForhold;
    }
    return GrafArray;
  }
 
  public static double[] SkaleYakse(double GrafArray[], double MaxY) {
    double ArrayMax = FindMax(GrafArray);
    double SkaleringsForhold = MaxY / ArrayMax;
   
    for (int Taeller = 0; Taeller < GrafArray.length; Taeller++) {
      GrafArray[Taeller] = MaxY-(GrafArray[Taeller] * (MaxY / ArrayMax));//SkaleringsForhold);
    }
    return GrafArray;
  }
 
    public static void main(String args[])
    {
        double Xpos[] = {50.0,100.0,200.0,300.0,400.0,500.0,600.0,700.0,800.0,900.0,1000.0};
        double Ypos[] = {15.0,30.0,70.0,130.0,150.0,170.0,190.0,230.0,140.0,100.0,70.0};

        Ypos = GraphFunc.SkaleYakse(Ypos,200.0);
        Xpos = GraphFunc.SkaleXakse(Xpos, 300.0);
       
        for(int i = 0;i<Xpos.length;i++)
        {
            System.out.println(Xpos[i] +", " +Ypos[i]);   
        }
       
        int j = 100/200;
        System.out.println("j: "+j);
        double n1 = 234.56;
        int n2 = (int) n1;
        System.out.println("n1:"+ n1+"n2: "+n2);
       
    }
}

og så konvertere til int når du skal tegne
Avatar billede conrad Nybegynder
15. april 2003 - 19:03 #5
grunden er at MaxY / ArrayMax afrundes til et heltal.
Feks 0 hvis ArrayMax > MaxY.
Avatar billede sion Nybegynder
16. april 2003 - 19:26 #6
conrad, du er simpelthen min redningsmand! Mange tak! Det virker helt perfekt, hvilket betyder at jeg alligvel kan blive færdig med projektet - jeg har satme brugt mange timer på at hive mig i håret over det her problem. Takker ydmygst mange gange for din uvurderlige hjælpe!
MVH Sion
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester