diff options
Diffstat (limited to 'navit/item.c')
-rw-r--r-- | navit/item.c | 102 |
1 files changed, 77 insertions, 25 deletions
diff --git a/navit/item.c b/navit/item.c index c17f31f8b..ab590cb4e 100644 --- a/navit/item.c +++ b/navit/item.c @@ -165,6 +165,22 @@ int item_coord_get(struct item *it, struct coord *c, int count) { } /** + * @brief Gets the number of coordinates left for this item + * + * This function returnes the number of coordinates left to get for this item. It does not + * change the "coordinates pointer". + * + * @param it The map item + * @returns The number of coordinates left. -1 if not supported by the actual map. + */ +int item_coords_left(struct item * it) { + if(!it->meth->item_coords_left) { + return (-1); + } + return it->meth->item_coords_left(it->priv_data); +} + +/** * @brief Sets coordinates of an item * * This function supports different modes: @@ -195,33 +211,69 @@ int item_coord_set(struct item *it, struct coord *c, int count, enum change_mode return it->meth->item_coord_set(it->priv_data, c, count, mode); } +/** + * @brief Get coordinates within selection + * This function returns the coordinates of an item if at least one coordinate of that item is inside the + * selection. If the given buffer is too small, it returns the buffer size if at least one coordinate + * intersects with the selection, otherwise it returnes 0 + * + * If the return value equals count, the content of c is undefined. + * + * @param it requested item + * @param c preallocated buffer for the result + * @param count number of coordinates in c + * @param sel current map selection + * @return number of coordinates read to c, or count if out of space, or 0 if not intersecting, or <0 on read error. + */ int item_coord_get_within_selection(struct item *it, struct coord *c, int count, struct map_selection *sel) { - int i,ret=it->meth->item_coord_get(it->priv_data, c, count); - struct coord_rect r; - struct map_selection *curr; - if (ret <= 0 || !sel) - return ret; - r.lu=c[0]; - r.rl=c[0]; - for (i = 1 ; i < ret ; i++) { - if (r.lu.x > c[i].x) - r.lu.x=c[i].x; - if (r.rl.x < c[i].x) - r.rl.x=c[i].x; - if (r.rl.y > c[i].y) - r.rl.y=c[i].y; - if (r.lu.y < c[i].y) - r.lu.y=c[i].y; - } - curr=sel; - while (curr) { - struct coord_rect *sr=&curr->u.c_rect; - if (r.lu.x <= sr->rl.x && r.rl.x >= sr->lu.x && - r.lu.y >= sr->rl.y && r.rl.y <= sr->lu.y) - return ret; - curr=curr->next; + int in_coords; + int ret = 0; + struct coord_rect bbox; + int intersects=0; + + /* scan all coordinates. Even if buffer is too small */ + while ((in_coords=item_coord_get(it, c, count)) > 0) { + int i; + struct map_selection *curr; + /* update ret */ + if(ret == 0) { + ret=in_coords; + /* init bbox */ + bbox.lu=c[0]; + bbox.rl=c[0]; + } + + /* update bbox */ + for (i = 0 ; i < in_coords ; i++) { + if (bbox.lu.x > c[i].x) + bbox.lu.x=c[i].x; + if (bbox.rl.x < c[i].x) + bbox.rl.x=c[i].x; + if (bbox.rl.y > c[i].y) + bbox.rl.y=c[i].y; + if (bbox.lu.y < c[i].y) + bbox.lu.y=c[i].y; + } + /* check if bbox intersects already with selection */ + curr=sel; + while ((!intersects) && (curr)) { + struct coord_rect *sr=&curr->u.c_rect; + if (bbox.lu.x <= sr->rl.x && bbox.rl.x >= sr->lu.x && + bbox.lu.y >= sr->rl.y && bbox.rl.y <= sr->lu.y) + intersects=1; + curr=curr->next; + } + + /* abort on the special case to read only one coord. */ + if(count == 1) + break; + /* we can abort if already intersecting. */ + if(intersects) + break; } - return 0; + if(!intersects) + ret=0; + return ret; } /** |