From 17f1a6ec6aebbc51a67be6ac6064d231ce02a62e Mon Sep 17 00:00:00 2001 From: Stefan Wildemann Date: Sat, 1 Jan 2022 14:12:44 +0100 Subject: feature: graphics: allow spiked lines for cliff and embarkments (#1174) * feature: graphics: allow spiked lines for cliff and embarkments This adds another drwing element to graphics system. It can produce lines with spikes as used for cliffs on maps. Additionally this adds embarlment support for map. * review fixes. Add changes requested by review, plus add paranoia check on xml parameter. --- navit/attr.h | 1 + navit/attr_def.h | 2 ++ navit/graphics.c | 67 ++++++++++++++++++++++++++++++++++++++ navit/item_def.h | 1 + navit/layout.c | 33 +++++++++++++++++++ navit/layout.h | 7 +++- navit/maptool/osm.c | 1 + navit/navit.dtd | 6 +++- navit/navit_layout_car_shipped.xml | 10 +++++- navit/xmlconfig.c | 8 ++++- 10 files changed, 132 insertions(+), 4 deletions(-) (limited to 'navit') diff --git a/navit/attr.h b/navit/attr.h index a49f033fe..cae591ffd 100644 --- a/navit/attr.h +++ b/navit/attr.h @@ -192,6 +192,7 @@ struct attr { struct icon *icon; struct image *image; struct arrows *arrows; + struct spikes *spikes; struct element *element; struct speech *speech; struct cursor *cursor; diff --git a/navit/attr_def.h b/navit/attr_def.h index 951b57060..a2863edea 100644 --- a/navit/attr_def.h +++ b/navit/attr_def.h @@ -204,6 +204,7 @@ ATTR(virtual_dpi) ATTR(real_dpi) ATTR(underground_alpha) ATTR(sunrise_degrees) +ATTR(distance) ATTR2(0x00027500,type_rel_abs_begin) /* These attributes are int that can either hold relative or absolute values. See the * documentation of ATTR_REL_RELSHIFT for details. @@ -495,6 +496,7 @@ ATTR(layout) ATTR(profile_option) ATTR(script) ATTR(traffic) +ATTR(spikes) ATTR2(0x0008ffff,type_object_end) ATTR2(0x00090000,type_coord_begin) ATTR2(0x0009ffff,type_coord_end) diff --git a/navit/graphics.c b/navit/graphics.c index aabe9b7bc..08de16a1e 100644 --- a/navit/graphics.c +++ b/navit/graphics.c @@ -1720,6 +1720,67 @@ static void display_draw_arrows(struct graphics *gra, struct display_context *dc } } +static void display_draw_spike(struct point *p, navit_float dx, navit_float dy, navit_float width, + struct display_context *dc, + struct graphics *gra) { + struct point pnt[2]; + navit_float l=navit_sqrt(dx*dx+dy*dy); + pnt[0]=pnt[1]=*p; + pnt[1].x+=(-dy/l)*width; + pnt[1].y+=(dx/l)*width; + graphics_draw_lines(gra, dc->gc, pnt, 2); +} + +/** + * @brief draw spikes along a multi polygon line + * + * This function draws spikes along a multi polygon line, and scales the + * spikes according to current view settings by interpolating sizes at + * given spike position, + * + * @param gra current graphics instance handle + * @param dc current drawing context + * @param pnt array of points for this polyline + * @param count number of points in pnt + * @param width array of integers giving the expected line width at the corresponding point + * @param distance giving the distance between spikes + */ +static void display_draw_spikes(struct graphics *gra, struct display_context *dc, struct point *pnt, int count, + int *width, int distance) { + navit_float dx,dy,dw,l; + int i; + struct point p; + int w; + for (i = 0 ; i < count-1 ; i++) { + /* get the X and Y size */ + dx=pnt[i+1].x-pnt[i].x; + dy=pnt[i+1].y-pnt[i].y; + dw=width[i+1] - width[i]; + /* calculate the length of the way segment */ + l=navit_sqrt(dx*dx+dy*dy); + if (l != 0) { + /* length is not zero */ + if(l > width[i]) { + /* length is bigger than the length of one spike */ + int a; + int spike_count = l / distance; + /* calculate the vector per spike */ + dx=dx/spike_count; + dy=dy/spike_count; + dw=dw/spike_count; + for( a=0; a < spike_count; a++ ) { + p=pnt[i]; + p.x+=dx*a; + p.y+=dy*a; + w=width[i]; + w+=dw*a; + display_draw_spike(&p, dx, dy, w, dc, gra); + } + } + } + } +} + static int intersection(struct point * a1, int adx, int ady, struct point * b1, int bdx, int bdy, struct point * res) { int n, a, b; dbg(lvl_debug,"%d,%d - %d,%d x %d,%d-%d,%d",a1->x,a1->y,a1->x+adx,a1->y+ady,b1->x,b1->y,b1->x+bdx,b1->y+bdy); @@ -2954,6 +3015,9 @@ static void displayitem_draw(struct displayitem *di, struct layout *l, struct di else if (dc->e->type == element_arrows) count=transform_point_buf(dc->trans, dc->pro, di->c, pa, pa_buf_size, count, mindist, e->u.arrows.width, width); + else if (dc->e->type == element_spikes) + count=transform_point_buf(dc->trans, dc->pro, di->c, pa, pa_buf_size, count, mindist, e->u.spikes.width, + width); else count=transform_point_buf(dc->trans, dc->pro, di->c, pa, pa_buf_size, count, mindist, 0, NULL); switch (e->type) { @@ -2978,6 +3042,9 @@ static void displayitem_draw(struct displayitem *di, struct layout *l, struct di case element_arrows: display_draw_arrows(gra,dc,pa,count, width, e->oneway); break; + case element_spikes: + display_draw_spikes(gra,dc,pa,count, width, e->u.spikes.distance); + break; default: dbg(lvl_error, "Unhandled element type %d", e->type); diff --git a/navit/item_def.h b/navit/item_def.h index 82f49d2a0..ae716e7c8 100644 --- a/navit/item_def.h +++ b/navit/item_def.h @@ -529,6 +529,7 @@ ITEM(former_itinerary_part) ITEM(cliff) ITEM(sports_track) ITEM(archaeological_site) +ITEM(embankment) /* Area */ ITEM2(0xc0000000,area) ITEM2(0xc0000001,area_unspecified) diff --git a/navit/layout.c b/navit/layout.c index 0889fb52b..2300ab68d 100644 --- a/navit/layout.c +++ b/navit/layout.c @@ -399,6 +399,7 @@ int itemgra_add_attr(struct itemgra *itemgra, struct attr *attr) { case attr_icon: case attr_image: case attr_arrows: + case attr_spikes: itemgra->elements = g_list_append(itemgra->elements, attr->u.element); return 1; default: @@ -446,6 +447,27 @@ static void element_set_arrows_width(struct element *e, struct attr **attrs) { e->u.arrows.width=10; } +static void element_set_spikes_width(struct element *e, struct attr **attrs) { + struct attr *width; + width=attr_search(attrs, attr_width); + if (width) + e->u.spikes.width=width->u.num; + else + e->u.spikes.width=10; +} + +static void element_set_spikes_distance(struct element *e, struct attr **attrs) { + struct attr *distance; + distance=attr_search(attrs, attr_distance); + if (distance) { + e->u.spikes.distance=distance->u.num; + /* paranoia check. We divide with that value */ + if(e->u.spikes.distance < 1) + e->u.spikes.distance = 1; + } else + e->u.spikes.distance=10; +} + static void element_set_polyline_width(struct element *e, struct attr **attrs) { struct attr *width; width=attr_search(attrs, attr_width); @@ -651,6 +673,17 @@ arrows_new(struct attr *parent, struct attr **attrs) { return (struct arrows *)e; } +struct spikes * +spikes_new(struct attr *parent, struct attr **attrs) { + struct element *e; + e = g_malloc0(sizeof(*e)); + e->type=element_spikes; + element_set_color(e, attrs); + element_set_spikes_width(e, attrs); + element_set_spikes_distance(e, attrs); + return (struct spikes *)e; +} + int element_add_attr(struct element *e, struct attr *attr) { switch (attr->type) { case attr_coord: diff --git a/navit/layout.h b/navit/layout.h index 47b078ab1..210519a83 100644 --- a/navit/layout.h +++ b/navit/layout.h @@ -34,7 +34,7 @@ struct poly_hole { }; struct element { - enum { element_point, element_polyline, element_polygon, element_circle, element_text, element_icon, element_image, element_arrows } type; + enum { element_point, element_polyline, element_polygon, element_circle, element_text, element_icon, element_image, element_arrows, element_spikes } type; struct color color; int text_size; int oneway; @@ -77,6 +77,10 @@ struct element { struct element_arrows { int width; } arrows; + struct element_spikes { + int width; + int distance; + } spikes; } u; int coord_count; struct coord *coord; @@ -162,6 +166,7 @@ struct text *text_new(struct attr *parent, struct attr **attrs); struct icon *icon_new(struct attr *parent, struct attr **attrs); struct image *image_new(struct attr *parent, struct attr **attrs); struct arrows *arrows_new(struct attr *parent, struct attr **attrs); +struct spikes *spikes_new(struct attr *parent, struct attr **attrs); int element_add_attr(struct element *e, struct attr *attr); /* end of prototypes */ diff --git a/navit/maptool/osm.c b/navit/maptool/osm.c index aece0ea7e..73984853e 100644 --- a/navit/maptool/osm.c +++ b/navit/maptool/osm.c @@ -768,6 +768,7 @@ static char *attrmap= { "w natural=wetland poly_mud\n" "w natural=wood poly_wood\n" "w natural=cliff cliff\n" + "w man_made=embankment embankment\n" "w piste:type=downhill,piste:difficulty=advanced piste_downhill_advanced\n" "w piste:type=downhill,piste:difficulty=easy piste_downhill_easy\n" "w piste:type=downhill,piste:difficulty=expert piste_downhill_expert\n" diff --git a/navit/navit.dtd b/navit/navit.dtd index 4d6b4cfe6..2c743ada0 100644 --- a/navit/navit.dtd +++ b/navit/navit.dtd @@ -129,7 +129,7 @@ - + @@ -165,6 +165,10 @@ + + + + diff --git a/navit/navit_layout_car_shipped.xml b/navit/navit_layout_car_shipped.xml index 3c25259c1..a9d7a62fe 100644 --- a/navit/navit_layout_car_shipped.xml +++ b/navit/navit_layout_car_shipped.xml @@ -1361,9 +1361,17 @@ - + + + + + + + + + diff --git a/navit/xmlconfig.c b/navit/xmlconfig.c index c47c82163..a40001de3 100644 --- a/navit/xmlconfig.c +++ b/navit/xmlconfig.c @@ -227,6 +227,7 @@ static int xmlconfig_announce(struct xmlstate *state) { static struct object_func object_funcs[] = { { attr_announcement,NEW(announcement_new), GET(announcement_get_attr), NULL, NULL, SET(announcement_set_attr), ADD(announcement_add_attr) }, { attr_arrows, NEW(arrows_new)}, + { attr_spikes, NEW(spikes_new)}, { attr_circle, NEW(circle_new), NULL, NULL, NULL, NULL, ADD(element_add_attr)}, { attr_coord, NEW(coord_new_from_attrs)}, { attr_cursor, NEW(cursor_new), NULL, NULL, NULL, NULL, ADD(cursor_add_attr)}, @@ -334,7 +335,7 @@ static char *element_fixmes[]= { }; static void initStatic(void) { - elements=g_new0(struct element_func, 45); //44 is a number of elements + ending NULL element + elements=g_new0(struct element_func, 46); //45 is a number of elements + ending NULL element elements[0].name="config"; elements[0].parent=NULL; @@ -554,6 +555,11 @@ static void initStatic(void) { elements[43].parent="navit"; elements[43].func=NULL; elements[43].type=attr_traffic; + + elements[44].name="spikes"; + elements[44].parent="itemgra"; + elements[44].func=NULL; + elements[44].type=attr_spikes; } /** -- cgit v1.2.1