freetype-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[freetype2] anuj-distance-field 9b30e65: [sdf] Precompute the orthogonal


From: Anuj Verma
Subject: [freetype2] anuj-distance-field 9b30e65: [sdf] Precompute the orthogonality.
Date: Sun, 5 Jul 2020 23:43:23 -0400 (EDT)

branch: anuj-distance-field
commit 9b30e65675a93702dfdd8f24081a20b753749751
Author: Anuj Verma <anujv@iitbhilai.ac.in>
Commit: Anuj Verma <anujv@iitbhilai.ac.in>

    [sdf] Precompute the orthogonality.
---
 [GSoC]ChangeLog |  19 ++++++++
 src/sdf/ftsdf.c | 132 ++++++++++++++++++++++++++++++--------------------------
 2 files changed, 89 insertions(+), 62 deletions(-)

diff --git a/[GSoC]ChangeLog b/[GSoC]ChangeLog
index 6c92594..7e103f1 100644
--- a/[GSoC]ChangeLog
+++ b/[GSoC]ChangeLog
@@ -1,3 +1,22 @@
+2020-07-06  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+       [sdf] Precompute the orthogonality.
+
+       * src/sdf/ftsdf.c (SDF_Signed_Distance): Remove unused
+         fields.
+
+       * src/sdf/ftsdf.c (resolve_corner): The function can be
+         simplified to a single line. Instead of computing
+         orthogonality here, we precompute it in the corresponding
+         `get_min_distance_' functions more efficiently.
+
+       * src/sdf/ftsdf.c (get_min_distance_): Precompute orthogonality/
+         cross product of direction and the distance vector. Since
+         in these function we know that weather the distance vector
+         and the direction are perpendicular, we can simply set
+         the cross to 1 (sin(90) = 1) in case they are perpendicular.
+         This can reduce the number of `FT_Vector_NormLen' calls.
+
 2020-07-05  Anuj Verma  <anujv@iitbhilai.ac.in>
 
        [sdf] Added bounding box optimization.
diff --git a/src/sdf/ftsdf.c b/src/sdf/ftsdf.c
index d480252..77cf3e6 100644
--- a/src/sdf/ftsdf.c
+++ b/src/sdf/ftsdf.c
@@ -156,16 +156,6 @@
 
   typedef struct SDF_Signed_Distance_
   {
-    /* Nearest point the outline to a given point.    */
-    /* [note]: This is not a *direction* vector, this */
-    /*         simply a *point* vector on the grid.   */
-    FT_16D16_Vec  nearest_point;
-
-    /* The normalized direction of the curve at the   */
-    /* above point.                                   */
-    /* [note]: This is a *direction* vector.          */
-    FT_16D16_Vec  direction;
-
     /* Unsigned shortest distance from the point to   */
     /* the above `nearest_point'.                     */
     /* [NOTE]: This can represent both squared as or  */
@@ -173,7 +163,11 @@
     /* `USE_SQUARED_DISTANCES' macro.                 */
     FT_16D16      distance;
 
-    /* Represent weather the `nearest_point' is outside */
+    /* The cross product of distance vector and the   */
+    /* direction. ( aka orthogonality )               */
+    FT_16D16      cross;
+
+    /* Represent weather the distance vector is outside */
     /* or inside the contour corresponding to the edge. */
     /* [note]: This sign may or may not be correct,     */
     /*         therefore it must be checked properly in */
@@ -203,8 +197,7 @@
   const SDF_Shape    null_shape   = { NULL, { NULL, NULL } };
 
   static
-  const SDF_Signed_Distance  max_sdf = { { 0, 0 }, { 0, 0 },
-                                         INT_MAX, 0 };
+  const SDF_Signed_Distance  max_sdf = { INT_MAX, 0, 0 };
 
   /* Creates a new `SDF_Edge' on the heap and assigns the `edge' */
   /* pointer to the newly allocated memory.                      */
@@ -1072,6 +1065,9 @@
    *   We can see that `x' lies in the plane of `a', so we take the sign
    *   determined by `a'. This can be easily done by calculating the 
    *   orthogonality and taking the greater one.
+   *   The orthogonality is nothing but the sinus of the two vectors (i.e.
+   *   ( x - o ) and the corresponding direction. The orthogonality is pre
+   *   computed by the corresponding `get_min_distance_' functions efficiently.
    *
    * @Input:
    *   [TODO]
@@ -1081,40 +1077,9 @@
    */
   static SDF_Signed_Distance
   resolve_corner( SDF_Signed_Distance  sdf1,
-                  SDF_Signed_Distance  sdf2,
-                  FT_26D6_Vec          point )
+                  SDF_Signed_Distance  sdf2 )
   {
-    FT_16D16_Vec  dist1;
-    FT_16D16_Vec  dist2;
-
-    FT_16D16      ortho1;
-    FT_16D16      ortho2;
-
-
-    /* if there is not ambiguity in the sign return any */
-    if ( sdf1.sign == sdf2.sign )
-      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;
-
-    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( &dist1 );
-    FT_Vector_NormLen( &dist2 );
-
-    /* use cross product to find orthogonality */
-    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, dist2.y ) -
-             FT_MulFix( sdf2.direction.y, dist2.x );
-    ortho2 = FT_ABS( ortho2 );
-
-    return ortho1 > ortho2 ? sdf1 : sdf2;
+    return FT_ABS( sdf1.cross ) > FT_ABS( sdf2.cross ) ? sdf1 : sdf2;
   }
 
   /**************************************************************************
@@ -1245,14 +1210,26 @@
     cross = FT_MulFix( nearest_vector.x, line_segment.y ) -
             FT_MulFix( nearest_vector.y, line_segment.x );
 
-    /* [OPTIMIZATION]: Pre-compute this direction. */
-    FT_Vector_NormLen( &line_segment );
-
     /* assign the output */
-    out->nearest_point = nearest_point;
     out->sign = cross < 0 ? 1 : -1;
     out->distance = VECTOR_LENGTH_16D16( nearest_vector );
-    out->direction = line_segment;
+
+    /* Instead of finding cross for checking corner we */
+    /* directly set it here. This is more efficient    */
+    /* because if the distance is perpendicular we can */
+    /* directly set it to 1.                           */
+    if ( factor != 0 && factor != FT_INT_16D16( 1 ) )
+      out->cross = FT_INT_16D16( 1 );
+    else
+    {
+      /* [OPTIMIZATION]: Pre-compute this direction. */
+      /* if not perpendicular then compute the cross */
+      FT_Vector_NormLen( &line_segment );
+      FT_Vector_NormLen( &nearest_vector );
+
+      out->cross = FT_MulFix( line_segment.x, nearest_vector.y ) -
+                   FT_MulFix( line_segment.y, nearest_vector.x );
+    }
 
   Exit:
     return error;
@@ -1475,13 +1452,23 @@
 
     /* assign the values */
     out->distance = min;
-    out->nearest_point = nearest_point;
     out->sign = cross < 0 ? 1 : -1;
 
-    FT_Vector_NormLen( &direction );
+    if ( min_factor != 0 && min_factor != FT_INT_16D16( 1 ) )
+      out->cross = FT_INT_16D16( 1 );   /* the two are perpendicular */
+    else
+    {
+      /* convert to nearest vector */
+      nearest_point.x -= FT_26D6_16D16( p.x );
+      nearest_point.y -= FT_26D6_16D16( p.y );
 
-    out->direction = direction;
+      /* if not perpendicular then compute the cross */
+      FT_Vector_NormLen( &direction );
+      FT_Vector_NormLen( &nearest_point );
 
+      out->cross = FT_MulFix( direction.x, nearest_point.y ) -
+                   FT_MulFix( direction.y, nearest_point.x );
+    }
   Exit:
     return error;
   }
@@ -1698,12 +1685,23 @@
 
     /* assign the values */
     out->distance = min;
-    out->nearest_point = nearest_point;
     out->sign = cross < 0 ? 1 : -1;
 
-    FT_Vector_NormLen( &direction );
+    if ( min_factor != 0 && min_factor != FT_INT_16D16( 1 ) )
+      out->cross = FT_INT_16D16( 1 );   /* the two are perpendicular */
+    else
+    {
+      /* convert to nearest vector */
+      nearest_point.x -= FT_26D6_16D16( p.x );
+      nearest_point.y -= FT_26D6_16D16( p.y );
 
-    out->direction = direction;
+      /* if not perpendicular then compute the cross */
+      FT_Vector_NormLen( &direction );
+      FT_Vector_NormLen( &nearest_point );
+
+      out->cross = FT_MulFix( direction.x, nearest_point.y ) -
+                   FT_MulFix( direction.y, nearest_point.x );
+    }
 
   Exit:
     return error;
@@ -1944,13 +1942,23 @@
 
     /* assign the values */
     out->distance = min;
-    out->nearest_point = nearest_point;
     out->sign = cross < 0 ? 1 : -1;
 
-    FT_Vector_NormLen( &direction );
+    if ( min_factor != 0 && min_factor != FT_INT_16D16( 1 ) )
+      out->cross = FT_INT_16D16( 1 );   /* the two are perpendicular */
+    else
+    {
+      /* convert to nearest vector */
+      nearest_point.x -= FT_26D6_16D16( p.x );
+      nearest_point.y -= FT_26D6_16D16( p.y );
 
-    out->direction = direction;
+      /* if not perpendicular then compute the cross */
+      FT_Vector_NormLen( &direction );
+      FT_Vector_NormLen( &nearest_point );
 
+      out->cross = FT_MulFix( direction.x, nearest_point.y ) -
+                   FT_MulFix( direction.y, nearest_point.x );
+    }
   Exit:
     return error;
   }
@@ -2053,7 +2061,7 @@
 
 
         if ( FT_ABS(diff ) < CORNER_CHECK_EPSILON )
-          min_dist = resolve_corner( min_dist, current_dist, point );
+          min_dist = resolve_corner( min_dist, current_dist );
         else if ( diff < 0 )
           min_dist = current_dist;
       }
@@ -2511,7 +2519,7 @@
 
     FT_CALL( sdf_outline_decompose( outline, shape ) );
 
-    FT_CALL( sdf_generate_bounding_box( shape, sdf_params->spread, 
+    FT_CALL( sdf_generate( shape, sdf_params->spread, 
                            sdf_params->root.target ) );
 
   Exit:



reply via email to

[Prev in Thread] Current Thread [Next in Thread]