[gtk/path-work-rebased: 117/121] Add gsk_path_measure_get_curvature
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/path-work-rebased: 117/121] Add gsk_path_measure_get_curvature
- Date: Sun, 5 Dec 2021 03:59:05 +0000 (UTC)
commit 811f8e7d020f1a129835c2cb68dc6fd18cd6a7c1
Author: Matthias Clasen <mclasen redhat com>
Date: Wed Dec 23 18:52:05 2020 -0500
Add gsk_path_measure_get_curvature
gsk/gskcontour.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++
gsk/gskcontourprivate.h | 4 +++
gsk/gskpathmeasure.c | 55 ++++++++++++++++++++++++++++++++++++++
gsk/gskpathmeasure.h | 5 ++++
4 files changed, 135 insertions(+)
---
diff --git a/gsk/gskcontour.c b/gsk/gskcontour.c
index 81a7ddaa27..bcbed9153a 100644
--- a/gsk/gskcontour.c
+++ b/gsk/gskcontour.c
@@ -62,6 +62,10 @@ struct _GskContourClass
float distance,
graphene_point_t *pos,
graphene_vec2_t *tangent);
+ float (* get_curvature) (const GskContour *contour,
+ gpointer measure_data,
+ float distance,
+ graphene_point_t *center);
gboolean (* get_closest_point) (const GskContour *contour,
gpointer measure_data,
float tolerance,
@@ -301,6 +305,15 @@ gsk_rect_contour_get_point (const GskContour *contour,
graphene_vec2_init (tangent, 0.0f, - copysignf (self->height, 1.0f));
}
+static float
+gsk_rect_contour_get_curvature (const GskContour *contour,
+ gpointer measure_data,
+ float distance,
+ graphene_point_t *center)
+{
+ return 0;
+}
+
static gboolean
gsk_rect_contour_get_closest_point (const GskContour *contour,
gpointer measure_data,
@@ -564,6 +577,7 @@ static const GskContourClass GSK_RECT_CONTOUR_CLASS =
gsk_rect_contour_init_measure,
gsk_rect_contour_free_measure,
gsk_rect_contour_get_point,
+ gsk_rect_contour_get_curvature,
gsk_rect_contour_get_closest_point,
gsk_rect_contour_copy,
gsk_rect_contour_add_segment,
@@ -765,6 +779,20 @@ gsk_circle_contour_get_point (const GskContour *contour,
}
}
+static float
+gsk_circle_contour_get_curvature (const GskContour *contour,
+ gpointer measure_data,
+ float distance,
+ graphene_point_t *center)
+{
+ const GskCircleContour *self = (const GskCircleContour *) contour;
+
+ if (center)
+ *center = self->center;
+
+ return 1 / self->radius;
+}
+
static gboolean
gsk_circle_contour_get_closest_point (const GskContour *contour,
gpointer measure_data,
@@ -950,6 +978,7 @@ static const GskContourClass GSK_CIRCLE_CONTOUR_CLASS =
gsk_circle_contour_init_measure,
gsk_circle_contour_free_measure,
gsk_circle_contour_get_point,
+ gsk_circle_contour_get_curvature,
gsk_circle_contour_get_closest_point,
gsk_circle_contour_copy,
gsk_circle_contour_add_segment,
@@ -1286,6 +1315,38 @@ gsk_standard_contour_get_point (const GskContour *contour,
gsk_curve_get_tangent (&curve, progress, tangent);
}
+static float
+gsk_standard_contour_get_curvature (const GskContour *contour,
+ gpointer measure_data,
+ float distance,
+ graphene_point_t *center)
+{
+ GskStandardContour *self = (GskStandardContour *) contour;
+ GArray *array = measure_data;
+ guint index;
+ float progress;
+ GskStandardContourMeasure *measure;
+ GskCurve curve;
+
+ if (array->len == 0)
+ {
+ g_assert (distance == 0);
+ g_assert (gsk_pathop_op (self->ops[0]) == GSK_PATH_MOVE);
+ return 0;
+ }
+
+ if (!g_array_binary_search (array, &distance, gsk_standard_contour_find_measure, &index))
+ index = array->len - 1;
+ measure = &g_array_index (array, GskStandardContourMeasure, index);
+ progress = (distance - measure->start) / (measure->end - measure->start);
+ progress = measure->start_progress + (measure->end_progress - measure->start_progress) * progress;
+ g_assert (progress >= 0 && progress <= 1);
+
+ gsk_curve_init (&curve, self->ops[measure->op]);
+
+ return gsk_curve_get_curvature (&curve, progress, center);
+}
+
static gboolean
gsk_standard_contour_get_closest_point (const GskContour *contour,
gpointer measure_data,
@@ -1675,6 +1736,7 @@ static const GskContourClass GSK_STANDARD_CONTOUR_CLASS =
gsk_standard_contour_init_measure,
gsk_standard_contour_free_measure,
gsk_standard_contour_get_point,
+ gsk_standard_contour_get_curvature,
gsk_standard_contour_get_closest_point,
gsk_standard_contour_copy,
gsk_standard_contour_add_segment,
@@ -1803,6 +1865,15 @@ gsk_contour_get_point (const GskContour *self,
self->klass->get_point (self, measure_data, distance, pos, tangent);
}
+float
+gsk_contour_get_curvature (const GskContour *self,
+ gpointer measure_data,
+ float distance,
+ graphene_point_t *center)
+{
+ return self->klass->get_curvature (self, measure_data, distance, center);
+}
+
gboolean
gsk_contour_get_closest_point (const GskContour *self,
gpointer measure_data,
diff --git a/gsk/gskcontourprivate.h b/gsk/gskcontourprivate.h
index 077025e412..3bf233f3fe 100644
--- a/gsk/gskcontourprivate.h
+++ b/gsk/gskcontourprivate.h
@@ -74,6 +74,10 @@ void gsk_contour_get_point (const GskContou
float distance,
graphene_point_t *pos,
graphene_vec2_t *tangent);
+float gsk_contour_get_curvature (const GskContour *self,
+ gpointer measure_data,
+ float distance,
+ graphene_point_t *center);
gboolean gsk_contour_get_closest_point (const GskContour *self,
gpointer measure_data,
float tolerance,
diff --git a/gsk/gskpathmeasure.c b/gsk/gskpathmeasure.c
index 01c3bdc6c4..a1e6bb41e9 100644
--- a/gsk/gskpathmeasure.c
+++ b/gsk/gskpathmeasure.c
@@ -372,6 +372,61 @@ gsk_path_measure_get_point (GskPathMeasure *self,
tangent);
}
+/**
+ * gsk_path_measure_get_curvature:
+ * @self: a `GskPathMeasure`
+ * @distance: distance into the path
+ * @center: (optional) (out caller-allocates): The center
+ * of the osculating circle at the point
+ *
+ * Calculates the curvature at the point @distance units into
+ * the path.
+ *
+ * Optionally, returns the center of the osculating circle as well.
+ *
+ * If the curvature is infinite (at line segments), or does
+ * not exist (at sharp turns), zero is returned, and @center
+ * is not modified.
+ *
+ * Returns: The curvature of the path at the given point
+ */
+float
+gsk_path_measure_get_curvature (GskPathMeasure *self,
+ float distance,
+ graphene_point_t *center)
+{
+ gsize i;
+
+ g_return_val_if_fail (self != NULL, 0);
+
+ distance = gsk_path_measure_clamp_distance (self, distance);
+
+ for (i = self->first; i < self->last; i++)
+ {
+ if (distance < self->measures[i].length)
+ break;
+
+ distance -= self->measures[i].length;
+ }
+
+ /* weird corner cases */
+ if (i == self->last)
+ {
+ /* the empty path goes here */
+ if (self->first == self->last)
+ return 0;
+
+ /* rounding errors can make this happen */
+ i = self->last - 1;
+ distance = self->measures[i].length;
+ }
+
+ return gsk_contour_get_curvature (gsk_path_get_contour (self->path, i),
+ self->measures[i].contour_data,
+ distance,
+ center);
+}
+
/**
* gsk_path_measure_get_closest_point:
* @self: a `GskPathMeasure`
diff --git a/gsk/gskpathmeasure.h b/gsk/gskpathmeasure.h
index 4ea83af1c5..1194048934 100644
--- a/gsk/gskpathmeasure.h
+++ b/gsk/gskpathmeasure.h
@@ -65,6 +65,11 @@ void gsk_path_measure_get_point (GskPathMeasure
graphene_point_t *pos,
graphene_vec2_t *tangent);
GDK_AVAILABLE_IN_ALL
+float gsk_path_measure_get_curvature (GskPathMeasure *self,
+ float distance,
+ graphene_point_t *center);
+
+GDK_AVAILABLE_IN_ALL
float gsk_path_measure_get_closest_point (GskPathMeasure *self,
const graphene_point_t *point,
graphene_point_t *out_pos);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]