MeshKit  1.0
quadrics.cpp
Go to the documentation of this file.
00001 // $Id: quadrics.cxx,v 1.5 1997/10/01 14:07:28 garland Exp $
00002 
00003 //#include "qslim.h"
00004 #include <assert.h>
00005 #include "quadrics.h"
00006 #include "3D.h"
00007 #include "primitives.h"
00008 
00010 //
00011 // Primitive quadric construction and evaluation routines
00012 //
00013 
00014 //
00015 // Construct a quadric to evaluate the squared distance of any point
00016 // to the given point v.  Naturally, the iso-surfaces are just spheres
00017 // centered at v.
00018 //
00019 Mat4 quadrix_vertex_constraint(const Vec3& v)
00020 {
00021     Mat4 L(Mat4::identity);
00022 
00023     L(0,3) = -v[0];
00024     L(1,3) = -v[1];
00025     L(2,3) = -v[2];
00026     L(3,3) = v*v;
00027 
00028     L(3,0) = L(0,3);
00029     L(3,1) = L(1,3);
00030     L(3,2) = L(2,3);
00031 
00032     return L;
00033 }
00034 Mat4 quadrix_vertex_constraint(moab::EntityHandle vert)
00035 {
00036     Mat4 L(Mat4::identity);
00037     double v[3];
00038     mb->get_coords(&vert, 1 , v);
00039     L(0,3) = -v[0];
00040     L(1,3) = -v[1];
00041     L(2,3) = -v[2];
00042     L(3,3) = v[0]*v[0] + v[1]*v[1] + v[2]*v[2] ; //  v*v;
00043 
00044     L(3,0) = L(0,3);
00045     L(3,1) = L(1,3);
00046     L(3,2) = L(2,3);
00047 
00048     return L;
00049 }
00050 //
00051 // Construct a quadric to evaluate the squared distance of any point
00052 // to the given plane [ax+by+cz+d = 0].  This is the "fundamental error
00053 // quadric" discussed in the paper.
00054 //
00055 Mat4 quadrix_plane_constraint(double a, double b, double c, double d)
00056 {
00057     Mat4 K(Mat4::zero);
00058 
00059     K(0,0) = a*a;   K(0,1) = a*b;   K(0,2) = a*c;  K(0,3) = a*d;
00060     K(1,0) =K(0,1); K(1,1) = b*b;   K(1,2) = b*c;  K(1,3) = b*d;
00061     K(2,0) =K(0,2); K(2,1) =K(1,2); K(2,2) = c*c;  K(2,3) = c*d;
00062     K(3,0) =K(0,3); K(3,1) =K(1,3); K(3,2) =K(2,3);K(3,3) = d*d;
00063 
00064     return K;
00065 }
00066 
00067 //
00068 // Define some other convenient ways for constructing these plane quadrics.
00069 //
00070 Mat4 quadrix_plane_constraint(const Vec3& n, double d)
00071 {
00072     return quadrix_plane_constraint(n[X], n[Y], n[Z], d);
00073 }
00074 
00075 //Mat4 quadrix_plane_constraint(Face& T)
00076 Mat4 quadrix_plane_constraint(moab::EntityHandle triangle)
00077 {
00078     // const Plane& p = T.plane();
00079     Plane p=trianglePlane(mb, triangle);
00080     double a,b,c,d;
00081     p.coeffs(&a, &b, &c, &d);
00082 
00083     return quadrix_plane_constraint(a, b, c, d);
00084 }
00085 
00086 Mat4 quadrix_plane_constraint(const Vec3& v1, const Vec3& v2, const Vec3& v3)
00087 {
00088     Plane P(v1,v2,v3);
00089     double a,b,c,d;
00090     P.coeffs(&a, &b, &c, &d);
00091 
00092     return quadrix_plane_constraint(a, b, c, d);
00093 }
00094 
00095 double quadrix_evaluate_vertex(const Vec3& v, const Mat4& K)
00096 {
00097     double x=v[X], y=v[Y], z=v[Z];
00098 
00099 #ifndef VECTOR_COST_EVALUATION
00100     //
00101     // This is the fast way of computing (v^T Q v).
00102     // 
00103     return x*x*K(0,0) + 2*x*y*K(0,1) + 2*x*z*K(0,2) + 2*x*K(0,3)
00104                       + y*y*K(1,1)   + 2*y*z*K(1,2) + 2*y*K(1,3)
00105                                      + z*z*K(2,2)   + 2*z*K(2,3)
00106                                                     + K(3,3);
00107 #else
00108     //
00109     // The equivalent thing using matrix/vector operations.
00110     // It's a lot clearer, but it's also slower.
00111     //
00112     Vec4 v2(x,y,z,1);
00113     return v2*(K*v2);
00114 #endif
00115 }
00116 
00117 
00118 
00120 //
00121 // Routines for computing discontinuity constraints
00122 //
00123 
00124 //bool is_border(Edge *e )
00125 bool is_border(moab::EntityHandle eh )
00126 {
00127    //  use nb of triangles connected to check if number of tri is 1
00128     std::vector<moab::EntityHandle> adjTri;
00129     moab::ErrorCode rval = mb->get_adjacencies(&eh, 1, 2, false, adjTri,
00130                                       moab::Interface::UNION);
00131     if (moab::MB_SUCCESS==rval  && adjTri.size()==1)
00132          return true;
00133     return false;
00134 }
00135 
00136 bool check_for_discontinuity(moab::EntityHandle eh) //Edge *e)
00137 {
00138     return is_border(eh);
00139 }
00140 
00141 Mat4 quadrix_discontinuity_constraint( moab::EntityHandle mbe
00142     /*Edge *edge*/, const Vec3& n)
00143 {
00144     //Vec3& org = *edge->org();
00145     //Vec3& dest = *edge->dest();
00146     // to do: Vec3 origin of edge
00147         // is the orientation important for an edge?
00148         const moab::EntityHandle * conn;
00149         int num_nodes;
00150         mb->get_connectivity(mbe, conn, num_nodes);
00151     Vec3 dest = getVec3FromMBVertex(mb, conn[1]); //
00152     Vec3 org = getVec3FromMBVertex(mb, conn[0]);
00153     Vec3 e = dest - org;
00154 
00155     Vec3 n2 = e ^ n;
00156     unitize(n2);
00157 
00158     double d = -n2 * org;
00159     return quadrix_plane_constraint(n2, d);
00160 }
00161 
00162 
00163 Mat4 quadrix_discontinuity_constraint(moab::EntityHandle mbedge)// Edge *edge)
00164 {
00165     Mat4 D(Mat4::zero);
00166 
00167 /*
00168     face_buffer& faces = edge->faceUses();
00169 
00170     for(int i=0; i<faces.length(); i++)
00171         D += quadrix_discontinuity_constraint(edge,faces(i)->plane().normal());
00172 */
00173     // to do : to get the connected faces to the edge
00174 
00175         std::vector<moab::EntityHandle> adjFaces;
00176         moab::ErrorCode rval = mb->get_adjacencies(&mbedge, 1, 2, false,  adjFaces,
00177                                                                   moab::Interface::UNION);
00178         assert(rval == moab::MB_SUCCESS);
00179 
00180         for (unsigned int i=0; i<adjFaces.size(); i++)
00181         {
00182                 moab::EntityHandle F = adjFaces[i];
00183                 Plane p = trianglePlane( mb, F);
00184                 D += quadrix_discontinuity_constraint(mbedge, p.normal());
00185         }
00186     return D;
00187 }
00188 
00189 
00190 
00192 //
00193 // Routines for computing contraction target
00194 //
00195 
00196 bool quadrix_find_local_fit(const Mat4& K,
00197                             const Vec3& v1, const Vec3& v2,
00198                             Vec3& candidate)
00199 {
00200 
00201     Vec3 v3 = (v1 + v2) / 2;
00202 
00203     bool try_midpoint = opts.placement_policy > PLACE_ENDPOINTS;
00204 
00205     double c1 = quadrix_evaluate_vertex(v1, K);
00206     double c2 = quadrix_evaluate_vertex(v2, K);
00207     double c3;
00208     if( try_midpoint ) c3 = quadrix_evaluate_vertex(v3, K);
00209 
00210     if( c1<c2 )
00211     {
00212         if( try_midpoint && c3<c1 )
00213             candidate=v3;
00214         else
00215             candidate=v1;
00216     }
00217     else
00218     {
00219         if( try_midpoint && c3<c2 )
00220             candidate=v3;
00221         else
00222             candidate=v2;
00223     }
00224 
00225     return true;
00226 }
00227 
00228 bool quadrix_find_line_fit(const Mat4& Q,
00229                            const Vec3& v1, const Vec3& v2,
00230                            Vec3& candidate)
00231 {
00232     Vec3 d = v1-v2;
00233 
00234     Vec3 Qv2 = Q*v2;
00235     Vec3 Qd  = Q*d;
00236 
00237     double denom = 2*d*Qd;
00238 
00239     if( denom == 0.0 )
00240         return false;
00241 
00242     double a = (d*Qv2 + v2*Qd) / denom;
00243 
00244     if( a<0.0 ) a=0.0;
00245     if( a>1.0 ) a=1.0;
00246 
00247 
00248     candidate = a*d + v2;
00249     return true;
00250 }
00251 
00252 bool quadrix_find_best_fit(const Mat4& Q, Vec3& candidate)
00253 {
00254     Mat4 K = Q;
00255     K(3,0) = K(3,1) = K(3,2) = 0.0;  K(3,3) = 1;
00256 
00257 
00258     Mat4 M;
00259     double det = K.inverse(M);
00260     if( FEQ(det, 0.0, 1e-12) )
00261         return false;
00262 
00263 
00264 #ifdef SAFETY
00265     //
00266     // The homogeneous division SHOULDN'T be necessary.
00267     // But, when we're being SAFE, we do it anyway just in case.
00268     //
00269     candidate[X] = M(0,3)/M(3,3);
00270     candidate[Y] = M(1,3)/M(3,3);
00271     candidate[Z] = M(2,3)/M(3,3);
00272 #else
00273     candidate[X] = M(0,3);
00274     candidate[Y] = M(1,3);
00275     candidate[Z] = M(2,3);
00276 #endif
00277 
00278     return true;
00279 }
00280 
00281 
00282 double quadrix_pair_target(const Mat4& Q,
00283                          moab::EntityHandle v1, //Vertex *v1,
00284                          moab::EntityHandle v2, // Vertex *v2,
00285                          Vec3& candidate)
00286 {
00287     int policy = opts.placement_policy;
00288 
00289     //
00290     // This analytic boundary preservation isn't really necessary.  The
00291     // boundary constraint quadrics are quite effective.  But, I've left it
00292     // in anyway.
00293     //
00294     Vec3 vec1 = getVec3FromMBVertex(mb, v1);
00295     Vec3 vec2 = getVec3FromMBVertex(mb, v2);
00296     if( opts.will_preserve_boundaries )
00297     {
00298         int c1 = classifyVertex(mb, v1);
00299         int c2 = classifyVertex(mb, v2);
00300 
00301         // if both are on boundary, put a high penalty cost
00302         if (c1>0 && c2>0)
00303                 return 1.e11;// greater than quality error
00304         if( c1 > c2 )
00305         {
00306                 candidate = vec1;
00307                 return quadrix_evaluate_vertex(candidate, Q);
00308         }
00309         else if( c2 > c1 )
00310                 {
00311                         //candidate = *v2;
00312                         candidate = vec2;
00313                         return quadrix_evaluate_vertex(candidate, Q);
00314                 }
00315                 else if( c1>0 && policy>PLACE_LINE )
00316                         policy = PLACE_LINE;
00317 
00318         if( policy == PLACE_OPTIMAL ) assert(c1==0 && c2==0);
00319     }
00320 
00321     switch( policy )
00322     {
00323     case PLACE_OPTIMAL:
00324         if( quadrix_find_best_fit(Q, candidate) )
00325                 break;
00326 
00327     case PLACE_LINE:
00328         if( quadrix_find_line_fit(Q, vec1, vec2, candidate) )
00329                 break;
00330 
00331     default:
00332         quadrix_find_local_fit(Q, vec1, vec2, candidate);
00333                 break;
00334     }
00335 
00336     return quadrix_evaluate_vertex(candidate, Q);
00337 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines