* src/sdf/ftsdf.c (sdf_contour_get_min_distance): Use epsilon.

This commit is contained in:
Anuj Verma 2020-07-03 10:01:37 +05:30 committed by anujverma
parent 76e67227ec
commit 5baa2cefc6
2 changed files with 45 additions and 24 deletions

View File

@ -1,3 +1,15 @@
2020-07-03 Anuj Verma <anujv@iitbhilai.ac.in>
* src/sdf/ftsdf.c (resolve_corner): [Bug] Remove the
nearest_point check. Two distances can be same and
can give opposite sign, but they may not have a
common nearest_point. Also remove distance check
because due to precision errors the two distances can
be really really close. Therefore use epsilon instead.
* src/sdf/ftsdf.c (sdf_contour_get_min_distance): Use
epsilon for comparing distances.
2020-07-03 Anuj Verma <anujv@iitbhilai.ac.in> 2020-07-03 Anuj Verma <anujv@iitbhilai.ac.in>
* src/sdf/ftsdf.c (sdf_shape_dump): Add more info * src/sdf/ftsdf.c (sdf_shape_dump): Add more info

View File

@ -41,6 +41,11 @@
/* the shortest distance. */ /* the shortest distance. */
#define MAX_NEWTON_STEPS 4 #define MAX_NEWTON_STEPS 4
/* This is the distance in 16.16 which is used for corner resolving. If */
/* the difference of two distance is less than `CORNER_CHECK_EPSILON' */
/* then they will be checked for corner if they have ambiguity. */
#define CORNER_CHECK_EPSILON 32
/************************************************************************** /**************************************************************************
* *
* macros * macros
@ -986,39 +991,34 @@
SDF_Signed_Distance sdf2, SDF_Signed_Distance sdf2,
FT_26D6_Vec point ) FT_26D6_Vec point )
{ {
FT_16D16_Vec dist; FT_16D16_Vec dist1;
FT_16D16_Vec dist2;
FT_16D16 ortho1; FT_16D16 ortho1;
FT_16D16 ortho2; FT_16D16 ortho2;
/* if they are not equal return the shorter */
if ( sdf1.distance != sdf2.distance )
return sdf1.distance < sdf2.distance ?
sdf1 : sdf2;
/* if there is not ambiguity in the sign return any */ /* if there is not ambiguity in the sign return any */
if ( sdf1.sign == sdf2.sign ) if ( sdf1.sign == sdf2.sign )
return sdf1; return sdf1;
/* final check: Make sure nearest point is same. If not */ /* calculate the distance vectors */
/* then return any, it is not the shortest distance. */ dist1.x = FT_26D6_16D16( point.x ) - sdf1.nearest_point.x;
if ( sdf1.nearest_point.x != sdf2.nearest_point.x || dist1.y = FT_26D6_16D16( point.y ) - sdf1.nearest_point.y;
sdf1.nearest_point.y != sdf2.nearest_point.y )
return sdf1;
/* calculate the distance vectors, will be same for both */ dist2.x = FT_26D6_16D16( point.x ) - sdf2.nearest_point.x;
dist.x = sdf1.nearest_point.x - FT_26D6_16D16( point.x ); dist2.y = FT_26D6_16D16( point.y ) - sdf2.nearest_point.y;
dist.y = sdf1.nearest_point.y - FT_26D6_16D16( point.y );
FT_Vector_NormLen( &dist ); FT_Vector_NormLen( &dist1 );
FT_Vector_NormLen( &dist2 );
/* use cross product to find orthogonality */ /* use cross product to find orthogonality */
ortho1 = FT_MulFix( sdf1.direction.x, dist.y ) - ortho1 = FT_MulFix( sdf1.direction.x, dist1.y ) -
FT_MulFix( sdf1.direction.y, dist.x ); FT_MulFix( sdf1.direction.y, dist1.x );
ortho1 = FT_ABS( ortho1 ); ortho1 = FT_ABS( ortho1 );
ortho2 = FT_MulFix( sdf2.direction.x, dist.y ) - ortho2 = FT_MulFix( sdf2.direction.x, dist2.y ) -
FT_MulFix( sdf2.direction.y, dist.x ); FT_MulFix( sdf2.direction.y, dist2.x );
ortho2 = FT_ABS( ortho2 ); ortho2 = FT_ABS( ortho2 );
return ortho1 > ortho2 ? sdf1 : sdf2; return ortho1 > ortho2 ? sdf1 : sdf2;
@ -1700,18 +1700,27 @@
/* iterate through all the edges manually */ /* iterate through all the edges manually */
while ( edge_list.head ) { while ( edge_list.head ) {
SDF_Signed_Distance current_dist = max_sdf; SDF_Signed_Distance current_dist = max_sdf;
FT_16D16 diff;
FT_CALL( sdf_edge_get_min_distance( FT_CALL( sdf_edge_get_min_distance(
(SDF_Edge*)edge_list.head->data, (SDF_Edge*)edge_list.head->data,
point, &current_dist ) ); point, &current_dist ) );
if ( current_dist.distance >= 0 && if ( current_dist.distance >= 0 )
current_dist.distance < min_dist.distance ) {
min_dist = current_dist; diff = current_dist.distance - min_dist.distance;
else if ( current_dist.distance ==
min_dist.distance )
min_dist = resolve_corner( min_dist, current_dist, point ); if ( FT_ABS(diff ) < CORNER_CHECK_EPSILON )
min_dist = resolve_corner( min_dist, current_dist, point );
else if ( diff < 0 )
min_dist = current_dist;
}
else
{
FT_TRACE0(( "sdf_contour_get_min_distance: Overflowed.\n" ));
}
edge_list.head = edge_list.head->next; edge_list.head = edge_list.head->next;
} }