00001
00002
00003 00004 00005 00006 00007 00008 00009 00010 00011 00012 00013 00014 00015 00016 00017 00018 00019
00020
00021 #include <assert.h>
00022
00023 #include "IGPolygon.h"
00024
00025 IGPolygon::IGPolygon(
00026 ) :
00027 okForOpenGL(false)
00028 {
00029 }
00030
00031 IGPolygon::IGPolygon(
00032 const IGPolygon& P
00033 ) :
00034 corners(P.corners),
00035 center(P.center),
00036 normal(P.normal),
00037 okForOpenGL(P.okForOpenGL)
00038 {
00039 }
00040
00041 IGPolygon::~IGPolygon(
00042 ) {
00043 }
00044
00045 IGPolygon& IGPolygon::operator=(
00046 const IGPolygon& P
00047 ) {
00048 if(this!=&P) {
00049 corners =P.corners;
00050 center =P.center;
00051 normal =P.normal;
00052 okForOpenGL=P.okForOpenGL;
00053 }
00054 return(*this);
00055 }
00056
00057 void IGPolygon::CheckForOpenGL(
00058 ) {
00059 okForOpenGL=false;
00060
00061
00062 if(corners.size()<3) return;
00063 ComputeCenter();
00064 if(ComputeNormal()) {
00065 if(PointsInPlane()) {
00066 list<point> L;
00067 IGPoint p;
00068
00069
00070 if(fabs(normal[0])>=fabs(normal[1])&&
00071 fabs(normal[0])>=fabs(normal[2])) {
00072
00073 forall(p,corners) L.append(p.project_yz());
00074 }
00075 else if(fabs(normal[1])>=fabs(normal[0])&&
00076 fabs(normal[1])>=fabs(normal[2])) {
00077
00078 forall(p,corners) L.append(p.project_xz());
00079 }
00080 else {
00081
00082 forall(p,corners) L.append(p.project_xy());
00083 }
00084 if(IsSimpleAndConvex(L)) okForOpenGL=true;
00085 else {
00086 cout << "non simple-and-convex polygon found\n";
00087 }
00088 }
00089 }
00090 }
00091
00092 double IGPolygon::ComputeArea(
00093 const list<point>& L
00094 ) const {
00095 double area(0.0);
00096 list_item it(L.first());
00097 list_item jt(L.succ(it));
00098
00099 for(int i(L.size()); i>0; i--) {
00100 area+=L[it].xcoord()*L[jt].ycoord()-L[jt].xcoord()*L[it].ycoord();
00101 it=jt;
00102 jt=L.cyclic_succ(jt);
00103 }
00104 return area;
00105 }
00106
00107 void IGPolygon::ComputeCenter(
00108 ) {
00109 assert(!corners.empty());
00110 IGPoint p;
00111 d3_point o;
00112
00113 forall(p,corners) o=o+p.to_vector();
00114 center=d3_point(o.to_vector()*(1.0/corners.size()));
00115 }
00116
00117 bool IGPolygon::ComputeNormal(
00118 ) {
00119 IGPoint p;
00120 list<point> P;
00121
00122 forall(p,corners) P.append(p.project_xy());
00123 double A_xy(ComputeArea(P));
00124
00125 P.clear();
00126 forall(p,corners) P.append(p.project_xz());
00127 double A_xz(ComputeArea(P));
00128
00129 P.clear();
00130 forall(p,corners) P.append(p.project_yz());
00131 double A_yz(ComputeArea(P));
00132
00133
00134
00135 double epsilon(0.0001);
00136 if(fabs(A_xy)<epsilon&&
00137 fabs(A_xz)<epsilon&&
00138 fabs(A_yz)<epsilon
00139 ) {
00140 cout << "polygon with almost zero normal found\n";
00141 return false;
00142 }
00143
00144 normal=vector(A_yz,-A_xz,A_xy).norm();
00145 return true;
00146 }
00147
00148 void IGPolygon::Draw(
00149 ) const {
00150 glBegin(GL_POLYGON);
00151 IGPoint p;
00152
00153 forall(p,corners) p.Draw();
00154 glEnd();
00155 }
00156
00157 bool IGPolygon::IsBitonic(
00158 const list<double>& L
00159 ) const {
00160
00161 list_item it(L.min());
00162 list_item jt;
00163 bool up(true);
00164
00165 for(int i(L.size()); i>0; i--) {
00166 jt=L.cyclic_succ(it);
00167 if(up) {
00168 if(L[jt]<L[it]) up=false;
00169 }
00170 else if(L[jt]>L[it]) return false;
00171 it=L.cyclic_succ(it);
00172 }
00173 return true;
00174 }
00175
00176 bool IGPolygon::IsSimpleAndConvex(
00177 const list<point>& L
00178 ) const {
00179 list<double> C;
00180 point p;
00181
00182
00183 forall(p,L) C.append(p.xcoord());
00184 if(!IsBitonic(C)) return false;
00185 C.clear();
00186 forall(p,L) C.append(p.ycoord());
00187 if(!IsBitonic(C)) return false;
00188 return true;
00189 }
00190
00191 bool IGPolygon::PointsInPlane(
00192 ) const {
00193 IGPoint p;
00194 forall(p,corners) {
00195
00196
00197 if(fabs(normal*(p.to_vector()-center.to_vector()))>0.001) {
00198 cout << "corners are not sufficiently close to the plane\n";
00199 return false;
00200 }
00201 }
00202 return true;
00203 }
00204
00205 istream& operator>>(
00206 istream& in,
00207 IGPolygon& P
00208 ) {
00209 int n;
00210 IGPoint p;
00211
00212 P.corners.clear();
00213 P.okForOpenGL=false;
00214 in >> n;
00215 assert(n>0);
00216 for(int i(0); i<n; i++) {
00217 in >> p;
00218 P.corners.append(p);
00219 }
00220 P.CheckForOpenGL();
00221 return(in);
00222 }
00223
00224 ostream& operator<<(
00225 ostream& out,
00226 const IGPolygon& P
00227 ) {
00228 out << "Polygon: " << P.corners.size() << endl;
00229 out << "okForOpenGL: " << P.okForOpenGL << endl;
00230 out << "center: " << P.center << endl;
00231 out << "normal: " << P.normal << endl;
00232 IGPoint p;
00233 forall(p,P.corners) out << p;
00234 return(out);
00235 }
00236