ftp.nice.ch/pub/next/science/cartography/ICAO.0.7b.s.tar.gz#/ICAOfNEXT.0.7b/IcaoObjects.c

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.