[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[freetype2] anuj-distance-field 063b65d 16/93: [sdf] Added function to f
From: |
Anuj Verma |
Subject: |
[freetype2] anuj-distance-field 063b65d 16/93: [sdf] Added function to find shortest distance from a point to a line. |
Date: |
Sun, 2 Aug 2020 07:04:11 -0400 (EDT) |
branch: anuj-distance-field
commit 063b65d583ea2fadcadc6f44380e28ffa679443c
Author: Anuj Verma <anujv@iitbhilai.ac.in>
Commit: anujverma <anujv@iitbhilai.ac.in>
[sdf] Added function to find shortest distance from a point to a line.
---
[GSoC]ChangeLog | 14 +++++
src/sdf/ftsdf.c | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 172 insertions(+), 14 deletions(-)
diff --git a/[GSoC]ChangeLog b/[GSoC]ChangeLog
index 8fd4fc1..64c5493 100644
--- a/[GSoC]ChangeLog
+++ b/[GSoC]ChangeLog
@@ -1,5 +1,19 @@
2020-06-27 Anuj Verma <anujv@iitbhilai.ac.in>
+ [sdf] Added function to find shortest distance from
+ a point to a line.
+
+ * src/sdf/ftsdf.c (get_min_distance_line): The function
+ calculate the shortest signed distance from a point
+ to a line segment.
+
+ * src/sdf/ftsdf.c (sdf_contour_get_min_distance): Typo.
+
+ * src/sdf/ftsdf.c (SDF_Signed_Distance): Use squared
+ distance instead of actual distance for performance.
+
+2020-06-27 Anuj Verma <anujv@iitbhilai.ac.in>
+
* src/sdf/ftsdf.c (SDF_Iterator_IO): Removed.
* src/sdf/ftsdf.c (sdf_edge_iterator_func => sdf_edge_get_min_distance
diff --git a/src/sdf/ftsdf.c b/src/sdf/ftsdf.c
index 971b379..6a25775 100644
--- a/src/sdf/ftsdf.c
+++ b/src/sdf/ftsdf.c
@@ -12,7 +12,9 @@
*
*/
- #define FT_INT_26D6( x ) ( x * 64 ) /* convert int to 26.6 fixed point */
+ #define FT_INT_26D6( x ) ( x * 64 ) /* convert int to 26.6 fixed point
*/
+ #define FT_INT_16D16( x ) ( x * 65536 ) /* convert int to 16.16 fixed
point */
+ #define FT_26D6_16D16( x ) ( x * 1024 ) /* convert 26.6 to 16.16 fixed
point */
/* Convenient macro which calls the function */
@@ -34,6 +36,7 @@
typedef FT_Vector FT_16D16_Vec; /* with 16.16 fixed point components */
typedef FT_Fixed FT_16D16; /* 16.16 fixed point representation */
+ typedef FT_Fixed FT_26D6; /* 26.6 fixed point representation */
/**************************************************************************
*
@@ -99,9 +102,9 @@
/* [note]: This is a *direction* vector. */
FT_16D16_Vec direction;
- /* Unsigned shortest distance from the point to */
- /* the above `nearest_point'. */
- FT_16D16 distance;
+ /* Unsigned shortest squared distance from the */
+ /* point to the above `nearest_point'. */
+ FT_16D16 squared_distance;
/* Represent weather the `nearest_point' is outside */
/* or inside the contour corresponding to the edge. */
@@ -607,6 +610,144 @@
/**************************************************************************
*
* @Function:
+ * get_min_distance_line
+ *
+ * @Description:
+ * This function find the shortest distance from the `line' to
+ * a given `point' and assigns it to `out'. Only use it for line
+ * segments.
+ *
+ * @Input:
+ * [TODO]
+ *
+ * @Return:
+ * [TODO]
+ */
+ static FT_Error
+ get_min_distance_line( SDF_Edge* line,
+ FT_26D6_Vec point,
+ SDF_Signed_Distance* out )
+ {
+ /* in order to calculate the shortest distance from a point to */
+ /* a line segment. */
+ /* */
+ /* a = start point of the line segment */
+ /* b = end point of the line segment */
+ /* p = point from which shortest distance is to be calculated */
+ /* ----------------------------------------------------------- */
+ /* => we first write the parametric equation of the line */
+ /* point_on_line = a + ( b - a ) * t ( t is the factor ) */
+ /* */
+ /* => next we find the projection of point p on the line. the */
+ /* projection will be perpendicular to the line, that is */
+ /* why we can find it by making the dot product zero. */
+ /* ( point_on_line - a ) . ( p - point_on_line ) = 0 */
+ /* */
+ /* ( point_on_line ) */
+ /* ( a ) x-------o----------------x ( b ) */
+ /* |_| */
+ /* | */
+ /* | */
+ /* ( p ) */
+ /* */
+ /* => by simplifying the above equation we get the factor of */
+ /* point_on_line such that */
+ /* t = ( ( p - a ) . ( b - a ) ) / ( |b - a| ^ 2 ) */
+ /* */
+ /* => we clamp the factor t between [0.0f, 1.0f], because the */
+ /* point_on_line can be outside the line segment. */
+ /* */
+ /* ( point_on_line ) */
+ /* ( a ) x------------------------x ( b ) -----o--- */
+ /* |_| */
+ /* | */
+ /* | */
+ /* ( p ) */
+ /* */
+ /* => finally the distance becomes | point_on_line - p | */
+
+ FT_Error error = FT_Err_Ok;
+
+ const FT_Vector a = line->start_pos;
+ const FT_Vector b = line->end_pos;
+ const FT_Vector p = point;
+
+ FT_26D6_Vec line_segment; /* `b' - `a'*/
+ FT_26D6_Vec p_sub_a; /* `p' - `a' */
+
+ FT_26D6 sq_line_length; /* squared length of `line_segment' */
+ FT_16D16 factor; /* factor of the nearest point */
+ FT_26D6 cross; /* used to determine sign */
+
+ FT_16D16_Vec nearest_point; /* point on the line nearest to `point' */
+ FT_16D16_Vec nearest_vector; /* `p' - `nearest_point' */
+
+ if ( !line || !out )
+ {
+ error = FT_THROW( Invalid_Argument );
+ goto Exit;
+ }
+
+ if ( line->edge_type != SDF_EDGE_LINE )
+ {
+ error = FT_THROW( Invalid_Argument );
+ goto Exit;
+ }
+
+ line_segment.x = b.x - a.x;
+ line_segment.y = b.y - a.y;
+
+ p_sub_a.x = p.x - a.x;
+ p_sub_a.y = p.y - a.y;
+
+ sq_line_length = ( line_segment.x * line_segment.x ) / 64 +
+ ( line_segment.y * line_segment.y ) / 64;
+
+ /* currently factor is 26.6 */
+ factor = ( p_sub_a.x * line_segment.x ) / 64 +
+ ( p_sub_a.y * line_segment.y ) / 64;
+
+ /* now factor is 16.16 */
+ factor = FT_DivFix( factor, sq_line_length );
+
+ /* clamp the factor between 0.0 and 1.0 in fixed point */
+ if ( factor > FT_INT_16D16( 1 ) )
+ factor = FT_INT_16D16( 1 );
+ if ( factor < 0 )
+ factor = 0;
+
+ nearest_point.x = FT_MulFix( FT_26D6_16D16(line_segment.x),
+ factor );
+ nearest_point.y = FT_MulFix( FT_26D6_16D16(line_segment.y),
+ factor );
+
+ nearest_point.x = FT_26D6_16D16( a.x ) + nearest_point.x -
+ FT_26D6_16D16( p.x );
+ nearest_point.y = FT_26D6_16D16( a.y ) + nearest_point.y -
+ FT_26D6_16D16( p.y );
+
+ nearest_vector.x = nearest_point.x - FT_26D6_16D16( p.x );
+ nearest_vector.y = nearest_point.y - FT_26D6_16D16( p.y );
+
+ cross = FT_MulFix( nearest_vector.x, line_segment.y ) -
+ FT_MulFix( nearest_vector.y, line_segment.x );
+
+ FT_Vector_NormLen( &line_segment );
+
+ /* assign the output */
+ out->neartest_point = nearest_point;
+ out->sign = cross < 0 ? 1 : -1;
+ out->squared_distance = FT_MulFix( nearest_vector.x, nearest_vector.x ) +
+ FT_MulFix( nearest_vector.y, nearest_vector.y );
+ out->direction = line_segment;
+
+ Exit:
+ return error;
+ }
+
+ /**************************************************************************
+ *
+ * @Function:
* sdf_edge_get_min_distance
*
* @Description:
@@ -634,12 +775,14 @@
}
/* edge specific distance calculation */
- switch ( edge->edge_type ) {
- case SDF_EDGE_LINE:
- case SDF_EDGE_CONIC:
- case SDF_EDGE_CUBIC:
+ switch ( edge->edge_type ) {
+ case SDF_EDGE_LINE:
+ get_min_distance_line( edge, point, out );
+ break;
+ case SDF_EDGE_CONIC:
+ case SDF_EDGE_CUBIC:
default:
- error = FT_THROW( Invalid_Argument );
+ error = FT_THROW( Invalid_Argument );
}
Exit:
@@ -663,7 +806,7 @@
* [TODO]
*/
static FT_Error
- sdf_contour_get_min_distance( SDF_Contour* contuor,
+ sdf_contour_get_min_distance( SDF_Contour* contour,
FT_26D6_Vec point,
SDF_Signed_Distance* out)
{
@@ -672,13 +815,13 @@
FT_ListRec edge_list;
- if ( !contuor || !out )
+ if ( !contour || !out )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
}
- edge_list = contuor->edges;
+ edge_list = contour->edges;
/* iterate through all the edges manually */
while ( edge_list.head ) {
@@ -690,7 +833,7 @@
point, ¤t_dist ) );
/* [TODO]: *IMPORTANT* Add corner checking function. */
- if ( current_dist.distance < min_dist.distance )
+ if ( current_dist.squared_distance < min_dist.squared_distance )
min_dist = current_dist;
edge_list.head = edge_list.head->next;
@@ -786,7 +929,8 @@
(SDF_Contour*)contour_list.head->data,
grid_point, ¤t_dist ) );
- if ( current_dist.distance < min_dist.distance )
+ if ( current_dist.squared_distance <
+ min_dist.squared_distance )
min_dist = current_dist;
contour_list.head = contour_list.head->next;
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [freetype2] anuj-distance-field 063b65d 16/93: [sdf] Added function to find shortest distance from a point to a line.,
Anuj Verma <=