Commit c918b54f25340dcf1a6bf57f747f545ac1f30568

Anuj Verma 2020-08-18T10:28:16

[sdf] Add function to resolve corner distances. * src/sdf/ftsdf.c (resolve_corner): New function.

diff --git a/ChangeLog b/ChangeLog
index 7abe62d..c64b5f1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2020-08-18  Anuj Verma  <anujv@iitbhilai.ac.in>
 
+	[sdf] Add function to resolve corner distances.
+
+	* src/sdf/ftsdf.c (resolve_corner): New function.
+
+2020-08-18  Anuj Verma  <anujv@iitbhilai.ac.in>
+
 	[sdf] Add essential math functions.
 
 	* src/sdf/ftsdf.c (cube_root, arc_cos) [!USE_NEWTON_FOR_CONIC]: New
diff --git a/src/sdf/ftsdf.c b/src/sdf/ftsdf.c
index d518d87..2512155 100644
--- a/src/sdf/ftsdf.c
+++ b/src/sdf/ftsdf.c
@@ -1556,4 +1556,108 @@
 #endif /* !USE_NEWTON_FOR_CONIC */
 
 
+  /*************************************************************************/
+  /*************************************************************************/
+  /**                                                                     **/
+  /**  RASTERIZER                                                         **/
+  /**                                                                     **/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   resolve_corner
+   *
+   * @Description:
+   *   At some places on the grid two edges can give opposite directions;
+   *   this happens when the closest point is on one of the endpoint.  In
+   *   that case we need to check the proper sign.
+   *
+   *   This can be visualized by an example:
+   *
+   *   ```
+   *                x
+   *
+   *                   o
+   *                  ^ \
+   *                 /   \
+   *                /     \
+   *           (a) /       \  (b)
+   *              /         \
+   *             /           \
+   *            /             v
+   *   ```
+   *
+   *   Suppose `x` is the point whose shortest distance from an arbitrary
+   *   contour we want to find out.  It is clear that `o` is the nearest
+   *   point on the contour.  Now to determine the sign we do a cross
+   *   product of the shortest distance vector and the edge direction, i.e.,
+   *
+   *   ```
+   *   => sign = cross(x - o, direction(a))
+   *   ```
+   *
+   *   Using the right hand thumb rule we can see that the sign will be
+   *   positive.
+   *
+   *   If we use `b', however, we have
+   *
+   *   ```
+   *   => sign = cross(x - o, direction(b))
+   *   ```
+   *
+   *   In this case the sign will be negative.  To determine the correct
+   *   sign we thus divide the plane in two halves and check which plane the
+   *   point lies in.
+   *
+   *   ```
+   *                   |
+   *                x  |
+   *                   |
+   *                   o
+   *                  ^|\
+   *                 / | \
+   *                /  |  \
+   *           (a) /   |   \  (b)
+   *              /    |    \
+   *             /           \
+   *            /             v
+   *   ```
+   *
+   *   We can see that `x` lies in the plane of `a`, so we take the sign
+   *   determined by `a`.  This test can be easily done by calculating the
+   *   orthogonality and taking the greater one.
+   *
+   *   The orthogonality is simply the sinus of the two vectors (i.e.,
+   *   x - o) and the corresponding direction.  We efficiently pre-compute
+   *   the orthogonality with the corresponding `get_min_distance_`
+   *   functions.
+   *
+   * @Input:
+   *   sdf1 ::
+   *     First signed distance (can be any of `a` or `b`).
+   *
+   *   sdf1 ::
+   *     Second signed distance (can be any of `a` or `b`).
+   *
+   * @Return:
+   *   The correct signed distance, which is computed by using the above
+   *   algorithm.
+   *
+   * @Note:
+   *   The function does not care about the actual distance, it simply
+   *   returns the signed distance which has a larger cross product.  As a
+   *   consequence, this function should not be used if the two distances
+   *   are fairly apart.  In that case simply use the signed distance with
+   *   a shorter absolute distance.
+   *
+   */
+  static SDF_Signed_Distance
+  resolve_corner( SDF_Signed_Distance  sdf1,
+                  SDF_Signed_Distance  sdf2 )
+  {
+    return FT_ABS( sdf1.cross ) > FT_ABS( sdf2.cross ) ? sdf1 : sdf2;
+  }
+
 /* END */