[libshumate] vector: Line symbols
- From: Marcus Lundblad <mlundblad src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libshumate] vector: Line symbols
- Date: Thu, 23 Jun 2022 21:16:33 +0000 (UTC)
commit cc062e586338e6e53847f15e7b0b27994291a52c
Author: James Westman <james jwestman net>
Date: Fri Feb 4 10:08:48 2022 -0600
vector: Line symbols
demos/map-style.json | 14 ++
.../vector/shumate-vector-render-scope-private.h | 4 +
shumate/vector/shumate-vector-render-scope.c | 61 ++++++++
.../shumate-vector-symbol-container-private.h | 1 +
shumate/vector/shumate-vector-symbol-container.c | 14 +-
.../vector/shumate-vector-symbol-info-private.h | 8 +-
shumate/vector/shumate-vector-symbol-info.c | 9 ++
shumate/vector/shumate-vector-symbol-layer.c | 8 ++
shumate/vector/shumate-vector-symbol.c | 142 +++++++++++++++++-
shumate/vector/shumate-vector-utils-private.h | 36 ++++-
shumate/vector/shumate-vector-utils.c | 160 +++++++++++++++++++++
11 files changed, 449 insertions(+), 8 deletions(-)
---
diff --git a/demos/map-style.json b/demos/map-style.json
index 08ef218..2212534 100644
--- a/demos/map-style.json
+++ b/demos/map-style.json
@@ -64,6 +64,20 @@
"paint": {
"text-color": "#000000"
}
+ },
+ {
+ "id": "waterway",
+ "type": "symbol",
+ "source-layer": "waterway",
+ "layout": {
+ "text-field": "{name}",
+ "symbol-placement": "line",
+ "font-family": "Cantarell 16"
+ },
+ "paint": {
+ "text-color": "#000000"
+ }
}
]
}
+
diff --git a/shumate/vector/shumate-vector-render-scope-private.h
b/shumate/vector/shumate-vector-render-scope-private.h
index ac728a0..d53f3cb 100644
--- a/shumate/vector/shumate-vector-render-scope-private.h
+++ b/shumate/vector/shumate-vector-render-scope-private.h
@@ -21,6 +21,7 @@
#include <cairo/cairo.h>
#include "vector_tile.pb-c.h"
#include "shumate-vector-value-private.h"
+#include "shumate-vector-utils-private.h"
typedef struct {
cairo_t *cr;
@@ -45,4 +46,7 @@ void shumate_vector_render_scope_get_bounds (ShumateVectorRenderScope *self,
double *max_x,
double *max_y);
+void shumate_vector_render_scope_get_geometry (ShumateVectorRenderScope *self,
+ ShumateVectorLineString *linestring);
+
void shumate_vector_render_scope_get_variable (ShumateVectorRenderScope *self, const char *variable,
ShumateVectorValue *value);
diff --git a/shumate/vector/shumate-vector-render-scope.c b/shumate/vector/shumate-vector-render-scope.c
index 14e7644..3a156d6 100644
--- a/shumate/vector/shumate-vector-render-scope.c
+++ b/shumate/vector/shumate-vector-render-scope.c
@@ -87,6 +87,67 @@ shumate_vector_render_scope_exec_geometry (ShumateVectorRenderScope *self)
}
+void
+shumate_vector_render_scope_get_geometry (ShumateVectorRenderScope *self,
+ ShumateVectorLineString *linestring)
+{
+ ShumateVectorPoint *points = NULL;
+ gsize point_index = 0;
+ double x = 0, y = 0;
+
+ g_return_if_fail (self->feature != NULL);
+
+ for (int i = 0; i < self->feature->n_geometry; i ++)
+ {
+ int cmd = self->feature->geometry[i];
+ double start_x = 0, start_y = 0;
+
+ int op = cmd & 0x7;
+ int repeat = cmd >> 3;
+
+ points = g_realloc (points, (repeat + point_index) * sizeof (ShumateVectorPoint));
+ g_return_if_fail (points != NULL);
+
+ for (int j = 0; j < repeat; j ++)
+ {
+ switch (op) {
+ case 1:
+ g_return_if_fail (i + 2 < self->feature->n_geometry);
+ x += zigzag (self->feature->geometry[++i]);
+ y += zigzag (self->feature->geometry[++i]);
+ start_x = x;
+ start_y = y;
+ points[point_index++] = (ShumateVectorPoint) {
+ .x = x / self->layer->extent,
+ .y = y / self->layer->extent,
+ };
+ break;
+ case 2:
+ g_return_if_fail (i + 2 < self->feature->n_geometry);
+ x += zigzag (self->feature->geometry[++i]);
+ y += zigzag (self->feature->geometry[++i]);
+ points[point_index++] = (ShumateVectorPoint) {
+ .x = x / self->layer->extent,
+ .y = y / self->layer->extent,
+ };
+ break;
+ case 7:
+ points[point_index++] = (ShumateVectorPoint) {
+ .x = start_x / self->layer->extent,
+ .y = start_y / self->layer->extent,
+ };
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ }
+ }
+
+ linestring->n_points = point_index;
+ linestring->points = points;
+}
+
+
void
shumate_vector_render_scope_get_bounds (ShumateVectorRenderScope *self,
double *min_x,
diff --git a/shumate/vector/shumate-vector-symbol-container-private.h
b/shumate/vector/shumate-vector-symbol-container-private.h
index 33f752e..c86a507 100644
--- a/shumate/vector/shumate-vector-symbol-container-private.h
+++ b/shumate/vector/shumate-vector-symbol-container-private.h
@@ -40,4 +40,5 @@ void shumate_vector_symbol_container_remove_symbols (ShumateVectorSymbolContaine
int tile_y,
int zoom);
+ShumateMapSource *shumate_vector_symbol_container_get_map_source (ShumateVectorSymbolContainer *self);
G_END_DECLS
diff --git a/shumate/vector/shumate-vector-symbol-container.c
b/shumate/vector/shumate-vector-symbol-container.c
index c2681e5..c10aeb6 100644
--- a/shumate/vector/shumate-vector-symbol-container.c
+++ b/shumate/vector/shumate-vector-symbol-container.c
@@ -42,8 +42,9 @@ static GParamSpec *obj_properties[N_PROPS] = { NULL, };
typedef struct {
- // does not need to be freed because it's owned by the widget
+ // do not need to be freed because they're owned by the widget
ShumateVectorSymbol *symbol;
+ ShumateVectorSymbolInfo *symbol_info;
ShumateVectorCollisionMarker *marker;
@@ -223,6 +224,8 @@ shumate_vector_symbol_container_size_allocate (GtkWidget *widget,
alloc.height = child->height;
gtk_widget_size_allocate (GTK_WIDGET (child->symbol), &alloc, -1);
+ if (child->symbol_info->line_placement)
+ gtk_widget_queue_draw (GTK_WIDGET (child->symbol));
}
}
@@ -297,6 +300,7 @@ shumate_vector_symbol_container_add_symbols (ShumateVectorSymbolContainer *self,
ShumateVectorSymbol *symbol = shumate_vector_symbol_new (symbol_info);
info->symbol = symbol;
+ info->symbol_info = symbol_info;
gtk_widget_measure (GTK_WIDGET (symbol), GTK_ORIENTATION_HORIZONTAL, -1, NULL, &info->width, NULL,
NULL);
gtk_widget_measure (GTK_WIDGET (symbol), GTK_ORIENTATION_VERTICAL, -1, NULL, &info->height, NULL,
NULL);
info->x = symbol_info->x;
@@ -343,3 +347,11 @@ shumate_vector_symbol_container_remove_symbols (ShumateVectorSymbolContainer *se
self->children = g_list_remove_all (self->children, NULL);
}
+
+
+ShumateMapSource *
+shumate_vector_symbol_container_get_map_source (ShumateVectorSymbolContainer *self)
+{
+ g_return_val_if_fail (SHUMATE_IS_VECTOR_SYMBOL_CONTAINER (self), NULL);
+ return self->map_source;
+}
diff --git a/shumate/vector/shumate-vector-symbol-info-private.h
b/shumate/vector/shumate-vector-symbol-info-private.h
index 3552f8f..bfe19cd 100644
--- a/shumate/vector/shumate-vector-symbol-info-private.h
+++ b/shumate/vector/shumate-vector-symbol-info-private.h
@@ -19,6 +19,7 @@
#pragma once
#include <glib-object.h>
+#include "shumate-vector-utils-private.h"
#include "shumate-vector-render-scope-private.h"
@@ -34,10 +35,12 @@ struct _ShumateVectorSymbolInfo
GdkRGBA text_color;
double text_size;
char *text_font;
- gboolean line_placement;
+ guint line_placement : 1;
double x;
double y;
+ ShumateVectorLineString line;
+
/*< private >*/
guint ref_count;
};
@@ -50,6 +53,9 @@ ShumateVectorSymbolInfo *shumate_vector_symbol_info_new (const char
double x,
double y);
+void shumate_vector_symbol_info_set_line_points (ShumateVectorSymbolInfo *self,
+ ShumateVectorLineString *linestring);
+
GType shumate_vector_symbol_info_get_type (void) G_GNUC_CONST;
ShumateVectorSymbolInfo *shumate_vector_symbol_info_ref (ShumateVectorSymbolInfo *self);
void shumate_vector_symbol_info_unref (ShumateVectorSymbolInfo *self);
diff --git a/shumate/vector/shumate-vector-symbol-info.c b/shumate/vector/shumate-vector-symbol-info.c
index de8a605..8731b76 100644
--- a/shumate/vector/shumate-vector-symbol-info.c
+++ b/shumate/vector/shumate-vector-symbol-info.c
@@ -30,6 +30,7 @@ shumate_vector_symbol_info_free (ShumateVectorSymbolInfo *self)
g_clear_pointer (&self->text, g_free);
g_clear_pointer (&self->text_font, g_free);
+ shumate_vector_line_string_clear (&self->line);
g_free (self);
}
@@ -83,3 +84,11 @@ shumate_vector_symbol_info_new (const char *text,
return self;
}
+
+void
+shumate_vector_symbol_info_set_line_points (ShumateVectorSymbolInfo *self,
+ ShumateVectorLineString *linestring)
+{
+ shumate_vector_line_string_clear (&self->line);
+ self->line = *linestring;
+}
diff --git a/shumate/vector/shumate-vector-symbol-layer.c b/shumate/vector/shumate-vector-symbol-layer.c
index d57589d..a73fba9 100644
--- a/shumate/vector/shumate-vector-symbol-layer.c
+++ b/shumate/vector/shumate-vector-symbol-layer.c
@@ -130,6 +130,14 @@ shumate_vector_symbol_layer_render (ShumateVectorLayer *layer, ShumateVectorRend
self->line_placement,
x,
y);
+
+ if (self->line_placement)
+ {
+ ShumateVectorLineString linestring;
+ shumate_vector_render_scope_get_geometry (scope, &linestring);
+ shumate_vector_symbol_info_set_line_points (symbol_info, &linestring);
+ }
+
g_ptr_array_add (scope->symbols, symbol_info);
}
diff --git a/shumate/vector/shumate-vector-symbol.c b/shumate/vector/shumate-vector-symbol.c
index ed65242..e24a750 100644
--- a/shumate/vector/shumate-vector-symbol.c
+++ b/shumate/vector/shumate-vector-symbol.c
@@ -19,6 +19,8 @@
#include "shumate-vector-symbol-private.h"
#include "shumate-vector-utils-private.h"
#include "shumate-vector-symbol-info-private.h"
+#include "shumate-vector-symbol-container-private.h"
+#include "shumate-layer.h"
struct _ShumateVectorSymbol
@@ -26,6 +28,10 @@ struct _ShumateVectorSymbol
GtkWidget parent_instance;
ShumateVectorSymbolInfo *symbol_info;
+
+ GArray *glyphs;
+ int glyphs_length;
+ double line_length;
};
G_DEFINE_TYPE (ShumateVectorSymbol, shumate_vector_symbol, GTK_TYPE_WIDGET)
@@ -40,6 +46,18 @@ enum {
static GParamSpec *obj_properties[N_PROPS] = { NULL, };
+typedef struct {
+ GskRenderNode *node;
+ double width;
+} Glyph;
+
+static void
+glyph_clear (Glyph *glyph)
+{
+ g_clear_pointer (&glyph->node, gsk_render_node_unref);
+}
+
+
ShumateVectorSymbol *
shumate_vector_symbol_new (ShumateVectorSymbolInfo *symbol_info)
{
@@ -74,9 +92,60 @@ shumate_vector_symbol_constructed (GObject *object)
attr = pango_attr_size_new_absolute (self->symbol_info->text_size * PANGO_SCALE);
pango_attr_list_insert (attrs, attr);
- GtkWidget *label = gtk_label_new (self->symbol_info->text);
- gtk_label_set_attributes (GTK_LABEL (label), attrs);
- gtk_widget_set_parent (label, GTK_WIDGET (self));
+ if (self->symbol_info->line_placement)
+ {
+ PangoContext *context = gtk_widget_get_pango_context (GTK_WIDGET (self));
+ g_autoptr(PangoLayout) layout = pango_layout_new (context);
+ g_autoptr(PangoLayoutIter) iter = NULL;
+ PangoGlyphItem *current_item;
+ PangoGlyphString *glyph_string;
+ int i;
+
+ self->glyphs = g_array_new (FALSE, FALSE, sizeof (Glyph));
+ g_array_set_clear_func (self->glyphs, (GDestroyNotify)glyph_clear);
+
+ pango_layout_set_attributes (layout, attrs);
+ pango_layout_set_text (layout, self->symbol_info->text, -1);
+ iter = pango_layout_get_iter (layout);
+
+ pango_layout_get_size (layout, &self->glyphs_length, NULL);
+ self->glyphs_length /= PANGO_SCALE;
+ self->line_length = shumate_vector_line_string_length (&self->symbol_info->line);
+
+ do {
+ current_item = pango_layout_iter_get_run (iter);
+
+ if (current_item == NULL)
+ continue;
+
+ for (i = 0; i < current_item->glyphs->num_glyphs; i ++)
+ {
+ GskRenderNode *node;
+ Glyph glyph;
+
+ glyph_string = pango_glyph_string_new ();
+ pango_glyph_string_set_size (glyph_string, 1);
+ glyph_string->glyphs[0] = current_item->glyphs->glyphs[i];
+ glyph_string->log_clusters[0] = 0;
+
+ node =
+ gsk_text_node_new (current_item->item->analysis.font,
+ glyph_string,
+ &self->symbol_info->text_color,
+ &GRAPHENE_POINT_INIT (0, 0));
+
+ glyph.node = node;
+ glyph.width = glyph_string->glyphs[0].geometry.width / (double) PANGO_SCALE;
+ g_array_append_vals (self->glyphs, &glyph, 1);
+ }
+ } while (pango_layout_iter_next_run (iter));
+ }
+ else
+ {
+ GtkWidget *label = gtk_label_new (self->symbol_info->text);
+ gtk_label_set_attributes (GTK_LABEL (label), attrs);
+ gtk_widget_set_parent (label, GTK_WIDGET (self));
+ }
G_OBJECT_CLASS (shumate_vector_symbol_parent_class)->constructed (object);
}
@@ -92,6 +161,7 @@ shumate_vector_symbol_dispose (GObject *object)
gtk_widget_unparent (child);
g_clear_pointer (&self->symbol_info, shumate_vector_symbol_info_unref);
+ g_clear_pointer (&self->glyphs, g_array_unref);
G_OBJECT_CLASS (shumate_vector_symbol_parent_class)->dispose (object);
}
@@ -138,6 +208,67 @@ shumate_vector_symbol_set_property (GObject *object,
}
+static void
+shumate_vector_symbol_snapshot (GtkWidget *widget,
+ GtkSnapshot *snapshot)
+{
+ ShumateVectorSymbol *self = SHUMATE_VECTOR_SYMBOL (widget);
+
+ if (self->symbol_info->line_placement)
+ {
+ GtkWidget *parent = gtk_widget_get_parent (widget);
+ int i;
+ ShumateVectorPointIter iter;
+ double rotation = 0.0;
+ double scale = 512.0;
+
+ if (SHUMATE_IS_VECTOR_SYMBOL_CONTAINER (parent))
+ {
+ ShumateViewport *viewport = shumate_layer_get_viewport (SHUMATE_LAYER (parent));
+ ShumateMapSource *map_source = shumate_vector_symbol_container_get_map_source
(SHUMATE_VECTOR_SYMBOL_CONTAINER (parent));
+ scale = shumate_map_source_get_tile_size_at_zoom (map_source, shumate_viewport_get_zoom_level
(viewport));
+ rotation = shumate_viewport_get_rotation (viewport);
+ }
+
+ if (self->glyphs_length > self->line_length * scale)
+ return;
+
+ gtk_snapshot_rotate (snapshot, rotation * 180 / G_PI);
+
+ shumate_vector_point_iter_init (&iter, &self->symbol_info->line);
+ shumate_vector_point_iter_advance (&iter, (self->line_length - self->glyphs_length / scale) / 2.0);
+
+ for (i = 0; i < self->glyphs->len; i ++)
+ {
+ Glyph *glyph = &((Glyph *)self->glyphs->data)[i];
+ ShumateVectorPoint point;
+
+ shumate_vector_point_iter_get_current_point (&iter, &point);
+
+ /* Whitespace has no glyph, but still has a width that needs to be
+ * advanced in the point iter */
+ if (glyph->node != NULL)
+ {
+ gtk_snapshot_save (snapshot);
+ gtk_snapshot_translate (snapshot,
+ &GRAPHENE_POINT_INIT (
+ (point.x - self->symbol_info->x) * scale,
+ (point.y - self->symbol_info->y) * scale
+ ));
+ gtk_snapshot_rotate (snapshot, shumate_vector_point_iter_get_current_angle (&iter) * 180 /
G_PI);
+ gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (0, self->symbol_info->text_size / 2));
+ gtk_snapshot_append_node (snapshot, glyph->node);
+ gtk_snapshot_restore (snapshot);
+ }
+
+ shumate_vector_point_iter_advance (&iter, glyph->width / scale);
+ }
+ }
+ else
+ GTK_WIDGET_CLASS (shumate_vector_symbol_parent_class)->snapshot (widget, snapshot);
+}
+
+
static void
shumate_vector_symbol_class_init (ShumateVectorSymbolClass *klass)
{
@@ -149,6 +280,8 @@ shumate_vector_symbol_class_init (ShumateVectorSymbolClass *klass)
object_class->get_property = shumate_vector_symbol_get_property;
object_class->set_property = shumate_vector_symbol_set_property;
+ widget_class->snapshot = shumate_vector_symbol_snapshot;
+
obj_properties[PROP_SYMBOL_INFO] =
g_param_spec_boxed ("symbol-info",
"Symbol info",
@@ -156,9 +289,8 @@ shumate_vector_symbol_class_init (ShumateVectorSymbolClass *klass)
SHUMATE_TYPE_VECTOR_SYMBOL_INFO,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+ gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
g_object_class_install_properties (object_class, N_PROPS, obj_properties);
-
- gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
}
diff --git a/shumate/vector/shumate-vector-utils-private.h b/shumate/vector/shumate-vector-utils-private.h
index 51cf3ea..3c0d511 100644
--- a/shumate/vector/shumate-vector-utils-private.h
+++ b/shumate/vector/shumate-vector-utils-private.h
@@ -19,14 +19,26 @@
#include <json-glib/json-glib.h>
+typedef struct _ShumateVectorPoint ShumateVectorPoint;
+typedef struct _ShumateVectorLineString ShumateVectorLineString;
+typedef struct _ShumateVectorPointIter ShumateVectorPointIter;
struct _ShumateVectorPoint {
float x;
float y;
};
-typedef struct _ShumateVectorPoint ShumateVectorPoint;
+struct _ShumateVectorLineString {
+ gsize n_points;
+ ShumateVectorPoint *points;
+};
+struct _ShumateVectorPointIter {
+ gsize num_points;
+ ShumateVectorPoint *points;
+ gsize current_point;
+ float distance;
+};
gboolean shumate_vector_json_get_object (JsonNode *node,
JsonObject **dest,
@@ -60,3 +72,25 @@ gboolean shumate_vector_json_read_int_member (JsonReader *reader,
gboolean shumate_vector_json_read_double_member (JsonReader *reader,
const char *name,
double *dest);
+
+gboolean shumate_vector_json_get_object (JsonNode *node, JsonObject **dest, GError **error);
+gboolean shumate_vector_json_get_array (JsonNode *node, JsonArray **dest, GError **error);
+
+void shumate_vector_point_iter_init (ShumateVectorPointIter *iter,
+ ShumateVectorLineString *linestring);
+double shumate_vector_point_iter_next_segment (ShumateVectorPointIter *iter);
+double shumate_vector_point_iter_get_segment_length (ShumateVectorPointIter *iter);
+void shumate_vector_point_iter_get_segment_center (ShumateVectorPointIter *iter,
+ double remaining_distance,
+ ShumateVectorPoint *result);
+void shumate_vector_point_iter_get_current_point (ShumateVectorPointIter *iter,
+ ShumateVectorPoint *result);
+double shumate_vector_point_iter_get_average_angle (ShumateVectorPointIter *iter,
+ double remaining_distance);
+void shumate_vector_point_iter_advance (ShumateVectorPointIter *iter,
+ double distance);
+double shumate_vector_point_iter_get_current_angle (ShumateVectorPointIter *iter);
+
+
+void shumate_vector_line_string_clear (ShumateVectorLineString *linestring);
+double shumate_vector_line_string_length (ShumateVectorLineString *linestring);
diff --git a/shumate/vector/shumate-vector-utils.c b/shumate/vector/shumate-vector-utils.c
index c1bfac2..06dcf73 100644
--- a/shumate/vector/shumate-vector-utils.c
+++ b/shumate/vector/shumate-vector-utils.c
@@ -153,3 +153,163 @@ shumate_vector_json_get_string_member (JsonObject *object,
return shumate_vector_json_get_string (node, dest, error);
}
+
+
+void
+shumate_vector_point_iter_init (ShumateVectorPointIter *iter,
+ ShumateVectorLineString *linestring)
+{
+ *iter = (ShumateVectorPointIter) {
+ .num_points = linestring->n_points,
+ .points = linestring->points,
+ .current_point = 0,
+ .distance = 0,
+ };
+}
+
+
+double
+shumate_vector_point_iter_next_segment (ShumateVectorPointIter *iter)
+{
+ double res = shumate_vector_point_iter_get_segment_length (iter) - iter->distance;
+ iter->distance = 0;
+ iter->current_point ++;
+ return res;
+}
+
+
+static double
+point_distance (ShumateVectorPoint *a, ShumateVectorPoint *b)
+{
+ double x = a->x - b->x;
+ double y = a->y - b->y;
+ return sqrt (x*x + y*y);
+}
+
+static ShumateVectorPoint *
+get_prev_point (ShumateVectorPointIter *iter)
+{
+ return &iter->points[iter->current_point];
+}
+
+static ShumateVectorPoint *
+get_next_point (ShumateVectorPointIter *iter)
+{
+ if (iter->current_point >= iter->num_points - 1)
+ return &iter->points[iter->num_points - 1];
+ else
+ return &iter->points[iter->current_point + 1];
+}
+
+static void
+normalize (ShumateVectorPoint *point)
+{
+ double len = sqrt (point->x*point->x + point->y*point->y);
+ if (len == 0)
+ {
+ point->x = 0;
+ point->y = 0;
+ }
+ else
+ {
+ point->x /= len;
+ point->y /= len;
+ }
+}
+
+
+double
+shumate_vector_point_iter_get_segment_length (ShumateVectorPointIter *iter)
+{
+ ShumateVectorPoint *prev = get_prev_point (iter), *next = get_next_point (iter);
+ return point_distance (prev, next);
+}
+
+
+void
+shumate_vector_point_iter_get_current_point (ShumateVectorPointIter *iter,
+ ShumateVectorPoint *result)
+{
+ ShumateVectorPoint *prev = get_prev_point (iter), *next = get_next_point (iter);
+
+ result->x = next->x - prev->x;
+ result->y = next->y - prev->y;
+ normalize (result);
+
+ result->x *= iter->distance;
+ result->y *= iter->distance;
+ result->x += prev->x;
+ result->y += prev->y;
+}
+
+
+void
+shumate_vector_point_iter_advance (ShumateVectorPointIter *iter,
+ double distance)
+{
+ while (distance > 0)
+ {
+ if (iter->current_point >= iter->num_points - 1)
+ return;
+
+ if (iter->distance + distance > shumate_vector_point_iter_get_segment_length (iter))
+ distance -= shumate_vector_point_iter_next_segment (iter);
+ else
+ {
+ iter->distance += distance;
+ return;
+ }
+ }
+}
+
+
+double
+shumate_vector_point_iter_get_current_angle (ShumateVectorPointIter *iter)
+{
+ ShumateVectorPoint *prev = get_prev_point (iter), *next = get_next_point (iter);
+ return atan2 (next->y - prev->y, next->x - prev->x);
+}
+
+
+double
+shumate_vector_point_iter_get_average_angle (ShumateVectorPointIter *iter,
+ double remaining_distance)
+{
+ ShumateVectorPointIter iter2 = *iter;
+ double orig = shumate_vector_point_iter_get_current_angle (iter);
+ double orig_distance = remaining_distance;
+ double sum = 0.0;
+
+ while (remaining_distance > 0)
+ {
+ float angle = shumate_vector_point_iter_get_current_angle (&iter2);
+ float d = MIN (remaining_distance, shumate_vector_point_iter_next_segment (&iter2));
+ sum += d * (angle - orig);
+ remaining_distance -= d;
+ }
+
+ return sum / orig_distance;
+}
+
+
+void
+shumate_vector_line_string_clear (ShumateVectorLineString *linestring)
+{
+ g_clear_pointer (&linestring->points, g_free);
+ linestring->n_points = 0;
+}
+
+
+double
+shumate_vector_line_string_length (ShumateVectorLineString *linestring)
+{
+ ShumateVectorPointIter iter;
+ double len, sum = 0;
+
+ shumate_vector_point_iter_init (&iter, linestring);
+
+ while ((len = shumate_vector_point_iter_next_segment (&iter)))
+ sum += len;
+
+ return sum;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]