This is IcaoObjects.c in view mode; [Download] [Up]
/****************************************************************
* *
* I C A O M a p - *
* *
* A n A v i a t i o n U t i l i t y *
* *
* *
* Copyright (C) 1993, 1994 Martin Pauly *
* *
* N e x t V e r s i o n *
* *
* Copyright (C) 1994 Stefan Leuker & Oliver Meyer *
* *
* This file may be freely distributed only if it includes *
* the above copyright notice. *
* *
****************************************************************/
#import "IcaoObjects.h"
#define max(a,b) (a>b)?a:b
static LOCATION *templist; /* collect points before object is created */
static int nextpoint = 0; /* counter for above list */
static char order[5000];/* used to sort objects */
OBJECT **objectlist; /* array of pointers to OBJECTs */
int objectno; /* no. of objects that was created last (-1
* if none created yet) */
LOCATION curr_location; /* current (when reading the world file)
* location */
double curr_elev = UNKNOWN; /* current elevation */
TABLEENTRY *nametable;
int tableentries;
char **namearray;
int db_objects; /* exported database information */
int db_visible;
extern int currentline;
int
objects_init()
{
int i;
initmapobjects();
/* preset global variables to assure consistance on parse */
nextpoint = 0;
curr_location.longitude = 0;
curr_location.latitude = 0;
curr_elev = UNKNOWN;
currentline = 1;
if (!templist)
templist = (LOCATION *) malloc(MAXPOINTS * sizeof(LOCATION));
if (!templist)
return 1;
db_objects = db_visible = 0;
objectno = -1;
objectlist = (OBJECT **) NXZoneMalloc(theZone, MAXOBJECTS * sizeof(OBJECT *));
if (objectlist)
{
for (i = 0; i < MAXOBJECTS; i++)
objectlist[i] = NULL;
return 0;
} else
return 1;
}
/* sort objects in memory */
int
sortcomp(const void * a, const void * b)
{
return order[(*(OBJECT **)a)->type] - order[(*(OBJECT **)b)->type];
}
int
compname(const void * a, const void * b)
{
return strcmp(((TABLEENTRY *)a)->name, ((TABLEENTRY *)b)->name);
}
int compstr(const void *a, const void *b)
{
return strcmp(*(char **)a, *(char **)b);
}
char *
strdup(char *ein)
{
char *ptr = NULL;
if (ein != NULL)
{
ptr = (char *)NXZoneMalloc(theZone, strlen(ein) + 1);
strcpy(ptr, ein);
}
return ptr;
}
void
sort_objects()
{
int i; //, j, length;
char tempstr[100];
/* build order array for objects */
for (i = 0; i < 5000; i++)
order[i] = 0;
order[O_CTR] = -60;
order[O_TOWN] = -50;
order[O_RIVER] = -40;
order[O_HIGHWAY] = order[O_ROAD] = -30;
order[O_CVFR] = -20;
order[O_VILLAGE] = -10;
for (i = O_VOR; i <= O_BASIC_RADIO_FACILITY; i++)
order[i] = 10;
order[O_WAYPOINT] = 20;
for (i = O_INTLAIRPORT; i <= O_FREE_BALLON_SITE; i++)
order[i] = 30;
qsort(objectlist, objectno + 1, sizeof(OBJECT *),sortcomp);
/* this is also the time to build the alphabetical name index */
tableentries = 0;
nametable = (TABLEENTRY *) NXZoneMalloc(theZone, sizeof(TABLEENTRY) * 2 * db_objects);
for (i = 0; i < db_objects; i++)
if (objectlist[i]->name)
if (strlen(objectlist[i]->name))
if ((objectlist[i]->type < 300) ||
(objectlist[i]->type == O_WAYPOINT) ||
(objectlist[i]->type == O_LAKE) ||
(objectlist[i]->type == O_VILLAGE) ||
(objectlist[i]->type == O_ISLAND) ||
(objectlist[i]->type == O_TOWN))
{
if (objectlist[i]->type != O_WAYPOINT)
{
sprintf(tempstr, "%s (%s)", objectlist[i]->name,
objecttypestring(objectlist[i]->type));
nametable[tableentries].name = strdup(tempstr);
nametable[tableentries].index = i;
tableentries++;
} else
{
if (objectlist[i]->alias)
{
sprintf(tempstr, "%s %s", objectlist[i]->name, objectlist[i]->alias);
nametable[tableentries].name = strdup(tempstr);
nametable[tableentries].index = i;
tableentries++;
sprintf(tempstr, "%s %s", objectlist[i]->alias, objectlist[i]->name);
nametable[tableentries].name = strdup(tempstr);
nametable[tableentries].index = i;
tableentries++;
} else
{
nametable[tableentries].name = objectlist[i]->name;
nametable[tableentries].index = i;
tableentries++;
}
}
}
qsort(nametable, tableentries, sizeof(TABLEENTRY), compname);
/* build array of strings for browser */
namearray = (char **)NXZoneMalloc(theZone, (1 + tableentries) * sizeof(char *));
namearray[0] = IO_CLEARENTRY;
for (i = 0; i < tableentries; i++)
namearray[i + 1] = nametable[i].name;
tableentries++;
/* convert underscores in names to blanks */
#ifdef oliver
for (i = 0; i < tableentries; i++)
{
length = strlen(namearray[i]);
for (j = 0; j < length; j++)
if (namearray[i][j] == '_')
namearray[i][j] = ' ';
}
qsort(namearray, tableentries, sizeof(char *), compstr);
#endif
}
/* return pointer to an object by index of string in browser */
OBJECT *
objectfromnamelist(int listindex)
{
if (listindex)
return objectlist[nametable[listindex - 1].index];
else
return NULL;
}
int
objectThatMatches(const char *input)
{
int nearest = -1;
int pos, first, last, brk, len;
/*
* This iterally tests first fopr the full length of input, and
* then step by step a character less.
*/
len = strlen(input);
while (nearest == -1)
{
if (!len)
nearest = 0;
first = -1;
last = tableentries;
pos = last / 2;
while ((first+1 < last) && (nearest == -1))
{
brk = strncasecmp(namearray[pos], input, len);
if (brk == 0)
nearest = pos;
if (brk > 0)
{
last = pos;
pos = (first + pos) / 2;
}
if (brk < 0)
{
first = pos;
pos = (pos + last) / 2;
}
}
if (nearest != -1)
{
do
{
nearest--;
}
while ((nearest > 0) && (strncasecmp(namearray[nearest], input, len) == 0));
nearest++;
}
else
{
len--;
}
}
return nearest;
}
/* get object type string from type number */
char *
objecttypestring(int objecttype)
{
static char string[30];
switch (objecttype)
{
case O_INTLAIRPORT:
strcpy(string, "International Airport");
break;
case O_AIRPORT:
strcpy(string, "Airport");
break;
case O_AIRPORT_CIV_MIL:
strcpy(string, "Civil/Military Airport");
break;
case O_AIRPORT_MIL:
strcpy(string, "Military Airport");
break;
case O_AIRFIELD:
strcpy(string, "Public Airfield");
break;
case O_SPECIAL_AIRFIELD:
strcpy(string, "Special Airfield");
break;
case O_HELIPORT:
strcpy(string, "Heliport");
break;
case O_HELIPORT_AMB:
strcpy(string, "Ambulance Heliport");
break;
case O_GLIDER_SITE:
strcpy(string, "Glider Site");
break;
case O_HANG_GLIDER_SITE:
strcpy(string, "Hang Glider Site");
break;
case O_PARACHUTE_JUMPING_SITE:
strcpy(string, "Parachute Site");
break;
case O_FREE_BALLON_SITE:
strcpy(string, "Ballon Site");
break;
case O_VOR:
strcpy(string, "VOR");
break;
case O_VOR_DME:
strcpy(string, "VOR/DME");
break;
case O_VORTAC:
strcpy(string, "VORTAC");
break;
case O_TACAN:
strcpy(string, "TACAN");
break;
case O_NDB:
strcpy(string, "NDB");
break;
case O_MARKER_BEACON:
strcpy(string, "Marker Beacon");
break;
case O_BASIC_RADIO_FACILITY:
strcpy(string, "Radio Facility");
break;
case O_OBSTRUCTION:
strcpy(string, "Obstruction");
break;
case O_GROUP_OBSTRUCTION:
strcpy(string, "Obstructions");
break;
case O_FIRED_OBSTRUCTION:
strcpy(string, "Fired Obstruction");
break;
case O_FIRED_GROUP_OBSTRUCTION:
strcpy(string, "Fired Obstructions");
break;
case O_AERO_GROUND_LIGHT:
strcpy(string, "Ground Light");
break;
case O_REPORTING_POINT:
strcpy(string, "Reporting Point");
break;
case O_CTR:
strcpy(string, "CTR");
break;
case O_CVFR:
strcpy(string, "CVFR");
break;
case O_RIVER:
strcpy(string, "River");
break;
case O_LAKE:
strcpy(string, "Lake");
break;
case O_HIGHWAY:
strcpy(string, "Highway");
break;
case O_VILLAGE:
strcpy(string, "Village");
break;
case O_ISLAND:
strcpy (string, "Island");
break;
case O_BORDER:
strcpy (string, "Border");
break;
case O_STATE_BORDER:
strcpy (string, "State Border");
break;
case O_COUNTRY:
strcpy (string, "Country");
break;
case O_STATE:
strcpy (string, "State");
break;
case O_TOWN:
strcpy(string, "Town");
break;
case O_WAYPOINT:
strcpy(string, "Waypoint");
break;
default:
strcpy(string, "unknown type");
}
return string;
}
/* call-back routines for the parser */
void
new_location(LOCATION loc)
{
curr_location = loc;
}
void
new_elev(double elev)
{
curr_elev = elev;
}
void
new_object(int objecttype, char *identifier)
{
int i;
if (objectno < MAXOBJECTS - 1)/* check if we have a spare pointer */
{
objectno++;
/* allocate memory for new object and see if that was successful... */
objectlist[objectno] = (OBJECT *) NXZoneMalloc(theZone, sizeof(OBJECT));
if (objectlist[objectno] == NULL)
{
printf("Out of memory - %s not saved!\n", identifier);
objectno--;
} else
{
/*
* Added by Oliver because of the lakes.
* initialize to null
*/
memset(objectlist[objectno], 0, sizeof(OBJECT));
db_objects = objectno + 1;
objectlist[objectno]->type = objecttype;
objectlist[objectno]->name = identifier;
objectlist[objectno]->msl = curr_elev;
curr_elev = UNKNOWN;
objectlist[objectno]->top_msl = curr_elev;
objectlist[objectno]->range = UNKNOWN;
objectlist[objectno]->location = curr_location;
objectlist[objectno]->runways = NULL;
objectlist[objectno]->numpoints = 0;
objectlist[objectno]->points = NULL;
/* check for waiting polygon or list of points */
if (nextpoint)
{
#define CO objectlist[objectno]
CO->topleft = templist[0];
CO->bottomright = templist[0];
objectlist[objectno]->points = (LOCATION *) NXZoneMalloc(theZone, nextpoint * sizeof(LOCATION));
objectlist[objectno]->numpoints = nextpoint;
for (i = 0; i < nextpoint; i++) /* copy points from templist to
* object */
{
objectlist[objectno]->points[i] = templist[i];
/* get bounding rectangle */
if (CO->topleft.latitude < templist[i].latitude)
CO->topleft.latitude = templist[i].latitude;
if (CO->topleft.longitude > templist[i].longitude)
CO->topleft.longitude = templist[i].longitude;
if (CO->bottomright.latitude > templist[i].latitude)
CO->bottomright.latitude = templist[i].latitude;
if (CO->bottomright.longitude < templist[i].longitude)
CO->bottomright.longitude = templist[i].longitude;
}
nextpoint = 0; /* delete temporary list */
}
}
} else
printf("Too many objects - %s not saved!\n", identifier);
}
void
add_point(LOCATION point)
{
if (nextpoint < MAXPOINTS - 1)
{
templist[nextpoint] = point;
nextpoint++;
}
}
void
set_frequency(double freq)
{
objectlist[objectno]->frequency = freq;
}
void
set_alias(char *name)
{
objectlist[objectno]->alias = name;
}
void
set_topmsl(double height)
{
objectlist[objectno]->top_msl = height;
}
void
set_range(double range)
{
objectlist[objectno]->range = range;
}
void
add_runway(int direction, int length, char surface)
{
RUNWAYDEF *next_rwy, *tmp;
next_rwy = (RUNWAYDEF *) NXZoneMalloc(theZone, sizeof(RUNWAYDEF));
if (!next_rwy) /* not enough memory */
puts("Out of memory.");
else
{
tmp = objectlist[objectno]->runways;
if (!tmp) /* first object? */
objectlist[objectno]->runways = next_rwy;
else
{
while (tmp->next)
tmp = (RUNWAYDEF *) tmp->next; /* go to end of list */
tmp->next = next_rwy;
}
next_rwy->direction = direction;
next_rwy->length = length;
next_rwy->surface = surface;
next_rwy->next = NULL; /* mark end of list */
}
}
int digi_valid = 0;
static FILE *serialport = NULL;
static double offsetx, offsety; /* digitizer -> map
* coordinates */
static double a, b, c, d; /* conversion matrix */
static double x, y; /* map origin offset in cm */
static int u, v; /* and in digitizer pixels */
/* wait for button and get position, return button number */
int
digi_getpos(int *x, int *y)
{
char line[256];
int readx, ready, readbutton;
fgets(line, 255, serialport);
sscanf(line, "%d,%d,%d", &readx, &ready, &readbutton);
*x = readx;
*y = ready;
return readbutton;
}
/*
calibrate digitizer so that current map can be treated
parameters: the two reference points that have to be 'shot at'
*/
void
digi_calibrate(LOCATION ref1, LOCATION ref2)
{
int u1, v1, u2, v2; /* digitizer coordinations of reference
* points */
double x1, y1, x2, y2; /* map coordinates (cm) of the same
* reference points */
/* init map data */
mapWidthcm = mapHeightcm = 20;/* ca. size of map */
map_initcoord();
/* check if digitier input file is open, if not: open it */
if (!serialport)
{
serialport = fopen("/dev/podscat", "r");
}
if (!serialport)
{
puts("Unable to open digitzer input port!");
} else
{
puts("\ndigitizer calibration:");
printf("Please move to map origin (%s) and press a button!\n",
internal2string(map_origin));
digi_getpos(&u, &v);
printf("Please move to %s and press a button!\n",
internal2string(ref1));
digi_getpos(&u1, &v1);
printf("Please move to %s and press a button!\n",
internal2string(ref2));
digi_getpos(&u2, &v2);
/*
* get respective map coordinates (in cm) of the origin and reference
* points
*/
internal2cm(map_origin, &x, &y);
internal2cm(ref1, &x1, &y1);
internal2cm(ref2, &x2, &y2);
offsetx = x - u; /* translate to map origin */
offsety = y - v;
/*
* get digitizer and cm coordinates of reference points relativ to map
* origin
*/
u1 -= u;
u2 -= u;
x1 -= x;
x2 -= x;
v1 -= v;
v2 -= v;
y1 -= y;
y2 -= y;
/* calculate matrix of conversion function */
a = -(v1 * x2 - v2 * x1) / (-v1 * u2 + v2 * u1);
b = -(-v2 * y1 + y2 * v1) / (-v1 * u2 + v2 * u1);
c = (u1 * x2 - x1 * u2) / (-v1 * u2 + v2 * u1);
d = (-u2 * y1 + u1 * y2) / (-v1 * u2 + v2 * u1);
puts("Thank you, calibration was successful!\n");
digi_valid = 1;
}
}
int
is_digi_valid()
{
return digi_valid;
}
/*
read coordinates from digitizer using current map attributes
*/
LOCATION
digi_input()
{
int xx, yy, bb;
double xcm, ycm;
bb = digi_getpos(&xx, &yy);
xx -= u;
yy -= v;
xcm = a * xx + c * yy + x;
ycm = b * xx + d * yy + y;
printf("%s\n", cm2string(xcm, ycm));
digi_input();
return cm2internal(xcm, ycm);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.