JWS C++ Library
C++ language utility library
polygon.cpp
Go to the documentation of this file.
00001 /*
00002  * This work is licensed under a Creative Commons 
00003  * Attribution-Noncommercial-Share Alike 3.0 United States License.
00004  * 
00005  *    http://creativecommons.org/licenses/by-nc-sa/3.0/us/
00006  * 
00007  * You are free:
00008  * 
00009  *    to Share - to copy, distribute, display, and perform the work
00010  *    to Remix - to make derivative works
00011  * 
00012  * Under the following conditions:
00013  * 
00014  *    Attribution. You must attribute the work in the manner specified by the
00015  *    author or licensor (but not in any way that suggests that they endorse you
00016  *    or your use of the work).
00017  * 
00018  *    Noncommercial. You may not use this work for commercial purposes.
00019  * 
00020  *    Share Alike. If you alter, transform, or build upon this work, you may
00021  *    distribute the resulting work only under the same or similar license to
00022  *    this one.
00023  * 
00024  * For any reuse or distribution, you must make clear to others the license
00025  * terms of this work. The best way to do this is by including this header.
00026  * 
00027  * Any of the above conditions can be waived if you get permission from the
00028  * copyright holder.
00029  * 
00030  * Apart from the remix rights granted under this license, nothing in this
00031  * license impairs or restricts the author's moral rights.
00032  */
00033 
00034 
00047 #include <jwsc++/config.h>
00048 #include <jwsc/config.h>
00049 
00050 #include <cassert>
00051 #include <cmath>
00052 #include <iostream>
00053 #include <vector>
00054 
00055 #include <inttypes.h>
00056 
00057 #if defined JWSCXX_HAVE_OPENGL
00058 #include <GL/gl.h>
00059 #elif defined JWSCXX_HAVE_OPENGL_FRAMEWORK
00060 #include <OpenGL/gl.h>
00061 #endif
00062 
00063 #include <jwsc/base/bits.h>
00064 #include <jwsc/vector/vector.h>
00065 #include <jwsc/vector/vector_math.h>
00066 #include <jwsc/matrix/matrix.h>
00067 #include <jwsc/matrix/matrix_math.h>
00068 
00069 #include "jwsc++/base/exception.h"
00070 #include "jwsc++/graphics/camera.h"
00071 #include "jwsc++/graphics/polygon.h"
00072 
00073 #ifdef JWSCXX_HAVE_DMALLOC
00074 #include <dmalloc.h>
00075 #endif
00076 
00077 
00078 using namespace jwscxx::base;
00079 using namespace jwscxx::graphics;
00080 
00081 
00083 Polygon_f::Polygon_f()
00084 {
00085     normal = 0;
00086     centroid = 0;
00087     normal_flipped = 0;
00088     id = generate_id();
00089 }
00090 
00091 
00098 Polygon_f::Polygon_f(uint32_t N)
00099 {
00100     pts.reserve(N);
00101     normal = 0;
00102     centroid = 0;
00103     normal_flipped = 0;
00104     id = generate_id();
00105 }
00106 
00107 
00109 Polygon_f::Polygon_f(const Polygon_f& p)
00110     : pts(p.pts.capacity())
00111 {
00112     normal = 0;
00113     centroid = 0;
00114     *this = p;
00115 }
00116 
00117 
00126 Polygon_f::Polygon_f(const char* fname) 
00127     throw (jwscxx::base::Arg_error, jwscxx::base::IO_error)
00128 {
00129     normal = 0;
00130     centroid = 0;
00131     normal_flipped = 0;
00132 
00133     jwscxx::base::Readable::read(fname);
00134 }
00135 
00136 
00145 Polygon_f::Polygon_f(std::istream& in) 
00146     throw (jwscxx::base::Arg_error, jwscxx::base::IO_error)
00147 {
00148     normal = 0;
00149     centroid = 0;
00150     normal_flipped = 0;
00151 
00152     read(in);
00153 }
00154 
00155 
00157 Polygon_f::~Polygon_f()
00158 {
00159     free_vector_f(normal);
00160     free_vector_f(centroid);
00161 
00162     for (size_t i = 0; i < pts.size(); i++)
00163     {
00164         free_vector_f(pts[ i ]);
00165     }
00166 }
00167 
00168 
00176 Polygon_f& Polygon_f::operator= (const Polygon_f& p)
00177 {
00178     using namespace std;
00179     using namespace jwsc;
00180 
00181     size_t n = pts.size();
00182     size_t N = p.pts.size();
00183 
00184     if (n > N)
00185     {
00186         for (size_t i = N; i < n; i++)
00187         {
00188             free_vector_f(pts[ i ]);
00189         }
00190         pts.erase(pts.begin() + N, pts.end());
00191     }
00192     else
00193     {
00194         pts.reserve(N);
00195     }
00196 
00197     for (size_t i = 0; i < N; i++)
00198     {
00199         if (i < n)
00200         {
00201             copy_vector_f(&(pts[ i ]), p.pts[ i ]);
00202         }
00203         else
00204         {
00205             Vector_f* pt = 0;
00206             copy_vector_f(&pt, p.pts[ i ]);
00207             pts.push_back(pt);
00208         }
00209     }
00210 
00211     if (p.normal)
00212     {
00213         copy_vector_f(&normal, p.normal);
00214     }
00215     if (p.centroid)
00216     {
00217         copy_vector_f(&centroid, p.centroid);
00218     }
00219 
00220     normal_flipped = p.normal_flipped;
00221 
00222     id = p.id;
00223 
00224     return *this;
00225 }
00226 
00227 
00229 Polygon_f* Polygon_f::clone() const
00230 {
00231     return new Polygon_f(*this);
00232 }
00233 
00234 
00241 void Polygon_f::read(std::istream& in) throw (jwscxx::base::IO_error,
00242         jwscxx::base::Arg_error)
00243 {
00244     using namespace jwsc;
00245 
00246     in.read((char*)&id, sizeof(uint32_t));
00247     if (in.fail() || in.eof())
00248     {
00249         throw IO_error("Could not read id");
00250     }
00251 #ifndef JWSC_BIGENDIAN
00252     bswap_u32(&(id));
00253 #endif
00254 
00255     assert(sizeof(float) == sizeof(uint32_t));
00256 
00257     float x, y, z, w;
00258 
00259     // Number of points.
00260     uint32_t N;
00261 
00262     in.read((char*)&N, sizeof(uint32_t));
00263     if (in.fail() || in.eof())
00264     {
00265         throw IO_error("Could not read number of points");
00266     }
00267 
00268 #ifndef JWSC_BIGENDIAN
00269     bswap_u32(&(N));
00270 #endif
00271 
00272     // Reserve space in the pts vector.
00273     size_t n = pts.size();
00274 
00275     if (n > N)
00276     {
00277         for (size_t i = N; i < n; i++)
00278         {
00279             free_vector_f(pts[ i ]);
00280         }
00281         pts.erase(pts.begin() + N, pts.end());
00282     }
00283     else
00284     {
00285         pts.reserve(N);
00286     }
00287 
00288 
00289     // Points.
00290     for (size_t i = 0; i < N; i++)
00291     {
00292         in.read((char*)&x, sizeof(float));
00293         in.read((char*)&y, sizeof(float));
00294         in.read((char*)&z, sizeof(float));
00295         in.read((char*)&w, sizeof(float));
00296         if (in.fail() || in.eof())
00297         {
00298             throw IO_error("Could not read points");
00299         }
00300 
00301 #ifndef JWSC_BIGENDIAN
00302         bswap_u32((uint32_t*)&(x));
00303         bswap_u32((uint32_t*)&(y));
00304         bswap_u32((uint32_t*)&(z));
00305         bswap_u32((uint32_t*)&(w));
00306 #endif
00307 
00308         if (i < n)
00309         {
00310             pts[ i ]->elts[0] = x;
00311             pts[ i ]->elts[1] = y;
00312             pts[ i ]->elts[2] = z;
00313             pts[ i ]->elts[3] = w;
00314         }
00315         else
00316         {
00317             Vector_f* pt = 0;
00318             create_vector_f(&pt, 4);
00319 
00320             pt->elts[0] = x;
00321             pt->elts[1] = y;
00322             pt->elts[2] = z;
00323             pt->elts[3] = w;
00324 
00325             pts.push_back(pt);
00326         }
00327     }
00328 
00329 
00330     // Normal.
00331     if (N >= 3)
00332     {
00333         in.read((char*)&x, sizeof(float));
00334         in.read((char*)&y, sizeof(float));
00335         in.read((char*)&z, sizeof(float));
00336         in.read((char*)&w, sizeof(float));
00337         if (in.fail() || in.eof())
00338         {
00339             throw IO_error("Could not read normal");
00340         }
00341 
00342 #ifndef JWSC_BIGENDIAN
00343         bswap_u32((uint32_t*)&(x));
00344         bswap_u32((uint32_t*)&(y));
00345         bswap_u32((uint32_t*)&(z));
00346         bswap_u32((uint32_t*)&(w));
00347 #endif
00348 
00349         create_vector_f(&normal, 4);
00350         normal->elts[0] = x;
00351         normal->elts[1] = y;
00352         normal->elts[2] = z;
00353         normal->elts[3] = w;
00354     }
00355 
00356 
00357     // Centroid.
00358     if (N > 0)
00359     {
00360         in.read((char*)&x, sizeof(float));
00361         in.read((char*)&y, sizeof(float));
00362         in.read((char*)&z, sizeof(float));
00363         in.read((char*)&w, sizeof(float));
00364         if (in.fail() || in.eof())
00365         {
00366             throw IO_error("Could not read centroid");
00367         }
00368 
00369 #ifndef JWSC_BIGENDIAN
00370         bswap_u32((uint32_t*)&(x));
00371         bswap_u32((uint32_t*)&(y));
00372         bswap_u32((uint32_t*)&(z));
00373         bswap_u32((uint32_t*)&(w));
00374 #endif
00375 
00376         create_vector_f(&centroid, 4);
00377         centroid->elts[0] = x;
00378         centroid->elts[1] = y;
00379         centroid->elts[2] = z;
00380         centroid->elts[3] = w;
00381     }
00382 
00383     in.read((char*)&normal_flipped, sizeof(uint8_t));
00384 }
00385 
00386 
00394 void Polygon_f::write(std::ostream& out) const throw (jwscxx::base::IO_error)
00395 {
00396     using namespace jwsc;
00397 
00398     uint32_t id_cp = id;
00399 #ifndef JWSC_BIGENDIAN
00400     bswap_u32(&(id_cp));
00401 #endif
00402     out.write((char*)&id_cp, sizeof(uint32_t));
00403     if (out.fail() || out.eof())
00404     {
00405         throw IO_error("Could not write id");
00406     }
00407 
00408     assert(sizeof(float) == sizeof(uint32_t));
00409 
00410     float x, y, z, w;
00411 
00412     // Number of points.
00413     uint32_t N = pts.size();
00414 
00415 #ifndef JWSC_BIGENDIAN
00416     bswap_u32(&(N));
00417 #endif
00418 
00419     out.write((char*)&N, sizeof(uint32_t));
00420     if (out.fail() || out.eof())
00421     {
00422         throw IO_error("Could not write number of points");
00423     }
00424 
00425 
00426     // Points.
00427     for (size_t i = 0; i < pts.size(); i++)
00428     {
00429         Vector_f* pt = pts[ i ];
00430 
00431         x = pt->elts[0];
00432         y = pt->elts[1];
00433         z = pt->elts[2];
00434         w = pt->elts[3];
00435 
00436 #ifndef JWSC_BIGENDIAN
00437         bswap_u32((uint32_t*)&(x));
00438         bswap_u32((uint32_t*)&(y));
00439         bswap_u32((uint32_t*)&(z));
00440         bswap_u32((uint32_t*)&(w));
00441 #endif
00442 
00443         out.write((char*)&x, sizeof(float));
00444         out.write((char*)&y, sizeof(float));
00445         out.write((char*)&z, sizeof(float));
00446         out.write((char*)&w, sizeof(float));
00447         if (out.fail() || out.eof())
00448         {
00449             throw IO_error("Could not write points");
00450         }
00451     }
00452 
00453 
00454     // Normal.
00455     if (N >= 3)
00456     {
00457         assert(normal);
00458 
00459         x = normal->elts[0];
00460         y = normal->elts[1];
00461         z = normal->elts[2];
00462         w = normal->elts[3];
00463 
00464 #ifndef JWSC_BIGENDIAN
00465         bswap_u32((uint32_t*)&(x));
00466         bswap_u32((uint32_t*)&(y));
00467         bswap_u32((uint32_t*)&(z));
00468         bswap_u32((uint32_t*)&(w));
00469 #endif
00470 
00471         out.write((char*)&x, sizeof(float));
00472         out.write((char*)&y, sizeof(float));
00473         out.write((char*)&z, sizeof(float));
00474         out.write((char*)&w, sizeof(float));
00475         if (out.fail() || out.eof())
00476         {
00477             throw IO_error("Could not write normal");
00478         }
00479     }
00480 
00481 
00482     // Centroid.
00483     if (N > 0)
00484     {
00485         assert(centroid);
00486 
00487         x = centroid->elts[0];
00488         y = centroid->elts[1];
00489         z = centroid->elts[2];
00490         w = centroid->elts[3];
00491 
00492 #ifndef JWSC_BIGENDIAN
00493         bswap_u32((uint32_t*)&(x));
00494         bswap_u32((uint32_t*)&(y));
00495         bswap_u32((uint32_t*)&(z));
00496         bswap_u32((uint32_t*)&(w));
00497 #endif
00498 
00499         out.write((char*)&x, sizeof(float));
00500         out.write((char*)&y, sizeof(float));
00501         out.write((char*)&z, sizeof(float));
00502         out.write((char*)&w, sizeof(float));
00503         if (out.fail() || out.eof())
00504         {
00505             throw IO_error("Could not write centroid");
00506         }
00507     }
00508 
00509     out.write((char*)&normal_flipped, sizeof(uint8_t));
00510 }
00511 
00512 
00519 void Polygon_f::transform(const jwsc::Matrix_f* M) 
00520     throw (jwscxx::base::Arg_error)
00521 {
00522     using namespace jwsc;
00523 
00524     if (M->num_rows != 4 && M->num_cols != 4)
00525     {
00526         throw Arg_error("Transformation matrix not homogeneous");
00527     }
00528 
00529     size_t N = pts.size();
00530 
00531     // Transform the points.
00532     for (size_t i = 0; i < N; i++)
00533     {
00534         Vector_f* pt = pts[ i ];
00535 
00536         multiply_matrix_and_vector_f(&pt, M, pt);
00537     }
00538 
00539     // Transform the centroid.
00540     multiply_matrix_and_vector_f(&centroid, M, centroid);
00541 
00542     update_normal();
00543 }
00544 
00545 
00547 void Polygon_f::wire_render() const
00548 {
00549     using namespace jwsc;
00550 
00551     if (normal)
00552     {
00553         assert(fabs(normal->elts[3] - 1.0f) < 1.0e-8f);
00554         glNormal3f(normal->elts[0], normal->elts[1], normal->elts[2]);
00555     }
00556 
00557     Vector_f* pt;
00558 
00559     glBegin(GL_LINE_STRIP);
00560     for (size_t i = 0; i < pts.size(); i++)
00561     {
00562         pt = pts[ i ];
00563 
00564         glVertex4f(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]);
00565     }
00566     if (pts.size() > 0)
00567     {
00568         pt = pts[0];
00569         glVertex4f(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]);
00570     }
00571     glEnd();
00572 }
00573 
00574 
00581 void Polygon_f::wire_occlude_render() const
00582 {
00583     using namespace jwsc;
00584 
00585     glDisable(GL_DEPTH_TEST);
00586     glEnable(GL_STENCIL_TEST);
00587     glClear(GL_STENCIL_BUFFER_BIT);
00588     glStencilFunc(GL_ALWAYS, 1, 1);
00589     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
00590 
00591     GLboolean color_mask[4];
00592     glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
00593     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
00594 
00595 
00596     Vector_f* pt;
00597 
00598     glBegin(GL_LINE_STRIP);
00599     for (size_t i = 0; i < pts.size(); i++)
00600     {
00601         pt = pts[ i ];
00602 
00603         glVertex4f(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]);
00604     }
00605     if (pts.size() > 0)
00606     {
00607         pt = pts[0];
00608         glVertex4f(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]);
00609     }
00610     glEnd();
00611 
00612 
00613     glStencilFunc(GL_NOTEQUAL, 1, 1);
00614     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
00615 
00616     glEnable(GL_DEPTH_TEST);
00617 
00618     glBegin(GL_POLYGON);
00619     for (size_t i = 0; i < pts.size(); i++)
00620     {
00621         pt = pts[ i ];
00622 
00623         glVertex4f(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]);
00624     }
00625     glEnd();
00626 
00627     glDisable(GL_STENCIL_TEST);
00628 
00629     glColorMask(color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
00630 }
00631 
00640 void Polygon_f::wire_occluded_silhouette_render(std::vector<bool> & iVector, bool &iVisible) const
00641 {
00642     using namespace jwsc;
00643     
00644     assert(iVector.size() == pts.size());
00645 
00646     Vector_f* pt;
00647 
00648     glDisable(GL_DEPTH_TEST);
00649     glEnable(GL_STENCIL_TEST);
00650     glClear(GL_STENCIL_BUFFER_BIT);
00651     glStencilFunc(GL_ALWAYS, 1, 1);
00652     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
00653 
00654     GLboolean color_mask[4];
00655     glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
00656     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
00657 
00658     glBegin(GL_LINES);
00659     uint32_t i = 0;
00660     for(std::vector<bool>::const_iterator it = iVector.begin(); it != iVector.end(); it++,i++)
00661     {
00662         if(*it)
00663         {
00664             //If it is the last edge, we need to render the last and the first point of the polygon
00665             int j = ( (i+1) == pts.size()) ? 0 : (i+1);
00666             glVertex4d(pts[i]->elts[0], pts[i]->elts[1], pts[i]->elts[2], pts[i]->elts[3]);
00667             glVertex4d(pts[j]->elts[0], pts[j]->elts[1], pts[j]->elts[2], pts[j]->elts[3]);
00668         }
00669     }
00670     glEnd();
00671 
00672 
00673     glStencilFunc(GL_NOTEQUAL, 1, 1);
00674     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
00675     glEnable(GL_DEPTH_TEST);
00676 
00677     glBegin(GL_POLYGON);
00678     if(iVisible)
00679     {
00680     for (size_t i = 0; i < pts.size(); i++)
00681         {
00682             pt = pts[ i ];
00683             glVertex4d(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]);
00684         }
00685     }
00686     glEnd();
00687 
00688     glDisable(GL_STENCIL_TEST);
00689 
00690     glColorMask(color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
00691 }
00692 
00694 void Polygon_f::solid_render() const
00695 {
00696     using namespace jwsc;
00697 
00698     if (normal)
00699     {
00700         assert(fabs(normal->elts[3] - 1.0f) < 1.0e-8f);
00701         glNormal3f(normal->elts[0], normal->elts[1], normal->elts[2]);
00702     }
00703 
00704     glBegin(GL_POLYGON);
00705     for (size_t i = 0; i < pts.size(); i++)
00706     {
00707         Vector_f* pt = pts[ i ];
00708 
00709         glVertex4f(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]);
00710     }
00711     glEnd();
00712 }
00713 
00714 
00726 void Polygon_f::add_point(float x, float y, float z) 
00727     throw (jwscxx::base::Arg_error)
00728 {
00729     using namespace jwsc;
00730 
00731     Vector_f* pt = 0;
00732 
00733     create_vector_f(&pt, 4);
00734     pt->elts[0] = x;
00735     pt->elts[1] = y;
00736     pt->elts[2] = z;
00737     pt->elts[3] = 1.0f;
00738 
00739     add_point(pt);
00740 }
00741 
00742 
00753 void Polygon_f::add_point(jwsc::Vector_f* pt) throw (jwscxx::base::Arg_error)
00754 {
00755     using namespace jwsc;
00756 
00757     if (pt->num_elts != 4)
00758     {
00759         throw Arg_error("Point to add not homogeneous");
00760     }
00761     else if (fabs(pt->elts[3]) < 1.0e-10)
00762     {
00763         throw Arg_error("Homogeneous coordinate is zero");
00764     }
00765 
00766     size_t N = pts.size();
00767 
00768     pts.push_back(pt);
00769 
00770     if (N >= 3)
00771     {
00772         assert(normal);
00773 
00774         float dp1, dp2;
00775 
00776         calc_vector_dot_prod_f(&dp1, normal, pts[0]);
00777         calc_vector_dot_prod_f(&dp2, normal, pt);
00778 
00779         if (fabs(dp1 - dp2) > 1.0e-4)
00780         {
00781             throw Arg_error("Point to add not in the polygon's plane");
00782         }
00783     }
00784     else if (N == 2)
00785     {
00786         update_normal();
00787     }
00788 
00789     update_centroid();
00790 }
00791 
00792 
00797 const jwsc::Vector_f* Polygon_f::get_normal() const 
00798 { 
00799     return normal; 
00800 }
00801 
00802 
00806 const jwsc::Vector_f* Polygon_f::get_centroid() const 
00807 { 
00808     return centroid; 
00809 }
00810 
00811 
00812 size_t Polygon_f::get_num_points() const 
00813 { 
00814     return pts.size(); 
00815 }
00816 
00817 
00825 const jwsc::Vector_f* Polygon_f::get_point(size_t i) const 
00826     throw (jwscxx::base::Arg_error)
00827 { 
00828     if (i >= pts.size())
00829     { 
00830         throw jwscxx::base::Arg_error("Invalid point index"); 
00831     }
00832 
00833     return static_cast<const jwsc::Vector_f*>(pts[ i ]);
00834 }
00835 
00836 
00843 void Polygon_f::flip_normal() 
00844 { 
00845     normal_flipped = !normal_flipped; 
00846     update_normal(); 
00847 }
00848 
00849 
00857 void Polygon_f::project()
00858 {
00859     using namespace jwsc;
00860 
00861     GLfloat glM[16] = {0};
00862 
00863     glGetFloatv(GL_MODELVIEW_MATRIX, glM);
00864 
00865     glMatrixMode(GL_PROJECTION);
00866     glPushMatrix();
00867     glMultMatrixf(glM);
00868     glGetFloatv(GL_PROJECTION_MATRIX, glM);
00869     glPopMatrix();
00870     glMatrixMode(GL_MODELVIEW);
00871 
00872     Matrix_f* M = 0;
00873     create_matrix_f(&M, 4, 4);
00874     for (size_t row = 0; row < 4; row++)
00875     {
00876         for (size_t col = 0; col < 4; col++)
00877         {
00878             M->elts[ row ][ col ] = glM[ col*4 + row  ];
00879         }
00880     }
00881 
00882     float width  = Camera_f::get_gl_viewport_width();
00883     float height = Camera_f::get_gl_viewport_height();
00884 
00885     for (size_t i = 0; i < pts.size(); i++)
00886     {
00887         Vector_f* pt = pts[ i ];
00888 
00889         multiply_matrix_and_vector_f(&pt, M, pt);
00890 
00891         float w = 1.0f / pt->elts[ 3 ];
00892         pt->elts[ 0 ] = 0.5f*width* (pt->elts[ 0 ]*w + 1.0f);
00893         pt->elts[ 1 ] = 0.5f*height*(pt->elts[ 1 ]*w + 1.0f);
00894         pt->elts[ 2 ] = 0;
00895         pt->elts[ 3 ] = 1.0f;
00896     }
00897 
00898     free_matrix_f(M);
00899 }
00900 
00901 
00907 uint8_t Polygon_f::is_visible(const Camera_f* camera) const
00908 {
00909     if (!normal)
00910         return 0;
00911 
00912     const jwsc::Vector_f* prp = camera->get_prp();
00913 
00914     float x = prp->elts[0] - centroid->elts[0];
00915     float y = prp->elts[1] - centroid->elts[1];
00916     float z = prp->elts[2] - centroid->elts[2];
00917 
00918     if ((x*normal->elts[0] + y*normal->elts[1] + z*normal->elts[2]) > 0)
00919         return 1;
00920     return 0;
00921 }
00922 
00930 uint8_t Polygon_f::is_visible_up_to_epsilon(const Camera_d* camera, float & epsilon) const
00931 {
00932     if (!normal)
00933         return 0;
00934 
00935     const jwsc::Vector_d* prp = camera->get_prp();
00936 
00937     float x = prp->elts[0] - centroid->elts[0];
00938     float y = prp->elts[1] - centroid->elts[1];
00939     float z = prp->elts[2] - centroid->elts[2];
00940 
00941     float dp = ((float)(x*normal->elts[0] + y*normal->elts[1] + z*normal->elts[2]));
00942     
00943     return ( dp > epsilon);
00944 }
00945 
00946 
00947 uint32_t Polygon_f::get_id() const 
00948 { 
00949     return id; 
00950 }
00951 
00952 
00953 void Polygon_f::set_id(uint32_t id) 
00954 { 
00955     this->id = id; 
00956 }
00957 
00958 
00964 void Polygon_f::update_normal()
00965 {
00966     using namespace jwsc;
00967 
00968     size_t N = pts.size();
00969 
00970     if (N < 3)
00971         return;
00972 
00973     Vector_f* p1 = pts[0];
00974     Vector_f* p2 = pts[1];
00975     Vector_f* pN = pts[N-1];
00976 
00977     float w1 = pts[0]->elts[3];
00978     float w2 = pts[1]->elts[3];
00979     float wN = pts[N-1]->elts[3];
00980 
00981     assert(fabs(w1) >= 1.0e-10);
00982     assert(fabs(w2) >= 1.0e-10);
00983     assert(fabs(wN) >= 1.0e-10);
00984 
00985     w1 = 1.0f / w1;
00986     w2 = 1.0f / w2;
00987     wN = 1.0f / wN;
00988 
00989     // p2 - p1
00990     float v1_x = p2->elts[0]*w2 - p1->elts[0]*w1;
00991     float v1_y = p2->elts[1]*w2 - p1->elts[1]*w1;
00992     float v1_z = p2->elts[2]*w2 - p1->elts[2]*w1;
00993 
00994     // pN - p1
00995     float v2_x = pN->elts[0]*wN - p1->elts[0]*w1;
00996     float v2_y = pN->elts[1]*wN - p1->elts[1]*w1;
00997     float v2_z = pN->elts[2]*wN - p1->elts[2]*w1;
00998 
00999     // v1 x v2
01000     create_vector_f(&normal, 4);
01001     normal->elts[0] = v1_y*v2_z - v1_z*v2_y;
01002     normal->elts[1] = v1_z*v2_x - v1_x*v2_z;
01003     normal->elts[2] = v1_x*v2_y - v1_y*v2_x;
01004     normal->elts[3] = 0.0f;
01005 
01006     if (normal_flipped)
01007     {
01008         normal->elts[0] *= -1;
01009         normal->elts[1] *= -1;
01010         normal->elts[2] *= -1;
01011     }
01012 
01013     normalize_vector_mag_f(&normal, normal);
01014     normal->elts[3] = 1.0f;
01015 }
01016 
01017 
01026 void Polygon_f::update_centroid()
01027 {
01028     using namespace jwsc;
01029 
01030     size_t N = pts.size();
01031     float area = 0;
01032 
01033     if (N == 0)
01034     {
01035         return;
01036     }
01037     else if (N == 1)
01038     {
01039         copy_vector_f(&centroid, pts[0]);
01040         return;
01041     }
01042     else if (N == 2)
01043     {
01044         float x = (pts[0]->elts[0]/pts[0]->elts[3] + 
01045                    pts[1]->elts[0]/pts[1]->elts[3]) * 0.5f;
01046         float y = (pts[0]->elts[1]/pts[0]->elts[3] + 
01047                    pts[1]->elts[1]/pts[1]->elts[3]) * 0.5f;
01048         float z = (pts[0]->elts[2]/pts[0]->elts[3] + 
01049                    pts[1]->elts[2]/pts[1]->elts[3]) * 0.5f;
01050         create_zero_vector_f(&centroid, 4);
01051         centroid->elts[0] = x;
01052         centroid->elts[1] = y;
01053         centroid->elts[2] = z;
01054         centroid->elts[3] = 1.0f;
01055         return;
01056     }
01057 
01058     float x3 = pts[N-1]->elts[0];
01059     float y3 = pts[N-1]->elts[1];
01060     float z3 = pts[N-1]->elts[2];
01061 
01062     for (size_t i = 0; i < N - 2; i++)
01063     {
01064         float x1 = pts[i]->elts[0];
01065         float y1 = pts[i]->elts[1];
01066         float z1 = pts[i]->elts[2];
01067 
01068         float x2 = pts[i+1]->elts[0];
01069         float y2 = pts[i+1]->elts[1];
01070         float z2 = pts[i+1]->elts[2];
01071 
01072         float dot = (x2 - x1)*(x3 - x1) + 
01073                     (y2 - y1)*(y3 - y1) + 
01074                     (z2 - z1)*(z3 - z1);
01075 
01076         float base = sqrt((x2 - x1)*(x2 - x1) + 
01077                           (y2 - y1)*(y2 - y1) + 
01078                           (z2 - z1)*(z2 - z1));
01079 
01080         float height;
01081 
01082         if (base < 1.0e-8f)
01083         {
01084             height = 0;
01085         }
01086         else 
01087         {
01088             float alpha = dot / (base*base);
01089 
01090             float a = x3 - x1 - alpha*(x2 - x1);
01091             float b = y3 - y1 - alpha*(y2 - y1);
01092             float c = z3 - z1 - alpha*(z2 - z1);
01093 
01094             height = sqrt(a*a + b*b + c*c);
01095         }
01096 
01097         float tri_area = 0.5f * base * height;
01098 
01099         area += tri_area;
01100         centroid->elts[0] += tri_area * (x1 + x2 + x3) / 3.0f;
01101         centroid->elts[1] += tri_area * (y1 + y2 + y3) / 3.0f;
01102         centroid->elts[2] += tri_area * (z1 + z2 + z3) / 3.0f;
01103     }
01104 
01105     if (area > 1.0e-8f)
01106     {
01107         centroid->elts[0] /= area;
01108         centroid->elts[1] /= area;
01109         centroid->elts[2] /= area;
01110         centroid->elts[3]  = 1.0f;
01111     }
01112     else
01113     {
01114         copy_vector_f(&centroid, pts[0]);
01115     }
01116 }
01117 
01118 
01119 uint32_t Polygon_f::generate_id() 
01120 { 
01121     static uint32_t next_id = 1; 
01122     return next_id++; 
01123 }
01124 
01125 
01127 Polygon_d::Polygon_d()
01128 {
01129     normal = 0;
01130     centroid = 0;
01131     normal_flipped = 0;
01132     id = generate_id();
01133 }
01134 
01135 
01142 Polygon_d::Polygon_d(uint32_t N)
01143 {
01144     pts.reserve(N);
01145     normal = 0;
01146     centroid = 0;
01147     normal_flipped = 0;
01148     id = generate_id();
01149 }
01150 
01151 
01153 Polygon_d::Polygon_d(const Polygon_d& p)
01154     : pts(p.pts.capacity())
01155 {
01156     normal = 0;
01157     centroid = 0;
01158     *this = p;
01159 }
01160 
01161 
01170 Polygon_d::Polygon_d(const char* fname) 
01171     throw (jwscxx::base::Arg_error, jwscxx::base::IO_error)
01172 {
01173     normal = 0;
01174     centroid = 0;
01175     normal_flipped = 0;
01176 
01177     jwscxx::base::Readable::read(fname);
01178 }
01179 
01180 
01189 Polygon_d::Polygon_d(std::istream& in) 
01190     throw (jwscxx::base::Arg_error, jwscxx::base::IO_error)
01191 {
01192     normal = 0;
01193     centroid = 0;
01194     normal_flipped = 0;
01195 
01196     read(in);
01197 }
01198 
01199 
01201 Polygon_d::~Polygon_d()
01202 {
01203     free_vector_d(normal);
01204     free_vector_d(centroid);
01205 
01206     for (size_t i = 0; i < pts.size(); i++)
01207     {
01208         free_vector_d(pts[ i ]);
01209     }
01210 }
01211 
01212 
01220 Polygon_d& Polygon_d::operator= (const Polygon_d& p)
01221 {
01222     using namespace std;
01223     using namespace jwsc;
01224 
01225     size_t n = pts.size();
01226     size_t N = p.pts.size();
01227 
01228     if (n > N)
01229     {
01230         for (size_t i = N; i < n; i++)
01231         {
01232             free_vector_d(pts[ i ]);
01233         }
01234         pts.erase(pts.begin() + N, pts.end());
01235     }
01236     else
01237     {
01238         pts.reserve(N);
01239     }
01240 
01241     for (size_t i = 0; i < N; i++)
01242     {
01243         if (i < n)
01244         {
01245             copy_vector_d(&(pts[ i ]), p.pts[ i ]);
01246         }
01247         else
01248         {
01249             Vector_d* pt = 0;
01250             copy_vector_d(&pt, p.pts[ i ]);
01251             pts.push_back(pt);
01252         }
01253     }
01254 
01255     if (p.normal)
01256     {
01257         copy_vector_d(&normal, p.normal);
01258     }
01259     if (p.centroid)
01260     {
01261         copy_vector_d(&centroid, p.centroid);
01262     }
01263 
01264     normal_flipped = p.normal_flipped;
01265 
01266     id = p.id;
01267 
01268     return *this;
01269 }
01270 
01271 
01273 Polygon_d* Polygon_d::clone() const
01274 {
01275     return new Polygon_d(*this);
01276 }
01277 
01278 
01285 void Polygon_d::read(std::istream& in) throw (jwscxx::base::IO_error,
01286         jwscxx::base::Arg_error)
01287 {
01288     using namespace jwsc;
01289 
01290     in.read((char*)&id, sizeof(uint32_t));
01291     if (in.fail() || in.eof())
01292     {
01293         throw IO_error("Could not read id");
01294     }
01295 #ifndef JWSC_BIGENDIAN
01296     bswap_u32(&(id));
01297 #endif
01298 
01299     assert(sizeof(double) == sizeof(uint64_t));
01300 
01301     double x, y, z, w;
01302 
01303     // Number of points.
01304     uint32_t N;
01305 
01306     in.read((char*)&N, sizeof(uint32_t));
01307     if (in.fail() || in.eof())
01308     {
01309         throw IO_error("Could not read number of points");
01310     }
01311 
01312 #ifndef JWSC_BIGENDIAN
01313     bswap_u32(&(N));
01314 #endif
01315 
01316     // Reserve space in the pts vector.
01317     size_t n = pts.size();
01318 
01319     if (n > N)
01320     {
01321         for (size_t i = N; i < n; i++)
01322         {
01323             free_vector_d(pts[ i ]);
01324         }
01325         pts.erase(pts.begin() + N, pts.end());
01326     }
01327     else
01328     {
01329         pts.reserve(N);
01330     }
01331 
01332 
01333     // Points.
01334     for (size_t i = 0; i < N; i++)
01335     {
01336         in.read((char*)&x, sizeof(double));
01337         in.read((char*)&y, sizeof(double));
01338         in.read((char*)&z, sizeof(double));
01339         in.read((char*)&w, sizeof(double));
01340         if (in.fail() || in.eof())
01341         {
01342             throw IO_error("Could not read points");
01343         }
01344 
01345 #ifndef JWSC_BIGENDIAN
01346         bswap_u64((uint64_t*)&(x));
01347         bswap_u64((uint64_t*)&(y));
01348         bswap_u64((uint64_t*)&(z));
01349         bswap_u64((uint64_t*)&(w));
01350 #endif
01351 
01352         if (i < n)
01353         {
01354             pts[ i ]->elts[0] = x;
01355             pts[ i ]->elts[1] = y;
01356             pts[ i ]->elts[2] = z;
01357             pts[ i ]->elts[3] = w;
01358         }
01359         else
01360         {
01361             Vector_d* pt = 0;
01362             create_vector_d(&pt, 4);
01363 
01364             pt->elts[0] = x;
01365             pt->elts[1] = y;
01366             pt->elts[2] = z;
01367             pt->elts[3] = w;
01368 
01369             pts.push_back(pt);
01370         }
01371     }
01372 
01373 
01374     // Normal.
01375     if (N >= 3)
01376     {
01377         in.read((char*)&x, sizeof(double));
01378         in.read((char*)&y, sizeof(double));
01379         in.read((char*)&z, sizeof(double));
01380         in.read((char*)&w, sizeof(double));
01381         if (in.fail() || in.eof())
01382         {
01383             throw IO_error("Could not read normal");
01384         }
01385 
01386 #ifndef JWSC_BIGENDIAN
01387         bswap_u64((uint64_t*)&(x));
01388         bswap_u64((uint64_t*)&(y));
01389         bswap_u64((uint64_t*)&(z));
01390         bswap_u64((uint64_t*)&(w));
01391 #endif
01392 
01393         create_vector_d(&normal, 4);
01394         normal->elts[0] = x;
01395         normal->elts[1] = y;
01396         normal->elts[2] = z;
01397         normal->elts[3] = w;
01398     }
01399 
01400 
01401     // Centroid.
01402     if (N > 0)
01403     {
01404         in.read((char*)&x, sizeof(double));
01405         in.read((char*)&y, sizeof(double));
01406         in.read((char*)&z, sizeof(double));
01407         in.read((char*)&w, sizeof(double));
01408         if (in.fail() || in.eof())
01409         {
01410             throw IO_error("Could not read centroid");
01411         }
01412 
01413 #ifndef JWSC_BIGENDIAN
01414         bswap_u64((uint64_t*)&(x));
01415         bswap_u64((uint64_t*)&(y));
01416         bswap_u64((uint64_t*)&(z));
01417         bswap_u64((uint64_t*)&(w));
01418 #endif
01419 
01420         create_vector_d(&centroid, 4);
01421         centroid->elts[0] = x;
01422         centroid->elts[1] = y;
01423         centroid->elts[2] = z;
01424         centroid->elts[3] = w;
01425     }
01426 
01427     in.read((char*)&normal_flipped, sizeof(uint8_t));
01428 }
01429 
01430 
01438 void Polygon_d::write(std::ostream& out) const throw (jwscxx::base::IO_error)
01439 {
01440     using namespace jwsc;
01441 
01442     uint32_t id_cp = id;
01443 #ifndef JWSC_BIGENDIAN
01444     bswap_u32(&(id_cp));
01445 #endif
01446     out.write((char*)&id_cp, sizeof(uint32_t));
01447     if (out.fail() || out.eof())
01448     {
01449         throw IO_error("Could not write id");
01450     }
01451 
01452     assert(sizeof(double) == sizeof(uint64_t));
01453 
01454     double x, y, z, w;
01455 
01456     // Number of points.
01457     uint32_t N = pts.size();
01458 
01459 #ifndef JWSC_BIGENDIAN
01460     bswap_u32(&(N));
01461 #endif
01462 
01463     out.write((char*)&N, sizeof(uint32_t));
01464     if (out.fail() || out.eof())
01465     {
01466         throw IO_error("Could not write number of points");
01467     }
01468 
01469 
01470     // Points.
01471     for (size_t i = 0; i < pts.size(); i++)
01472     {
01473         Vector_d* pt = pts[ i ];
01474 
01475         x = pt->elts[0];
01476         y = pt->elts[1];
01477         z = pt->elts[2];
01478         w = pt->elts[3];
01479 
01480 #ifndef JWSC_BIGENDIAN
01481         bswap_u64((uint64_t*)&(x));
01482         bswap_u64((uint64_t*)&(y));
01483         bswap_u64((uint64_t*)&(z));
01484         bswap_u64((uint64_t*)&(w));
01485 #endif
01486 
01487         out.write((char*)&x, sizeof(double));
01488         out.write((char*)&y, sizeof(double));
01489         out.write((char*)&z, sizeof(double));
01490         out.write((char*)&w, sizeof(double));
01491         if (out.fail() || out.eof())
01492         {
01493             throw IO_error("Could not write points");
01494         }
01495     }
01496 
01497 
01498     // Normal.
01499     if (N >= 3)
01500     {
01501         assert(normal);
01502 
01503         x = normal->elts[0];
01504         y = normal->elts[1];
01505         z = normal->elts[2];
01506         w = normal->elts[3];
01507 
01508 #ifndef JWSC_BIGENDIAN
01509         bswap_u64((uint64_t*)&(x));
01510         bswap_u64((uint64_t*)&(y));
01511         bswap_u64((uint64_t*)&(z));
01512         bswap_u64((uint64_t*)&(w));
01513 #endif
01514 
01515         out.write((char*)&x, sizeof(double));
01516         out.write((char*)&y, sizeof(double));
01517         out.write((char*)&z, sizeof(double));
01518         out.write((char*)&w, sizeof(double));
01519         if (out.fail() || out.eof())
01520         {
01521             throw IO_error("Could not write normal");
01522         }
01523     }
01524 
01525 
01526     // Centroid.
01527     if (N > 0)
01528     {
01529         assert(centroid);
01530 
01531         x = centroid->elts[0];
01532         y = centroid->elts[1];
01533         z = centroid->elts[2];
01534         w = centroid->elts[3];
01535 
01536 #ifndef JWSC_BIGENDIAN
01537         bswap_u64((uint64_t*)&(x));
01538         bswap_u64((uint64_t*)&(y));
01539         bswap_u64((uint64_t*)&(z));
01540         bswap_u64((uint64_t*)&(w));
01541 #endif
01542 
01543         out.write((char*)&x, sizeof(double));
01544         out.write((char*)&y, sizeof(double));
01545         out.write((char*)&z, sizeof(double));
01546         out.write((char*)&w, sizeof(double));
01547         if (out.fail() || out.eof())
01548         {
01549             throw IO_error("Could not write centroid");
01550         }
01551     }
01552 
01553     out.write((char*)&normal_flipped, sizeof(uint8_t));
01554 }
01555 
01556 
01563 void Polygon_d::transform(const jwsc::Matrix_d* M) 
01564     throw (jwscxx::base::Arg_error)
01565 {
01566     using namespace jwsc;
01567 
01568     if (M->num_rows != 4 && M->num_cols != 4)
01569     {
01570         throw Arg_error("Transformation matrix not homogeneous");
01571     }
01572 
01573     size_t N = pts.size();
01574 
01575     // Transform the points.
01576     for (size_t i = 0; i < N; i++)
01577     {
01578         Vector_d* pt = pts[ i ];
01579 
01580         multiply_matrix_and_vector_d(&pt, M, pt);
01581     }
01582 
01583     // Transform the centroid.
01584     multiply_matrix_and_vector_d(&centroid, M, centroid);
01585 
01586     update_normal();
01587 }
01588 
01589 
01591 void Polygon_d::wire_render() const
01592 {
01593     using namespace jwsc;
01594 
01595     if (normal)
01596     {
01597         assert(fabs(normal->elts[3] - 1.0) < 1.0e-8);
01598         glNormal3d(normal->elts[0], normal->elts[1], normal->elts[2]);
01599     }
01600 
01601     Vector_d* pt;
01602 
01603     glBegin(GL_LINE_STRIP);
01604     for (size_t i = 0; i < pts.size(); i++)
01605     {
01606         pt = pts[ i ];
01607 
01608         glVertex4d(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]);
01609     }
01610     if (pts.size() > 0)
01611     {
01612         pt = pts[0];
01613         glVertex4d(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]);
01614     }
01615     glEnd();
01616 }
01617 
01618 
01625 void Polygon_d::wire_occlude_render() const
01626 {
01627     using namespace jwsc;
01628 
01629     glDisable(GL_DEPTH_TEST);
01630     glEnable(GL_STENCIL_TEST);
01631     glClear(GL_STENCIL_BUFFER_BIT);
01632     glStencilFunc(GL_ALWAYS, 1, 1);
01633     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
01634 
01635     GLboolean color_mask[4];
01636     glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
01637     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
01638 
01639     Vector_d* pt;
01640 
01641     glBegin(GL_LINE_STRIP);
01642     for (size_t i = 0; i < pts.size(); i++)
01643     {
01644         pt = pts[ i ];
01645 
01646         glVertex4d(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]);
01647     }
01648     if (pts.size() > 0)
01649     {
01650         pt = pts[0];
01651         glVertex4d(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]);
01652     }
01653     glEnd();
01654 
01655 
01656     glStencilFunc(GL_NOTEQUAL, 1, 1);
01657     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
01658 
01659     glEnable(GL_DEPTH_TEST);
01660 
01661     glBegin(GL_POLYGON);
01662     for (size_t i = 0; i < pts.size(); i++)
01663     {
01664         pt = pts[ i ];
01665 
01666         glVertex4d(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]);
01667     }
01668     glEnd();
01669 
01670     glDisable(GL_STENCIL_TEST);
01671 
01672     glColorMask(color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
01673 }
01674 
01683 void Polygon_d::wire_occluded_silhouette_render(std::vector<bool> & iVector, bool &visible) const
01684 {
01685     using namespace jwsc;
01686     
01687     assert(iVector.size() == pts.size());
01688 
01689     Vector_d* pt;
01690 
01691     glDisable(GL_DEPTH_TEST);
01692     glEnable(GL_STENCIL_TEST);
01693     glClear(GL_STENCIL_BUFFER_BIT);
01694     glStencilFunc(GL_ALWAYS, 1, 1);
01695     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
01696 
01697     GLboolean color_mask[4];
01698     glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
01699     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
01700 
01701     glBegin(GL_LINES);
01702     uint32_t i = 0;
01703     for(std::vector<bool>::const_iterator it = iVector.begin(); it != iVector.end(); it++,i++)
01704     {
01705         if(*it)
01706         {
01707             //If it is the last edge, we need to render the last and the first point of the polygon
01708             int j = ( (i+1) == pts.size()) ? 0 : (i+1);
01709             glVertex4d(pts[i]->elts[0], pts[i]->elts[1], pts[i]->elts[2], pts[i]->elts[3]);
01710             glVertex4d(pts[j]->elts[0], pts[j]->elts[1], pts[j]->elts[2], pts[j]->elts[3]);
01711         }
01712     }
01713     glEnd();
01714 
01715 
01716     glStencilFunc(GL_NOTEQUAL, 1, 1);
01717     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
01718     glEnable(GL_DEPTH_TEST);
01719 
01720     glBegin(GL_POLYGON);
01721     if(visible)
01722     {
01723     for (size_t i = 0; i < pts.size(); i++)
01724         {
01725             pt = pts[ i ];
01726             glVertex4d(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]);
01727         }
01728     }
01729     glEnd();
01730 
01731     glDisable(GL_STENCIL_TEST);
01732 
01733     glColorMask(color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
01734 }
01735 
01736 
01738 void Polygon_d::solid_render() const
01739 {
01740     using namespace jwsc;
01741 
01742     if (normal)
01743     {
01744         assert(fabs(normal->elts[3] - 1.0) < 1.0e-8);
01745         glNormal3d(normal->elts[0], normal->elts[1], normal->elts[2]);
01746     }
01747 
01748     glBegin(GL_POLYGON);
01749     for (size_t i = 0; i < pts.size(); i++)
01750     {
01751         Vector_d* pt = pts[ i ];
01752 
01753         glVertex4d(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]);
01754     }
01755     glEnd();
01756 }
01757 
01758 
01770 void Polygon_d::add_point(double x, double y, double z) 
01771     throw (jwscxx::base::Arg_error)
01772 {
01773     using namespace jwsc;
01774 
01775     Vector_d* pt = 0;
01776 
01777     create_vector_d(&pt, 4);
01778     pt->elts[0] = x;
01779     pt->elts[1] = y;
01780     pt->elts[2] = z;
01781     pt->elts[3] = 1.0;
01782 
01783     add_point(pt);
01784 }
01785 
01786 
01797 void Polygon_d::add_point(jwsc::Vector_d* pt) throw (jwscxx::base::Arg_error)
01798 {
01799     using namespace jwsc;
01800 
01801     if (pt->num_elts != 4)
01802     {
01803         throw Arg_error("Point to add not homogeneous");
01804     }
01805     else if (fabs(pt->elts[3]) < 1.0e-10)
01806     {
01807         throw Arg_error("Homogeneous coordinate is zero");
01808     }
01809 
01810     size_t N = pts.size();
01811 
01812     pts.push_back(pt);
01813 
01814     if (N >= 3)
01815     {
01816         assert(normal);
01817 
01818         double dp1, dp2;
01819 
01820         calc_vector_dot_prod_d(&dp1, normal, pts[0]);
01821         calc_vector_dot_prod_d(&dp2, normal, pt);
01822 
01823         if (fabs(dp1 - dp2) > 1.0e-4)
01824         {
01825             throw Arg_error("Point to add not in the polygon's plane");
01826         }
01827     }
01828     else if (N == 2)
01829     {
01830         update_normal();
01831     }
01832 
01833     update_centroid();
01834 }
01835 
01836 
01841 const jwsc::Vector_d* Polygon_d::get_normal() const 
01842 { 
01843     return normal; 
01844 }
01845 
01846 
01850 const jwsc::Vector_d* Polygon_d::get_centroid() const 
01851 { 
01852     return centroid; 
01853 }
01854 
01855 
01856 size_t Polygon_d::get_num_points() const 
01857 { 
01858     return pts.size(); 
01859 }
01860 
01861 
01869 const jwsc::Vector_d* Polygon_d::get_point(size_t i) const 
01870     throw (jwscxx::base::Arg_error)
01871 { 
01872     if (i >= pts.size())
01873     { 
01874         throw jwscxx::base::Arg_error("Invalid point index"); 
01875     }
01876 
01877     return static_cast<const jwsc::Vector_d*>(pts[ i ]);
01878 }
01879 
01880 
01887 void Polygon_d::flip_normal() 
01888 { 
01889     normal_flipped = !normal_flipped; 
01890     update_normal(); 
01891 }
01892 
01893 
01901 void Polygon_d::project()
01902 {
01903     using namespace jwsc;
01904 
01905     GLdouble glM[16] = {0};
01906 
01907     glGetDoublev(GL_MODELVIEW_MATRIX, glM);
01908 
01909     glMatrixMode(GL_PROJECTION);
01910     glPushMatrix();
01911     glMultMatrixd(glM);
01912     glGetDoublev(GL_PROJECTION_MATRIX, glM);
01913     glPopMatrix();
01914     glMatrixMode(GL_MODELVIEW);
01915 
01916     Matrix_d* M = 0;
01917     create_matrix_d(&M, 4, 4);
01918     for (size_t row = 0; row < 4; row++)
01919     {
01920         for (size_t col = 0; col < 4; col++)
01921         {
01922             M->elts[ row ][ col ] = glM[ col*4 + row  ];
01923         }
01924     }
01925 
01926     double width  = Camera_d::get_gl_viewport_width();
01927     double height = Camera_d::get_gl_viewport_height();
01928 
01929     for (size_t i = 0; i < pts.size(); i++)
01930     {
01931         Vector_d* pt = pts[ i ];
01932 
01933         multiply_matrix_and_vector_d(&pt, M, pt);
01934 
01935         double w = 1.0 / pt->elts[ 3 ];
01936         pt->elts[ 0 ] = 0.5*width* (pt->elts[ 0 ]*w + 1.0);
01937         pt->elts[ 1 ] = 0.5*height*(pt->elts[ 1 ]*w + 1.0);
01938         pt->elts[ 2 ] = 0;
01939         pt->elts[ 3 ] = 1.0;
01940     }
01941 
01942     free_matrix_d(M);
01943 }
01944 
01945 
01951 uint8_t Polygon_d::is_visible(const Camera_d* camera) const
01952 {
01953     if (!normal)
01954         return 0;
01955 
01956     const jwsc::Vector_d* prp = camera->get_prp();
01957 
01958     double x = prp->elts[0] - centroid->elts[0];
01959     double y = prp->elts[1] - centroid->elts[1];
01960     double z = prp->elts[2] - centroid->elts[2];
01961 
01962     if ((x*normal->elts[0] + y*normal->elts[1] + z*normal->elts[2]) > 0)
01963         return 1;
01964     return 0;
01965 }
01966 
01974 uint8_t Polygon_d::is_visible_up_to_epsilon(const Camera_d* camera, double & epsilon) const
01975 {
01976     if (!normal)
01977         return 0;
01978 
01979     const jwsc::Vector_d* prp = camera->get_prp();
01980 
01981     double x = prp->elts[0] - centroid->elts[0];
01982     double y = prp->elts[1] - centroid->elts[1];
01983     double z = prp->elts[2] - centroid->elts[2];
01984 
01985     double dp = ((double)(x*normal->elts[0] + y*normal->elts[1] + z*normal->elts[2]));
01986     
01987     return (dp > epsilon);
01988 }
01989 
01990 
01991 uint32_t Polygon_d::get_id() const 
01992 { 
01993     return id; 
01994 }
01995 
01996 
01997 void Polygon_d::set_id(uint32_t id) 
01998 { 
01999     this->id = id; 
02000 }
02001 
02002 
02008 void Polygon_d::update_normal()
02009 {
02010     using namespace jwsc;
02011 
02012     size_t N = pts.size();
02013 
02014     if (N < 3)
02015         return;
02016 
02017     Vector_d* p1 = pts[0];
02018     Vector_d* p2 = pts[1];
02019     Vector_d* pN = pts[N-1];
02020 
02021     double w1 = pts[0]->elts[3];
02022     double w2 = pts[1]->elts[3];
02023     double wN = pts[N-1]->elts[3];
02024 
02025     assert(fabs(w1) >= 1.0e-10);
02026     assert(fabs(w2) >= 1.0e-10);
02027     assert(fabs(wN) >= 1.0e-10);
02028 
02029     w1 = 1.0 / w1;
02030     w2 = 1.0 / w2;
02031     wN = 1.0 / wN;
02032 
02033     // p2 - p1
02034     double v1_x = p2->elts[0]*w2 - p1->elts[0]*w1;
02035     double v1_y = p2->elts[1]*w2 - p1->elts[1]*w1;
02036     double v1_z = p2->elts[2]*w2 - p1->elts[2]*w1;
02037 
02038     // pN - p1
02039     double v2_x = pN->elts[0]*wN - p1->elts[0]*w1;
02040     double v2_y = pN->elts[1]*wN - p1->elts[1]*w1;
02041     double v2_z = pN->elts[2]*wN - p1->elts[2]*w1;
02042 
02043     // v1 x v2
02044     create_vector_d(&normal, 4);
02045     normal->elts[0] = v1_y*v2_z - v1_z*v2_y;
02046     normal->elts[1] = v1_z*v2_x - v1_x*v2_z;
02047     normal->elts[2] = v1_x*v2_y - v1_y*v2_x;
02048     normal->elts[3] = 0.0;
02049 
02050     if (normal_flipped)
02051     {
02052         normal->elts[0] *= -1;
02053         normal->elts[1] *= -1;
02054         normal->elts[2] *= -1;
02055     }
02056 
02057     normalize_vector_mag_d(&normal, normal);
02058     normal->elts[3] = 1.0;
02059 }
02060 
02061 
02070 void Polygon_d::update_centroid()
02071 {
02072     using namespace jwsc;
02073 
02074     size_t N = pts.size();
02075     double area = 0;
02076 
02077     if (N == 0)
02078     {
02079         return;
02080     }
02081     else if (N == 1)
02082     {
02083         copy_vector_d(&centroid, pts[0]);
02084         return;
02085     }
02086     else if (N == 2)
02087     {
02088         double x = (pts[0]->elts[0]/pts[0]->elts[3] + 
02089                     pts[1]->elts[0]/pts[1]->elts[3]) * 0.5;
02090         double y = (pts[0]->elts[1]/pts[0]->elts[3] + 
02091                     pts[1]->elts[1]/pts[1]->elts[3]) * 0.5;
02092         double z = (pts[0]->elts[2]/pts[0]->elts[3] + 
02093                     pts[1]->elts[2]/pts[1]->elts[3]) * 0.5;
02094         create_zero_vector_d(&centroid, 4);
02095         centroid->elts[0] = x;
02096         centroid->elts[1] = y;
02097         centroid->elts[2] = z;
02098         centroid->elts[3] = 1.0;
02099         return;
02100     }
02101 
02102     double x3 = pts[N-1]->elts[0];
02103     double y3 = pts[N-1]->elts[1];
02104     double z3 = pts[N-1]->elts[2];
02105 
02106     for (size_t i = 0; i < N - 2; i++)
02107     {
02108         double x1 = pts[i]->elts[0];
02109         double y1 = pts[i]->elts[1];
02110         double z1 = pts[i]->elts[2];
02111 
02112         double x2 = pts[i+1]->elts[0];
02113         double y2 = pts[i+1]->elts[1];
02114         double z2 = pts[i+1]->elts[2];
02115 
02116         double dot = (x2 - x1)*(x3 - x1) + 
02117                      (y2 - y1)*(y3 - y1) + 
02118                      (z2 - z1)*(z3 - z1);
02119 
02120         double base = sqrt((x2 - x1)*(x2 - x1) + 
02121                            (y2 - y1)*(y2 - y1) + 
02122                            (z2 - z1)*(z2 - z1));
02123 
02124         double height;
02125 
02126         if (base < 1.0e-8)
02127         {
02128             height = 0;
02129         }
02130         else 
02131         {
02132             double alpha = dot / (base*base);
02133 
02134             double a = x3 - x1 - alpha*(x2 - x1);
02135             double b = y3 - y1 - alpha*(y2 - y1);
02136             double c = z3 - z1 - alpha*(z2 - z1);
02137 
02138             height = sqrt(a*a + b*b + c*c);
02139         }
02140 
02141         double tri_area = 0.5 * base * height;
02142 
02143         area += tri_area;
02144         centroid->elts[0] += tri_area * (x1 + x2 + x3) / 3.0;
02145         centroid->elts[1] += tri_area * (y1 + y2 + y3) / 3.0;
02146         centroid->elts[2] += tri_area * (z1 + z2 + z3) / 3.0;
02147     }
02148 
02149     if (area > 1.0e-8)
02150     {
02151         centroid->elts[0] /= area;
02152         centroid->elts[1] /= area;
02153         centroid->elts[2] /= area;
02154         centroid->elts[3]  = 1.0;
02155     }
02156     else
02157     {
02158         copy_vector_d(&centroid, pts[0]);
02159     }
02160 }
02161 
02162 
02163 uint32_t Polygon_d::generate_id() 
02164 { 
02165     static uint32_t next_id = 1; 
02166     return next_id++; 
02167 }