/*
Interpolate filter
Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
*/
#include "defs.h"
#include "filterdefs.h"
#include "grtcirc.h"
#if FILTERS_ENABLED
#define MYNAME "Interpolate filter"
static char *opt_interval = NULL;
int interval = 0;
static char *opt_dist = NULL;
double dist = 0;
static char *opt_route = NULL;
static
arglist_t interpfilt_args[] = {
{"time", &opt_interval, "Time interval in seconds", NULL,
ARGTYPE_BEGIN_EXCL | ARGTYPE_BEGIN_REQ | ARGTYPE_INT,
"0", NULL },
{"distance", &opt_dist, "Distance interval in miles or kilometers",
NULL, ARGTYPE_END_EXCL | ARGTYPE_END_REQ | ARGTYPE_STRING,
ARG_NOMINMAX },
{"route", &opt_route, "Interpolate routes instead", NULL,
ARGTYPE_BOOL, ARG_NOMINMAX },
ARG_TERMINATOR
};
void
interpfilt_process(void)
{
queue *backuproute = NULL;
queue *elem, *tmp, *elem2, *tmp2;
route_head *rte_new;
int count = 0;
int first = 0;
double lat1 = 0, lon1 = 0;
int time1 = 0;
int timen;
double distn;
double curdist;
double rt1, rn1, rt2, rn2;
if ( opt_route ) {
route_backup( &count, &backuproute );
route_flush_all_routes();
}
else {
track_backup( &count, &backuproute );
route_flush_all_tracks();
}
QUEUE_FOR_EACH( backuproute, elem, tmp )
{
route_head *rte_old = (route_head *)elem;
rte_new = route_head_alloc();
rte_new->rte_name = xstrdup( rte_old->rte_name );
rte_new->rte_desc = xstrdup( rte_old->rte_desc );
rte_new->fs = fs_chain_copy( rte_old->fs );
rte_new->rte_num = rte_old->rte_num;
if ( opt_route ) {
route_add_head( rte_new );
}
else {
track_add_head( rte_new );
}
first = 1;
QUEUE_FOR_EACH( &rte_old->waypoint_list, elem2, tmp2 )
{
waypoint *wpt = (waypoint *)elem2;
if ( first ) {
first = 0;
}
else {
if ( opt_interval &&
wpt->creation_time - time1 > interval ) {
for ( timen = time1+interval;
timen < wpt->creation_time;
timen += interval ) {
waypoint *wpt_new = waypt_dupe(wpt);
wpt_new->creation_time = timen;
if (wpt_new->shortname) xfree(wpt_new->shortname);
if (wpt_new->description) xfree(wpt_new->description);
wpt_new->shortname = wpt_new->description = NULL;
linepart( lat1, lon1,
wpt->latitude, wpt->longitude,
(double)(timen-time1)/
(double)(wpt->creation_time-time1),
&wpt_new->latitude,
&wpt_new->longitude );
if (opt_route)
route_add_wpt( rte_new, wpt_new);
else
track_add_wpt( rte_new, wpt_new);
}
}
else if ( opt_dist ) {
rt1 = RAD(lat1);
rn1 = RAD(lon1);
rt2 = RAD(wpt->latitude);
rn2 = RAD(wpt->longitude);
curdist = gcdist( rt1, rn1, rt2, rn2 );
curdist = radtomiles(curdist);
if ( curdist > dist ) {
for ( distn = dist;
distn < curdist;
distn += dist ) {
waypoint *wpt_new = waypt_dupe(wpt);
wpt_new->creation_time = distn/curdist*
(wpt->creation_time - time1) + time1;
if (wpt_new->shortname) xfree(wpt_new->shortname);
if (wpt_new->description) xfree(wpt_new->description);
wpt_new->shortname = wpt_new->description = NULL;
linepart( lat1, lon1,
wpt->latitude, wpt->longitude,
distn/curdist,
&wpt_new->latitude,
&wpt_new->longitude );
if (opt_route)
route_add_wpt( rte_new, wpt_new );
else
track_add_wpt( rte_new, wpt_new);
}
}
}
}
if ( opt_route ) {
route_add_wpt( rte_new, waypt_dupe(wpt));
}
else {
track_add_wpt( rte_new, waypt_dupe(wpt));
}
lat1 = wpt->latitude;
lon1 = wpt->longitude;
time1 = wpt->creation_time;
}
}
route_flush( backuproute );
xfree( backuproute );
}
void
interpfilt_init(const char *args) {
char *fm;
if ( opt_interval && opt_dist ) {
fatal( MYNAME ": Can't interpolate on both time and distance.\n");
}
else if (opt_interval && opt_route ) {
fatal( MYNAME ": Can't interpolate routes on time.\n" );
}
else if ( opt_interval ) {
interval = atoi(opt_interval);
}
else if ( opt_dist ) {
dist = strtod(opt_dist, &fm);
if ((*fm == 'k') || (*fm == 'K')) {
/* distance is kilometers, convert to miles */
dist *= .6214;
}
}
else {
fatal( MYNAME ": No interval specified.\n");
}
}
filter_vecs_t interpolatefilt_vecs = {
interpfilt_init,
interpfilt_process,
NULL,
NULL,
interpfilt_args
};
#endif // FILTERS_ENABLED
syntax highlighted by Code2HTML, v. 0.9.1