* 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>
* src/sdf/ftsdf.c (sdf_shape_dump): Add more info

View File

@ -41,6 +41,11 @@
/* the shortest distance. */
#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
@ -986,39 +991,34 @@
SDF_Signed_Distance sdf2,
FT_26D6_Vec point )
{
FT_16D16_Vec dist;
FT_16D16_Vec dist1;
FT_16D16_Vec dist2;
FT_16D16 ortho1;
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 ( sdf1.sign == sdf2.sign )
return sdf1;
/* final check: Make sure nearest point is same. If not */
/* then return any, it is not the shortest distance. */
if ( sdf1.nearest_point.x != sdf2.nearest_point.x ||
sdf1.nearest_point.y != sdf2.nearest_point.y )
return sdf1;
/* calculate the distance vectors */
dist1.x = FT_26D6_16D16( point.x ) - sdf1.nearest_point.x;
dist1.y = FT_26D6_16D16( point.y ) - sdf1.nearest_point.y;
/* calculate the distance vectors, will be same for both */
dist.x = sdf1.nearest_point.x - FT_26D6_16D16( point.x );
dist.y = sdf1.nearest_point.y - FT_26D6_16D16( point.y );
dist2.x = FT_26D6_16D16( point.x ) - sdf2.nearest_point.x;
dist2.y = FT_26D6_16D16( point.y ) - sdf2.nearest_point.y;
FT_Vector_NormLen( &dist );
FT_Vector_NormLen( &dist1 );
FT_Vector_NormLen( &dist2 );
/* use cross product to find orthogonality */
ortho1 = FT_MulFix( sdf1.direction.x, dist.y ) -
FT_MulFix( sdf1.direction.y, dist.x );
ortho1 = FT_MulFix( sdf1.direction.x, dist1.y ) -
FT_MulFix( sdf1.direction.y, dist1.x );
ortho1 = FT_ABS( ortho1 );
ortho2 = FT_MulFix( sdf2.direction.x, dist.y ) -
FT_MulFix( sdf2.direction.y, dist.x );
ortho2 = FT_MulFix( sdf2.direction.x, dist2.y ) -
FT_MulFix( sdf2.direction.y, dist2.x );
ortho2 = FT_ABS( ortho2 );
return ortho1 > ortho2 ? sdf1 : sdf2;
@ -1700,18 +1700,27 @@
/* iterate through all the edges manually */
while ( edge_list.head ) {
SDF_Signed_Distance current_dist = max_sdf;
FT_16D16 diff;
FT_CALL( sdf_edge_get_min_distance(
(SDF_Edge*)edge_list.head->data,
point, &current_dist ) );
if ( current_dist.distance >= 0 &&
current_dist.distance < min_dist.distance )
min_dist = current_dist;
else if ( current_dist.distance ==
min_dist.distance )
min_dist = resolve_corner( min_dist, current_dist, point );
if ( current_dist.distance >= 0 )
{
diff = current_dist.distance - min_dist.distance;
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;
}