2013-06-23 16:18:38 +00:00
/* ADMesh -- process triangulated solid meshes
2014-09-23 12:34:37 +00:00
* Copyright ( C ) 1995 , 1996 Anthony D . Martin < amartin @ engr . csulb . edu >
* Copyright ( C ) 2013 , 2014 several contributors , see AUTHORS
2013-06-23 16:18:38 +00:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
2014-09-23 12:34:37 +00:00
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
2013-06-23 16:18:38 +00:00
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
2014-09-23 12:34:37 +00:00
* You should have received a copy of the GNU General Public License along
* with this program ; if not , write to the Free Software Foundation , Inc . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
2013-06-23 16:18:38 +00:00
*
2014-09-23 12:34:37 +00:00
* Questions , comments , suggestions , etc to
* https : //github.com/admesh/admesh/issues
2013-06-23 16:18:38 +00:00
*/
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <math.h>
# include "stl.h"
2017-08-03 15:31:31 +00:00
static int stl_check_normal_vector ( stl_file * stl , int facet_num , int normal_fix_flag ) ;
2013-06-23 16:18:38 +00:00
static void
2014-09-23 12:34:37 +00:00
stl_reverse_facet ( stl_file * stl , int facet_num ) {
2013-06-23 16:18:38 +00:00
stl_vertex tmp_vertex ;
/* int tmp_neighbor;*/
int neighbor [ 3 ] ;
int vnot [ 3 ] ;
stl - > stats . facets_reversed + = 1 ;
2014-09-23 12:34:37 +00:00
2013-06-23 16:18:38 +00:00
neighbor [ 0 ] = stl - > neighbors_start [ facet_num ] . neighbor [ 0 ] ;
neighbor [ 1 ] = stl - > neighbors_start [ facet_num ] . neighbor [ 1 ] ;
neighbor [ 2 ] = stl - > neighbors_start [ facet_num ] . neighbor [ 2 ] ;
vnot [ 0 ] = stl - > neighbors_start [ facet_num ] . which_vertex_not [ 0 ] ;
vnot [ 1 ] = stl - > neighbors_start [ facet_num ] . which_vertex_not [ 1 ] ;
vnot [ 2 ] = stl - > neighbors_start [ facet_num ] . which_vertex_not [ 2 ] ;
/* reverse the facet */
tmp_vertex = stl - > facet_start [ facet_num ] . vertex [ 0 ] ;
2014-09-23 12:34:37 +00:00
stl - > facet_start [ facet_num ] . vertex [ 0 ] =
2013-06-23 16:18:38 +00:00
stl - > facet_start [ facet_num ] . vertex [ 1 ] ;
stl - > facet_start [ facet_num ] . vertex [ 1 ] = tmp_vertex ;
/* fix the vnots of the neighboring facets */
if ( neighbor [ 0 ] ! = - 1 )
2014-09-23 12:34:37 +00:00
stl - > neighbors_start [ neighbor [ 0 ] ] . which_vertex_not [ ( vnot [ 0 ] + 1 ) % 3 ] =
( stl - > neighbors_start [ neighbor [ 0 ] ] .
which_vertex_not [ ( vnot [ 0 ] + 1 ) % 3 ] + 3 ) % 6 ;
2013-06-23 16:18:38 +00:00
if ( neighbor [ 1 ] ! = - 1 )
2014-09-23 12:34:37 +00:00
stl - > neighbors_start [ neighbor [ 1 ] ] . which_vertex_not [ ( vnot [ 1 ] + 1 ) % 3 ] =
( stl - > neighbors_start [ neighbor [ 1 ] ] .
which_vertex_not [ ( vnot [ 1 ] + 1 ) % 3 ] + 4 ) % 6 ;
2013-06-23 16:18:38 +00:00
if ( neighbor [ 2 ] ! = - 1 )
2014-09-23 12:34:37 +00:00
stl - > neighbors_start [ neighbor [ 2 ] ] . which_vertex_not [ ( vnot [ 2 ] + 1 ) % 3 ] =
( stl - > neighbors_start [ neighbor [ 2 ] ] .
which_vertex_not [ ( vnot [ 2 ] + 1 ) % 3 ] + 2 ) % 6 ;
2013-06-23 16:18:38 +00:00
/* swap the neighbors of the facet that is being reversed */
stl - > neighbors_start [ facet_num ] . neighbor [ 1 ] = neighbor [ 2 ] ;
stl - > neighbors_start [ facet_num ] . neighbor [ 2 ] = neighbor [ 1 ] ;
/* swap the vnots of the facet that is being reversed */
stl - > neighbors_start [ facet_num ] . which_vertex_not [ 1 ] = vnot [ 2 ] ;
stl - > neighbors_start [ facet_num ] . which_vertex_not [ 2 ] = vnot [ 1 ] ;
/* reverse the values of the vnots of the facet that is being reversed */
stl - > neighbors_start [ facet_num ] . which_vertex_not [ 0 ] =
( stl - > neighbors_start [ facet_num ] . which_vertex_not [ 0 ] + 3 ) % 6 ;
stl - > neighbors_start [ facet_num ] . which_vertex_not [ 1 ] =
( stl - > neighbors_start [ facet_num ] . which_vertex_not [ 1 ] + 3 ) % 6 ;
stl - > neighbors_start [ facet_num ] . which_vertex_not [ 2 ] =
( stl - > neighbors_start [ facet_num ] . which_vertex_not [ 2 ] + 3 ) % 6 ;
}
void
2014-09-23 12:34:37 +00:00
stl_fix_normal_directions ( stl_file * stl ) {
2013-06-23 16:18:38 +00:00
char * norm_sw ;
/* int edge_num;*/
/* int vnot;*/
int checked = 0 ;
int facet_num ;
/* int next_facet;*/
int i ;
int j ;
2014-09-23 12:34:37 +00:00
struct stl_normal {
2013-06-23 16:18:38 +00:00
int facet_num ;
struct stl_normal * next ;
} ;
struct stl_normal * head ;
struct stl_normal * tail ;
struct stl_normal * newn ;
struct stl_normal * temp ;
2014-09-23 12:34:37 +00:00
2018-02-15 15:10:47 +00:00
int * reversed_ids ;
int reversed_count = 0 ;
int id ;
int force_exit = 0 ;
2014-09-23 12:34:37 +00:00
if ( stl - > error ) return ;
2013-06-23 16:18:38 +00:00
/* Initialize linked list. */
2014-09-23 12:34:37 +00:00
head = ( struct stl_normal * ) malloc ( sizeof ( struct stl_normal ) ) ;
2013-06-23 16:18:38 +00:00
if ( head = = NULL ) perror ( " stl_fix_normal_directions " ) ;
2014-09-23 12:34:37 +00:00
tail = ( struct stl_normal * ) malloc ( sizeof ( struct stl_normal ) ) ;
2013-06-23 16:18:38 +00:00
if ( tail = = NULL ) perror ( " stl_fix_normal_directions " ) ;
head - > next = tail ;
tail - > next = tail ;
/* Initialize list that keeps track of already fixed facets. */
norm_sw = ( char * ) calloc ( stl - > stats . number_of_facets , sizeof ( char ) ) ;
if ( norm_sw = = NULL ) perror ( " stl_fix_normal_directions " ) ;
2014-09-23 12:34:37 +00:00
2018-02-15 15:10:47 +00:00
/* Initialize list that keeps track of reversed facets. */
reversed_ids = ( int * ) calloc ( stl - > stats . number_of_facets , sizeof ( int ) ) ;
if ( reversed_ids = = NULL ) perror ( " stl_fix_normal_directions reversed_ids " ) ;
2013-06-23 16:18:38 +00:00
facet_num = 0 ;
2014-09-23 12:34:37 +00:00
/* If normal vector is not within tolerance and backwards:
Arbitrarily starts at face 0. If this one is wrong , we ' re screwed . Thankfully , the chances
of it being wrong randomly are low if most of the triangles are right : */
2018-02-15 15:10:47 +00:00
if ( stl_check_normal_vector ( stl , 0 , 0 ) = = 2 ) {
stl_reverse_facet ( stl , 0 ) ;
reversed_ids [ reversed_count + + ] = 0 ;
}
2013-07-30 22:01:53 +00:00
2014-09-23 12:34:37 +00:00
/* Say that we've fixed this facet: */
2013-06-23 16:18:38 +00:00
norm_sw [ facet_num ] = 1 ;
checked + + ;
2014-09-23 12:34:37 +00:00
for ( ; ; ) {
/* Add neighbors_to_list.
Add unconnected neighbors to the list : a */
for ( j = 0 ; j < 3 ; j + + ) {
/* Reverse the neighboring facets if necessary. */
if ( stl - > neighbors_start [ facet_num ] . which_vertex_not [ j ] > 2 ) {
/* If the facet has a neighbor that is -1, it means that edge isn't shared by another facet */
2018-02-15 15:10:47 +00:00
if ( stl - > neighbors_start [ facet_num ] . neighbor [ j ] ! = - 1 ) {
if ( norm_sw [ stl - > neighbors_start [ facet_num ] . neighbor [ j ] ] = = 1 ) {
/* trying to modify a facet already marked as fixed, revert all changes made until now and exit (fixes: #716, #574, #413, #269, #262, #259, #230, #228, #206) */
for ( id = reversed_count - 1 ; id > = 0 ; - - id ) {
stl_reverse_facet ( stl , reversed_ids [ id ] ) ;
}
force_exit = 1 ;
break ;
} else {
stl_reverse_facet ( stl , stl - > neighbors_start [ facet_num ] . neighbor [ j ] ) ;
reversed_ids [ reversed_count + + ] = stl - > neighbors_start [ facet_num ] . neighbor [ j ] ;
}
}
2014-09-23 12:34:37 +00:00
}
/* If this edge of the facet is connected: */
if ( stl - > neighbors_start [ facet_num ] . neighbor [ j ] ! = - 1 ) {
/* If we haven't fixed this facet yet, add it to the list: */
if ( norm_sw [ stl - > neighbors_start [ facet_num ] . neighbor [ j ] ] ! = 1 ) {
/* Add node to beginning of list. */
newn = ( struct stl_normal * ) malloc ( sizeof ( struct stl_normal ) ) ;
if ( newn = = NULL ) perror ( " stl_fix_normal_directions " ) ;
newn - > facet_num = stl - > neighbors_start [ facet_num ] . neighbor [ j ] ;
newn - > next = head - > next ;
head - > next = newn ;
}
}
2013-06-23 16:18:38 +00:00
}
2018-02-15 15:10:47 +00:00
/* an error occourred, quit the for loop and exit */
if ( force_exit ) break ;
2014-09-23 12:34:37 +00:00
/* Get next facet to fix from top of list. */
if ( head - > next ! = tail ) {
facet_num = head - > next - > facet_num ;
if ( norm_sw [ facet_num ] ! = 1 ) { /* If facet is in list mutiple times */
norm_sw [ facet_num ] = 1 ; /* Record this one as being fixed. */
checked + + ;
}
temp = head - > next ; /* Delete this facet from the list. */
head - > next = head - > next - > next ;
free ( temp ) ;
} else { /* if we ran out of facets to fix: */
/* All of the facets in this part have been fixed. */
stl - > stats . number_of_parts + = 1 ;
if ( checked > = stl - > stats . number_of_facets ) {
/* All of the facets have been checked. Bail out. */
break ;
} else {
/* There is another part here. Find it and continue. */
for ( i = 0 ; i < stl - > stats . number_of_facets ; i + + ) {
if ( norm_sw [ i ] = = 0 ) {
/* This is the first facet of the next part. */
facet_num = i ;
if ( stl_check_normal_vector ( stl , i , 0 ) = = 2 ) {
2018-02-15 15:10:47 +00:00
stl_reverse_facet ( stl , i ) ;
reversed_ids [ reversed_count + + ] = i ;
2014-09-23 12:34:37 +00:00
}
norm_sw [ facet_num ] = 1 ;
checked + + ;
break ;
}
}
}
}
}
2013-06-23 16:18:38 +00:00
free ( head ) ;
free ( tail ) ;
2018-02-15 15:10:47 +00:00
free ( reversed_ids ) ;
2013-06-23 16:18:38 +00:00
free ( norm_sw ) ;
}
2017-08-03 15:31:31 +00:00
static int stl_check_normal_vector ( stl_file * stl , int facet_num , int normal_fix_flag ) {
2013-06-23 16:18:38 +00:00
/* Returns 0 if the normal is within tolerance */
/* Returns 1 if the normal is not within tolerance, but direction is OK */
/* Returns 2 if the normal is not within tolerance and backwards */
/* Returns 4 if the status is unknown. */
2014-09-23 12:34:37 +00:00
2013-06-23 16:18:38 +00:00
stl_facet * facet ;
facet = & stl - > facet_start [ facet_num ] ;
2018-08-22 13:03:35 +00:00
stl_normal normal ;
2013-06-23 16:18:38 +00:00
stl_calculate_normal ( normal , facet ) ;
stl_normalize_vector ( normal ) ;
2018-08-22 13:03:35 +00:00
stl_normal normal_dif = ( normal - facet - > normal ) . cwiseAbs ( ) ;
2014-09-23 12:34:37 +00:00
2018-08-22 13:03:35 +00:00
const float eps = 0.001f ;
if ( normal_dif ( 0 ) < eps & & normal_dif ( 1 ) < eps & & normal_dif ( 2 ) < eps ) {
2014-09-23 12:34:37 +00:00
/* It is not really necessary to change the values here */
/* but just for consistency, I will. */
2018-08-22 13:03:35 +00:00
facet - > normal = normal ;
2014-09-23 12:34:37 +00:00
return 0 ;
}
2018-08-22 13:03:35 +00:00
stl_normal test_norm = facet - > normal ;
2013-06-23 16:18:38 +00:00
stl_normalize_vector ( test_norm ) ;
2018-08-22 13:03:35 +00:00
normal_dif = ( normal - test_norm ) . cwiseAbs ( ) ;
if ( normal_dif ( 0 ) < eps & & normal_dif ( 1 ) < eps & & normal_dif ( 2 ) < eps ) {
2014-09-23 12:34:37 +00:00
if ( normal_fix_flag ) {
2018-08-22 13:03:35 +00:00
facet - > normal = normal ;
2014-09-23 12:34:37 +00:00
stl - > stats . normals_fixed + = 1 ;
2013-06-23 16:18:38 +00:00
}
2014-09-23 12:34:37 +00:00
return 1 ;
}
2013-06-23 16:18:38 +00:00
2018-08-22 13:03:35 +00:00
test_norm * = - 1.f ;
normal_dif = ( normal - test_norm ) . cwiseAbs ( ) ;
if ( normal_dif ( 0 ) < eps & & normal_dif ( 1 ) < eps & & normal_dif ( 2 ) < eps ) {
// Facet is backwards.
2014-09-23 12:34:37 +00:00
if ( normal_fix_flag ) {
2018-08-22 13:03:35 +00:00
facet - > normal = normal ;
2013-06-23 16:18:38 +00:00
stl - > stats . normals_fixed + = 1 ;
2014-09-23 12:34:37 +00:00
}
return 2 ;
}
if ( normal_fix_flag ) {
2018-08-22 13:03:35 +00:00
facet - > normal = normal ;
2014-09-23 12:34:37 +00:00
stl - > stats . normals_fixed + = 1 ;
}
2013-06-23 16:18:38 +00:00
return 4 ;
}
2018-08-22 13:03:35 +00:00
void stl_fix_normal_values ( stl_file * stl ) {
2013-06-23 16:18:38 +00:00
int i ;
2014-09-23 12:34:37 +00:00
if ( stl - > error ) return ;
for ( i = 0 ; i < stl - > stats . number_of_facets ; i + + ) {
stl_check_normal_vector ( stl , i , 1 ) ;
}
2013-06-23 16:18:38 +00:00
}
2018-08-22 13:03:35 +00:00
void stl_reverse_all_facets ( stl_file * stl )
{
if ( stl - > error )
return ;
2014-09-23 12:34:37 +00:00
2018-08-22 13:03:35 +00:00
stl_normal normal ;
for ( int i = 0 ; i < stl - > stats . number_of_facets ; i + + ) {
2014-09-23 12:34:37 +00:00
stl_reverse_facet ( stl , i ) ;
stl_calculate_normal ( normal , & stl - > facet_start [ i ] ) ;
stl_normalize_vector ( normal ) ;
2018-08-22 13:03:35 +00:00
stl - > facet_start [ i ] . normal = normal ;
2014-09-23 12:34:37 +00:00
}
2013-06-23 16:18:38 +00:00
}