This is old C++ code originally intended to be a playground for 3D math.
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

#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&auml;lt w&auml;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&auml;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&auml;lt jetzt die aktuellen Vertexindizies,
// f&uuml;r den n&auml;chsten durchlauf mu&szlig; 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);
}
}