Geometrie/Promítání
Základní promítání
editovatPromí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í.
Rovnoběžné promítání
editovatPokud 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.
Axonometrie
editovatPatří mezi rovnoběžné promítání. Axonometrické promítání používá projekční roviny, které nejsou rovnoběžné s hlavními osami.
Perspektivní promítání
editovatPokud 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ě.
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í.
Dvouúběžníková perspektiva – je určena dvěma středy promítání.
Tříúběžníková perspektiva – je určena třemi středy promítání.
Algoritmizace
editovatKaždý druh rovinného promítání charakterizuje určitá transformační matice 4 x 4 pro transformaci bodů ve scéně na body 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
- matice středového promítání
- matice axonometrie
- 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
Kód v jazyce C#
editovatPomocné objekty a metody
editovatVý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));
}
}
Matice promítání
editovatPromí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;
}
}
Středové promítání na válcovou plochu
editovatPopis
editovatJde 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 ( ) platí tedy následující rovnice
Z částečných rovnic přímky procházející počátkem soustavy souřadnic:
(1)
a rovnice válcové plochy se středem v počátku soustavy souřadnic:
spočítáme parametr
a po dosazení za parametr do (1) dostáváme výsledný bod na válcové ploše.
Algoritmizace
editovatPro 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
Kód v jazyce C#
editovatPříklad řešení v jazyce C#.
Pomocné objekty a metody
editovatUká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);
}
Vlastní algoritmus
editovatUká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;
}
Panoramatické zobrazení
editovatPř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;
}
Středové promítání na kulovou plochu
editovatPopis
editovatJde 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 ( ) platí tedy následující rovnice
Z částečných rovnic přímky procházející počátkem soustavy souřadnic:
(1)
a rovnice kulové plochy se středem v počátku soustavy souřadnic:
spočítáme parametr
a po dosazení za parametr do (1) dostáváme výsledný bod na kulové ploše.
Algoritmizace
editovatPro 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
Kód v jazyce C#
editovatPříklad řešení v jazyce C#.
Pomocné objekty a metody
editovatUká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);
}
Vlastní algoritmus
editovatUká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;
}
Autoři
editovatTento 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.