Polygon.cc

Go to the documentation of this file.
00001 #include <esg/Definitions.h>
00002 #include <esg/geometry/Polygon.h>
00003 #include <esg/mesh/PolygonMesh.h>
00004 
00005 using namespace esg;
00006 
00007 Mesh* esg::Polygon::_mesh(int) const
00008 {
00009     Mesh *tmp_polyg;
00010 #if defined(_MSC_VER)
00011     unsigned *indices = new unsigned [_nVert];
00012 #else
00013     unsigned indices [_nVert];
00014 #endif
00015 
00016     for (unsigned i = 0; i < _nVert; i++) indices[i] = i;
00017     
00018     if (haveVertNormals()) {
00019         tmp_polyg = (Mesh*) new PolygonMesh(_vertices,
00020                                             indices,
00021                                             _nVert,
00022                                             _normals,
00023                                             indices,
00024                                             _normal,
00025                                             _fxyz);
00026 #if defined(_MSC_VER)
00027         delete [] indices;
00028 #endif
00029         return tmp_polyg;
00030     } else {
00031         tmp_polyg = (Mesh*) new PolygonMesh(_vertices,
00032                                             indices,
00033                                             _nVert,
00034                                             NULL,
00035                                             NULL,
00036                                             _normal,
00037                                             _fxyz);
00038 #if defined(_MSC_VER)
00039         delete [] indices;
00040 #endif
00041         return tmp_polyg;
00042     }
00043 }
00044  
00045 void esg::Polygon::_duplicate_attributes(const Geometry& src)
00046 {
00047     Geometry::_duplicate_attributes(src);
00048 
00049     _nVert = ((Polygon&)src)._nVert;
00050     
00051     _vertices = new Vector3 [_nVert];
00052     for (unsigned i = 0; i < _nVert; i++)
00053         _vertices[i].set(((Polygon&)src)._vertices[i]);
00054     
00055     if (((Polygon&)src)._normals) {
00056         _normals = new Vector3 [_nVert];
00057         for (unsigned i = 0; i < _nVert; i++)
00058             _normals[i].set(((Polygon&)src)._normals[i]);
00059     } else
00060         _normals = NULL;
00061 
00062     if (((Polygon&)src)._uvCoords) {
00063         _uvCoords = new Vector2 [_nVert];
00064         for (unsigned i = 0; i < _nVert; i++)
00065             _uvCoords[i].set(((Polygon&)src)._uvCoords[i]);
00066     } else
00067         _uvCoords = NULL;
00068     
00069     _normal.set(((Polygon&)src)._normal);
00070     _normalFixed = ((Polygon&)src)._normalFixed;
00071     
00072     _fxyz  = ((Polygon&)src)._fxyz;
00073 
00074     _edgeProjection = ((Polygon&)src)._edgeProjection;
00075 
00076     _proj = NULL;
00077     _area = ((Polygon&)src)._area;
00078 }
00079 
00080 Vector3 esg::Polygon::_get_facet_normal() const
00081 {
00082     Vector3 result; // = (0,0,0)
00083     result.cross(_get_vertex(1) - _get_vertex(0),
00084                  _get_vertex(_nVert-1) - _get_vertex(0));
00085     result.normalize();
00086     return result;
00087 }
00088 
00089 Vertex3 esg::Polygon::_get_vertex(unsigned index) const 
00090 {
00091     return _vertices[index];
00092 }
00093 
00094 Vertex3 esg::Polygon::_get_vert_normal(unsigned index) const 
00095 {
00096     return _normals[index];
00097 }
00098 
00099 Vertex2 esg::Polygon::_get_vert_uv_coord(unsigned index) const
00100 {
00101     return _uvCoords[index];
00102 }
00103 
00104 void esg::Polygon::_set_edge_projection(void)
00105 {
00106     // find projection plane
00107     Vector3 absNorm(_normal);
00108     absNorm.absolute();
00109     if (absNorm.x >= absNorm.y && absNorm.x >= absNorm.z)
00110         _edgeProjection = YZ;
00111     else if (absNorm.y >= absNorm.x && absNorm.y >= absNorm.z)
00112         _edgeProjection = XZ;
00113     else
00114         _edgeProjection = XY;
00115 }
00116 
00117 double (*esg::Polygon::_precompute_proj(void)) [6]
00118 {
00119     double (*proj)[6] = new double [_nVert-2][6];
00120     double aux;
00121     Vector3 v0(_get_vertex(0));
00122     for (register unsigned i = 2; i < _nVert; i++) {
00123         switch (_edgeProjection) {
00124         case XY:
00125             proj[i-2][0] = _get_vertex(i-1).x - v0.x;
00126             proj[i-2][1] = _get_vertex(i-1).y - v0.y;
00127             proj[i-2][2] = _get_vertex(i).x   - v0.x;
00128             proj[i-2][3] = _get_vertex(i).y   - v0.y;
00129             break;
00130         case YZ:
00131             proj[i-2][0] = _get_vertex(i-1).y - v0.y;
00132             proj[i-2][1] = _get_vertex(i-1).z - v0.z;
00133             proj[i-2][2] = _get_vertex(i).y   - v0.y;
00134             proj[i-2][3] = _get_vertex(i).z   - v0.z;
00135             break;
00136         case XZ:
00137             proj[i-2][0] = _get_vertex(i-1).x - v0.x;
00138             proj[i-2][1] = _get_vertex(i-1).z - v0.z;
00139             proj[i-2][2] = _get_vertex(i).x   - v0.x;
00140             proj[i-2][3] = _get_vertex(i).z   - v0.z;
00141             break;
00142         case NONE_PROJ:
00143             delete [] proj;
00144             return NULL;
00145         }
00146         aux = proj[i-2][3] * proj[i-2][0] - proj[i-2][2] * proj[i-2][1];
00147         proj[i-2][4] = proj[i-2][0] / aux;
00148         proj[i-2][5] = proj[i-2][1] / aux;
00149     }
00150 
00151     return proj;
00152 }
00153 
00154 bool esg::Polygon::_separation_by_plane(const Geometry& geom) const
00155 {
00156     Interval ext = geom.extent(_normal);
00157     if (ext.min <= _fxyz && _fxyz <= ext.max) return true;
00158     else return false;
00159 }
00160 
00161 bool esg::Polygon::_separation_by_edges(Geometry& geom) const
00162 {
00163     PointEnv pointEnv1, pointEnv2;
00164     Vector3  ray1;
00165     Vector3  ray2;
00166 
00167     for (register unsigned i = 0; i < _nVert; i++) {
00168         Vector3 edge(_get_vertex((i+1)%_nVert) - _get_vertex(i));
00169         
00170         ray1.set(edge);
00171         ray1.normalize();
00172         ray2.set(ray1);
00173         ray2.negate();
00174         
00175         geom.rayIntersection(&pointEnv1,
00176                              ENV_WANT_INTERSECTION,
00177                              _get_vertex(i),
00178                              ray1);
00179         geom.rayIntersection(&pointEnv2,
00180                              ENV_WANT_INTERSECTION,
00181                              _get_vertex(i),
00182                              ray2);
00183         
00184         if ((pointEnv1.mask & ENV_HAVE_INTERSECTION) && // vertex i is inside
00185             (pointEnv2.mask& ENV_HAVE_INTERSECTION)) return false;
00186 
00187         if ((pointEnv1.mask & ENV_HAVE_INTERSECTION) &&
00188             (ray1.dot(pointEnv1.intersection) <= edge.length())) return false;
00189 
00190         if ((pointEnv2.mask & ENV_HAVE_INTERSECTION) &&
00191             (ray2.dot(pointEnv2.intersection) <= edge.length())) return false;
00192     }
00193 
00194     return true;
00195 }
00196 
00197 bool esg::Polygon::_point_inside_polygon(const Vector3& v, Vector3* n, Vector2* uv)
00198 {
00199     /*
00200      * Check if point of intersection is inside the polygon's area
00201      *
00202      * Algorithm reference:
00203      *    Glassner A. S., Graphics Gems, Academic Press Professional,
00204      *    Cambridge, 1990, p. 390-393,735
00205      *
00206      * Here we use a little bit faster implementation.
00207      */
00208 
00209     float   alpha = 0.0, beta = 0.0;
00210     float   ux = 0.0, vx = 0.0;
00211     Vector3 v0(_get_vertex(0));
00212 
00213     switch (_edgeProjection) {
00214     case XY: ux = v.x - v0.x; vx = v.y - v0.y; break;
00215     case YZ: ux = v.y - v0.y; vx = v.z - v0.z; break;
00216     case XZ: ux = v.x - v0.x; vx = v.z - v0.z; break;
00217     case NONE_PROJ: return false;
00218     }
00219 
00220     if (!_proj) _proj = _precompute_proj();
00221     
00222     register unsigned i = 0;
00223     register double*  p = &_proj[0][0]; // fast access to precomputed values
00224     do {
00225         if (*p != 0.) {
00226             beta = vx * *(p+4) - ux * *(p+5);
00227             if ((beta >= 0.) && (beta <= 1.)) {
00228                 alpha = (ux - beta * *(p+2)) / *p;
00229                 if ((alpha >= 0.) && ((alpha+beta) <= 1.)) break;
00230             }
00231         } else {
00232             beta = ux / *(p+2);
00233             if ((beta >= 0.) && (beta <= 1.)) {
00234                 alpha = (vx - beta * *(p+3)) / *(p+1);
00235                 if ((alpha >= 0.) && ((alpha+beta) <= 1.)) break;
00236             }
00237         }
00238         if (++i >= _nVert-2) return false; // point is outside 
00239         p += 6;
00240     } while (true);
00241 
00242     // Tripple (vert[0], vert[i+1], vert[i+2]) determines triangle
00243     // including the point of intersection.
00244 
00245     if (n) { // interpolate normal
00246         n->set(_get_vert_normal(0)   * (1.0 - alpha - beta));
00247         n->add(_get_vert_normal(i+1) * alpha);
00248         n->add(_get_vert_normal(i+2) * beta);
00249     }
00250 
00251     if (uv) { // compute UV coord.  of the point of intersection
00252         uv->set(_get_vert_uv_coord(0)   * (1.0 - alpha - beta));
00253         uv->add(_get_vert_uv_coord(i+1) * alpha);
00254         uv->add(_get_vert_uv_coord(i+2) * beta);
00255     }
00256 
00257     return true;
00258 }
00259 
00260 /* this edge to edge test is based on Franlin Antonio's gem:
00261    "Faster Line Segment Intersection", in Graphics Gems III,
00262    pp. 199-202 */
00263 #define ESG_EDGE_EDGE_TEST(V0,U0,U1)                  \
00264   switch (_edgeProjection) {                          \
00265   case Polygon::XY: Bx=U0.x-U1.x;By=U0.y-U1.y;Cx=V0.x-U0.x;Cy=V0.y-U0.y;break;\
00266   case Polygon::YZ: Bx=U0.y-U1.y;By=U0.z-U1.z;Cx=V0.y-U0.y;Cy=V0.z-U0.z;break;\
00267   case Polygon::XZ: Bx=U0.x-U1.x;By=U0.z-U1.z;Cx=V0.x-U0.x;Cy=V0.z-U0.z;break;\
00268   case Polygon::NONE_PROJ: return false;              \
00269   }                                                   \
00270   f = Ay*Bx-Ax*By;                                    \
00271   d = By*Cx-Bx*Cy;                                    \
00272   if((f>0 && d>=0 && d<=f) || (f<0 && d<=0 && d>=f))  \
00273   {                                                   \
00274     e=Ax*Cy-Ay*Cx;                                    \
00275     if(f>0)                                           \
00276     {                                                 \
00277       if(e>=0 && e<=f) return true;                   \
00278     }                                                 \
00279     else                                              \
00280     {                                                 \
00281       if(e<=0 && e>=f) return true;                   \
00282     }                                                 \
00283   }
00284 
00285 #define ESG_EDGE_AGAINST_TRI_EDGES(V0,V1,U0,U1,U2)             \
00286 {                                                              \
00287   double Ax=0.0,Ay=0.0,Bx=0.0,By=0.0,Cx=0.0,Cy=0.0,e,d,f;      \
00288   switch (p._edgeProjection) {                                 \
00289   case Polygon::XY: Ax = V1.x - V0.x; Ay = V1.y - V0.y; break; \
00290   case Polygon::YZ: Ax = V1.y - V0.y; Ay = V1.z - V0.z; break; \
00291   case Polygon::XZ: Ax = V1.x - V0.x; Ay = V1.z - V0.z; break; \
00292   case Polygon::NONE_PROJ: return false;                       \
00293   }                                                            \
00294   /* test edge U0,U1 against V0,V1 */                          \
00295   ESG_EDGE_EDGE_TEST(V0,U0,U1);                                \
00296   /* test edge U1,U2 against V0,V1 */                          \
00297   ESG_EDGE_EDGE_TEST(V0,U1,U2);                                \
00298   /* test edge U2,U1 against V0,V1 */                          \
00299   ESG_EDGE_EDGE_TEST(V0,U2,U0);                                \
00300 }
00301 
00302 bool esg::Polygon::_coplanar_tri_collision(Polygon&       p,
00303                                       const Vector3& v0,
00304                                       const Vector3& v1,
00305                                       const Vector3& v2,
00306                                       const Vector3& u0,
00307                                       const Vector3& u1,
00308                                       const Vector3& u2)
00309 {
00310     ESG_EDGE_AGAINST_TRI_EDGES(v0,v1,u0,u1,u2);  
00311     ESG_EDGE_AGAINST_TRI_EDGES(v1,v2,u0,u1,u2);
00312     ESG_EDGE_AGAINST_TRI_EDGES(v2,v0,u0,u1,u2);
00313     
00314     /* finally, test if tri1 is totally contained in tri2 or vice versa */
00315     if (_point_inside_polygon(v0, NULL, NULL)) return true;
00316     if (p._point_inside_polygon(u0, NULL, NULL)) return true;
00317     return false;
00318 }
00319 
00320 #undef ESG_EDGE_EDGE_TEST
00321 #undef ESG_AGAINST_TRI_EDGES
00322 
00323 
00324 #define ESG_COMPUTE_INTERVALS(VV0,VV1,VV2,D0,D1,D2,D0D1,D0D2,A,B,C,X0,X1) \
00325 { \
00326         if(D0D1 > 0.0f) { \
00327             /* here we know that D0D2<=0.0 */ \
00328             /* that is D0, D1 are on the same side, D2 on the other */ \
00329             /* or on the plane */ \
00330             A=VV2; B=(VV0-VV2)*D2; C=(VV1-VV2)*D2; X0=D2-D0; X1=D2-D1; \
00331         } else if(D0D2>0.0f) { \
00332             /* here we know that d0d1<=0.0 */ \
00333             A=VV1; B=(VV0-VV1)*D1; C=(VV2-VV1)*D1; X0=D1-D0; X1=D1-D2; \
00334         } else if(D1*D2>0.0f || D0!=0.0f) { \
00335             /* here we know that d0d1<=0.0 or that D0!=0.0 */ \
00336             A=VV0; B=(VV1-VV0)*D0; C=(VV2-VV0)*D0; X0=D0-D1; X1=D0-D2; \
00337         } else if(D1!=0.0f) { \
00338             A=VV1; B=(VV0-VV1)*D1; C=(VV2-VV1)*D1; X0=D1-D0; X1=D1-D2; \
00339         } else if(D2!=0.0f) { \
00340             A=VV2; B=(VV0-VV2)*D2; C=(VV1-VV2)*D2; X0=D2-D0; X1=D2-D1; \
00341         } else { \
00342             /* triangles are coplanar */ \
00343             return _coplanar_tri_collision(p,                             \
00344                                            p2Vertex0,p2Vertex1,p2Vertex2, \
00345                                            p2Vertex0,p2Vertex1,p2Vertex2);\
00346         } \
00347 }
00348 
00349 #define ESG_SORT(a,b) if (a>b) { double c; c=a; a=b; b=c; }
00350 
00351 int esg::Polygon::_triTriCollision(Polygon& p)
00352 {
00353     if (_nVert < 3 || p.numVertices() < 3) return -1;
00354     
00355     double  du0,du1,du2,dv0,dv1,dv2;
00356     Vector3 D;
00357     Vertex3 p1Vertex0(_get_vertex(0));
00358     Vertex3 p1Vertex1(_get_vertex(1));
00359     Vertex3 p1Vertex2(_get_vertex(2));
00360     Vertex3 p2Vertex0(p._get_vertex(0));
00361     Vertex3 p2Vertex1(p._get_vertex(1));
00362     Vertex3 p2Vertex2(p._get_vertex(2));
00363     double  isect1[2], isect2[2];
00364     double  du0du1,du0du2,dv0dv1,dv0dv2;
00365     double  vp0,vp1,vp2;
00366     double  up0,up1,up2;
00367 
00368     // put U0,U1,U2 into plane equation 1 to compute signed
00369     // distances to the plane
00370     du0 = p._normal.dot(p1Vertex0) + p._fxyz;
00371     du1 = p._normal.dot(p1Vertex1) + p._fxyz;
00372     du2 = p._normal.dot(p1Vertex2) + p._fxyz;
00373 
00374     // coplanarity robustness check
00375     if (fabs(du0) < Geometry::EPS) du0 = 0.0;
00376     if (fabs(du1) < Geometry::EPS) du1 = 0.0;
00377     if (fabs(du2) < Geometry::EPS) du2 = 0.0;
00378     
00379     du0du1 = du0 * du1;
00380     du0du2 = du0 * du2;
00381 
00382     // same sign on all of them + not equal 0 => no intersection occurs
00383     if (du0du1 > 0.0 && du0du2 > 0.0) return false;
00384 
00385     // put V0,V1,V2 into plane equation 2 
00386     dv0 = _normal.dot(p2Vertex0) + _fxyz;
00387     dv1 = _normal.dot(p2Vertex1) + _fxyz;
00388     dv2 = _normal.dot(p2Vertex2) + _fxyz;
00389 
00390     if (fabs(dv0) < Geometry::EPS) dv0 = 0.0;
00391     if (fabs(dv1) < Geometry::EPS) dv1 = 0.0;
00392     if (fabs(dv2) < Geometry::EPS) dv2 = 0.0;
00393 
00394     dv0dv1 = dv0 * dv1;
00395     dv0dv2 = dv0 * dv2;
00396 
00397     // same sign on all of them + not equal 0 => no intersection occurs
00398     if (dv0dv1 > 0.0 && dv0dv2 > 0.0) return false;
00399 
00400     // compute direction of intersection line
00401     D.cross(p._normal, _normal);
00402 
00403     // compute and index to the largest component of D
00404     D.absolute();
00405     if (D.x > D.y) {
00406         if (D.x > D.z) {
00407             vp0 = p2Vertex0.x;
00408             vp1 = p2Vertex1.x;
00409             vp2 = p2Vertex2.x;
00410             up0 = p1Vertex0.x;
00411             up1 = p1Vertex1.x;
00412             up2 = p1Vertex2.x;
00413         } else {
00414             vp0 = p2Vertex0.z;
00415             vp1 = p2Vertex1.z;
00416             vp2 = p2Vertex2.z;
00417             up0 = p1Vertex0.z;
00418             up1 = p1Vertex1.z;
00419             up2 = p1Vertex2.z;
00420         }
00421     } else
00422         if (D.y > D.z) {
00423             vp0 = p2Vertex0.y;
00424             vp1 = p2Vertex1.y;
00425             vp2 = p2Vertex2.y;
00426             up0 = p1Vertex0.y;
00427             up1 = p1Vertex1.y;
00428             up2 = p1Vertex2.y;
00429         } else {
00430             vp0 = p2Vertex0.z;
00431             vp1 = p2Vertex1.z;
00432             vp2 = p2Vertex2.z;
00433             up0 = p1Vertex0.z;
00434             up1 = p1Vertex1.z;
00435             up2 = p1Vertex2.z;
00436         }
00437     
00438     // compute interval for triangle 1 
00439     double a,b,c,x0,x1;
00440     ESG_COMPUTE_INTERVALS(vp0,vp1,vp2,dv0,dv1,dv2,dv0dv1,dv0dv2,a,b,c,x0,x1);
00441 
00442     // compute interval for triangle 2 
00443     double d,e,f,y0,y1;
00444     ESG_COMPUTE_INTERVALS(up0,up1,up2,du0,du1,du2,du0du1,du0du2,d,e,f,y0,y1);
00445 
00446     double xx,yy,xxyy,tmp;
00447     xx   = x0 * x1;
00448     yy   = y0 * y1;
00449     xxyy = xx * yy;
00450 
00451     tmp       = a * xxyy;
00452     isect1[0] = tmp + b * x1 * yy;
00453     isect1[1] = tmp + c * x0 * yy;
00454 
00455     tmp       = d * xxyy;
00456     isect2[0] = tmp + e * xx * y1;
00457     isect2[1] = tmp + f * xx * y0;
00458 
00459     ESG_SORT(isect1[0],isect1[1]);
00460     ESG_SORT(isect2[0],isect2[1]);
00461 
00462     return ((isect1[1] < isect2[0] || isect2[1] < isect1[0]) ? false : true);
00463 }
00464 
00465 #undef ESG_COMPUTE_INTERVALS
00466 #undef ESG_SORT
00467 
00468 
00469 void esg::Polygon::_rotateX(float a)
00470 {
00471     Matrix3d trMat;
00472     trMat.rotX(a);
00473     for (unsigned i = 0; i < _nVert; i++) {
00474         trMat.transform(_vertices[i]);
00475         if (haveVertNormals()) trMat.transform(_normals[i]);
00476     }
00477     trMat.transform(_normal);
00478     _set_edge_projection();
00479     if (_proj) { delete [] _proj; _proj = NULL; }
00480     _proj = _precompute_proj();
00481     _fxyz = - _normal.dot(_get_vertex(0));
00482 }
00483 
00484 void esg::Polygon::_rotateY(float a)
00485 {
00486     Matrix3d trMat;
00487     trMat.rotY(a);
00488     for (unsigned i = 0; i < _nVert; i++) {
00489         trMat.transform(_vertices[i]);
00490         if (haveVertNormals()) trMat.transform(_normals[i]);
00491     }
00492     trMat.transform(_normal);
00493     _set_edge_projection();
00494     if (_proj) { delete [] _proj; _proj = NULL; }
00495     _fxyz = - _normal.dot(_get_vertex(0));
00496 }
00497 
00498 void esg::Polygon::_rotateZ(float a)
00499 {
00500     Matrix3d trMat;
00501     trMat.rotZ(a);
00502     for (unsigned i = 0; i < _nVert; i++) {
00503         trMat.transform(_vertices[i]);
00504         if (haveVertNormals()) trMat.transform(_normals[i]);
00505     }
00506     trMat.transform(_normal);
00507     _set_edge_projection();
00508     if (_proj) { delete [] _proj; _proj = NULL; }
00509     _fxyz = - _normal.dot(_get_vertex(0));
00510 }
00511 
00512 void esg::Polygon::_rotate(float a, const Vector3& axis)
00513 {
00514     Matrix4d trMat;
00515     Matrix3d rotMat;
00516     trMat.rotationGL(a, axis);
00517     trMat.get(rotMat);
00518     for (unsigned i = 0; i < _nVert; i++) {
00519         trMat.transform(_vertices[i]);
00520         if (haveVertNormals()) rotMat.transform(_normals[i]);
00521     }
00522     rotMat.transform(_normal);
00523     _set_edge_projection();
00524     if (_proj) { delete [] _proj; _proj = NULL; }
00525     _fxyz = - _normal.dot(_get_vertex(0));
00526 }
00527 
00528 void esg::Polygon::_rotate(const Matrix3& rotMat)
00529 {
00530     for (unsigned i = 0; i < _nVert; i++) {
00531         rotMat.transform(_vertices[i]);
00532         if (haveVertNormals()) rotMat.transform(_normals[i]);
00533     }
00534     rotMat.transform(_normal);
00535     _set_edge_projection();
00536     if (_proj) { delete [] _proj; _proj = NULL; }
00537     _fxyz = - _normal.dot(_get_vertex(0));
00538 }
00539 
00540 void esg::Polygon::_translate(float x, float y, float z)
00541 {
00542     for (unsigned i = 0; i < _nVert; i++) {
00543         _vertices[i].add(Vector3d(x,y,z));
00544     }
00545     _fxyz = - _normal.dot(_get_vertex(0));
00546 }
00547 
00548 void esg::Polygon::_transform(const Matrix4& trMat)
00549 {
00550     Matrix3d rotMat;
00551     trMat.get(rotMat);
00552     for (unsigned i = 0; i < _nVert; i++) {
00553         trMat.transform(_vertices[i]);
00554         if (haveVertNormals()) rotMat.transform(_normals[i]);
00555     }
00556     rotMat.transform(_normal);
00557     _set_edge_projection();
00558     if (_proj) { delete [] _proj; _proj = NULL; }
00559     _fxyz = - _normal.dot(_get_vertex(0));
00560 }
00561 
00562 void esg::Polygon::_scale(float s)
00563 {
00564     for (unsigned i = 0; i < _nVert; i++) _vertices[i].scale(s);
00565     if (_proj) { delete [] _proj; _proj = NULL; }
00566     //_proj = _precompute_proj();
00567     _fxyz *= s;
00568 }
00569 
00570 
00571 
00572 //------ public ------
00573 
00574 esg::Polygon::Polygon()
00575 {
00576     _vertices  = NULL;
00577     _normals   = NULL;
00578     _uvCoords  = NULL;
00579     _nVert     = 0;
00580     _fxyz      = 0;
00581     _area      = 0;
00582     _proj      = NULL;    
00583 }
00584 
00585 esg::Polygon::Polygon(const Vector3* va,
00586                       const Vector3* na,
00587                       const Vector2* uva,
00588                       unsigned       n)
00589 {
00590     _vertices  = NULL;
00591     _normals   = NULL;
00592     _uvCoords  = NULL;
00593     _nVert     = n;
00594     _proj      = NULL;
00595 
00596     (setVertices(va, n) && setNormals(na) && setUVCoords(uva));
00597 }
00598 
00599 esg::Polygon::Polygon(const Vector3* va,
00600                       const Vector3* na,
00601                       const Vector2* uva,
00602                       unsigned       n,
00603                       const Vector3& norm,
00604                       bool           fixedn)
00605 {
00606     _vertices  = NULL;
00607     _normals   = NULL;
00608     _uvCoords  = NULL;
00609     _nVert     = n;
00610     _proj      = NULL;
00611 
00612     if (setVertices(va, n) && setNormals(na) && setUVCoords(uva))
00613         setFacetNormal(norm, fixedn);
00614 }
00615 
00616 esg::Polygon::~Polygon()
00617 {
00618     if (_vertices) delete [] _vertices;
00619     if (_normals)  delete [] _normals;
00620     if (_uvCoords) delete [] _uvCoords;
00621     if (_proj)     delete [] _proj;
00622 }
00623 
00624 void esg::Polygon::rayIntersection(PointEnv* pPE,
00625                               int            mask, 
00626                               const Vector3& origin,
00627                               const Vector3& direction,
00628                               float          maxDist)
00629 {
00630     if (!pPE) return;
00631     
00632     pPE->mask = ENV_HAVE_NOTHING;
00633 
00634     if (_nVert < 3) return;
00635 
00636     /*
00637      * get point of intersection with support plane
00638      */
00639 
00640     double&  np1 = pPE->nd;
00641     double&  no  = pPE->no;
00642     double&  t   = pPE->distance;
00643     Vector3& v   = pPE->intersection;
00644 
00645     np1 = _normal.dot(direction);
00646     if (fabs(np1) < Geometry::EPS) return; // Parallel
00647     no = _normal.dot(origin);
00648     t = (no + _fxyz) / -np1;
00649     if (t < Geometry::EPS || t > maxDist) return; // Directs outward or too far
00650 
00651     v.set(direction); // point of intersection itself
00652     v.scaleAdd(t, origin);
00653 
00654 
00655     /*
00656      * Set output
00657      */
00658 
00659     Vector3* n  = (((mask&ENV_WANT_NORMAL)  && haveVertNormals())
00660                    ? &(pPE->normal): NULL);
00661     Vector2* uv = (((mask&ENV_WANT_UV_COORD) && haveVertUVCoords())
00662                    ? &(pPE->uvCoord) : NULL);
00663 
00664     if (!_point_inside_polygon(v, n, uv)) return;
00665 
00666     if (n) {
00667         pPE->normalOrientation = PointEnv::OUTWARDS_NORMAL;
00668         pPE->mask |= ENV_HAVE_NORMAL;
00669     } else {
00670         if (mask & ENV_WANT_NORMAL) {
00671             // intersection is found but the normal vector
00672             // cannot be interpolated  => set it to the facet normal
00673             pPE->normal.set(_normal);
00674             if (_normalFixed) pPE->normalOrientation = PointEnv::OUTWARDS_NORMAL;
00675             else              pPE->normalOrientation = PointEnv::RANDOM_NORMAL;
00676             pPE->mask |= ENV_HAVE_NORMAL|ENV_HAVE_N_DOT_O|ENV_HAVE_N_DOT_D;
00677         }
00678     }
00679 
00680     pPE->mask |= ((uv) ?
00681                   ENV_HAVE_INTERFERENCE|ENV_HAVE_N_DOT_O|
00682                   ENV_HAVE_INTERSECTION|ENV_HAVE_DISTANCE|ENV_HAVE_UV_COORD :
00683                   ENV_HAVE_INTERFERENCE|ENV_HAVE_N_DOT_O|
00684                   ENV_HAVE_INTERSECTION|ENV_HAVE_DISTANCE);
00685 }
00686 
00687 bool esg::Polygon::mapToUV(const Vector3& v, Vector2& uv)
00688 {
00689     return _point_inside_polygon(v, NULL, &uv);
00690 }
00691 
00692 void esg::Polygon::randomSample(int mask, PointEnv& pe, double* pdf)
00693 {
00694     pe.mask = ENV_HAVE_NOTHING;
00695     if (!(mask & ENV_WANT_SURFACE_POINT|ENV_WANT_UV_COORD|ENV_WANT_NORMAL))
00696         return;
00697 
00698     // get rectangle packing the plygon
00699     Vector3  u(_get_vertex(1)); u.sub(_get_vertex(0)); u.normalize();
00700     Vector3  v; v.cross(u, _normal); v.normalize();
00701     Interval uExt, vExt;
00702     double   ud, vd, p0u = 0, p0v = 0;
00703     for (register unsigned i = 0; i < _nVert; i++) {
00704         ud = u.dot(_get_vertex(i));
00705         vd = v.dot(_get_vertex(i));
00706         if (i == 0) { p0u = ud; p0v = vd; }
00707         if (ud > uExt.max) uExt.max = ud;
00708         if (ud < uExt.min) uExt.min = ud;
00709         if (vd > vExt.max) vExt.max = vd;
00710         if (vd < vExt.min) vExt.min = vd;
00711     }
00712 
00713     Vector3* n  = ((((mask&ENV_WANT_NORMAL)  && haveVertNormals())
00714                     ? &(pe.normal) : NULL));
00715     Vector2* uv = ((((mask&ENV_WANT_UV_COORD) && haveVertUVCoords())
00716                     ? &(pe.uvCoord) : NULL));
00717     Vector3  auxU, auxV;
00718 
00719     // set p0 to the bottom-left corner of rectangle
00720     auxU.set(u);
00721     auxV.set(v);
00722     auxU.scale(uExt.min - p0u);
00723     auxV.scale(vExt.min - p0v);
00724     Vector3 p0(_get_vertex(0));
00725     p0.add(auxU);
00726     p0.add(auxV);
00727 
00728     ud = uExt.max - uExt.min;
00729     vd = vExt.max - vExt.min;
00730 
00731     do { // rejection sampling
00732         auxU.set(u);
00733         auxU.scale(ESG_DBL_RAND * ud);
00734         auxV.set(v);
00735         auxV.scale(ESG_DBL_RAND * vd);
00736         pe.intersection.set(p0);
00737         pe.intersection.add(auxU);
00738         pe.intersection.add(auxV);
00739     } while(!_point_inside_polygon(pe.intersection, n, uv));
00740 
00741     if (n) {
00742         pe.normalOrientation = PointEnv::OUTWARDS_NORMAL;
00743         pe.mask |= ENV_HAVE_NORMAL;
00744     } else {
00745         if (mask & ENV_WANT_NORMAL) {
00746             // intersection is found but the normal vector
00747             // cannot be interpolated  => set it to the facet normal
00748             pe.normal.set(_normal);
00749             if (_normalFixed) pe.normalOrientation = PointEnv::OUTWARDS_NORMAL;
00750             else              pe.normalOrientation = PointEnv::RANDOM_NORMAL;
00751             pe.mask |= ENV_HAVE_NORMAL;
00752         }
00753     }
00754     
00755     pe.mask |= ((uv) ?
00756                 ENV_HAVE_INTERFERENCE|ENV_HAVE_INTERSECTION|ENV_HAVE_UV_COORD :
00757                 ENV_HAVE_INTERFERENCE|ENV_HAVE_INTERSECTION);
00758 
00759     if (pdf) *pdf = 1./_area;
00760 }
00761 
00762 bool esg::Polygon::randomDirection(const Vector3& pov, Vector3&, double* pdf) 
00763 {
00764     if (_normalFixed && _normal.dot(pov) < _fxyz) return false;
00765     fprintf(stderr,"Polygon::randomDirection(): Not implemented\n");
00766     return false;
00767 }
00768 
00769 Interval esg::Polygon::extent(const Vector3& direction) const
00770 {
00771     float    vertExt;
00772     Interval retInt;
00773     
00774     retInt.min = MAXFLOAT;
00775     //  retInt.max = MINFLOAT;
00776     retInt.max = - MAXFLOAT;
00777     
00778     for (register unsigned i = 0; i < _nVert; i++) {
00779         vertExt = direction.dot(_get_vertex(i));
00780         if (retInt.min > vertExt) retInt.min = vertExt;
00781         if (retInt.max < vertExt) retInt.max = vertExt;
00782     }
00783     return retInt;
00784 }
00785 
00786 
00787 Geometry* esg::Polygon::clone(const Matrix4* pTrMat) const
00788 {
00789     Polygon* pRet = new Polygon;
00790     pRet->_duplicate_attributes(*this);
00791     if (pTrMat) pRet->_transform(*pTrMat);
00792     return pRet;
00793 }
00794 
00795 Vertex3 esg::Polygon::centroid() const
00796 {
00797     Vertex3 pog(0.0, 0.0, 0.0);
00798     for (register unsigned i = 0; i < _nVert; i++) {
00799         Vertex3 aux(_get_vertex(i));
00800         aux.scale(1.0/_nVert);
00801         pog.add(aux);
00802     }
00803     return pog;
00804 }
00805 
00806 double esg::Polygon::radius(const Vector3& centroid) const
00807 {
00808     double  r = -MAXDOUBLE;
00809     double  auxR;
00810     Vector3 auxV;
00811     for (register unsigned i = 0; i < _nVert; i++) {
00812         auxV.set(_get_vertex(i));
00813         auxV.sub(centroid);
00814         auxR = auxV.length();
00815         if (auxR > r) r = auxR;
00816     }
00817     return r;
00818 }
00819 
00820 bool esg::Polygon::separation(Geometry& geom, Vector3* pDir) 
00821 {
00822     try {
00823         int c = _triTriCollision(dynamic_cast<Polygon&>(geom));
00824         if (c >= 0) return (!c);
00825     } catch (bad_cast) {
00826         // geom is not a polygon => continue
00827     }
00828 
00829     // either geom is not polygon or triTriCollision failed:
00830     
00831     if (_separation_by_plane(geom)) {
00832         if (pDir) pDir->set(_normal);
00833         return true;
00834     }
00835 
00836     if (!_separation_by_edges(geom)) return false;
00837     
00838     return false; // don't know => return false
00839 }
00840 
00841 double esg::Polygon::distance(const Geometry& geom, Vector3* pDir) 
00842 {
00843     return MINDOUBLE; 
00844 }
00845 
00846 void esg::Polygon::dump(const char* intent, const char* tab)
00847 {
00848     printf("%s geometry Polygon {\n", intent);
00849     printf("%s %s numVertices %d\n", intent, tab, _nVert);
00850     if (_normalFixed) 
00851         printf("%s %s normal %f %f %f\n", intent, tab, _normal.x, _normal.y, _normal.z);
00852     if (_vertices) {
00853         printf("%s %s vertex [\n", intent, tab);
00854         for (register unsigned i = 0; i < _nVert; i++)
00855             printf("%s %s %s %f %f %f\n", intent, tab, tab, _vertices[i].x, _vertices[i].y, _vertices[i].z);
00856         printf("%s %s ]\n", intent, tab);
00857     }
00858     if (haveVertNormals()) {
00859         printf("%s %s vertexNormal [\n", intent, tab);
00860         for (register unsigned i = 0; i < _nVert; i++)
00861             printf("%s %s %s %f %f %f\n", intent, tab, tab, _normals[i].x, _normals[i].y, _normals[i].z);
00862         printf("%s %s ]\n", intent, tab);
00863     }
00864     if (_uvCoords) {
00865         printf("%s %s uvCoord [\n", intent, tab);
00866         for (register unsigned i = 0; i < _nVert; i++)
00867             printf("%s %s %s %f %f\n", intent, tab, tab, _uvCoords[i].x, _uvCoords[i].y);
00868         printf("%s %s ]\n", intent, tab);
00869     }
00870     printf("%s }\n", intent);
00871 }
00872 
00873 Vector3 esg::Polygon::getFacetNormal() const
00874 {
00875     return _normal;
00876 }
00877 
00878 bool esg::Polygon::haveFixedNormal() const
00879 {
00880     return _normalFixed;
00881 }
00882 
00883 Vertex3 esg::Polygon::getVertex(unsigned index) const 
00884 {
00885     return ((index < _nVert) ? _get_vertex(index) : Vertex3(0,0,0));
00886 }
00887 
00888 Vertex3 esg::Polygon::getVertNormal(unsigned index) const 
00889 {
00890     return ((haveVertNormals() && index < _nVert) ?
00891             _get_vert_normal(index) :
00892             Vertex3(0,0,0));
00893 }
00894 
00895 bool esg::Polygon::haveVertNormals() const
00896 {
00897     return (_normals != NULL);
00898 }
00899 
00900 Vertex2 esg::Polygon::getVertUVCoord(unsigned index) const 
00901 {
00902     return ((haveVertUVCoords() && index < _nVert)
00903             ? _get_vert_uv_coord(index)
00904             : Vertex2(0,0));
00905 }
00906 
00907 bool esg::Polygon::haveVertUVCoords() const
00908 {
00909     return (_uvCoords != NULL);
00910 }
00911 
00912 unsigned esg::Polygon::numVertices() const
00913 {
00914     return _nVert;
00915 }
00916 
00917 double esg::Polygon::getFXYZ() const
00918 {
00919     return _fxyz;
00920 }
00921 
00922 esg::Polygon::edgeProjection esg::Polygon::getEdgeProjection() const
00923 {
00924     return _edgeProjection;
00925 }
00926 
00927 bool esg::Polygon::setVertices(const Vector3* va, unsigned n)
00928 {
00929     if (_vertices) delete [] _vertices;
00930     if (_normals)  delete [] _normals;
00931     if (_uvCoords) delete [] _uvCoords;
00932     if (_proj)     delete [] _proj;
00933 
00934     _vertices  = NULL;
00935     _normals   = NULL;
00936     _uvCoords  = NULL;
00937     _nVert     = n;
00938     _proj      = NULL;
00939 
00940     if (_nVert > 2) {
00941         _vertices = new Vector3d [_nVert];
00942         for (unsigned i = 0; i < _nVert; i++) _vertices[i].set(va[i]);
00943         _normal.set(_get_facet_normal());
00944         _normalFixed = false;
00945         _fxyz = - _normal.dot(_get_vertex(0));
00946         _set_edge_projection();
00947     } else {
00948         cerr << "setVerices() error: Number of vertices is less then 3" << endl;
00949         return false;
00950     }
00951 
00952 #ifndef WIN32
00953 #warning "FIXME: Area of polygon"
00954 #endif
00955     _area = 1;
00956 
00957     return true;
00958 }
00959 
00960 bool esg::Polygon::setNormals(const Vector3* na)
00961 {
00962     if (_nVert < 3) {
00963         cerr << "setNormals() error: Number of vertices is less then 3" << endl;
00964         return false;
00965     }
00966 
00967     if (_normals)  {
00968         delete [] _normals;
00969         _normals   = NULL;
00970     }
00971 
00972     if (na) {
00973         _normals = new Vector3 [_nVert];
00974         for (unsigned i = 0; i < _nVert; i++) _normals[i].set(na[i]);
00975     }
00976 
00977     return true;
00978 }
00979 
00980 bool esg::Polygon::setUVCoords(const Vector2* uva)
00981 {
00982     if (_nVert < 3) {
00983         cerr << "setUVCoords() error: Number of vertices is less then 3" << endl;
00984         return false;
00985     }
00986 
00987     if (_uvCoords)  {
00988         delete [] _uvCoords;
00989         _uvCoords = NULL;
00990     }
00991 
00992     if (uva) {
00993         _uvCoords = new Vector2 [_nVert];
00994         for (unsigned i = 0; i < _nVert; i++) _uvCoords[i].set(uva[i]);
00995     }
00996 
00997     return true;
00998 }
00999 
01000 void esg::Polygon::setFacetNormal(const Vector3& norm, bool fixedn)
01001 {
01002     _normal.set(norm);
01003     _normalFixed = fixedn;
01004     _fxyz = - _normal.dot(_get_vertex(0));
01005     _set_edge_projection();
01006 }
01007 
01008 
01009 void esg::Polygon::__debug()
01010 {
01011     //fprintf(stderr,"Polygon: normal: %f %f %f\n",
01012     //      _normal.x,_normal.y,_normal.z);
01013     fprintf(stderr,"Polygon vertices:\n");
01014     for (unsigned i = 0; i < _nVert; i++)
01015         fprintf(stderr,"%f %f %f\n",
01016                 getVertex(i).x,getVertex(i).y,getVertex(i).z);
01017     fprintf(stderr,"Polygon's normal: %f %f %f\n",_normal.x,_normal.y,_normal.z);
01018 }

Generated on Wed Jun 28 12:24:32 2006 for esg by  doxygen 1.4.6