LCOV - code coverage report
Current view: top level - algs/Qslim - quadrics.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 78 135 57.8 %
Date: 2020-07-01 15:24:36 Functions: 12 17 70.6 %
Branches: 71 229 31.0 %

           Branch data     Line data    Source code
       1                 :            : // $Id: quadrics.cxx,v 1.5 1997/10/01 14:07:28 garland Exp $
       2                 :            : 
       3                 :            : //#include "qslim.h"
       4                 :            : #include <assert.h>
       5                 :            : #include "quadrics.h"
       6                 :            : #include "3D.h"
       7                 :            : #include "primitives.h"
       8                 :            : 
       9                 :            : ////////////////////////////////////////////////////////////////////////
      10                 :            : //
      11                 :            : // Primitive quadric construction and evaluation routines
      12                 :            : //
      13                 :            : 
      14                 :            : //
      15                 :            : // Construct a quadric to evaluate the squared distance of any point
      16                 :            : // to the given point v.  Naturally, the iso-surfaces are just spheres
      17                 :            : // centered at v.
      18                 :            : //
      19                 :          0 : Mat4 quadrix_vertex_constraint(const Vec3& v)
      20                 :            : {
      21                 :          0 :     Mat4 L(Mat4::identity);
      22                 :            : 
      23                 :          0 :     L(0,3) = -v[0];
      24                 :          0 :     L(1,3) = -v[1];
      25                 :          0 :     L(2,3) = -v[2];
      26                 :          0 :     L(3,3) = v*v;
      27                 :            : 
      28                 :          0 :     L(3,0) = L(0,3);
      29                 :          0 :     L(3,1) = L(1,3);
      30                 :          0 :     L(3,2) = L(2,3);
      31                 :            : 
      32                 :          0 :     return L;
      33                 :            : }
      34                 :          0 : Mat4 quadrix_vertex_constraint(moab::EntityHandle vert)
      35                 :            : {
      36         [ #  # ]:          0 :     Mat4 L(Mat4::identity);
      37                 :            :     double v[3];
      38         [ #  # ]:          0 :     mb->get_coords(&vert, 1 , v);
      39         [ #  # ]:          0 :     L(0,3) = -v[0];
      40         [ #  # ]:          0 :     L(1,3) = -v[1];
      41         [ #  # ]:          0 :     L(2,3) = -v[2];
      42         [ #  # ]:          0 :     L(3,3) = v[0]*v[0] + v[1]*v[1] + v[2]*v[2] ; //  v*v;
      43                 :            : 
      44 [ #  # ][ #  # ]:          0 :     L(3,0) = L(0,3);
      45 [ #  # ][ #  # ]:          0 :     L(3,1) = L(1,3);
      46 [ #  # ][ #  # ]:          0 :     L(3,2) = L(2,3);
      47                 :            : 
      48                 :          0 :     return L;
      49                 :            : }
      50                 :            : //
      51                 :            : // Construct a quadric to evaluate the squared distance of any point
      52                 :            : // to the given plane [ax+by+cz+d = 0].  This is the "fundamental error
      53                 :            : // quadric" discussed in the paper.
      54                 :            : //
      55                 :      10400 : Mat4 quadrix_plane_constraint(double a, double b, double c, double d)
      56                 :            : {
      57                 :      10400 :     Mat4 K(Mat4::zero);
      58                 :            : 
      59                 :      10400 :     K(0,0) = a*a;   K(0,1) = a*b;   K(0,2) = a*c;  K(0,3) = a*d;
      60                 :      10400 :     K(1,0) =K(0,1); K(1,1) = b*b;   K(1,2) = b*c;  K(1,3) = b*d;
      61                 :      10400 :     K(2,0) =K(0,2); K(2,1) =K(1,2); K(2,2) = c*c;  K(2,3) = c*d;
      62                 :      10400 :     K(3,0) =K(0,3); K(3,1) =K(1,3); K(3,2) =K(2,3);K(3,3) = d*d;
      63                 :            : 
      64                 :      10400 :     return K;
      65                 :            : }
      66                 :            : 
      67                 :            : //
      68                 :            : // Define some other convenient ways for constructing these plane quadrics.
      69                 :            : //
      70                 :        400 : Mat4 quadrix_plane_constraint(const Vec3& n, double d)
      71                 :            : {
      72                 :        400 :     return quadrix_plane_constraint(n[X], n[Y], n[Z], d);
      73                 :            : }
      74                 :            : 
      75                 :            : //Mat4 quadrix_plane_constraint(Face& T)
      76                 :      10000 : Mat4 quadrix_plane_constraint(moab::EntityHandle triangle)
      77                 :            : {
      78                 :            :     // const Plane& p = T.plane();
      79         [ +  - ]:      10000 :     Plane p=trianglePlane(mb, triangle);
      80                 :            :     double a,b,c,d;
      81         [ +  - ]:      10000 :     p.coeffs(&a, &b, &c, &d);
      82                 :            : 
      83         [ +  - ]:      10000 :     return quadrix_plane_constraint(a, b, c, d);
      84                 :            : }
      85                 :            : 
      86                 :          0 : Mat4 quadrix_plane_constraint(const Vec3& v1, const Vec3& v2, const Vec3& v3)
      87                 :            : {
      88         [ #  # ]:          0 :     Plane P(v1,v2,v3);
      89                 :            :     double a,b,c,d;
      90         [ #  # ]:          0 :     P.coeffs(&a, &b, &c, &d);
      91                 :            : 
      92         [ #  # ]:          0 :     return quadrix_plane_constraint(a, b, c, d);
      93                 :            : }
      94                 :            : 
      95                 :      60616 : double quadrix_evaluate_vertex(const Vec3& v, const Mat4& K)
      96                 :            : {
      97                 :      60616 :     double x=v[X], y=v[Y], z=v[Z];
      98                 :            : 
      99                 :            : #ifndef VECTOR_COST_EVALUATION
     100                 :            :     //
     101                 :            :     // This is the fast way of computing (v^T Q v).
     102                 :            :     // 
     103                 :      60616 :     return x*x*K(0,0) + 2*x*y*K(0,1) + 2*x*z*K(0,2) + 2*x*K(0,3)
     104                 :      60616 :                       + y*y*K(1,1)   + 2*y*z*K(1,2) + 2*y*K(1,3)
     105                 :      60616 :                                      + z*z*K(2,2)   + 2*z*K(2,3)
     106                 :      60616 :                                                     + K(3,3);
     107                 :            : #else
     108                 :            :     //
     109                 :            :     // The equivalent thing using matrix/vector operations.
     110                 :            :     // It's a lot clearer, but it's also slower.
     111                 :            :     //
     112                 :            :     Vec4 v2(x,y,z,1);
     113                 :            :     return v2*(K*v2);
     114                 :            : #endif
     115                 :            : }
     116                 :            : 
     117                 :            : 
     118                 :            : 
     119                 :            : ////////////////////////////////////////////////////////////////////////
     120                 :            : //
     121                 :            : // Routines for computing discontinuity constraints
     122                 :            : //
     123                 :            : 
     124                 :            : //bool is_border(Edge *e )
     125                 :      15200 : bool is_border(moab::EntityHandle eh )
     126                 :            : {
     127                 :            :    //  use nb of triangles connected to check if number of tri is 1
     128         [ +  - ]:      15200 :     std::vector<moab::EntityHandle> adjTri;
     129                 :            :     moab::ErrorCode rval = mb->get_adjacencies(&eh, 1, 2, false, adjTri,
     130         [ +  - ]:      15200 :                                       moab::Interface::UNION);
     131 [ +  - ][ +  + ]:      15200 :     if (moab::MB_SUCCESS==rval  && adjTri.size()==1)
                 [ +  + ]
     132                 :        400 :          return true;
     133                 :      15200 :     return false;
     134                 :            : }
     135                 :            : 
     136                 :          0 : bool check_for_discontinuity(moab::EntityHandle eh) //Edge *e)
     137                 :            : {
     138                 :          0 :     return is_border(eh);
     139                 :            : }
     140                 :            : 
     141                 :        400 : Mat4 quadrix_discontinuity_constraint( moab::EntityHandle mbe
     142                 :            :     /*Edge *edge*/, const Vec3& n)
     143                 :            : {
     144                 :            :     //Vec3& org = *edge->org();
     145                 :            :     //Vec3& dest = *edge->dest();
     146                 :            :     // to do: Vec3 origin of edge
     147                 :            :         // is the orientation important for an edge?
     148                 :            :         const moab::EntityHandle * conn;
     149                 :            :         int num_nodes;
     150         [ +  - ]:        400 :         mb->get_connectivity(mbe, conn, num_nodes);
     151         [ +  - ]:        400 :     Vec3 dest = getVec3FromMBVertex(mb, conn[1]); //
     152         [ +  - ]:        400 :     Vec3 org = getVec3FromMBVertex(mb, conn[0]);
     153         [ +  - ]:        400 :     Vec3 e = dest - org;
     154                 :            : 
     155         [ +  - ]:        400 :     Vec3 n2 = e ^ n;
     156         [ +  - ]:        400 :     unitize(n2);
     157                 :            : 
     158 [ +  - ][ +  - ]:        400 :     double d = -n2 * org;
     159         [ +  - ]:        400 :     return quadrix_plane_constraint(n2, d);
     160                 :            : }
     161                 :            : 
     162                 :            : 
     163                 :        400 : Mat4 quadrix_discontinuity_constraint(moab::EntityHandle mbedge)// Edge *edge)
     164                 :            : {
     165         [ +  - ]:        400 :     Mat4 D(Mat4::zero);
     166                 :            : 
     167                 :            : /*
     168                 :            :     face_buffer& faces = edge->faceUses();
     169                 :            : 
     170                 :            :     for(int i=0; i<faces.length(); i++)
     171                 :            :         D += quadrix_discontinuity_constraint(edge,faces(i)->plane().normal());
     172                 :            : */
     173                 :            :     // to do : to get the connected faces to the edge
     174                 :            : 
     175         [ +  - ]:        400 :         std::vector<moab::EntityHandle> adjFaces;
     176                 :            :         moab::ErrorCode rval = mb->get_adjacencies(&mbedge, 1, 2, false,  adjFaces,
     177         [ +  - ]:        400 :                                                                   moab::Interface::UNION);
     178 [ -  + ][ #  # ]:        400 :         assert(rval == moab::MB_SUCCESS);
     179                 :            : 
     180         [ +  + ]:        800 :         for (unsigned int i=0; i<adjFaces.size(); i++)
     181                 :            :         {
     182         [ +  - ]:        400 :                 moab::EntityHandle F = adjFaces[i];
     183         [ +  - ]:        400 :                 Plane p = trianglePlane( mb, F);
     184 [ +  - ][ +  - ]:        400 :                 D += quadrix_discontinuity_constraint(mbedge, p.normal());
                 [ +  - ]
     185                 :            :         }
     186                 :        400 :     return D;
     187                 :            : }
     188                 :            : 
     189                 :            : 
     190                 :            : 
     191                 :            : ////////////////////////////////////////////////////////////////////////
     192                 :            : //
     193                 :            : // Routines for computing contraction target
     194                 :            : //
     195                 :            : 
     196                 :          0 : bool quadrix_find_local_fit(const Mat4& K,
     197                 :            :                             const Vec3& v1, const Vec3& v2,
     198                 :            :                             Vec3& candidate)
     199                 :            : {
     200                 :            : 
     201 [ #  # ][ #  # ]:          0 :     Vec3 v3 = (v1 + v2) / 2;
     202                 :            : 
     203                 :          0 :     bool try_midpoint = opts.placement_policy > PLACE_ENDPOINTS;
     204                 :            : 
     205         [ #  # ]:          0 :     double c1 = quadrix_evaluate_vertex(v1, K);
     206         [ #  # ]:          0 :     double c2 = quadrix_evaluate_vertex(v2, K);
     207                 :            :     double c3;
     208 [ #  # ][ #  # ]:          0 :     if( try_midpoint ) c3 = quadrix_evaluate_vertex(v3, K);
     209                 :            : 
     210         [ #  # ]:          0 :     if( c1<c2 )
     211                 :            :     {
     212 [ #  # ][ #  # ]:          0 :         if( try_midpoint && c3<c1 )
     213         [ #  # ]:          0 :             candidate=v3;
     214                 :            :         else
     215         [ #  # ]:          0 :             candidate=v1;
     216                 :            :     }
     217                 :            :     else
     218                 :            :     {
     219 [ #  # ][ #  # ]:          0 :         if( try_midpoint && c3<c2 )
     220         [ #  # ]:          0 :             candidate=v3;
     221                 :            :         else
     222         [ #  # ]:          0 :             candidate=v2;
     223                 :            :     }
     224                 :            : 
     225                 :          0 :     return true;
     226                 :            : }
     227                 :            : 
     228                 :          2 : bool quadrix_find_line_fit(const Mat4& Q,
     229                 :            :                            const Vec3& v1, const Vec3& v2,
     230                 :            :                            Vec3& candidate)
     231                 :            : {
     232         [ +  - ]:          2 :     Vec3 d = v1-v2;
     233                 :            : 
     234         [ +  - ]:          2 :     Vec3 Qv2 = Q*v2;
     235         [ +  - ]:          2 :     Vec3 Qd  = Q*d;
     236                 :            : 
     237 [ +  - ][ +  - ]:          2 :     double denom = 2*d*Qd;
     238                 :            : 
     239         [ -  + ]:          2 :     if( denom == 0.0 )
     240                 :          0 :         return false;
     241                 :            : 
     242 [ +  - ][ +  - ]:          2 :     double a = (d*Qv2 + v2*Qd) / denom;
     243                 :            : 
     244         [ +  - ]:          2 :     if( a<0.0 ) a=0.0;
     245         [ -  + ]:          2 :     if( a>1.0 ) a=1.0;
     246                 :            : 
     247                 :            : 
     248 [ +  - ][ +  - ]:          2 :     candidate = a*d + v2;
                 [ +  - ]
     249                 :          2 :     return true;
     250                 :            : }
     251                 :            : 
     252                 :      60616 : bool quadrix_find_best_fit(const Mat4& Q, Vec3& candidate)
     253                 :            : {
     254         [ +  - ]:      60616 :     Mat4 K = Q;
     255 [ +  - ][ +  - ]:      60616 :     K(3,0) = K(3,1) = K(3,2) = 0.0;  K(3,3) = 1;
         [ +  - ][ +  - ]
     256                 :            : 
     257                 :            : 
     258         [ +  - ]:      60616 :     Mat4 M;
     259         [ +  - ]:      60616 :     double det = K.inverse(M);
     260 [ +  - ][ +  + ]:      60616 :     if( FEQ(det, 0.0, 1e-12) )
     261                 :          2 :         return false;
     262                 :            : 
     263                 :            : 
     264                 :            : #ifdef SAFETY
     265                 :            :     //
     266                 :            :     // The homogeneous division SHOULDN'T be necessary.
     267                 :            :     // But, when we're being SAFE, we do it anyway just in case.
     268                 :            :     //
     269                 :            :     candidate[X] = M(0,3)/M(3,3);
     270                 :            :     candidate[Y] = M(1,3)/M(3,3);
     271                 :            :     candidate[Z] = M(2,3)/M(3,3);
     272                 :            : #else
     273 [ +  - ][ +  - ]:      60614 :     candidate[X] = M(0,3);
     274 [ +  - ][ +  - ]:      60614 :     candidate[Y] = M(1,3);
     275 [ +  - ][ +  - ]:      60614 :     candidate[Z] = M(2,3);
     276                 :            : #endif
     277                 :            : 
     278                 :      60616 :     return true;
     279                 :            : }
     280                 :            : 
     281                 :            : 
     282                 :      60616 : double quadrix_pair_target(const Mat4& Q,
     283                 :            :                          moab::EntityHandle v1, //Vertex *v1,
     284                 :            :                          moab::EntityHandle v2, // Vertex *v2,
     285                 :            :                          Vec3& candidate)
     286                 :            : {
     287                 :      60616 :     int policy = opts.placement_policy;
     288                 :            : 
     289                 :            :     //
     290                 :            :     // This analytic boundary preservation isn't really necessary.  The
     291                 :            :     // boundary constraint quadrics are quite effective.  But, I've left it
     292                 :            :     // in anyway.
     293                 :            :     //
     294         [ +  - ]:      60616 :     Vec3 vec1 = getVec3FromMBVertex(mb, v1);
     295         [ +  - ]:      60616 :     Vec3 vec2 = getVec3FromMBVertex(mb, v2);
     296         [ -  + ]:      60616 :     if( opts.will_preserve_boundaries )
     297                 :            :     {
     298         [ #  # ]:          0 :         int c1 = classifyVertex(mb, v1);
     299         [ #  # ]:          0 :         int c2 = classifyVertex(mb, v2);
     300                 :            : 
     301                 :            :         // if both are on boundary, put a high penalty cost
     302 [ #  # ][ #  # ]:          0 :         if (c1>0 && c2>0)
     303                 :          0 :                 return 1.e11;// greater than quality error
     304         [ #  # ]:          0 :         if( c1 > c2 )
     305                 :            :         {
     306         [ #  # ]:          0 :                 candidate = vec1;
     307         [ #  # ]:          0 :                 return quadrix_evaluate_vertex(candidate, Q);
     308                 :            :         }
     309         [ #  # ]:          0 :         else if( c2 > c1 )
     310                 :            :                 {
     311                 :            :                         //candidate = *v2;
     312         [ #  # ]:          0 :                         candidate = vec2;
     313         [ #  # ]:          0 :                         return quadrix_evaluate_vertex(candidate, Q);
     314                 :            :                 }
     315 [ #  # ][ #  # ]:          0 :                 else if( c1>0 && policy>PLACE_LINE )
     316                 :          0 :                         policy = PLACE_LINE;
     317                 :            : 
     318 [ #  # ][ #  # ]:          0 :         if( policy == PLACE_OPTIMAL ) assert(c1==0 && c2==0);
         [ #  # ][ #  # ]
     319                 :            :     }
     320                 :            : 
     321      [ +  -  - ]:      60616 :     switch( policy )
     322                 :            :     {
     323                 :            :     case PLACE_OPTIMAL:
     324 [ +  - ][ +  + ]:      60616 :         if( quadrix_find_best_fit(Q, candidate) )
     325                 :      60614 :                 break;
     326                 :            : 
     327                 :            :     case PLACE_LINE:
     328 [ +  - ][ +  - ]:          2 :         if( quadrix_find_line_fit(Q, vec1, vec2, candidate) )
     329                 :          2 :                 break;
     330                 :            : 
     331                 :            :     default:
     332         [ #  # ]:          0 :         quadrix_find_local_fit(Q, vec1, vec2, candidate);
     333                 :          0 :                 break;
     334                 :            :     }
     335                 :            : 
     336         [ +  - ]:      60616 :     return quadrix_evaluate_vertex(candidate, Q);
     337 [ +  - ][ +  - ]:        312 : }

Generated by: LCOV version 1.11