Exemplo n.º 1
0
double NormalDriver::compute_l1_error( const SurfTrack& surf )
{
    
    double total_error = 0.0;
    double total_area = 0.0;
    
    for ( unsigned int i = 0; i < surf.get_num_vertices(); ++i )
    {
        if ( surf.m_mesh.m_vertex_to_triangle_map[i].empty() )
        {
            // ignore deleted vertices
            continue;
        }
        
        double dist = fabs( signed_distance_entropy( surf.get_position(i), sphere_a_centre, sphere_b_centre, max_radius, interior_radius ) );
        
        double area = 0;
        for ( unsigned int j = 0; j < surf.m_mesh.m_vertex_to_triangle_map[i].size(); ++j )
        {
            area += surf.get_triangle_area( surf.m_mesh.m_vertex_to_triangle_map[i][j] );
        }
        area /= 3;
        
        total_error += dist * area;
        total_area += area;
    }
    
    total_error /= total_area;
    
    return total_error;
    
}
void MidpointScheme::generate_new_midpoint( size_t edge_index, const SurfTrack& surface, Vec3d& new_point )
{
    const NonDestructiveTriMesh& mesh = surface.m_mesh;
    const std::vector<Vec3d>& positions = surface.get_positions();
    size_t p1_index = mesh.m_edges[edge_index][0];
	size_t p2_index = mesh.m_edges[edge_index][1];   
    
    new_point = 0.5 * ( positions[ p1_index ] + positions[ p2_index ] );
}
Exemplo n.º 3
0
double NormalDriver::compute_inf_error( const SurfTrack& surf )
{
    
    double max_error = -1.0;
    
    for ( unsigned int i = 0; i < surf.get_num_vertices(); ++i )
    {
        if ( surf.m_mesh.m_vertex_to_triangle_map[i].empty() )
        {
            // ignore deleted vertices
            continue;
        }
        
        double dist = signed_distance_entropy( surf.get_position(i), sphere_a_centre, sphere_b_centre, max_radius, interior_radius );
        max_error = max( max_error, fabs(dist) );
    }
    
    return max_error;
    
}
void ButterflyScheme::generate_new_midpoint( size_t edge_index, const SurfTrack& surface, Vec3d& new_point )
{
    const NonDestructiveTriMesh& mesh = surface.m_mesh;
    const std::vector<Vec3d>& positions = surface.get_positions();
    
    size_t p1_index = mesh.m_edges[edge_index][0];
	size_t p2_index = mesh.m_edges[edge_index][1];
	
    size_t tri0 = mesh.m_edge_to_triangle_map[edge_index][0];
    size_t tri1 = mesh.m_edge_to_triangle_map[edge_index][1];
    
	size_t p3_index = mesh.get_third_vertex( mesh.m_edges[edge_index][0], mesh.m_edges[edge_index][1], mesh.get_triangle(tri0) );
	size_t p4_index = mesh.get_third_vertex( mesh.m_edges[edge_index][0], mesh.m_edges[edge_index][1], mesh.get_triangle(tri1) );
	
	size_t adj_edges[4] = { mesh.get_edge_index( p1_index, p3_index ),
        mesh.get_edge_index( p2_index, p3_index ),
        mesh.get_edge_index( p1_index, p4_index ),
        mesh.get_edge_index( p2_index, p4_index ) };
    
	size_t q_indices[4];
	
	for ( size_t i = 0; i < 4; ++i )
	{
		const std::vector<size_t>& adj_tris = mesh.m_edge_to_triangle_map[ adj_edges[i] ];
		if ( adj_tris.size() != 2 )
		{
            // abort
			new_point = 0.5 * ( positions[ p1_index ] + positions[ p2_index ] );
            return;
		}
		
		if ( adj_tris[0] == tri0 || adj_tris[0] == tri1 )
		{
			q_indices[i] = mesh.get_third_vertex( mesh.m_edges[ adj_edges[i] ][0], mesh.m_edges[ adj_edges[i] ][1], mesh.get_triangle( adj_tris[1] ) );
		}
		else
		{
			q_indices[i] = mesh.get_third_vertex( mesh.m_edges[ adj_edges[i] ][0], mesh.m_edges[ adj_edges[i] ][1], mesh.get_triangle( adj_tris[0] ) );
		}
	}
    
	new_point =   8. * positions[ p1_index ] + 8. * positions[ p2_index ] + 2. * positions[ p3_index ] + 2. * positions[ p4_index ]
    - positions[ q_indices[0] ] - positions[ q_indices[1] ] - positions[ q_indices[2] ] - positions[ q_indices[3] ];
    
	new_point *= 0.0625;
    
}
Exemplo n.º 5
0
void NormalDriver::set_predicted_vertex_positions( const SurfTrack& surf, std::vector<Vec3d>& predicted_positions, double current_t, double& adaptive_dt )
{
    std::vector<Vec3d> displacements( surf.get_num_vertices(), Vec3d(0,0,0) );
    std::vector<Vec3d> velocities( surf.get_num_vertices(), Vec3d(0,0,0) );
    
    for ( unsigned int i = 0; i < surf.get_num_vertices(); ++i )
    {
        if ( surf.m_mesh.m_vertex_to_triangle_map[i].empty() ) 
        { 
            displacements[i] = Vec3d(0,0,0);
            continue;
        }
        
        Vec3d normal(0,0,0);
        double sum_areas = 0.0;
        for ( unsigned int j = 0; j < surf.m_mesh.m_vertex_to_triangle_map[i].size(); ++j )
        {
            double area = surf.get_triangle_area( surf.m_mesh.m_vertex_to_triangle_map[i][j] );
            normal += surf.get_triangle_normal( surf.m_mesh.m_vertex_to_triangle_map[i][j] ) * area;
            sum_areas += area;
        }
        //normal /= sum_areas;
        normal /= mag(normal);
        
        double switch_speed = (current_t >= 1.0) ? -speed : speed;
        velocities[i] = switch_speed * normal;
        displacements[i] = adaptive_dt * velocities[i];
    }
    
    double capped_dt = MeshSmoother::compute_max_timestep_quadratic_solve( surf.m_mesh.get_triangles(), surf.get_positions(), displacements, false );
    
    adaptive_dt = min( adaptive_dt, capped_dt );
    
    for ( unsigned int i = 0; i < surf.get_num_vertices(); ++i )
    {
        predicted_positions[i] = surf.get_position(i) + adaptive_dt * velocities[i];
    }
    
}
void QuadraticErrorMinScheme::generate_new_midpoint( size_t edge_index, const SurfTrack& surface, Vec3d& new_point )
{
    const NonDestructiveTriMesh& mesh = surface.m_mesh;
    const std::vector<Vec3d>& positions = surface.get_positions();
    
    size_t v0 = mesh.m_edges[edge_index][0];
    size_t v1 = mesh.m_edges[edge_index][1];
    
    Mat33d Q;
    zero(Q);
    Vec3d b;
    zero(b);
    
    std::vector<size_t> triangles_counted;
    
    Mat<1,1,double> constant_dist;
    constant_dist.a[0] = 0;
    
    for ( size_t i = 0; i < mesh.m_vertex_to_triangle_map[v0].size(); ++i )
    {
        size_t t = mesh.m_vertex_to_triangle_map[v0][i];
        const Vec3d& plane_normal = surface.get_triangle_normal( t );
        Q += outer( plane_normal, plane_normal );
        b += dot( positions[v0], plane_normal ) * plane_normal;
        constant_dist.a[0] += dot( plane_normal, positions[v0] ) * dot( plane_normal, positions[v0] );
        triangles_counted.push_back(t);
    }
    
    for ( size_t i = 0; i < mesh.m_vertex_to_triangle_map[v1].size(); ++i )
    {
        size_t t = mesh.m_vertex_to_triangle_map[v1][i];
        
        bool already_counted = false;
        for ( size_t j = 0; j < triangles_counted.size(); ++j ) 
        {
            if ( t == triangles_counted[j] )
            {
                already_counted = true;
            }
        }
        
        if ( !already_counted )
        {
            const Vec3d& plane_normal = surface.get_triangle_normal( t );
            Q += outer( plane_normal, plane_normal );
            b += dot( positions[v1], plane_normal ) * plane_normal;
            constant_dist.a[0] += dot( plane_normal, positions[v1] ) * dot( plane_normal, positions[v1] );
        }
    }
    
    // Compute normal direction
    Vec3d normal = 0.5 * (surface.get_vertex_normal(v0) + surface.get_vertex_normal(v1));
    normalize(normal);
    
    Mat<3,1,double> n;
    n(0,0) = normal[0];
    n(1,0) = normal[1];
    n(2,0) = normal[2];
    
    // Compute edge midpoint
    Vec3d midpoint = 0.5 * (positions[v0] + positions[v1]);   
    Mat<3,1,double> m;
    m(0,0) = midpoint[0];
    m(1,0) = midpoint[1];
    m(2,0) = midpoint[2]; 
    
    Mat<3,1,double> d;
    d(0,0) = b[0];
    d(1,0) = b[1];
    d(2,0) = b[2];
    
    double LHS = 2.0 * (n.transpose()*Q*n).a[0];              // result of multiplication is Mat<1,1,double>, hence the .a[0]
    double RHS = ( 2.0 * (n.transpose()*d) - (n.transpose()*Q*m) - (m.transpose()*Q*n) ).a[0];
    
    double a;
    if ( fabs(LHS) > 1e-10 )
    {
        a = RHS / LHS;
    }
    else
    {
        a = 0.0;
    }
    
    Mat<3,1,double> v = m + (a * n);
    
    double v_error = (v.transpose() * Q * v - 2.0 * (v.transpose() * d) + constant_dist).a[0];
    double m_error = (m.transpose() * Q * m - 2.0 * (m.transpose() * d) + constant_dist).a[0];
    
    //assert( v_error < m_error + 1e-8 );
    
    if ( surface.m_verbose )
    {
        std::cout << "a: " << a << std::endl;
        std::cout << "error at v: " << v_error << std::endl;
        std::cout << "error at midpoint: " << m_error << std::endl;
    }
    
    new_point = Vec3d( v.a[0], v.a[1], v.a[2] );
    
}
Exemplo n.º 7
0
void FaceOffDriver::set_predicted_vertex_positions( const SurfTrack& surf, 
                                                   std::vector<Vec3d>& new_positions, 
                                                   double current_t, 
                                                   double& adaptive_dt )
{
    const NonDestructiveTriMesh& mesh = surf.m_mesh;
    std::vector<double> triangle_areas;
    triangle_areas.reserve(mesh.num_triangles());
    std::vector<Vec3d> triangle_normals;
    triangle_normals.reserve(mesh.num_triangles());
    std::vector<Vec3d> triangle_centroids;
    triangle_centroids.reserve(mesh.num_triangles());
    std::vector<double> triangle_plane_distances;
    triangle_plane_distances.reserve(mesh.num_triangles());
    
    const std::vector<Vec3st>& tris = mesh.get_triangles();
    for ( size_t i = 0; i < tris.size(); ++i )
    {
        if ( tris[i][0] == tris[i][1] )
        {
            triangle_areas.push_back( 0 );
            triangle_normals.push_back( Vec3d(0,0,0) );
            triangle_centroids.push_back( Vec3d(0,0,0) );
        }
        else
        {
            triangle_areas.push_back( surf.get_triangle_area( i ) );
            triangle_normals.push_back( surf.get_triangle_normal( i ) );
            triangle_centroids.push_back( (surf.get_position(tris[i][0]) + surf.get_position(tris[i][1]) + surf.get_position(tris[i][2])) / 3 );
        }
        
        double switch_speed = (current_t >= 1.0) ? -speed : speed;
        triangle_plane_distances.push_back( adaptive_dt * switch_speed );
    }
    
    std::vector<Vec3d> displacements;
    displacements.resize( surf.get_num_vertices() );
    
    //
    // Null space smoothing
    //
    
    {
        for ( size_t i = 0; i < surf.get_num_vertices(); ++i )
        {
            const MeshSmoother& smoother = surf.m_smoother;
            smoother.null_space_smooth_vertex( i, triangle_areas, triangle_normals, triangle_centroids, displacements[i] );
        }
    }
    
    //
    // Primary space displacement
    //
    
    for ( size_t p = 0; p < surf.get_num_vertices(); ++p )
    {
        Vec3d normal_dispacement;
        intersection_point( triangle_normals, triangle_plane_distances, triangle_areas, mesh.m_vertex_to_triangle_map[p], normal_dispacement );
        displacements[p] += normal_dispacement;
        
        //
        // Entropy solution
        //
        
        if ( surf.m_mesh.m_vertex_to_triangle_map[p].empty() )
        {
            continue;
        }
        
        double sum_mu_l = 0, sum_mu = 0;
        
        const std::vector<size_t>& incident_triangles = mesh.m_vertex_to_triangle_map[p];
        
        for ( size_t j = 0; j < incident_triangles.size(); ++j )
        {
            size_t triangle_index = incident_triangles[j];
            
            const Vec3st& tri = surf.m_mesh.get_triangle( triangle_index );
            
            Vec3d edge_vector;
            if ( tri[0] == p )
            {
                edge_vector = surf.get_position(tri[1]) - surf.get_position(tri[2]);
            }
            else if ( tri[1] == p )
            {
                edge_vector = surf.get_position(tri[2]) - surf.get_position(tri[0]);
            }
            else
            {
                edge_vector = surf.get_position(tri[0]) - surf.get_position(tri[1]);
            }
            
            Vec3d s = cross( triangle_normals[triangle_index], edge_vector );   // orthogonal to normal and edge oposite vertex
            
            bool contracting = dot( s, displacements[p] ) >= 0.0;
            
            double cos_theta = dot( triangle_normals[triangle_index], normal_dispacement ) / mag(normal_dispacement);
            
            double mu = triangle_areas[triangle_index];
            if ( contracting )
            {
                mu *= cos_theta * cos_theta;
            }
            
            double li = fabs( triangle_plane_distances[triangle_index] ); 
            
            if ( contracting )
            {
                li /= fabs( cos_theta );
            }
            
            sum_mu_l += mu * li;
            sum_mu += mu;
        }
        
        double length = sum_mu_l / sum_mu;
        
        displacements[p] += length * normal_dispacement / mag(normal_dispacement);
        
    }
    
    double beta = MeshSmoother::compute_max_timestep_quadratic_solve( surf.m_mesh.get_triangles(), surf.get_positions(), displacements, false );
    
    adaptive_dt *= beta;
    
    for(size_t i = 0; i < surf.get_num_vertices(); i++)
    {
        new_positions[i] = surf.get_position(i) + beta * displacements[i];
    }
    
    
}