Geometrie/Promítání

Z Wikiknih

< Geometrie(Přesměrováno z Promítání)
Přejít na: navigace, hledání

Obsah

[editovat] Základní promítání

Promítání je transformace, která charakterizuje převod trojrozměrného objektu do dvojrozměrné reprezentace. Při promítání dochází ke ztrátě prostorové informace a tím i k možnému zkreslení názoru pozorovatele na skutečný tvar objektu. Proto jsou pro určité obory vybírány různé způsoby promítání a jsou doplňovány dalšími pravidly a postupy pro zvýšení reálného vjemu promítnutého objektu.

Obecně je promítání určeno středem (směrem) promítání a průmětnou. Pro oba druhy promítání lze volit umístění (obvykle) rovinné průmětny v prostoru. Rovinné projekce dělíme na dvě základní třídy - rovnoběžné(paralelní) a perspektivní.

[editovat] Rovnoběžné promítání

Pokud je střed promítání nevlastní, mluvíme o rovnoběžném promítání a promítací přímky jsou určeny směrem promítání (všechny promítací paprsky mají stejný směr). Rovnoběžné promítání zachovává relativní velikost modelu.

Promitani rovnobezne.png

[editovat] Axonometrie

Patří mezi rovnoběžné promítání. Axonometrické promítání používá projekční roviny, které nejsou rovnoběžné s hlavními osami.

Promitani axonometrie.png

[editovat] Perspektivní promítání

Pokud je střed promítání vlastní, mluvíme o perspektivním promítání a promítací přímky procházejí tímto středem promítání (promítací paprsky vycházejí z jediného bodu). Perspektivní promítání respektuje optický model, který vyjadřuje lidské vidění reálného světa. Modeluje proporcionální změnu předmětů při vzrůstající vzdálenosti od pozorovatele. Poskytuje dobrý prostorový vjem na rovinné průmětně.

Promitani stredove.png

Rozlišujeme tři základní druhy perspektivního promítání:

Jednoúběžníková perspektiva – je určena jedním středem promítání.

Promitani perspektiva 1bodova.png

Dvouúběžníková perspektiva – je určena dvěma středy promítání.

Promitani perspektiva 2bodova.png

Tříúběžníková perspektiva – je určena třemi středy promítání.

Promitani perspektiva 3bodova.png

[editovat] Algoritmizace

Každý druh rovinného promítání charakterizuje určitá transformační matice 4 x 4 pro transformaci bodů [xs; ys; zs; 1] ve scéně na body [xp; yp; zp; 1] v projekční rovině (v homogenních souřadnicích).

Vlastní rovnoběžné a perspektivní promítání lze jednotně popsat dále uvedeným postupem: - posunutí počátku soustavy souřadnic do bodu scény - projekce bodu scény do projekční roviny - zpětné posunutí soustavy souřadnic do původní pozice

Příslušné transformační matice:

- matice posunutí soustavy souřadnic

Promitani matice posunuti.png

- matice středového promítání

Promitani matice stredove.png

- matice axonometrie

Promitani matice axonometrie.png

- matice jednoúběžníkové, dvouúběžníkové, tříúběžníkové projekce vzniknou vynásobením příslušné úbežníkové matice s promítací maticí (v programu použita matice středového promítání). Jednoúběžníková, dvouúběžníková a tříúběžníková matice

Promitani matice perspektivy.png

[editovat] Kód v jazyce C#

[editovat] Pomocné objekty a metody

Výpisy metod a objektů, které byly detailně popsány výše.

public class Bod3D
{
  private float[] souradnice; //pole pro uložení souřadnic
  public Bod3D()
     {   souradnice=new float[3]{0,0,0};   }
  public Bod3D(float x,float y, float z)
     {   souradnice=new float[3]{x,y,z};   }
  public float x {
     get {   return this.souradnice[0];   }
  }
  public float y {
     get {   return this.souradnice[1];   }
  }
  public float z {
     get {   return this.souradnice[2];   }
  }
  public float[] Souradnice {
     get {   return this.souradnice;   }
  }
  public Bod3D NasobeniSkalarem (float f) {
     return new Bod3D(this.x*f,this.y*f,this.z*f); 
  }
  public void Pricti(Bod3D b) {
     this.souradnice[0]+=b.x;this.souradnice[1]+=b.y;this.souradnice[2]+=b.z;
  }
  public float SkalarniSoucin(Bod3D vektor) {
     return souradnice[0]*vektor.souradnice[0]+
            souradnice[1]*vektor.souradnice[1]+
            souradnice[2]*vektor.souradnice[2]; 
  }
  public Bod3D VektorovySoucin(Bod3D v) {
     return new Bod3D(souradnice[1]*v.souradnice[2]-souradnice[2]*v.souradnice[1],
           souradnice[2]*v.souradnice[0]-souradnice[0]*v.souradnice[2],
           souradnice[0]*v.souradnice[1]-souradnice[1]*v.souradnice[0]);
  }
  public Bod3D Normalizovany() {
     float len=(float)Math.Sqrt(this.SkalarniSoucin(this));
     return new Bod3D(souradnice[0]/len,souradnice[1]/len,souradnice[2]/len);
  }
  public static Bod3D operator + (Bod3D a,Bod3D b) {
     return new Bod3D(a.souradnice[0]+b.souradnice[0],
        a.souradnice[1]+b.souradnice[1],a.souradnice[2]+b.souradnice[2]);
  }
  public static Bod3D operator - (Bod3D a,Bod3D b) {
     return new Bod3D(a.souradnice[0]-b.souradnice[0],
           a.souradnice[1]-b.souradnice[1],a.souradnice[2]-b.souradnice[2]);
  }
}

public class Hrana
{
  private int ibod1;private int ibod2;
  private bool orientace;
  public Hrana()   {
     ibod1=0;ibod2=0;orientace=true;
  }
  public Hrana(int indexbodu1,int indexbodu2) {
     ibod1=indexbodu1;ibod2=indexbodu2;orientace=true;
  }
  public Hrana(int indexbodu1,int indexbodu2,bool klasickaorientace) {
     ibod1=indexbodu1;ibod2=indexbodu2;orientace=klasickaorientace;
  }
  public int indexbod1 {
     get {   return ibod1;   }
     set {   ibod1=value;   }
  }
  public int indexbod2 {
     get {   return ibod2;   }
     set {   ibod2=value;   }
  }
  public bool klasickaorientace {
     get {   return orientace;   }
     set {   orientace=value;   }
  }
}

public class Stena
{
   public ArrayList hrany;
   public Stena(){
       hrany=new ArrayList(); 
   }
}

public class Matice
{
  private float [,] hodnoty;
  private int radku;private int sloupcu;
  public Matice(int pocetRadku,int pocetSloupcu){
     hodnoty=new float [pocetRadku,pocetSloupcu];
     radku=pocetRadku;
     sloupcu=pocetSloupcu;
     for(int i=1;i<=radku;i++)
        for(int j=1;j<=sloupcu;j++)
           hodnoty[i-1,j-1]=0f;
  }
  public void NastavRS(int radek,int sloupec,float hodnota){
         hodnoty[radek-1,sloupec-1]=hodnota;   }
  public float VratRS(int radek,int sloupec){   
         return hodnoty[radek-1,sloupec-1];   }
  public int PocetRadku(){
         return radku;   }
  public int PocetSloupcu(){
         return sloupcu;   }
  public static Matice operator *(Matice m1, Matice m2)
     {   if(m1.PocetSloupcu()==m2.PocetRadku())
        {
           Matice ret;
           ret=new Matice(m1.PocetRadku(),m2.PocetSloupcu());
           for (int i=1;i<=m1.PocetRadku();i++)
           for(int j=1;j<=m2.PocetSloupcu();j++){
              float x;x=0;
              for (int k=1;k<=m1.PocetSloupcu();k++)
                 x+=m1.VratRS(i,k)*m2.VratRS(k,j);
              ret.NastavRS(i,j,x); 
           }
           return ret;
        }else return null;
     }
  public static Bod3D operator *(Bod3D bod, Matice m2){
     Matice m1=new Matice(1,4);
     m1.NastavRS(1,1,(float)(bod.x));m1.NastavRS(1,2,(float)(bod.y));
     m1.NastavRS(1,3,(float)(bod.z));m1.NastavRS(1,4,1f);
     Matice x=m1*m2;
     return new Bod3D(x.VratRS(1,1)/x.VratRS(1,4),
        x.VratRS(1,2)/x.VratRS(1,4),x.VratRS(1,3)/x.VratRS(1,4)); 
     }
}

[editovat] Matice promítání

Promítací matice pro popsané typy promítání.

public class MaticePromitani
{
     public MaticePromitani(){
     }
     private double StupenNaRadian(int stupen){
        return (double)(stupen*Math.PI/180);
     }
     public Matice Axonometrie(int azimut,int zenit){
        Matice pom;
        pom=new Matice(4,4);
        pom.NastavRS(1,1,(float)(-1f*(float)(Math.Sin(StupenNaRadian(azimut)))));  
        pom.NastavRS(2,1,(float)((float)(Math.Cos(StupenNaRadian(azimut)))));  
        pom.NastavRS(1,2,(-1f*(float)(Math.Cos(StupenNaRadian(azimut))) *
                  (float)(Math.Cos(StupenNaRadian(zenit))) ));  
        pom.NastavRS(2,2,(float)(-1f*(float)(Math.Sin(StupenNaRadian(azimut)))*
                    (float)(Math.Cos(StupenNaRadian(zenit)))));  
        pom.NastavRS(3,2,(float)((float)(Math.Sin(StupenNaRadian(zenit)))));  
        pom.NastavRS(1,3,(float)((float)(Math.Cos(StupenNaRadian(azimut)))*
                    (float)(Math.Sin(StupenNaRadian(zenit))))); 
        pom.NastavRS(2,3,(float)((float)(Math.Sin(StupenNaRadian(azimut)))*
                    (float)(Math.Sin(StupenNaRadian(zenit)))));  
        pom.NastavRS(3,3,(float)((float) Math.Cos(StupenNaRadian(zenit))));
        pom.NastavRS(4,4,(float)(1f));  
        return pom;   //puvodni
     /*   Matice pom; pom=new Matice(4,4);//zjednodušená verze
        pom.NastavRS(1,1,(float)(-(Math.Cos(StupenNaRadian(azimut)))));  
        pom.NastavRS(2,1,(float)(Math.Sin(StupenNaRadian(azimut))));  
        pom.NastavRS(1,2,(float)(-(Math.Sin(StupenNaRadian(azimut))))*
                   (float)(Math.Sin(StupenNaRadian(zenit))));
        pom.NastavRS(2,2,(float)(-(Math.Cos(StupenNaRadian(azimut))))*
                    (float)(Math.Sin(StupenNaRadian(zenit))));
        pom.NastavRS(3,2,(float)(Math.Cos(StupenNaRadian(zenit))));
        pom.NastavRS(4,4,(float)(1f));  
        return pom; */
     }
     public Matice Posunuti(Bod3D vektor){
        Matice pom;pom=new Matice(4,4);
        pom.NastavRS(1,1,1f);pom.NastavRS(2,2,1f);
        pom.NastavRS(3,3,1f);pom.NastavRS(4,4,1f);
        pom.NastavRS(4,1,-1f*vektor.x);
        pom.NastavRS(4,2,-1f*vektor.y);
        pom.NastavRS(4,3,-1f*vektor.z);
        return pom;
     }
    public Matice Stredove(float distance){
        Matice pom;pom=new Matice(4,4);
        pom.NastavRS(1,1,distance);pom.NastavRS(2,2,distance);
        pom.NastavRS(3,4,1f);pom.NastavRS(4,4,distance);
        return pom;
     }
     public Matice Pespektiva1(float distancez){
        Matice pom;pom=new Matice(4,4);
        pom.NastavRS(1,1,1f);pom.NastavRS(2,2,1f); 
        pom.NastavRS(3,3,1f);pom.NastavRS(4,4,1f); 
        pom.NastavRS(3,4,1/distancez); 
        return pom;
     }
     public Matice Pespektiva2(float distancey,float distancez){
        Matice pom;pom=new Matice(4,4);
        pom.NastavRS(1,1,1f);pom.NastavRS(2,2,1f); 
        pom.NastavRS(3,3,1f);pom.NastavRS(4,4,1f); 
        pom.NastavRS(2,4,1/distancey); 
        pom.NastavRS(3,4,1/distancez);
        return pom;
     }
     public Matice Pespektiva3(float distancex,float distancey,float distancez){
        Matice pom;pom=new Matice(4,4);
        pom.NastavRS(1,1,1f);pom.NastavRS(2,2,1f); 
        pom.NastavRS(3,3,1f);pom.NastavRS(4,4,1f); 
        pom.NastavRS(1,4,1/distancex); 
        pom.NastavRS(2,4,1/distancey); 
        pom.NastavRS(3,4,1/distancez); 
        return pom;
        
     } 
}

[editovat] Středové promítání na válcovou plochu

[editovat] Popis

Jde vlastně o středové promítání na válcovou plochu se středem v počátku soustavy souřadnic. Bodem je proložena přímka procházející počátkem soustavy souřadnic a její průsečík s válcovou plochou je hledaným obrazem.

místo pro obr. projekce_na_valec

Pro vzor v o souřadnicích (x1,y1,z1) platí tedy následující rovnice

Z částečných rovnic přímky procházející počátkem soustavy souřadnic:

x=t \cdot x_1

y=t \cdot y_1

z=t \cdot z_1 (1)

a rovnice válcové plochy se středem v počátku soustavy souřadnic:

x2 + y2 = r2

spočítáme parametr t

t=\frac{r}{\sqrt{x_1^2+y_1^2}}

a po dosazení za parametr t do (1) dostáváme výsledný bod na válcové ploše.

[editovat] Algoritmizace

Pro každý bod zobrazovaného objektu najdeme jeho průsečík s válcovou plochou. Nově nalezený bod (obraz) nahradí svůj vzor a vazby mezi body, hranami a stěnami zůstávají zachovány. Takto získaný model poté můžeme libovolnou metodou promítnout na zobrazovací plochu.

Bod3D 
Třída popisující bod
Cylinder 
Třída popisující Válec a poskytující metody nutné k promítnutí modelu na plochu válce.
Model 
Třída reprezentující stěnový model geometrického objektu

[editovat] Kód v jazyce C#

Příklad řešení v jazyce C#.

[editovat] Pomocné objekty a metody

Ukázka možné implementace třídy Bod3D (pro naše potřeby postačí následující torzo)

public class Bod3D
{
 private float[] souradnice; //pole pro uložení souřadnic
 public Bod3D(float x,float y, float z)
 {
  this.souradnice= new float[3]{x,y,z};
 }
 ...
}

Ukázka možné implementace třídy Cylinder (pro naše potřeby postačí následující torzo)

public class Cylinder
{
 private float radius;
 public Cylinder(float initRadius)
 {
  this.radius = initRadius;
 }
 ...
}

Ukázka možné implementace metody Recording

 public Bod3D Recording(Bod3D mapped)
 {
  float x,y,z;
  x = this.radius*mapped.x/(float)(Math.Sqrt(Math.Pow(mapped.x,2)+Math.Pow(mapped.z,2)));
  y = this.radius*mapped.y/(float)(Math.Sqrt(Math.Pow(mapped.x,2)+Math.Pow(mapped.z,2)));
  z = this.radius*mapped.z/(float)(Math.Sqrt(Math.Pow(mapped.x,2)+Math.Pow(mapped.z,2)));
  return new Bod3D(x,y,z);
 }

[editovat] Vlastní algoritmus

Ukázka možné implementace metody CylindricalProjection

public static Model CylindricalProjection(Cylinder c, Model model)
 {
  Model ret = new Model();
  for(int i=1;i<=model.body.Count;i++)
  {
   Bod3D vzor = (Bod3D)model.body[i];
   Bod3D obraz;
   obraz = c.Recording(vzor);
   ret.body.Add(i,obraz); 
  }
  ret.hrany = model.hrany;
  ret.steny = model.steny;
  return ret;
 }

[editovat] Panoramatické zobrazení

Při zobrazení do roviny můžeme rozvinutím válce získat panoramatický obraz. Z-tová souřadnice předpokládejme, že osou válce je osa z) bodu na válci může určovat y-ovou rozvinutého válce, x-ové souřadnice určíme pomocí úhlů polárních souřadnic bodů válce.

Ukázka možné implementace metody RollOpen

public static Model RollOpen(Cylinder c, Model model)
{
 Model ret = new Model();
 for(int i=1;i<=model.body.Count;i++)
 {
  Bod3D vzor = (Bod3D)model.body[i];
  vzor = Coord.CartesianToPolar(vzor);
  Bod3D obraz;
  float x,y,z;
  float radius = c.radius;
  float aux = (float)Math.PI*radius;
  y = vzor.z;
  x = radius*vzor.y-aux;
  z = vzor.z;
  obraz = new Bod3D(x,y,z);
  ret.body.Add(i,obraz);
 }
 ret.hrany = model.hrany;
 ret.steny = model.steny;
 return ret;
}

[editovat] Středové promítání na kulovou plochu

[editovat] Popis

Jde vlastně o středové promítání na kulovou plochu se středem v počátku soustavy souřadnic. Bodem je proložena přímka procházející počátkem soustavy souřadnic a její průsečík s kulovou plochou je hledaným obrazem.

místo pro obr. projekce_na_kouli

Pro vzor v o souřadnicích (x1,y1,z1) platí tedy následující rovnice

Z částečných rovnic přímky procházející počátkem soustavy souřadnic:

x=t \cdot x_1

y=t \cdot y_1

z=t \cdot z_1 (1)

a rovnice kulové plochy se středem v počátku soustavy souřadnic:

x2 + y2 + z2 = r2

spočítáme parametr t

t=\frac{r}{\sqrt{x_1^2+y_1^2+z_1^2}}

a po dosazení za parametr t do (1) dostáváme výsledný bod na kulové ploše.

[editovat] Algoritmizace

Pro každý bod zobrazovaného objektu najdeme pomocí jeho průsečík s kulovou plochou. Nově nalezený bod (obraz) nahradí svůj vzor a vazby mezi body, hranami a stěnami zůstávají zachovány. Takto získaný model poté můžeme libovolnou metodou promítnout na zobrazovací plochu.

Bod3D 
Třída popisující bod
Sphere 
Třída popisující kouli a poskytující metody nutné k promítnutí modelu na kulovou plochu.
Model 
Třída reprezentující stěnový model geometrického objektu

[editovat] Kód v jazyce C#

Příklad řešení v jazyce C#.

[editovat] Pomocné objekty a metody

Ukázka možné implementace třídy Bod3D (pro naše potřeby postačí následující torzo)

public class Bod3D
{
 private float[] souradnice; //pole pro uložení souřadnic
 public Bod3D(float x,float y, float z)
 {
  this.souradnice= new float[3]{x,y,z};
 }
 ...
}

Ukázka možné implementace třídy Sphere (pro naše potřeby postačí následující torzo)

public class Sphere
{
 private float radius;
 public Sphere(float initRadius)
 {
  this.radius = initRadius;
 }
 ...
}

Ukázka možné implementace metody Recording

 public Bod3D Recording(Bod3D mapped)
 {
  float aux = this.radius/(float)(Math.Sqrt(Math.Pow(mapped.x,2)+Math.Pow(mapped.y,2)+
               Math.Pow(mapped.z,2))); 
  float x,y,z;
  x = mapped.x*aux;
  y = mapped.y*aux;
  z = mapped.z*aux;
  return new Bod3D(x,y,z);
 }

[editovat] Vlastní algoritmus

Ukázka možné implementace metody SphericalProjection

public static Model SphericalProjection(Sphere s, Model model)
{
 Model ret = new Model();
 for(int i=1;i<=model.body.Count;i++)
 {
  Bod3D vzor = (Bod3D)model.body[i];
  Bod3D obraz;
  obraz = s.Recording(vzor);
  ret.body.Add(i,obraz); 
 }
 ret.hrany = model.hrany;
 ret.steny = model.steny;
 return ret;
}

[editovat] Autoři

Tento text vypracovali studenti Univerzity Palackého v Olomouci katedry Matematické informatiky jako součást zápočtového úkolu do předmětu Počítačová geometrie.