JWS C++ Library
C++ language utility library
parapiped.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 
00046 #include <jwsc++/config.h>
00047 
00048 #include <cassert>
00049 #include <cmath>
00050 #include <iostream>
00051 #include <vector>
00052 
00053 #include <inttypes.h>
00054 
00055 #if defined JWSCXX_HAVE_OPENGL
00056 #include <GL/gl.h>
00057 #elif defined JWSCXX_HAVE_OPENGL_FRAMEWORK
00058 #include <OpenGL/gl.h>
00059 #endif
00060 
00061 #include <jwsc/base/bits.h>
00062 #include <jwsc/vector/vector.h>
00063 #include <jwsc/vector/vector_math.h>
00064 #include <jwsc/matrix/matrix.h>
00065 #include <jwsc/matrix/matrix_math.h>
00066 
00067 #include <jwsc++/base/exception.h>
00068 #include <jwsc++/graphics/polygon.h>
00069 #include <jwsc++/graphics/parapiped.h>
00070 
00071 #ifdef JWSCXX_HAVE_DMALLOC
00072 #include <dmalloc.h>
00073 #endif
00074 
00075 
00076 using namespace jwscxx::base;
00077 using namespace jwscxx::graphics;
00078 
00079 
00080 static void create_adjacency(jwsc::Matrix_u32** adjacency_out)
00081 {
00082     using namespace jwsc;
00083 
00084     create_matrix_u32(adjacency_out, 6, 4);
00085     Matrix_u32* adjacency = *adjacency_out;
00086 
00087     adjacency->elts[5][0] = 1;
00088     adjacency->elts[5][1] = 2;
00089     adjacency->elts[5][2] = 0;
00090     adjacency->elts[5][3] = 3;
00091 
00092     adjacency->elts[3][0] = 0;
00093     adjacency->elts[3][1] = 4;
00094     adjacency->elts[3][2] = 1;
00095     adjacency->elts[3][3] = 5;
00096 
00097     adjacency->elts[0][0] = 2;
00098     adjacency->elts[0][1] = 4;
00099     adjacency->elts[0][2] = 3;
00100     adjacency->elts[0][3] = 5;
00101 
00102     adjacency->elts[2][0] = 0;
00103     adjacency->elts[2][1] = 5;
00104     adjacency->elts[2][2] = 1;
00105     adjacency->elts[2][3] = 4;
00106 
00107     adjacency->elts[4][0] = 2;
00108     adjacency->elts[4][1] = 1;
00109     adjacency->elts[4][2] = 3;
00110     adjacency->elts[4][3] = 0;
00111 
00112     adjacency->elts[1][0] = 3;
00113     adjacency->elts[1][1] = 4;
00114     adjacency->elts[1][2] = 2;
00115     adjacency->elts[1][3] = 5;
00116 }
00117 
00118 
00165 Parapiped_f::Parapiped_f
00166 (
00167     float x1, float y1, float z1,
00168     float x2, float y2, float z2,
00169     float x3, float y3, float z3,
00170     float x4, float y4, float z4
00171 )
00172 : faces(6, (Polygon_f*)0), points(4, (jwsc::Vector_f*)0)
00173 {
00174     using namespace jwsc;
00175 
00176     center = 0;
00177     adjacency = 0;
00178 
00179     faces[5] = new Polygon_f(4);
00180     faces[5]->add_point(x1, y1, z1);
00181     faces[5]->add_point(x1 + (x3 - x2), y1 + (y3 - y2), z1 + (z3 - z2));
00182     faces[5]->add_point(x3, y3, z3);
00183     faces[5]->add_point(x2, y2, z2);
00184 
00185     faces[3] = new Polygon_f(4);
00186     faces[3]->add_point(x2, y2, z2);
00187     faces[3]->add_point(x2 + (x4 - x3), y2 + (y4 - y3), z2 + (z4 - z3));
00188     faces[3]->add_point(x1 + (x4 - x3), y1 + (y4 - y3), z1 + (z4 - z3));
00189     faces[3]->add_point(x1, y1, z1);
00190 
00191     faces[0] = new Polygon_f(4);
00192     faces[0]->add_point(x3, y3, z3);
00193     faces[0]->add_point(x4, y4, z4);
00194     faces[0]->add_point(x2 + (x4 - x3), y2 + (y4 - y3), z2 + (z4 - z3));
00195     faces[0]->add_point(x2, y2, z2);
00196 
00197     faces[2] = new Polygon_f(4);
00198     faces[2]->add_point(x4, y4, z4);
00199     faces[2]->add_point(x3, y3, z3);
00200     faces[2]->add_point(x3 + (x1 - x2), y3 + (y1 - y2), z3 + (z1 - z2));
00201     faces[2]->add_point(x4 + (x1 - x2), y4 + (y1 - y2), z4 + (z1 - z2));
00202 
00203     faces[4] = new Polygon_f(4);
00204     faces[4]->add_point(x4, y4, z4);
00205     faces[4]->add_point(x4 + (x1 - x2), y4 + (y1 - y2), z4 + (z1 - z2));
00206     faces[4]->add_point(x1 + (x4 - x3), y1 + (y4 - y3), z1 + (z4 - z3));
00207     faces[4]->add_point(x2 + (x4 - x3), y2 + (y4 - y3), z2 + (z4 - z3));
00208 
00209     faces[1] = new Polygon_f(4);
00210     faces[1]->add_point(x1, y1, z1);
00211     faces[1]->add_point(x1 + (x4 - x3), y1 + (y4 - y3), z1 + (z4 - z3));
00212     faces[1]->add_point(x4 + (x1 - x2), y4 + (y1 - y2), z4 + (z1 - z2));
00213     faces[1]->add_point(x3 + (x1 - x2), y3 + (y1 - y2), z3 + (z1 - z2));
00214 
00215     create_init_vector_f(&(points[0]), 4, 1);
00216     points[0]->elts[0] = x1;
00217     points[0]->elts[1] = y1;
00218     points[0]->elts[2] = z1;
00219 
00220     create_init_vector_f(&(points[1]), 4, 1);
00221     points[1]->elts[0] = x2;
00222     points[1]->elts[1] = y2;
00223     points[1]->elts[2] = z2;
00224 
00225     create_init_vector_f(&(points[2]), 4, 1);
00226     points[2]->elts[0] = x3;
00227     points[2]->elts[1] = y3;
00228     points[2]->elts[2] = z3;
00229 
00230     create_init_vector_f(&(points[3]), 4, 1);
00231     points[3]->elts[0] = x4;
00232     points[3]->elts[1] = y4;
00233     points[3]->elts[2] = z4;
00234 
00235     create_zero_vector_f(&center, 4);
00236     create_adjacency(&adjacency);
00237 
00238     for (size_t i = 0; i < 6; i++)
00239     {
00240         const Vector_f* centroid = faces[ i ]->get_centroid();
00241 
00242         // Ignore the homogeneous coordinate, since it must be 1.
00243         center->elts[0] += centroid->elts[0];
00244         center->elts[1] += centroid->elts[1];
00245         center->elts[2] += centroid->elts[2];
00246     }
00247 
00248     center->elts[0] /= 6.0f;
00249     center->elts[1] /= 6.0f;
00250     center->elts[2] /= 6.0f;
00251     center->elts[3]  = 1.0f;
00252 }
00253 
00254 
00292 Parapiped_f::Parapiped_f
00293 (
00294     const jwsc::Vector_f* p1, 
00295     const jwsc::Vector_f* p2, 
00296     const jwsc::Vector_f* p3, 
00297     const jwsc::Vector_f* p4
00298 )
00299 throw (jwscxx::base::Arg_error)
00300 : faces(6, (Polygon_f*)0), points(4, (jwsc::Vector_f*)0)
00301 {
00302     using namespace jwsc;
00303 
00304     center = 0;
00305     adjacency = 0;
00306 
00307     if (p1->num_elts != 3 || p2->num_elts != 3 ||
00308         p3->num_elts != 3 || p4->num_elts != 3)
00309     {
00310         throw Arg_error("Vectors for parapiped not 3D");
00311     }
00312 
00313     float x1 = p1->elts[0]; float y1 = p1->elts[1]; float z1 = p1->elts[2];
00314     float x2 = p2->elts[0]; float y2 = p2->elts[1]; float z2 = p2->elts[2];
00315     float x3 = p3->elts[0]; float y3 = p3->elts[1]; float z3 = p3->elts[2];
00316     float x4 = p4->elts[0]; float y4 = p4->elts[1]; float z4 = p4->elts[2];
00317 
00318     faces[5] = new Polygon_f(4);
00319     faces[5]->add_point(x1, y1, z1);
00320     faces[5]->add_point(x1 + (x3 - x2), y1 + (y3 - y2), z1 + (z3 - z2));
00321     faces[5]->add_point(x3, y3, z3);
00322     faces[5]->add_point(x2, y2, z2);
00323 
00324     faces[3] = new Polygon_f(4);
00325     faces[3]->add_point(x2, y2, z2);
00326     faces[3]->add_point(x2 + (x4 - x3), y2 + (y4 - y3), z2 + (z4 - z3));
00327     faces[3]->add_point(x1 + (x4 - x3), y1 + (y4 - y3), z1 + (z4 - z3));
00328     faces[3]->add_point(x1, y1, z1);
00329 
00330     faces[0] = new Polygon_f(4);
00331     faces[0]->add_point(x3, y3, z3);
00332     faces[0]->add_point(x4, y4, z4);
00333     faces[0]->add_point(x2 + (x4 - x3), y2 + (y4 - y3), z2 + (z4 - z3));
00334     faces[0]->add_point(x2, y2, z2);
00335 
00336     faces[2] = new Polygon_f(4);
00337     faces[2]->add_point(x4, y4, z4);
00338     faces[2]->add_point(x3, y3, z3);
00339     faces[2]->add_point(x3 + (x1 - x2), y3 + (y1 - y2), z3 + (z1 - z2));
00340     faces[2]->add_point(x4 + (x1 - x2), y4 + (y1 - y2), z4 + (z1 - z2));
00341 
00342     faces[4] = new Polygon_f(4);
00343     faces[4]->add_point(x4, y4, z4);
00344     faces[4]->add_point(x4 + (x1 - x2), y4 + (y1 - y2), z4 + (z1 - z2));
00345     faces[4]->add_point(x1 + (x4 - x3), y1 + (y4 - y3), z1 + (z4 - z3));
00346     faces[4]->add_point(x2 + (x4 - x3), y2 + (y4 - y3), z2 + (z4 - z3));
00347 
00348     faces[1] = new Polygon_f(4);
00349     faces[1]->add_point(x1, y1, z1);
00350     faces[1]->add_point(x1 + (x4 - x3), y1 + (y4 - y3), z1 + (z4 - z3));
00351     faces[1]->add_point(x4 + (x1 - x2), y4 + (y1 - y2), z4 + (z1 - z2));
00352     faces[1]->add_point(x3 + (x1 - x2), y3 + (y1 - y2), z3 + (z1 - z2));
00353 
00354     create_init_vector_f(&(points[0]), 4, 1);
00355     points[0]->elts[0] = x1;
00356     points[0]->elts[1] = y1;
00357     points[0]->elts[2] = z1;
00358 
00359     create_init_vector_f(&(points[1]), 4, 1);
00360     points[1]->elts[0] = x2;
00361     points[1]->elts[1] = y2;
00362     points[1]->elts[2] = z2;
00363 
00364     create_init_vector_f(&(points[2]), 4, 1);
00365     points[2]->elts[0] = x3;
00366     points[2]->elts[1] = y3;
00367     points[2]->elts[2] = z3;
00368 
00369     create_init_vector_f(&(points[3]), 4, 1);
00370     points[3]->elts[0] = x4;
00371     points[3]->elts[1] = y4;
00372     points[3]->elts[2] = z4;
00373 
00374     create_zero_vector_f(&center, 4);
00375     create_adjacency(&adjacency);
00376 
00377     for (size_t i = 0; i < 6; i++)
00378     {
00379         const Vector_f* centroid = faces[ i ]->get_centroid();
00380 
00381         // Ignore the homogeneous coordinate, since it must be 1.
00382         center->elts[0] += centroid->elts[0];
00383         center->elts[1] += centroid->elts[1];
00384         center->elts[2] += centroid->elts[2];
00385     }
00386 
00387     center->elts[0] /= 6.0f;
00388     center->elts[1] /= 6.0f;
00389     center->elts[2] /= 6.0f;
00390     center->elts[3]  = 1.0f;
00391 }
00392 
00393 
00395 Parapiped_f::Parapiped_f(const Parapiped_f& p)
00396     : faces(6, (Polygon_f*)0), points(4, (jwsc::Vector_f*)0)
00397 {
00398     center = 0;
00399 
00400     for (size_t i = 0; i < 6; i++)
00401     {
00402         faces[ i ] = p.faces[ i ]->clone();
00403     }
00404 
00405     for (size_t i = 0; i < 4; i++)
00406     {
00407         copy_vector_f(&(points[ i ]), p.points[ i ]);
00408     }
00409 
00410     copy_vector_f(&center, p.center);
00411     copy_matrix_u32(&adjacency, p.adjacency);
00412 }
00413 
00414 
00423 Parapiped_f::Parapiped_f(const char* fname) 
00424     throw (jwscxx::base::Arg_error, jwscxx::base::IO_error)
00425     : faces(6, (Polygon_f*)0), points(4, (jwsc::Vector_f*)0)
00426 {
00427     center = 0;
00428     adjacency = 0;
00429 
00430     jwscxx::base::Readable::read(fname);
00431 }
00432 
00433 
00442 Parapiped_f::Parapiped_f(std::istream& in)
00443     throw (jwscxx::base::Arg_error, jwscxx::base::IO_error)
00444     : faces(6, (Polygon_f*)0), points(4, (jwsc::Vector_f*)0)
00445 {
00446     center = 0;
00447     adjacency = 0;
00448 
00449     read(in);
00450 }
00451 
00452 
00454 Parapiped_f::~Parapiped_f()
00455 {
00456     for (size_t i = 0; i < 6; i++)
00457     {
00458         delete faces[ i ];
00459     }
00460 
00461     for (size_t i = 0; i < 4; i++)
00462     {
00463         free_vector_f(points[ i ]);
00464     }
00465 
00466     free_vector_f(center);
00467     free_matrix_u32(adjacency);
00468 }
00469 
00470 
00478 Parapiped_f& Parapiped_f::operator= (const Parapiped_f& p)
00479 {
00480     // Don't try to assign to self.
00481     if (points[0] == p.points[0])
00482         return *this;
00483 
00484     for (size_t i = 0; i < 6; i++)
00485     {
00486         *(faces[ i ]) = *(p.faces[ i ]);
00487     }
00488 
00489     for (size_t i = 0; i < 4; i++)
00490     {
00491         copy_vector_f(&(points[ i ]), p.points[ i ]);
00492     }
00493 
00494     copy_vector_f(&center, p.center);
00495     copy_matrix_u32(&adjacency, p.adjacency);
00496 
00497     return *this;
00498 }
00499 
00500 
00502 Parapiped_f* Parapiped_f::clone() const
00503 {
00504     return new Parapiped_f(*this);
00505 }
00506 
00507 
00508 size_t Parapiped_f::num_faces() const
00509 {
00510     return 6;
00511 }
00512 
00513 
00514 const jwsc::Vector_f* Parapiped_f::get_point(size_t i) const
00515     throw (jwscxx::base::Arg_error)
00516 {
00517     if (i >= 4)
00518     { 
00519         throw jwscxx::base::Arg_error("Invalid point index"); 
00520     }
00521 
00522     return static_cast<const jwsc::Vector_f*>(points[ i ]);
00523 }
00524 
00525 
00530 const jwsc::Vector_f* Parapiped_f::get_center() const 
00531 { 
00532     return center; 
00533 }
00534 
00535 
00543 const jwscxx::graphics::Polygon_f* Parapiped_f::get_face(size_t i) const 
00544     throw (jwscxx::base::Arg_error)
00545 { 
00546     if (i >= 6)
00547     { 
00548         throw jwscxx::base::Arg_error("Invalid face index"); 
00549     }
00550 
00551     return static_cast<const jwscxx::graphics::Polygon_f*>(faces[ i ]);
00552 }
00553 
00554 
00556 const std::vector<const jwscxx::graphics::Polygon_f*>& Parapiped_f::get_faces() 
00557     const
00558 {
00559     return (const std::vector<const jwscxx::graphics::Polygon_f*>&)(faces);
00560 }
00561 
00562 
00570 void Parapiped_f::set_face_id(size_t i, uint32_t id)
00571     throw (jwscxx::base::Arg_error)
00572 {
00573     if (i >= 6)
00574     {
00575         throw jwscxx::base::Arg_error("Invalid face index");
00576     }
00577 
00578     faces[ i ]->set_id(id);
00579 }
00580 
00581 
00588 void Parapiped_f::read(std::istream& in) throw (jwscxx::base::IO_error,
00589         jwscxx::base::Arg_error)
00590 {
00591     using namespace jwsc;
00592 
00593     for (size_t i = 0; i < 6; i++)
00594     {
00595         if (faces[ i ] == 0)
00596         {
00597             faces[ i ] = new Polygon_f(4);
00598         }
00599         faces[ i ]->read(in);
00600     }
00601 
00602     assert(sizeof(float) == sizeof(uint32_t));
00603 
00604     float x, y, z, w;
00605 
00606     for (size_t i = 0; i < 4; i++)
00607     {
00608         in.read((char*)&x, sizeof(float));
00609         in.read((char*)&y, sizeof(float));
00610         in.read((char*)&z, sizeof(float));
00611         in.read((char*)&w, sizeof(float));
00612         if (in.fail() || in.eof())
00613         {
00614             throw IO_error("Could not read point");
00615         }
00616 
00617 #ifndef JWSC_BIGENDIAN
00618         bswap_u32((uint32_t*)&(x));
00619         bswap_u32((uint32_t*)&(y));
00620         bswap_u32((uint32_t*)&(z));
00621         bswap_u32((uint32_t*)&(w));
00622 #endif
00623 
00624         create_vector_f(&(points[ i ]), 4);
00625         points[ i ]->elts[0] = x;
00626         points[ i ]->elts[1] = y;
00627         points[ i ]->elts[2] = z;
00628         points[ i ]->elts[3] = w;
00629     }
00630 
00631     in.read((char*)&x, sizeof(float));
00632     in.read((char*)&y, sizeof(float));
00633     in.read((char*)&z, sizeof(float));
00634     in.read((char*)&w, sizeof(float));
00635     if (in.fail() || in.eof())
00636     {
00637         throw IO_error("Could not read center");
00638     }
00639 
00640 #ifndef JWSC_BIGENDIAN
00641     bswap_u32((uint32_t*)&(x));
00642     bswap_u32((uint32_t*)&(y));
00643     bswap_u32((uint32_t*)&(z));
00644     bswap_u32((uint32_t*)&(w));
00645 #endif
00646 
00647     create_vector_f(&center, 4);
00648     center->elts[0] = x;
00649     center->elts[1] = y;
00650     center->elts[2] = z;
00651     center->elts[3] = w;
00652 
00653     create_adjacency(&adjacency);
00654 }
00655 
00656 
00664 void Parapiped_f::write(std::ostream& out) const throw (jwscxx::base::IO_error)
00665 {
00666     using namespace jwsc;
00667 
00668     for (size_t i = 0; i < 6; i++)
00669     {
00670         faces[ i ]->write(out);
00671     }
00672 
00673     assert(sizeof(float) == sizeof(uint32_t));
00674 
00675     for (size_t i = 0; i < 4; i++)
00676     {
00677         float x = points[ i ]->elts[0];
00678         float y = points[ i ]->elts[1];
00679         float z = points[ i ]->elts[2];
00680         float w = points[ i ]->elts[3];
00681 
00682 #ifndef JWSC_BIGENDIAN
00683         bswap_u32((uint32_t*)&(x));
00684         bswap_u32((uint32_t*)&(y));
00685         bswap_u32((uint32_t*)&(z));
00686         bswap_u32((uint32_t*)&(w));
00687 #endif
00688 
00689         out.write((char*)&x, sizeof(float));
00690         out.write((char*)&y, sizeof(float));
00691         out.write((char*)&z, sizeof(float));
00692         out.write((char*)&w, sizeof(float));
00693         if (out.fail() || out.eof())
00694         {
00695             throw IO_error("Could not write point");
00696         }
00697     }
00698 
00699     float x = center->elts[0];
00700     float y = center->elts[1];
00701     float z = center->elts[2];
00702     float w = center->elts[3];
00703 
00704 #ifndef JWSC_BIGENDIAN
00705     bswap_u32((uint32_t*)&(x));
00706     bswap_u32((uint32_t*)&(y));
00707     bswap_u32((uint32_t*)&(z));
00708     bswap_u32((uint32_t*)&(w));
00709 #endif
00710 
00711     out.write((char*)&x, sizeof(float));
00712     out.write((char*)&y, sizeof(float));
00713     out.write((char*)&z, sizeof(float));
00714     out.write((char*)&w, sizeof(float));
00715     if (out.fail() || out.eof())
00716     {
00717         throw IO_error("Could not write center");
00718     }
00719 }
00720 
00721 
00729 void Parapiped_f::transform(const jwsc::Matrix_f* M) 
00730     throw (jwscxx::base::Arg_error)
00731 {
00732     for (size_t i = 0; i < 6; i++)
00733     {
00734         faces[ i ]->transform(M);
00735     }
00736 
00737     for (size_t i = 0; i < 4; i++)
00738     {
00739         multiply_matrix_and_vector_f(&(points[ i ]), M, points[ i ]);
00740     }
00741 
00742     // Transform the center.
00743     multiply_matrix_and_vector_f(&center, M, center);
00744 }
00745 
00746 
00748 void Parapiped_f::wire_render() const
00749 {
00750     for (size_t i = 0; i < 6; i++)
00751     {
00752         faces[ i ]->wire_render();
00753     }
00754 }
00755 
00756 
00763 void Parapiped_f::wire_occlude_render() const
00764 {
00765     for (size_t i = 0; i < 6; i++)
00766     {
00767         faces[ i ]->wire_occlude_render();
00768     }
00769 }
00770 
00771 
00773 void Parapiped_f::solid_render() const
00774 {
00775     for (size_t i = 0; i < 6; i++)
00776     {
00777         faces[ i ]->solid_render();
00778     }
00779 }
00780 
00781 
00789 void Parapiped_f::project()
00790 {
00791     for (size_t i = 0; i < 6; i++)
00792     {
00793         faces[ i ]->project();
00794     }
00795 }
00796 
00797 
00808 uint32_t Parapiped_f::adjacent_face(uint32_t i, uint32_t p) const 
00809     throw (jwscxx::base::Arg_error)
00810 {
00811     if (i >= 6)
00812     { 
00813         throw jwscxx::base::Arg_error("Invalid face index"); 
00814     }
00815     if (p > 3)
00816     {
00817         throw jwscxx::base::Arg_error("Invalid face point index");
00818     }
00819 
00820     return adjacency->elts[ i ][ p ];
00821 }
00822 
00823 
00870 Parapiped_d::Parapiped_d
00871 (
00872     double x1, double y1, double z1,
00873     double x2, double y2, double z2,
00874     double x3, double y3, double z3,
00875     double x4, double y4, double z4
00876 )
00877 : faces(6, (Polygon_d*)0), points(4, (jwsc::Vector_d*)0)
00878 {
00879     using namespace jwsc;
00880 
00881     center = 0;
00882     adjacency = 0;
00883 
00884     faces[5] = new Polygon_d(4);
00885     faces[5]->add_point(x1, y1, z1);
00886     faces[5]->add_point(x1 + (x3 - x2), y1 + (y3 - y2), z1 + (z3 - z2));
00887     faces[5]->add_point(x3, y3, z3);
00888     faces[5]->add_point(x2, y2, z2);
00889 
00890     faces[3] = new Polygon_d(4);
00891     faces[3]->add_point(x2, y2, z2);
00892     faces[3]->add_point(x2 + (x4 - x3), y2 + (y4 - y3), z2 + (z4 - z3));
00893     faces[3]->add_point(x1 + (x4 - x3), y1 + (y4 - y3), z1 + (z4 - z3));
00894     faces[3]->add_point(x1, y1, z1);
00895 
00896     faces[0] = new Polygon_d(4);
00897     faces[0]->add_point(x3, y3, z3);
00898     faces[0]->add_point(x4, y4, z4);
00899     faces[0]->add_point(x2 + (x4 - x3), y2 + (y4 - y3), z2 + (z4 - z3));
00900     faces[0]->add_point(x2, y2, z2);
00901 
00902     faces[2] = new Polygon_d(4);
00903     faces[2]->add_point(x4, y4, z4);
00904     faces[2]->add_point(x3, y3, z3);
00905     faces[2]->add_point(x3 + (x1 - x2), y3 + (y1 - y2), z3 + (z1 - z2));
00906     faces[2]->add_point(x4 + (x1 - x2), y4 + (y1 - y2), z4 + (z1 - z2));
00907 
00908     faces[4] = new Polygon_d(4);
00909     faces[4]->add_point(x4, y4, z4);
00910     faces[4]->add_point(x4 + (x1 - x2), y4 + (y1 - y2), z4 + (z1 - z2));
00911     faces[4]->add_point(x1 + (x4 - x3), y1 + (y4 - y3), z1 + (z4 - z3));
00912     faces[4]->add_point(x2 + (x4 - x3), y2 + (y4 - y3), z2 + (z4 - z3));
00913 
00914     faces[1] = new Polygon_d(4);
00915     faces[1]->add_point(x1, y1, z1);
00916     faces[1]->add_point(x1 + (x4 - x3), y1 + (y4 - y3), z1 + (z4 - z3));
00917     faces[1]->add_point(x4 + (x1 - x2), y4 + (y1 - y2), z4 + (z1 - z2));
00918     faces[1]->add_point(x3 + (x1 - x2), y3 + (y1 - y2), z3 + (z1 - z2));
00919 
00920     create_init_vector_d(&(points[0]), 4, 1);
00921     points[0]->elts[0] = x1;
00922     points[0]->elts[1] = y1;
00923     points[0]->elts[2] = z1;
00924 
00925     create_init_vector_d(&(points[1]), 4, 1);
00926     points[1]->elts[0] = x2;
00927     points[1]->elts[1] = y2;
00928     points[1]->elts[2] = z2;
00929 
00930     create_init_vector_d(&(points[2]), 4, 1);
00931     points[2]->elts[0] = x3;
00932     points[2]->elts[1] = y3;
00933     points[2]->elts[2] = z3;
00934 
00935     create_init_vector_d(&(points[3]), 4, 1);
00936     points[3]->elts[0] = x4;
00937     points[3]->elts[1] = y4;
00938     points[3]->elts[2] = z4;
00939 
00940     create_zero_vector_d(&center, 4);
00941     create_adjacency(&adjacency);
00942 
00943     for (size_t i = 0; i < 6; i++)
00944     {
00945         const Vector_d* centroid = faces[ i ]->get_centroid();
00946 
00947         // Ignore the homogeneous coordinate, since it must be 1.
00948         center->elts[0] += centroid->elts[0];
00949         center->elts[1] += centroid->elts[1];
00950         center->elts[2] += centroid->elts[2];
00951     }
00952 
00953     center->elts[0] /= 6.0;
00954     center->elts[1] /= 6.0;
00955     center->elts[2] /= 6.0;
00956     center->elts[3]  = 1.0;
00957 }
00958 
00959 
00997 Parapiped_d::Parapiped_d
00998 (
00999     const jwsc::Vector_d* p1, 
01000     const jwsc::Vector_d* p2, 
01001     const jwsc::Vector_d* p3, 
01002     const jwsc::Vector_d* p4
01003 )
01004 throw (jwscxx::base::Arg_error)
01005 : faces(6, (Polygon_d*)0), points(4, (jwsc::Vector_d*)0)
01006 {
01007     using namespace jwsc;
01008 
01009     center = 0;
01010     adjacency = 0;
01011 
01012     if (p1->num_elts != 3 || p2->num_elts != 3 ||
01013         p3->num_elts != 3 || p4->num_elts != 3)
01014     {
01015         throw Arg_error("Vectors for parapiped not 3D");
01016     }
01017 
01018     double x1 = p1->elts[0]; double y1 = p1->elts[1]; double z1 = p1->elts[2];
01019     double x2 = p2->elts[0]; double y2 = p2->elts[1]; double z2 = p2->elts[2];
01020     double x3 = p3->elts[0]; double y3 = p3->elts[1]; double z3 = p3->elts[2];
01021     double x4 = p4->elts[0]; double y4 = p4->elts[1]; double z4 = p4->elts[2];
01022 
01023     faces[5] = new Polygon_d(4);
01024     faces[5]->add_point(x1, y1, z1);
01025     faces[5]->add_point(x1 + (x3 - x2), y1 + (y3 - y2), z1 + (z3 - z2));
01026     faces[5]->add_point(x3, y3, z3);
01027     faces[5]->add_point(x2, y2, z2);
01028 
01029     faces[3] = new Polygon_d(4);
01030     faces[3]->add_point(x2, y2, z2);
01031     faces[3]->add_point(x2 + (x4 - x3), y2 + (y4 - y3), z2 + (z4 - z3));
01032     faces[3]->add_point(x1 + (x4 - x3), y1 + (y4 - y3), z1 + (z4 - z3));
01033     faces[3]->add_point(x1, y1, z1);
01034 
01035     faces[0] = new Polygon_d(4);
01036     faces[0]->add_point(x3, y3, z3);
01037     faces[0]->add_point(x4, y4, z4);
01038     faces[0]->add_point(x2 + (x4 - x3), y2 + (y4 - y3), z2 + (z4 - z3));
01039     faces[0]->add_point(x2, y2, z2);
01040 
01041     faces[2] = new Polygon_d(4);
01042     faces[2]->add_point(x4, y4, z4);
01043     faces[2]->add_point(x3, y3, z3);
01044     faces[2]->add_point(x3 + (x1 - x2), y3 + (y1 - y2), z3 + (z1 - z2));
01045     faces[2]->add_point(x4 + (x1 - x2), y4 + (y1 - y2), z4 + (z1 - z2));
01046 
01047     faces[4] = new Polygon_d(4);
01048     faces[4]->add_point(x4, y4, z4);
01049     faces[4]->add_point(x4 + (x1 - x2), y4 + (y1 - y2), z4 + (z1 - z2));
01050     faces[4]->add_point(x1 + (x4 - x3), y1 + (y4 - y3), z1 + (z4 - z3));
01051     faces[4]->add_point(x2 + (x4 - x3), y2 + (y4 - y3), z2 + (z4 - z3));
01052 
01053     faces[1] = new Polygon_d(4);
01054     faces[1]->add_point(x1, y1, z1);
01055     faces[1]->add_point(x1 + (x4 - x3), y1 + (y4 - y3), z1 + (z4 - z3));
01056     faces[1]->add_point(x4 + (x1 - x2), y4 + (y1 - y2), z4 + (z1 - z2));
01057     faces[1]->add_point(x3 + (x1 - x2), y3 + (y1 - y2), z3 + (z1 - z2));
01058 
01059     create_init_vector_d(&(points[0]), 4, 1);
01060     points[0]->elts[0] = x1;
01061     points[0]->elts[1] = y1;
01062     points[0]->elts[2] = z1;
01063 
01064     create_init_vector_d(&(points[1]), 4, 1);
01065     points[1]->elts[0] = x2;
01066     points[1]->elts[1] = y2;
01067     points[1]->elts[2] = z2;
01068 
01069     create_init_vector_d(&(points[2]), 4, 1);
01070     points[2]->elts[0] = x3;
01071     points[2]->elts[1] = y3;
01072     points[2]->elts[2] = z3;
01073 
01074     create_init_vector_d(&(points[3]), 4, 1);
01075     points[3]->elts[0] = x4;
01076     points[3]->elts[1] = y4;
01077     points[3]->elts[2] = z4;
01078 
01079     create_zero_vector_d(&center, 4);
01080     create_adjacency(&adjacency);
01081 
01082     for (size_t i = 0; i < 6; i++)
01083     {
01084         const Vector_d* centroid = faces[ i ]->get_centroid();
01085 
01086         // Ignore the homogeneous coordinate, since it must be 1.
01087         center->elts[0] += centroid->elts[0];
01088         center->elts[1] += centroid->elts[1];
01089         center->elts[2] += centroid->elts[2];
01090     }
01091 
01092     center->elts[0] /= 6.0;
01093     center->elts[1] /= 6.0;
01094     center->elts[2] /= 6.0;
01095     center->elts[3]  = 1.0;
01096 }
01097 
01098 
01100 Parapiped_d::Parapiped_d(const Parapiped_d& p)
01101     : faces(6, (Polygon_d*)0), points(4, (jwsc::Vector_d*)0)
01102 {
01103     center = 0;
01104     adjacency = 0;
01105 
01106     for (size_t i = 0; i < 6; i++)
01107     {
01108         faces[ i ] = p.faces[ i ]->clone();
01109     }
01110 
01111     for (size_t i = 0; i < 4; i++)
01112     {
01113         copy_vector_d(&(points[ i ]), p.points[ i ]);
01114     }
01115 
01116     copy_vector_d(&center, p.center);
01117     copy_matrix_u32(&adjacency, p.adjacency);
01118 }
01119 
01120 
01129 Parapiped_d::Parapiped_d(const char* fname) 
01130     throw (jwscxx::base::Arg_error, jwscxx::base::IO_error)
01131     : faces(6, (Polygon_d*)0), points(4, (jwsc::Vector_d*)0)
01132 {
01133     center = 0;
01134     adjacency = 0;
01135 
01136     jwscxx::base::Readable::read(fname);
01137 }
01138 
01139 
01148 Parapiped_d::Parapiped_d(std::istream& in)
01149     throw (jwscxx::base::Arg_error, jwscxx::base::IO_error)
01150     : faces(6, (Polygon_d*)0), points(4, (jwsc::Vector_d*)0)
01151 {
01152     center = 0;
01153     adjacency = 0;
01154 
01155     read(in);
01156 }
01157 
01158 
01160 Parapiped_d::~Parapiped_d()
01161 {
01162     for (size_t i = 0; i < 6; i++)
01163     {
01164         delete faces[ i ];
01165     }
01166 
01167     for (size_t i = 0; i < 4; i++)
01168     {
01169         free_vector_d(points[ i ]);
01170     }
01171 
01172     free_vector_d(center);
01173     free_matrix_u32(adjacency);
01174 }
01175 
01176 
01184 Parapiped_d& Parapiped_d::operator= (const Parapiped_d& p)
01185 {
01186     // Don't try to assign to self.
01187     if (points[0] == p.points[0])
01188         return *this;
01189 
01190     for (size_t i = 0; i < 6; i++)
01191     {
01192         *(faces[ i ]) = *(p.faces[ i ]);
01193     }
01194 
01195     for (size_t i = 0; i < 4; i++)
01196     {
01197         copy_vector_d(&(points[ i ]), p.points[ i ]);
01198     }
01199 
01200     copy_vector_d(&center, p.center);
01201     copy_matrix_u32(&adjacency, p.adjacency);
01202 
01203     return *this;
01204 }
01205 
01206 
01208 Parapiped_d* Parapiped_d::clone() const
01209 {
01210     return new Parapiped_d(*this);
01211 }
01212 
01213 
01214 size_t Parapiped_d::num_faces() const
01215 {
01216     return 6;
01217 }
01218 
01219 
01220 const jwsc::Vector_d* Parapiped_d::get_point(size_t i) const
01221     throw (jwscxx::base::Arg_error)
01222 {
01223     if (i >= 4)
01224     { 
01225         throw jwscxx::base::Arg_error("Invalid point index"); 
01226     }
01227 
01228     return static_cast<const jwsc::Vector_d*>(points[ i ]);
01229 }
01230 
01231 
01236 const jwsc::Vector_d* Parapiped_d::get_center() const 
01237 { 
01238     return center; 
01239 }
01240 
01241 
01249 const jwscxx::graphics::Polygon_d* Parapiped_d::get_face(size_t i) const 
01250     throw (jwscxx::base::Arg_error)
01251 { 
01252     if (i >= 6)
01253     { 
01254         throw jwscxx::base::Arg_error("Invalid face index"); 
01255     }
01256 
01257     return static_cast<const jwscxx::graphics::Polygon_d*>(faces[ i ]);
01258 }
01259 
01260 
01262 const std::vector<const jwscxx::graphics::Polygon_d*>& Parapiped_d::get_faces() 
01263     const
01264 {
01265     return (const std::vector<const jwscxx::graphics::Polygon_d*>&)(faces);
01266 }
01267 
01268 
01276 void Parapiped_d::set_face_id(size_t i, uint32_t id)
01277     throw (jwscxx::base::Arg_error)
01278 {
01279     if (i >= 6)
01280     {
01281         throw jwscxx::base::Arg_error("Invalid face index");
01282     }
01283 
01284     faces[ i ]->set_id(id);
01285 }
01286 
01287 
01294 void Parapiped_d::read(std::istream& in) throw (jwscxx::base::IO_error,
01295         jwscxx::base::Arg_error)
01296 {
01297     using namespace jwsc;
01298 
01299     for (size_t i = 0; i < 6; i++)
01300     {
01301         if (faces[ i ] == 0)
01302         {
01303             faces[ i ] = new Polygon_d(4);
01304         }
01305         faces[ i ]->read(in);
01306     }
01307 
01308     assert(sizeof(double) == sizeof(uint64_t));
01309 
01310     double x, y, z, w;
01311 
01312     for (size_t i = 0; i < 4; i++)
01313     {
01314         in.read((char*)&x, sizeof(double));
01315         in.read((char*)&y, sizeof(double));
01316         in.read((char*)&z, sizeof(double));
01317         in.read((char*)&w, sizeof(double));
01318         if (in.fail() || in.eof())
01319         {
01320             throw IO_error("Could not read point");
01321         }
01322 
01323 #ifndef JWSC_BIGENDIAN
01324         bswap_u64((uint64_t*)&(x));
01325         bswap_u64((uint64_t*)&(y));
01326         bswap_u64((uint64_t*)&(z));
01327         bswap_u64((uint64_t*)&(w));
01328 #endif
01329 
01330         create_vector_d(&(points[ i ]), 4);
01331         points[ i ]->elts[0] = x;
01332         points[ i ]->elts[1] = y;
01333         points[ i ]->elts[2] = z;
01334         points[ i ]->elts[3] = w;
01335     }
01336 
01337     in.read((char*)&x, sizeof(double));
01338     in.read((char*)&y, sizeof(double));
01339     in.read((char*)&z, sizeof(double));
01340     in.read((char*)&w, sizeof(double));
01341     if (in.fail() || in.eof())
01342     {
01343         throw IO_error("Could not read center");
01344     }
01345 
01346 #ifndef JWSC_BIGENDIAN
01347     bswap_u64((uint64_t*)&(x));
01348     bswap_u64((uint64_t*)&(y));
01349     bswap_u64((uint64_t*)&(z));
01350     bswap_u64((uint64_t*)&(w));
01351 #endif
01352 
01353     create_vector_d(&center, 4);
01354     center->elts[0] = x;
01355     center->elts[1] = y;
01356     center->elts[2] = z;
01357     center->elts[3] = w;
01358 
01359     create_adjacency(&adjacency);
01360 }
01361 
01362 
01370 void Parapiped_d::write(std::ostream& out) const throw (jwscxx::base::IO_error)
01371 {
01372     using namespace jwsc;
01373 
01374     for (size_t i = 0; i < 6; i++)
01375     {
01376         faces[ i ]->write(out);
01377     }
01378 
01379     assert(sizeof(double) == sizeof(uint64_t));
01380 
01381     for (size_t i = 0; i < 4; i++)
01382     {
01383         double x = points[ i ]->elts[0];
01384         double y = points[ i ]->elts[1];
01385         double z = points[ i ]->elts[2];
01386         double w = points[ i ]->elts[3];
01387 
01388 #ifndef JWSC_BIGENDIAN
01389         bswap_u64((uint64_t*)&(x));
01390         bswap_u64((uint64_t*)&(y));
01391         bswap_u64((uint64_t*)&(z));
01392         bswap_u64((uint64_t*)&(w));
01393 #endif
01394 
01395         out.write((char*)&x, sizeof(double));
01396         out.write((char*)&y, sizeof(double));
01397         out.write((char*)&z, sizeof(double));
01398         out.write((char*)&w, sizeof(double));
01399         if (out.fail() || out.eof())
01400         {
01401             throw IO_error("Could not write point");
01402         }
01403     }
01404 
01405     double x = center->elts[0];
01406     double y = center->elts[1];
01407     double z = center->elts[2];
01408     double w = center->elts[3];
01409 
01410 #ifndef JWSC_BIGENDIAN
01411     bswap_u64((uint64_t*)&(x));
01412     bswap_u64((uint64_t*)&(y));
01413     bswap_u64((uint64_t*)&(z));
01414     bswap_u64((uint64_t*)&(w));
01415 #endif
01416 
01417     out.write((char*)&x, sizeof(double));
01418     out.write((char*)&y, sizeof(double));
01419     out.write((char*)&z, sizeof(double));
01420     out.write((char*)&w, sizeof(double));
01421     if (out.fail() || out.eof())
01422     {
01423         throw IO_error("Could not write center");
01424     }
01425 }
01426 
01427 
01435 void Parapiped_d::transform(const jwsc::Matrix_d* M) 
01436     throw (jwscxx::base::Arg_error)
01437 {
01438     for (size_t i = 0; i < 6; i++)
01439     {
01440         faces[ i ]->transform(M);
01441     }
01442 
01443     for (size_t i = 0; i < 4; i++)
01444     {
01445         multiply_matrix_and_vector_d(&(points[ i ]), M, points[ i ]);
01446     }
01447 
01448     // Transform the center.
01449     multiply_matrix_and_vector_d(&center, M, center);
01450 }
01451 
01452 
01454 void Parapiped_d::wire_render() const
01455 {
01456     for (size_t i = 0; i < 6; i++)
01457     {
01458         faces[ i ]->wire_render();
01459     }
01460 }
01461 
01462 
01469 void Parapiped_d::wire_occlude_render() const
01470 {
01471     for (size_t i = 0; i < 6; i++)
01472     {
01473         faces[ i ]->wire_occlude_render();
01474     }
01475 }
01476 
01477 
01479 void Parapiped_d::solid_render() const
01480 {
01481     for (size_t i = 0; i < 6; i++)
01482     {
01483         faces[ i ]->solid_render();
01484     }
01485 }
01486 
01487 
01495 void Parapiped_d::project()
01496 {
01497     for (size_t i = 0; i < 6; i++)
01498     {
01499         faces[ i ]->project();
01500     }
01501 }
01502 
01503 
01514 uint32_t Parapiped_d::adjacent_face(uint32_t i, uint32_t p) const 
01515     throw (jwscxx::base::Arg_error)
01516 {
01517     if (i >= 6)
01518     { 
01519         throw jwscxx::base::Arg_error("Invalid face index"); 
01520     }
01521     if (p > 3)
01522     {
01523         throw jwscxx::base::Arg_error("Invalid face point index");
01524     }
01525 
01526     return adjacency->elts[ i ][ p ];
01527 }