[gtk/matthiasc/lottie2] Implement gsk_circle_contour_get_closest_point



commit 107a2a773365643198c5b2d009cb2632a02072f4
Author: Matthias Clasen <mclasen redhat com>
Date:   Wed Nov 25 18:34:01 2020 -0500

    Implement gsk_circle_contour_get_closest_point

 gsk/gskpath.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 57 insertions(+), 2 deletions(-)
---
diff --git a/gsk/gskpath.c b/gsk/gskpath.c
index ae9a6d8fd3..8bc81e23f1 100644
--- a/gsk/gskpath.c
+++ b/gsk/gskpath.c
@@ -465,6 +465,7 @@ gsk_rect_contour_init (GskContour *contour,
 /* CIRCLE CONTOUR */
 
 #define DEG_TO_RAD(x)          ((x) * (G_PI / 180.f))
+#define RAD_TO_DEG(x)          ((x) / (G_PI / 180.f))
 
 typedef struct _GskCircleContour GskCircleContour;
 struct _GskCircleContour
@@ -631,8 +632,62 @@ gsk_circle_contour_get_closest_point (const GskContour       *contour,
                                       float                  *out_offset,
                                       graphene_vec2_t        *out_tangent)
 {
-  g_warning ("FIXME");
-  return FALSE;
+  const GskCircleContour *self = (const GskCircleContour *) contour;
+  graphene_vec2_t dir;
+  float angle;
+  float closest_angle;
+  float offset;
+  graphene_point_t pos;
+  float distance;
+
+  if (graphene_point_distance (point, &self->center, NULL, NULL) > threshold + self->radius)
+    return FALSE;
+
+  graphene_vec2_init (&dir,
+                      point->x - self->center.x,
+                      point->y - self->center.y);
+  graphene_vec2_normalize (&dir, &dir);
+  angle = acos (graphene_vec2_dot (&dir, graphene_vec2_x_axis ()));
+  if (point->y - self->center.y < 0)
+    angle += M_PI;
+
+  angle = RAD_TO_DEG (angle);
+
+  if ((self->start_angle <= angle && angle <= self->end_angle) ||
+      (self->end_angle <= angle && angle <= self->start_angle))
+    {
+      closest_angle = angle;
+    }
+  else
+    {
+      float d1, d2;
+
+      d1 = fabs (self->start_angle - angle);
+      d1 = MIN (d1, 360 - d1);
+      d2 = fabs (self->end_angle - angle);
+      d2 = MIN (d2, 360 - d2);
+      if (d1 < d2)
+        closest_angle = self->start_angle;
+      else
+        closest_angle = self->end_angle;
+    }
+
+  offset = self->radius * 2 * M_PI * (closest_angle - self->start_angle) / (self->end_angle - 
self->start_angle);
+
+  gsk_circle_contour_get_point (contour, NULL, offset, &pos, out_tangent);
+
+  distance = graphene_point_distance (&pos, point, NULL, NULL);
+  if (threshold < distance)
+    return FALSE;
+
+  if (out_offset)
+    *out_offset = offset;
+  if (out_pos)
+    *out_pos = pos;
+  if (out_distance)
+    *out_distance = distance;
+
+  return TRUE;
 }
 
 static void


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