2045 |
|
|
2046 |
/* ----------------------- track related stuff ----------------------- */ |
/* ----------------------- track related stuff ----------------------- */ |
2047 |
|
|
2048 |
|
static gboolean track_pos2lpos(bounds_t *bounds, pos_t *pos, lpos_t *lpos) { |
2049 |
|
pos2lpos(bounds, pos, lpos); |
2050 |
|
|
2051 |
|
/* check if point is within bounds */ |
2052 |
|
return ((lpos->x >= bounds->min.x) && (lpos->x <= bounds->max.x) && |
2053 |
|
(lpos->y >= bounds->min.y) && (lpos->y <= bounds->max.y)); |
2054 |
|
} |
2055 |
|
|
2056 |
void map_track_draw_seg(map_t *map, track_seg_t *seg) { |
void map_track_draw_seg(map_t *map, track_seg_t *seg) { |
2057 |
|
bounds_t *bounds = map->appdata->osm->bounds; |
2058 |
|
|
2059 |
/* a track_seg needs at least 2 points to be drawn */ |
/* a track_seg needs at least 2 points to be drawn */ |
2060 |
guint pnum = track_seg_points(seg); |
guint pnum = track_seg_points(seg); |
2061 |
printf("seg of length %d\n", pnum); |
printf("seg of length %d\n", pnum); |
2062 |
|
|
2063 |
if(pnum == 1) { |
if(!pnum) |
2064 |
g_assert(!seg->item); |
return; |
2065 |
|
|
2066 |
seg->item = canvas_circle_new(map->canvas, CANVAS_GROUP_TRACK, |
/* nothing should have been drawn by now ... */ |
2067 |
seg->track_point->lpos.x, seg->track_point->lpos.y, |
g_assert(!seg->item_chain); |
2068 |
map->style->track.width/2.0, 0, map->style->track.color, NO_COLOR); |
|
2069 |
} |
track_item_chain_t **itemP = &seg->item_chain; |
2070 |
|
track_point_t *track_point = seg->track_point; |
2071 |
|
while(track_point) { |
2072 |
|
lpos_t lpos; |
2073 |
|
|
2074 |
|
/* skip all points not on screen */ |
2075 |
|
track_point_t *last = NULL; |
2076 |
|
while(track_point && !track_pos2lpos(bounds, &track_point->pos, &lpos)) { |
2077 |
|
last = track_point; |
2078 |
|
track_point = track_point->next; |
2079 |
|
} |
2080 |
|
|
2081 |
|
int visible = 0; |
2082 |
|
|
2083 |
|
/* count nodes that _are_ on screen */ |
2084 |
|
track_point_t *tmp = track_point; |
2085 |
|
while(tmp && track_pos2lpos(bounds, &tmp->pos, &lpos)) { |
2086 |
|
tmp = tmp->next; |
2087 |
|
visible++; |
2088 |
|
} |
2089 |
|
|
2090 |
|
/* actually start drawing with the last position that was offscreen */ |
2091 |
|
/* so the track nicely enters the viewing area */ |
2092 |
|
if(last) { |
2093 |
|
track_point = last; |
2094 |
|
visible++; |
2095 |
|
} |
2096 |
|
|
2097 |
|
/* also use last one that's offscreen to nicely leave the visible area */ |
2098 |
|
if(tmp && tmp->next) |
2099 |
|
visible++; |
2100 |
|
|
|
if(pnum > 1) { |
|
|
|
|
2101 |
/* allocate space for nodes */ |
/* allocate space for nodes */ |
2102 |
canvas_points_t *points = canvas_points_new(pnum); |
canvas_points_t *points = canvas_points_new(visible); |
2103 |
|
|
2104 |
int point = 0; |
printf("visible are %d\n", visible); |
2105 |
track_point_t *track_point = seg->track_point; |
int point; |
2106 |
while(track_point) { |
for(point=0;point<visible;point++) { |
2107 |
points->coords[point++] = track_point->lpos.x; |
track_pos2lpos(bounds, &track_point->pos, &lpos); |
2108 |
points->coords[point++] = track_point->lpos.y; |
|
2109 |
|
points->coords[2*point+0] = lpos.x; |
2110 |
|
points->coords[2*point+1] = lpos.y; |
2111 |
track_point = track_point->next; |
track_point = track_point->next; |
2112 |
} |
} |
|
|
|
|
/* there may be a circle (one point line) */ |
|
|
if(seg->item) |
|
|
canvas_item_destroy(seg->item); |
|
2113 |
|
|
2114 |
seg->item = canvas_polyline_new(map->canvas, CANVAS_GROUP_TRACK, |
*itemP = g_new0(track_item_chain_t, 1); |
2115 |
points, map->style->track.width, map->style->track.color); |
(*itemP)->item = canvas_polyline_new(map->canvas, CANVAS_GROUP_TRACK, |
2116 |
|
points, map->style->track.width, map->style->track.color); |
2117 |
|
itemP = &(*itemP)->next; |
2118 |
|
|
2119 |
canvas_points_free(points); |
canvas_points_free(points); |
2120 |
} |
} |
2121 |
} |
} |
2122 |
|
|
2123 |
|
/* update the last visible fragment of this segment since a */ |
2124 |
|
/* gps position may have been added */ |
2125 |
void map_track_update_seg(map_t *map, track_seg_t *seg) { |
void map_track_update_seg(map_t *map, track_seg_t *seg) { |
2126 |
|
bounds_t *bounds = map->appdata->osm->bounds; |
2127 |
|
|
2128 |
|
printf("-- APPENDING TO TRACK --\n"); |
2129 |
|
|
2130 |
/* a track_seg needs at least 2 points to be drawn */ |
/* a track_seg needs at least 2 points to be drawn */ |
2131 |
guint pnum = track_seg_points(seg); |
guint pnum = track_seg_points(seg); |
2132 |
printf("seg of length %d\n", pnum); |
printf("seg of length %d\n", pnum); |
2133 |
|
|
2134 |
if(pnum > 1) { |
/* there are two cases: either the second last point was on screen */ |
2135 |
|
/* or it wasn't. We'll have to start a new screen item if the latter */ |
2136 |
|
/* is the case */ |
2137 |
|
|
2138 |
|
/* search last point */ |
2139 |
|
track_point_t *begin = seg->track_point, *second_last = seg->track_point; |
2140 |
|
lpos_t lpos; |
2141 |
|
while(second_last && second_last->next && second_last->next->next) { |
2142 |
|
if(!track_pos2lpos(bounds, &second_last->pos, &lpos)) |
2143 |
|
begin = second_last; |
2144 |
|
|
2145 |
|
second_last = second_last->next; |
2146 |
|
} |
2147 |
|
track_point_t *last = second_last->next; |
2148 |
|
|
2149 |
|
/* since we are updating an existing track, it sure has at least two */ |
2150 |
|
/* points, second_last must be valid and its "next" (last) also */ |
2151 |
|
g_assert(second_last); |
2152 |
|
g_assert(last); |
2153 |
|
|
2154 |
|
/* check if the last and second_last points are visible */ |
2155 |
|
gboolean last_is_visible = |
2156 |
|
track_pos2lpos(bounds, &last->pos, &lpos); |
2157 |
|
gboolean second_last_is_visible = |
2158 |
|
track_pos2lpos(bounds, &second_last->pos, &lpos); |
2159 |
|
|
2160 |
|
/* if both are invisible, then nothing has changed on screen */ |
2161 |
|
if(!last_is_visible && !second_last_is_visible) { |
2162 |
|
printf("second_last and last entry are invisible -> doing nothing\n"); |
2163 |
|
return; |
2164 |
|
} |
2165 |
|
|
2166 |
|
/* search last element in item chain */ |
2167 |
|
track_item_chain_t *item = seg->item_chain; |
2168 |
|
while(item && item->next) |
2169 |
|
item = item->next; |
2170 |
|
|
2171 |
|
if(second_last_is_visible) { |
2172 |
|
/* there must be something already on the screen and there must */ |
2173 |
|
/* be visible nodes in the chain */ |
2174 |
|
g_assert(item); |
2175 |
|
g_assert(begin); |
2176 |
|
|
2177 |
|
printf("second_last is visible -> append\n"); |
2178 |
|
|
2179 |
|
/* count points to be placed */ |
2180 |
|
int npoints = 0; |
2181 |
|
track_point_t *tmp = begin; |
2182 |
|
while(tmp) { |
2183 |
|
tmp = tmp->next; |
2184 |
|
npoints++; |
2185 |
|
} |
2186 |
|
|
2187 |
|
printf("updating last segment to %d points\n", npoints); |
2188 |
|
|
2189 |
|
canvas_points_t *points = canvas_points_new(npoints); |
2190 |
|
|
2191 |
|
gint point = 0; |
2192 |
|
while(begin) { |
2193 |
|
track_pos2lpos(bounds, &begin->pos, &lpos); |
2194 |
|
canvas_point_set_pos(points, point++, &lpos); |
2195 |
|
begin = begin->next; |
2196 |
|
} |
2197 |
|
|
2198 |
/* allocate space for nodes */ |
canvas_item_set_points(item->item, points); |
2199 |
canvas_points_t *points = canvas_points_new(pnum); |
canvas_points_free(points); |
2200 |
|
|
2201 |
int point = 0; |
} else { |
2202 |
track_point_t *track_point = seg->track_point; |
printf("second last is invisible -> start new screen segment\n"); |
2203 |
while(track_point) { |
|
2204 |
canvas_point_set_pos(points, point++, &track_point->lpos); |
/* the search for the "begin" ends with the second_last item */ |
2205 |
track_point = track_point->next; |
/* verify the last one also */ |
2206 |
|
if(begin->next && !track_pos2lpos(bounds, &begin->next->pos, &lpos)) |
2207 |
|
begin = begin->next; |
2208 |
|
|
2209 |
|
item->next = g_new0(track_item_chain_t, 1); |
2210 |
|
item = item->next; |
2211 |
|
|
2212 |
|
/* count points to be placed */ |
2213 |
|
int npoints = 0; |
2214 |
|
track_point_t *tmp = begin; |
2215 |
|
while(tmp) { |
2216 |
|
tmp = tmp->next; |
2217 |
|
npoints++; |
2218 |
|
} |
2219 |
|
|
2220 |
|
printf("attaching new segment with %d points\n", npoints); |
2221 |
|
|
2222 |
|
canvas_points_t *points = canvas_points_new(npoints); |
2223 |
|
|
2224 |
|
gint point = 0; |
2225 |
|
while(begin) { |
2226 |
|
track_pos2lpos(bounds, &begin->pos, &lpos); |
2227 |
|
canvas_point_set_pos(points, point++, &lpos); |
2228 |
|
begin = begin->next; |
2229 |
} |
} |
2230 |
|
|
2231 |
g_assert(seg->item); |
item->item = canvas_polyline_new(map->canvas, CANVAS_GROUP_TRACK, |
2232 |
canvas_item_set_points(seg->item, points); |
points, map->style->track.width, map->style->track.color); |
2233 |
|
|
2234 |
canvas_points_free(points); |
canvas_points_free(points); |
2235 |
} |
} |
2236 |
|
|
2237 |
} |
} |
2238 |
|
|
2239 |
void map_track_draw(map_t *map, track_t *track) { |
void map_track_draw(map_t *map, track_t *track) { |
2256 |
/* remove all segments */ |
/* remove all segments */ |
2257 |
track_seg_t *seg = track->track_seg; |
track_seg_t *seg = track->track_seg; |
2258 |
while(seg) { |
while(seg) { |
2259 |
if(seg->item) { |
track_item_chain_t *item = seg->item_chain; |
2260 |
canvas_item_destroy(seg->item); |
while(item) { |
2261 |
seg->item = NULL; |
track_item_chain_t *next = item->next; |
2262 |
|
canvas_item_destroy(item->item); |
2263 |
|
item = next; |
2264 |
} |
} |
2265 |
|
|
2266 |
|
seg->item_chain = NULL; |
2267 |
seg = seg->next; |
seg = seg->next; |
2268 |
} |
} |
2269 |
} |
} |
2270 |
|
|
2271 |
void map_track_pos(appdata_t *appdata, lpos_t *lpos) { |
void map_track_pos(appdata_t *appdata, pos_t *pos) { |
2272 |
if(appdata->track.gps_item) { |
if(appdata->track.gps_item) { |
2273 |
canvas_item_destroy(appdata->track.gps_item); |
canvas_item_destroy(appdata->track.gps_item); |
2274 |
appdata->track.gps_item = NULL; |
appdata->track.gps_item = NULL; |
2275 |
} |
} |
2276 |
|
|
2277 |
if(lpos) |
if(pos) { |
2278 |
|
lpos_t lpos; |
2279 |
|
pos2lpos(appdata->osm->bounds, pos, &lpos); |
2280 |
|
|
2281 |
appdata->track.gps_item = |
appdata->track.gps_item = |
2282 |
canvas_circle_new(appdata->map->canvas, CANVAS_GROUP_GPS, |
canvas_circle_new(appdata->map->canvas, CANVAS_GROUP_GPS, |
2283 |
lpos->x, lpos->y, appdata->map->style->track.width/2.0, 0, |
lpos.x, lpos.y, appdata->map->style->track.width/2.0, 0, |
2284 |
appdata->map->style->track.gps_color, NO_COLOR); |
appdata->map->style->track.gps_color, NO_COLOR); |
2285 |
|
} |
2286 |
} |
} |
2287 |
|
|
2288 |
/* ------------------- map background ------------------ */ |
/* ------------------- map background ------------------ */ |