You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
234 lines
7.3 KiB
234 lines
7.3 KiB
#include "polygon.h"
|
|
|
|
void polygon::_init_normal_(void) {
|
|
if(vl && count>0) {
|
|
for(unsigned i=0; i<count; i++) {
|
|
center[O_X]+=(*vl)[content[i]][O_X];
|
|
center[O_Y]+=(*vl)[content[i]][O_Y];
|
|
center[O_Z]+=(*vl)[content[i]][O_Z];
|
|
}
|
|
|
|
center[X]=center[O_X]/=count;
|
|
center[Y]=center[O_Y]/=count;
|
|
center[Z]=center[O_Z]/=count;
|
|
center[W]=center[O_W]=1;
|
|
|
|
normal=center+
|
|
(((*vl)[content[1]]-(*vl)[content[0]])|
|
|
((*vl)[content[count-1]]-(*vl)[content[0]])).norm();
|
|
}
|
|
else {
|
|
center=vertex();
|
|
normal=vertex();
|
|
}
|
|
}
|
|
|
|
void polygon::transform(const Mmn<double>& tm, int p) {
|
|
for(unsigned i=0; i<count; i++) {
|
|
(*vl)[content[i]].transform(tm, p);
|
|
}
|
|
|
|
transform_normal(tm, p);
|
|
}
|
|
|
|
void polygon::transform_normal(const Mmn<double>& tm, int p) {
|
|
center.transform(tm, p);
|
|
normal.transform(tm, p);
|
|
}
|
|
|
|
void polygon::reset(void) {
|
|
/* for(unsigned i=0; i<count; i++) {
|
|
(*vl)[content[i]].reset();
|
|
}*/
|
|
|
|
center.reset();
|
|
normal.reset();
|
|
}
|
|
|
|
/**
|
|
* \brief Clipping gegen eine vordere Z-Ebene
|
|
*
|
|
* Dieser Algorithmus clippt das polygon gegen eine vordere Z-Ebene
|
|
*
|
|
* \param this Das ungeclippte unprojezierte Polygon.
|
|
* \return ein geclipptes Polygon.
|
|
*/
|
|
polygon polygon::clip_front_z(double min_Z) const {
|
|
container<unsigned> clip;
|
|
polygon ret;
|
|
|
|
for(unsigned j=0; j<(*this).card(); j++) {
|
|
double x0=(*vl)[container<unsigned>::operator[](j)][X],
|
|
y0=(*vl)[container<unsigned>::operator[](j)][Y],
|
|
z0=(*vl)[container<unsigned>::operator[](j)][Z],
|
|
x1=(*vl)[container<unsigned>::operator[]((j+1)%(*this).card())][X],
|
|
y1=(*vl)[container<unsigned>::operator[]((j+1)%(*this).card())][Y],
|
|
z1=(*vl)[container<unsigned>::operator[]((j+1)%(*this).card())][Z];
|
|
|
|
// Wenn beide drin sind den zweiten übernehmen.
|
|
if(z0>min_Z && z1>min_Z)
|
|
// Nur P2 nach clip übernehmen
|
|
clip[clip.card()]=
|
|
container<unsigned>::operator[]((j+1)%(*this).card());
|
|
|
|
// Wenn nur P2 drin ist
|
|
if(z0<=min_Z && z1>min_Z) {
|
|
// Schnittpunkt berechnen und nach temp übernehmen
|
|
unsigned idx=(*vl).card();
|
|
double t=(min_Z-z0)/(z1-z0);
|
|
double x=x0+t*(x1-x0);
|
|
double y=y0+t*(y1-y0);
|
|
|
|
// neuen Vertex zur Vertexliste.
|
|
(*vl)[idx]=vertex(x, y, min_Z, COORD);
|
|
|
|
// und ins geclippte polygon
|
|
clip[clip.card()]=idx;
|
|
// und P2 ins geclippte polygon
|
|
clip[clip.card()]=
|
|
container<unsigned>::operator[]((j+1)%(*this).card());
|
|
}
|
|
|
|
// Wenn nur P1 drin ist
|
|
if(z0>min_Z && z1<=min_Z) {
|
|
// Schnittpunkt berechnen und nach temp übernehmen
|
|
unsigned idx=(*vl).card();
|
|
double t=(min_Z-z1)/(z0-z1);
|
|
double x=x1+t*(x0-x1);
|
|
double y=y1+t*(y0-y1);
|
|
|
|
// neuen Vertex zur Vertexliste.
|
|
(*vl)[idx]=vertex(x, y, min_Z, COORD);
|
|
|
|
// und ins geclippte polygon
|
|
clip[clip.card()]=idx;
|
|
}
|
|
}
|
|
|
|
// Das geclippte Polygon zurückliefern.
|
|
ret=polygon(clip, vl);
|
|
ret.set_id(id);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* \brief Clippings nach Sutherland-Hodgman
|
|
*
|
|
* Cliped das Polygon an dem Polygon p. Es wird ein neues Polygon
|
|
* erzeugt, das diesem Polygon innerhalb des Polygons p entspricht.
|
|
* Dieses neue Polygon nutzt die selbe Vertexliste.
|
|
*
|
|
* \param p Das Polygon an dem geclipped werden soll.
|
|
* \returns Ein in p passendes Polygon.
|
|
*/
|
|
polygon polygon::clip_2d(const polygon& p) const {
|
|
//! enthält während des clippings die aktuellen
|
|
//! Vertex_listen indizies.
|
|
container<unsigned> clip;
|
|
|
|
// Zuerst Origialdaten sichern.
|
|
clip=(container<unsigned>)*this;
|
|
|
|
// Solange unbearbeitete Kanten im Clippolygon sind...
|
|
for(unsigned i=0; i<p.card(); i++) {
|
|
//! enthält immer die neuen geclippten VL-Indizies
|
|
container<unsigned> temp;
|
|
|
|
//! Hole nächste Kante des Clippolygons und sichere sie als
|
|
//! Vektor. Diese ist definiert über die beiden Punkte
|
|
//! p[i] und p[(i+1)%p.card()]
|
|
double x0=p[i][X],
|
|
y0=p[i][Y],
|
|
x1=p[(i+1)%p.card()][X],
|
|
y1=p[(i+1)%p.card()][Y];
|
|
|
|
// Jetzt muss zunaechst ein Vektor erzeugt werden der senkrecht
|
|
// von der Kante ins Poligon zeigt
|
|
// chk=(X=P1.Y-P2.Y, Y=P2.X-P1.X, 0)
|
|
vertex chk(y0-y1, x1-x0, 0, VEKTOR);
|
|
|
|
// Solange Kanten nicht bearbeitet wurden
|
|
for(unsigned j=0; j<clip.card(); j++) {
|
|
//! hole nächste Kante aus clipped Prüfe ob Punkt1 und/oder
|
|
//! Punkt2 immerhalb des Clippolygons sind.
|
|
//! Kante ist (*vl)[clip[j]] und (*vl)[clip[(j+1)%clip.count]]
|
|
double x0s=(*vl)[clip[j]][X],
|
|
y0s=(*vl)[clip[j]][Y],
|
|
x1s=(*vl)[clip[(j+1)%clip.card()]][X],
|
|
y1s=(*vl)[clip[(j+1)%clip.card()]][Y];
|
|
|
|
//! Liegt der erste Punkt innerhalb des Clippolygons
|
|
//! chk%(P1 - clipP1) > 0.05 und/oder
|
|
double chk_p1=chk%((*vl)[clip[j]] - (*p.vl)[i]);
|
|
//! liegt der zweite Punkt innerhalb des Clippolygons
|
|
//! chk%(P2 - clipP1) > 0.05
|
|
double chk_p2=chk%((*vl)[clip[(j+1)%clip.card()]] -
|
|
(*p.vl)[i]);
|
|
|
|
// 0.05 ist ein Epsilon um Ungenauigkeiten auszugleichen und
|
|
// ganz sicher zu gehen das der Punkt wirklich innerhalb liegt.
|
|
|
|
// Wenn beide drin sind
|
|
if(chk_p1>0.05 && chk_p2>0.05)
|
|
// Nur P2 nach temp übernehmen
|
|
temp[temp.card()]=clip[(j+1)%clip.card()];
|
|
|
|
// Wenn nur P1 drin ist
|
|
if(chk_p1>0.05 && chk_p2<=0.05) {
|
|
// Schnittpunkt berechnen und nach temp übernehmen
|
|
unsigned idx=(*vl).card();
|
|
double x,y;
|
|
|
|
x=x0+((((x1s-x0s)*(y0-y0s))+((y1s-y0s)*(x0s-x0)))/
|
|
(((x1-x0)*(y1s-y0s))-((y1-y0)*(x1s-x0s))))*(x1-x0);
|
|
|
|
y=y0+((((x1s-x0s)*(y0-y0s))+((y1s-y0s)*(x0s-x0)))/
|
|
(((x1-x0)*(y1s-y0s))-((y1-y0)*(x1s-x0s))))*(y1-y0);
|
|
|
|
// neuen Vertex zur Vertexliste.
|
|
(*vl)[idx]=vertex(x, y, 0, COORD);
|
|
|
|
temp[temp.card()]=idx;
|
|
}
|
|
|
|
// Wenn nur P2 drin ist
|
|
if(chk_p1<=0.05 && chk_p2>0.05) {
|
|
// Schnittpunkt berechnen und nach temp übernehmen
|
|
unsigned idx=(*vl).card();
|
|
double x,y;
|
|
|
|
x=x0+((((x1s-x0s)*(y0-y0s))+((y1s-y0s)*(x0s-x0)))/
|
|
(((x1-x0)*(y1s-y0s))-((y1-y0)*(x1s-x0s))))*(x1-x0);
|
|
|
|
y=y0+((((x1s-x0s)*(y0-y0s))+((y1s-y0s)*(x0s-x0)))/
|
|
(((x1-x0)*(y1s-y0s))-((y1-y0)*(x1s-x0s))))*(y1-y0);
|
|
|
|
// neuen Vertex zur Vertexliste.
|
|
(*vl)[idx]=vertex(x, y, 0, COORD);
|
|
|
|
temp[temp.card()]=idx;
|
|
|
|
// P2 nach temp übernehmen
|
|
temp[temp.card()]=clip[(j+1)%clip.card()];
|
|
}
|
|
|
|
// Wenn keiner drin ist
|
|
// Nichts nach temp
|
|
}
|
|
|
|
// temp enthält jetzt die aktuellen Vertexindizies,
|
|
// für den nächsten durchlauf muß clip
|
|
// darauf gesetzt werden.
|
|
clip=temp;
|
|
}
|
|
|
|
// Das geclippte Polygon zurückliefern.
|
|
return polygon(clip, vl);
|
|
}
|
|
|
|
void polygon::project_2d(double lcx, double sw, double sh,
|
|
double ph_ar, double sy, int p) {
|
|
for(unsigned i=0; i<count; i++) {
|
|
(*vl)[content[i]].project_2d(lcx, sw, sh, ph_ar, sy, p);
|
|
}
|
|
}
|