diff -c -r -N xastir-1.2.0/src/Makefile.am xastir-1.2.0-p/src/Makefile.am *** xastir-1.2.0/src/Makefile.am 2003-02-18 17:05:30.000000000 -0500 --- xastir-1.2.0-p/src/Makefile.am 2003-06-21 13:46:26.000000000 -0400 *************** *** 1,4 **** ! # $Id: Makefile.am,v 1.4 2003/02/18 22:05:30 kg4ijb Exp $ bin_PROGRAMS = xastir --- 1,4 ---- ! # $Id: Makefile.am,v 1.5 2003/06/21 17:46:26 alan Exp $ bin_PROGRAMS = xastir *************** *** 22,28 **** location.c \ location_gui.c \ main.c main.h \ ! maps.c maps.h \ messages.c messages.h \ messages_gui.c \ popup.h \ --- 22,29 ---- location.c \ location_gui.c \ main.c main.h \ ! maps.c maps.h map_shp.c map_dos.c map_pdb.c map_tif.c map_geo.c \ ! map_tiger.c map_gnis.c \ messages.c messages.h \ messages_gui.c \ popup.h \ diff -c -r -N xastir-1.2.0/src/Makefile.in xastir-1.2.0-p/src/Makefile.in *** xastir-1.2.0/src/Makefile.in 2003-06-21 13:54:19.000000000 -0400 --- xastir-1.2.0-p/src/Makefile.in 2003-06-21 13:50:04.000000000 -0400 *************** *** 14,20 **** @SET_MAKE@ ! # $Id: Makefile.am,v 1.4 2003/02/18 22:05:30 kg4ijb Exp $ SHELL = @SHELL@ srcdir = @srcdir@ --- 14,20 ---- @SET_MAKE@ ! # $Id: Makefile.am,v 1.5 2003/06/21 17:46:26 alan Exp $ SHELL = @SHELL@ srcdir = @srcdir@ *************** *** 122,128 **** location.c \ location_gui.c \ main.c main.h \ ! maps.c maps.h \ messages.c messages.h \ messages_gui.c \ popup.h \ --- 122,129 ---- location.c \ location_gui.c \ main.c main.h \ ! maps.c maps.h map_shp.c map_dos.c map_pdb.c map_tif.c map_geo.c \ ! map_tiger.c map_gnis.c \ messages.c messages.h \ messages_gui.c \ popup.h \ *************** *** 155,165 **** interface.$(OBJEXT) interface_gui.$(OBJEXT) lang.$(OBJEXT) \ list_gui.$(OBJEXT) locate_gui.$(OBJEXT) location.$(OBJEXT) \ location_gui.$(OBJEXT) main.$(OBJEXT) maps.$(OBJEXT) \ ! messages.$(OBJEXT) messages_gui.$(OBJEXT) popup_gui.$(OBJEXT) \ ! rac_data.$(OBJEXT) rotated.$(OBJEXT) sound.$(OBJEXT) \ ! track_gui.$(OBJEXT) util.$(OBJEXT) view_message_gui.$(OBJEXT) \ ! wx.$(OBJEXT) wx_gui.$(OBJEXT) xa_config.$(OBJEXT) \ ! snprintf.$(OBJEXT) xastir_OBJECTS = $(am_xastir_OBJECTS) xastir_LDADD = $(LDADD) xastir_DEPENDENCIES = --- 156,168 ---- interface.$(OBJEXT) interface_gui.$(OBJEXT) lang.$(OBJEXT) \ list_gui.$(OBJEXT) locate_gui.$(OBJEXT) location.$(OBJEXT) \ location_gui.$(OBJEXT) main.$(OBJEXT) maps.$(OBJEXT) \ ! map_shp.$(OBJEXT) map_dos.$(OBJEXT) map_pdb.$(OBJEXT) \ ! map_tif.$(OBJEXT) map_geo.$(OBJEXT) map_tiger.$(OBJEXT) \ ! map_gnis.$(OBJEXT) messages.$(OBJEXT) messages_gui.$(OBJEXT) \ ! popup_gui.$(OBJEXT) rac_data.$(OBJEXT) rotated.$(OBJEXT) \ ! sound.$(OBJEXT) track_gui.$(OBJEXT) util.$(OBJEXT) \ ! view_message_gui.$(OBJEXT) wx.$(OBJEXT) wx_gui.$(OBJEXT) \ ! xa_config.$(OBJEXT) snprintf.$(OBJEXT) xastir_OBJECTS = $(am_xastir_OBJECTS) xastir_LDADD = $(LDADD) xastir_DEPENDENCIES = *************** *** 179,186 **** @AMDEP_TRUE@ ./$(DEPDIR)/interface_gui.Po ./$(DEPDIR)/lang.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/list_gui.Po ./$(DEPDIR)/locate_gui.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/location.Po ./$(DEPDIR)/location_gui.Po \ ! @AMDEP_TRUE@ ./$(DEPDIR)/main.Po ./$(DEPDIR)/maps.Po \ ! @AMDEP_TRUE@ ./$(DEPDIR)/messages.Po ./$(DEPDIR)/messages_gui.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/popup_gui.Po ./$(DEPDIR)/rac_data.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/rotated.Po ./$(DEPDIR)/snprintf.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/sound.Po ./$(DEPDIR)/track_gui.Po \ --- 182,193 ---- @AMDEP_TRUE@ ./$(DEPDIR)/interface_gui.Po ./$(DEPDIR)/lang.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/list_gui.Po ./$(DEPDIR)/locate_gui.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/location.Po ./$(DEPDIR)/location_gui.Po \ ! @AMDEP_TRUE@ ./$(DEPDIR)/main.Po ./$(DEPDIR)/map_dos.Po \ ! @AMDEP_TRUE@ ./$(DEPDIR)/map_geo.Po ./$(DEPDIR)/map_gnis.Po \ ! @AMDEP_TRUE@ ./$(DEPDIR)/map_pdb.Po ./$(DEPDIR)/map_shp.Po \ ! @AMDEP_TRUE@ ./$(DEPDIR)/map_tif.Po ./$(DEPDIR)/map_tiger.Po \ ! @AMDEP_TRUE@ ./$(DEPDIR)/maps.Po ./$(DEPDIR)/messages.Po \ ! @AMDEP_TRUE@ ./$(DEPDIR)/messages_gui.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/popup_gui.Po ./$(DEPDIR)/rac_data.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/rotated.Po ./$(DEPDIR)/snprintf.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/sound.Po ./$(DEPDIR)/track_gui.Po \ *************** *** 258,263 **** --- 265,277 ---- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/location.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/location_gui.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map_dos.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map_geo.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map_gnis.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map_pdb.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map_shp.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map_tif.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map_tiger.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maps.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/messages.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/messages_gui.Po@am__quote@ diff -c -r -N xastir-1.2.0/src/map_dos.c xastir-1.2.0-p/src/map_dos.c *** xastir-1.2.0/src/map_dos.c 1969-12-31 19:00:00.000000000 -0500 --- xastir-1.2.0-p/src/map_dos.c 2003-06-21 13:44:57.000000000 -0400 *************** *** 0 **** --- 1,1140 ---- + /* -*- c-basic-indent: 4; indent-tabs-mode: nil -*- + * $Id: map_dos.c,v 1.2 2003/06/21 17:44:57 alan Exp $ + * + * XASTIR, Amateur Station Tracking and Information Reporting + * Copyright (C) 1999,2000 Frank Giannandrea + * Copyright (C) 2000-2003 The Xastir Group + * + * 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-1307, USA. + * + * Look at the README for more information on the program. + * + * + * Please see separate copyright notice attached to the + * SHPRingDir_2d() function in this file. + * + */ + #include "config.h" + #include "snprintf.h" + + #include + #include + #include + #include + #include + #include + #include + #include + + // Needed for Solaris + #include + + #include + #include + #include + + #ifdef HAVE_X11_XPM_H + #include + #ifdef HAVE_LIBXPM // if we have both, prefer the extra library + #undef HAVE_XM_XPMI_H + #endif // HAVE_LIBXPM + #endif // HAVE_X11_XPM_H + + #ifdef HAVE_XM_XPMI_H + #include + #endif // HAVE_XM_XPMI_H + + #include + + #include + + #include "xastir.h" + #include "maps.h" + #include "alert.h" + #include "util.h" + #include "main.h" + #include "datum.h" + #include "draw_symbols.h" + #include "rotated.h" + #include "color.h" + #include "xa_config.h" + + #define CHECKMALLOC(m) if (!m) { fprintf(stderr, "***** Malloc Failed *****\n"); exit(0); } + + #define DOS_HDR_LINES 8 + #define GRID_MORE 5000 + + extern int npoints; /* tsk tsk tsk -- globals */ + extern int mag; + + /* MAP pointers */ + + static map_vectors *map_vectors_ptr; + static text_label *map_text_label_ptr; + static symbol_label *map_symbol_label_ptr; + + /* MAP counters */ + + static long vectors_num; + static long text_label_num; + static long object_label_num; + + + + + /********************************************************** + * map_plot() + * + * Plots vectors on the map. If "color" is non-zero, + * then it draws filled polygons in the color of + * "object_behavior"? Weird. + **********************************************************/ + void map_plot (Widget w, long max_x, long max_y, long x_long_cord, + long y_lat_cord, unsigned char color, long object_behavior, + int destination_pixmap, int draw_filled) { + + static int redraw_check; + static XPoint points[MAX_MAP_POINTS]; + static unsigned char last_color = (unsigned char)0; + static unsigned char last_behavior = (unsigned char)0, first_behavior = (unsigned char)0; + long x, y; + int draw_ok; + unsigned char line_behavior, fill_color; + char warning[200]; + + /* don't ever go over MAX_MAP_POINTS have a bad map not a crashed program */ + if (npoints > MAX_MAP_POINTS) { + xastir_snprintf(warning, sizeof(warning), "Warning line point count overflow: map_plot\b\n"); + XtAppWarning (app_context, warning); + npoints = MAX_MAP_POINTS; + } + + /* if map_color_levels are on see if we should draw the line? */ + draw_ok = 0; + if (map_color_levels) // Decide which colors to display at this zoom level + switch (color) { + case (0x01): + case (0x14): + case (0x18): + if (mag < 100) + draw_ok = 1; + break; + case (0x15): + case (0x19): + if (mag < 600) + draw_ok = 1; + break; + case (0x16): + if (mag < 800) + draw_ok = 1; + break; + default: + draw_ok = 1; + break; + } + else // Display all colors + draw_ok = 1; + + if (draw_ok) { + x = ((x_long_cord - x_long_offset) / scale_x); + y = ((y_lat_cord - y_lat_offset) / scale_y); + if (x < -MAX_OUTBOUND) + x = -MAX_OUTBOUND; + + if (y < -MAX_OUTBOUND) + y = -MAX_OUTBOUND; + + if (x > max_x) + x = max_x; + + if (y > max_y) + y = max_y; + + if (debug_level & 16) + fprintf(stderr," MAP Plot - max_x: %ld, max_y: %ld, x: %ld, y: %ld, color: %d, behavior: %lx, points: %d\n", + max_x, max_y, x, y, (int)color, (unsigned long)object_behavior, npoints); + + if ( (last_color != color) || (color == (unsigned char)0xff) ) { + if (npoints && (last_color != (unsigned char)0xff) ) { + line_behavior = last_behavior; + if (last_behavior & 0x80) { + if (color) { + fill_color = (last_behavior & ~0x80) + (unsigned char)0x60; + if (fill_color > (unsigned char)0x69) + fill_color = (unsigned char)0x60; + } else + fill_color = (unsigned char)object_behavior; + + + // Here's where we draw filled areas using fill_color. + + (void)XSetForeground (XtDisplay (w), gc, colors[(int)fill_color]); + + switch (destination_pixmap) { + + case DRAW_TO_PIXMAP: + // We must be drawing maps 'cuz this is the pixmap we use for it. + if (map_color_fill && draw_filled) { + + if (npoints >= 3) { + (void)XFillPolygon(XtDisplay(w), + pixmap, + gc, + points, + npoints, + Nonconvex, + CoordModeOrigin); + } + else { + fprintf(stderr, + "map_plot:Too few points:%d, Skipping XFillPolygon()", + npoints); + } + } + break; + + case DRAW_TO_PIXMAP_ALERTS: + fprintf(stderr,"You're calling the wrong routine to draw weather alerts!\n"); + break; + + case DRAW_TO_PIXMAP_FINAL: + // We must be drawing symbols/tracks 'cuz this is the pixmap we use for it. + + if (npoints >= 3) { + (void)XFillPolygon(XtDisplay(w), + pixmap_final, + gc, + points, + npoints, + Nonconvex, + CoordModeOrigin); + } + else { + fprintf(stderr, + "map_plot:Too few points:%d, Skipping XFillPolygon()", + npoints); + } + break; + } + + line_behavior = first_behavior; + } + if (line_behavior & 0x01) + (void)XSetLineAttributes (XtDisplay (w), gc, 2, LineSolid, CapButt,JoinMiter); + else + (void)XSetLineAttributes (XtDisplay (w), gc, 1, LineSolid, CapButt,JoinMiter); + + if (color == (unsigned char)0x56) + (void)XSetLineAttributes (XtDisplay (w), gc, 10, LineSolid, CapButt,JoinMiter); + + // Set the color for drawing lines/borders + (void)XSetForeground (XtDisplay (w), gc, colors[(int)last_color]); + + switch (destination_pixmap) { + + case DRAW_TO_PIXMAP_FINAL: + (void)XDrawLines (XtDisplay (w), pixmap_final, gc, points, npoints,CoordModeOrigin); + break; + + case DRAW_TO_PIXMAP: + (void)XDrawLines (XtDisplay (w), pixmap, gc, points, npoints,CoordModeOrigin); + break; + + case DRAW_TO_PIXMAP_ALERTS: + fprintf(stderr,"You're calling the wrong routine to draw weather alerts!\n"); + break; + } + + npoints = 0; + + /* check to see if we have been away from the screen too long */ + if (redraw_check > 1000) { + redraw_check = 0; + XmUpdateDisplay (XtParent (da)); + } + redraw_check++; + } + last_color = color; + if (color == (unsigned char)0xff) { + npoints = 0; + first_behavior = (unsigned char)object_behavior; + } + points[npoints].x = (short)x; + points[npoints].y = (short)y; + if ( (points[npoints].x > (-MAX_OUTBOUND)) + && (points[npoints].x < (short)max_x) + && (points[npoints].y > (-MAX_OUTBOUND)) + && (points[npoints].y < (short)max_y) + && (color != (unsigned char)0) ) + + npoints++; + + last_behavior = (unsigned char)object_behavior; + return; + } + points[npoints].x = (short)x; + points[npoints].y = (short)y; + last_behavior = (unsigned char)object_behavior; + + if (points[npoints].x != points[npoints - 1].x || points[npoints].y != points[npoints - 1].y) { + if (last_behavior & 0x80) + npoints++; + + else if (points[npoints].x > (-MAX_OUTBOUND) + && points[npoints].x < (short)max_x + && points[npoints].y > (-MAX_OUTBOUND) + && points[npoints].y < (short)max_y) + npoints++; + + } + } else { + npoints = 0; + } + } /* map_plot */ + + + + void + draw_dos_map(Widget w, + char *dir, + char *filenm, + alert_entry *alert, + u_char alert_color, + int destination_pixmap, + int draw_filled) + { + FILE *f; + char file[MAX_FILENAME]; + char map_it[MAX_FILENAME]; + + /* map header info */ + char map_type[5]; + char map_version[5]; + char file_name[33]; + char *ext; + char map_title[33]; + char map_creator[8]; + unsigned long creation_date; + unsigned long left_boundary; + unsigned long right_boundary; + unsigned long top_boundary; + unsigned long bottom_boundary; + char map_reserved1[9]; + long total_vector_points; + long total_labels; + char map_reserved2[141]; + char Buffer[2049]; + char *ptr; + int dos_labels; + int dos_flag; + long temp; + int points_per_degree; + int map_range; + + /* vector info */ + unsigned char vector_start; + unsigned char object_behavior; + unsigned long x_long_cord; + unsigned long y_lat_cord; + + /* label data */ + char label_type[3]; + unsigned long label_x_cord; + unsigned long label_y_cord; + int temp_mag; + int label_mag; + char label_symbol_del; + char label_symbol_char; + char label_text_color; + char label_text[50]; + + unsigned long year; + unsigned long days; + long count; + int label_length; + int i; + int map_maxed_vectors; + int map_maxed_text_labels; + int map_maxed_symbol_labels; + map_vectors *vectors_ptr; + text_label *text_ptr; + symbol_label *symbol_ptr; + int line_width; + int x, y; + int color; + long max_x, max_y; + int in_window = 0; + char symbol_table; + char symbol_id; + char symbol_color; + int embedded_object; + + x = 0; + y = 0; + color = -1; + line_width = 1; + mag = (1 * scale_y) / 2; // determines if details are drawn + + /* MAP counters */ + vectors_ptr = map_vectors_ptr; + text_ptr = map_text_label_ptr; + symbol_ptr = map_symbol_label_ptr; + + map_maxed_vectors = 0; + map_maxed_text_labels = 0; + map_maxed_symbol_labels = 0; + npoints = 0; + + xastir_snprintf(file, sizeof(file), "%s/%s", dir, filenm); + f = fopen (file, "r"); + if (f != NULL) { + (void)fread (map_type, 4, 1, f); + map_type[4] = '\0'; + dos_labels = FALSE; + points_per_degree = 300; + + // DOS-type map header portion of the code. + if (strtod (map_type, &ptr) > 0.01 && (*ptr == '\0' || *ptr == ' ' || *ptr == ',')) { + int j; + + if (debug_level & 512) + fprintf(stderr,"DOS Map\n"); + + //fprintf(stderr,"DOS Map\n"); + + top_boundary = left_boundary = bottom_boundary = right_boundary = 0; + rewind (f); + map_title[0] = map_creator[0] = Buffer[0] = '\0'; + strncpy (map_type, "DOS ", 4); // set map_type for DOS ASCII maps + strncpy (file_name, filenm, 32); + total_vector_points = 200000; + total_labels = 2000; + + for (j = 0; j < DOS_HDR_LINES;) { + if (!strlen(Buffer)) + j++; + + (void)fgets (&Buffer[strlen (Buffer)],(int)sizeof (Buffer) - (strlen (Buffer)), f); + while ((ptr = strpbrk (Buffer, "\r\n")) != NULL && j < DOS_HDR_LINES) { + *ptr = '\0'; + for (ptr++; *ptr == '\r' || *ptr == '\n'; ptr++) ; + switch (j) { + case 0: + top_boundary = (unsigned long) (-atof (Buffer) * 360000 + 32400000); + break; + + case 1: + left_boundary = (unsigned long) (-atof (Buffer) * 360000 + 64800000); + break; + + case 2: + points_per_degree = (int) atof (Buffer); + break; + + case 3: + bottom_boundary = (unsigned long) (-atof (Buffer) * 360000 + 32400000); + bottom_boundary = bottom_boundary + bottom_boundary - top_boundary; + break; + + case 4: + right_boundary = (unsigned long) (-atof (Buffer) * 360000 + 64800000); + right_boundary = right_boundary + right_boundary - left_boundary; + break; + + case 5: + map_range = (int) atof (Buffer); + break; + + case 7: + strncpy (map_version, Buffer, 4); + break; + } + strcpy (Buffer, ptr); + if (strlen (Buffer)) + j++; + } + } // End of DOS-type map header portion + } else { + // Windows-type map header portion + + if (debug_level & 512) + fprintf(stderr,"Windows map\n"); + + //fprintf(stderr,"Windows map\n"); + + (void)fread (map_version, 4, 1, f); + map_version[4] = '\0'; + + (void)fread (file_name, 32, 1, f); + file_name[32] = '\0'; + + (void)fread (map_title, 32, 1, f); + map_title[32] = '\0'; + if (debug_level & 16) + fprintf(stderr,"Map Title %s\n", map_title); + + (void)fread (map_creator, 8, 1, f); + map_creator[8] = '\0'; + if (debug_level & 16) + fprintf(stderr,"Map Creator %s\n", map_creator); + + (void)fread (&temp, 4, 1, f); + creation_date = ntohl (temp); + if (debug_level & 16) + fprintf(stderr,"Creation Date %lX\n", creation_date); + + year = creation_date / 31536000l; + days = (creation_date - (year * 31536000l)) / 86400l; + if (debug_level & 16) + fprintf(stderr,"year is %ld + days %ld\n", 1904l + year, (long)days); + + (void)fread (&temp, 4, 1, f); + left_boundary = ntohl (temp); + + (void)fread (&temp, 4, 1, f); + right_boundary = ntohl (temp); + + (void)fread (&temp, 4, 1, f); + top_boundary = ntohl (temp); + + (void)fread (&temp, 4, 1, f); + bottom_boundary = ntohl (temp); + + if (strcmp (map_version, "2.00") != 0) { + left_boundary *= 10; + right_boundary *= 10; + top_boundary *= 10; + bottom_boundary *= 10; + } + (void)fread (map_reserved1, 8, 1, f); + (void)fread (&temp, 4, 1, f); + total_vector_points = (long)ntohl (temp); + (void)fread (&temp, 4, 1, f); + total_labels = (long)ntohl (temp); + (void)fread (map_reserved2, 140, 1, f); + + } // End of Windows-type map header portion + + + // Done processing map header info. The rest of this + // function performs the actual drawing of both DOS-type + // and Windows-type maps to the screen. + + + if (debug_level & 16) { + fprintf(stderr,"Map Type %s, Version: %s, Filename %s\n", map_type,map_version, file_name); + fprintf(stderr,"Left Boundary %ld, Right Boundary %ld\n", (long)left_boundary,(long)right_boundary); + fprintf(stderr,"Top Boundary %ld, Bottom Boundary %ld\n", (long)top_boundary,(long)bottom_boundary); + fprintf(stderr,"Total vector points %ld, total labels %ld\n",total_vector_points, total_labels); + } + + + // Check whether we're indexing or drawing the map + if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS) + || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) { + + // We're indexing only. Save the extents in the index. + index_update_xastir(filenm, // Filename only + bottom_boundary, // Bottom + top_boundary, // Top + left_boundary, // Left + right_boundary); // Right + + (void)fclose (f); + + return; // Done indexing this file + } + + + in_window = map_onscreen(left_boundary, right_boundary, top_boundary, bottom_boundary); + + if (in_window) { + unsigned char last_behavior, special_fill = (unsigned char)FALSE; + object_behavior = '\0'; + + + // Check whether we're indexing or drawing the map + if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS) + || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) { + xastir_snprintf(map_it, sizeof(map_it), langcode ("BBARSTA039"), filenm); + } + else { + xastir_snprintf(map_it, sizeof(map_it), langcode ("BBARSTA028"), filenm); + } + statusline(map_it,0); // Loading/Indexing ... + + + if (debug_level & 16) + fprintf(stderr,"in Boundary %s\n", map_it); + + (void)XSetLineAttributes (XtDisplay (w), gc, line_width, LineSolid, CapButt,JoinMiter); + + /* read vectors */ + max_x = screen_width + MAX_OUTBOUND; + max_y = screen_height + MAX_OUTBOUND; + + x_long_cord = 0; + y_lat_cord = 0; + color = 0; + dos_flag = 0; + for (count = 0l;count < total_vector_points && !feof (f) && !dos_labels; count++) { + if (strncmp ("DOS ", map_type, 4) == 0) { + (void)fgets (&Buffer[strlen (Buffer)],(int)sizeof (Buffer) - (strlen (Buffer)), f); + while ((ptr = strpbrk (Buffer, "\r\n")) != NULL && !dos_labels) { + long LatHld = 0, LongHld; + char *trailer; + *ptr = '\0'; + for (ptr++; *ptr == '\r' || *ptr == '\n'; ptr++) ; + + process: + + if (strncasecmp ("Line", map_version, 4) == 0) { + int k; + color = (int)strtol (Buffer, &trailer, 0); + if (trailer && (*trailer == ',' || *trailer == ' ')) { + trailer++; + if (color == -1) { + dos_labels = (int)TRUE; + strcpy (Buffer, ptr); + break; + } + for (k = strlen (trailer) - 1; k >= 0; k--) + trailer[k] = (char)( (int)trailer[k] - 27 ); + + while (*trailer) { + LongHld = (long)( (int)(*(unsigned char *)trailer) * 16); + trailer++; + LatHld = (long)( (int)(*(unsigned char *)trailer) * 8); + trailer++; + LongHld += (long)((*trailer >> 3) & 0xf); + LatHld += (long)( (*trailer) & 0x7); + trailer++; + LatHld = ((double)LatHld * 360000.0) / points_per_degree; + LongHld = ((double)LongHld * 360000.0) / points_per_degree; + x_long_cord = LongHld + left_boundary; + y_lat_cord = LatHld + top_boundary; + map_plot (w, + max_x, + max_y, + (long)x_long_cord, + (long)y_lat_cord, + (unsigned char)color, + 0, + destination_pixmap, + draw_filled); + } + map_plot (w, + max_x, + max_y, + (long)x_long_cord, + (long)y_lat_cord, + '\0', + 0, + destination_pixmap, + draw_filled); + } + } else if (strncasecmp ("ASCII", map_version, 4) == 0) { + if (color == 0) { + color = (int)strtol (Buffer, &trailer, 0); + if (trailer && strpbrk (trailer, ", ")) { + for (; *trailer == ',' || *trailer == ' '; trailer++) ; + dos_flag = (int)strtol (trailer, &trailer, 0); + if (dos_flag == -1) + dos_labels = (int)TRUE; + } + } else { + LongHld = strtol (Buffer, &trailer, 0); + if (trailer && strpbrk (trailer, ", ")) { + for (; *trailer == ',' || *trailer == ' '; trailer++) ; + LatHld = strtol (trailer, &trailer, 0); + } else if (LongHld == 0 && *trailer != '\0') { + strncpy (map_version, "Comp", 4); + goto process; + } + if (LongHld == 0 && LatHld == 0) { + color = 0; + map_plot (w, + max_x, + max_y, + (long)x_long_cord, + (long)y_lat_cord, + (unsigned char)color, + 0, + destination_pixmap, + draw_filled); + } else if (LongHld == 0 && LatHld == -1) { + dos_labels = (int)TRUE; + map_plot (w, + max_x, + max_y, + (long)x_long_cord, + (long)y_lat_cord, + '\0', + 0, + destination_pixmap, + draw_filled); + } else { + LatHld = ((double)LatHld * 360000.0) / points_per_degree; + LongHld = ((double)LongHld * 360000.0) / points_per_degree; + x_long_cord = LongHld + left_boundary; + y_lat_cord = LatHld + top_boundary; + map_plot (w, + max_x, + max_y, + (long)x_long_cord, + (long)y_lat_cord, + (unsigned char)color, + 0, + destination_pixmap, + draw_filled); + } + } + } else if (strncasecmp ("Comp", map_version, 4) == 0) { + char Tag[81]; + int k; + Tag[80] = '\0'; + if (color == 0) { + color = (int)strtol (Buffer, &trailer, 0); + if (trailer && strpbrk (trailer, ", ")) { + for (; *trailer == ',' || *trailer == ' '; trailer++) ; + dos_flag = (int)strtol (trailer, &trailer, 0); + strncpy (Tag, trailer, 80); + if (dos_flag == -1) + dos_labels = (int)TRUE; + } + } else { + LongHld = strtol (Buffer, &trailer, 0); + for (; *trailer == ',' || *trailer == ' '; trailer++) ; + LatHld = strtol (trailer, &trailer, 0); + if (LatHld == 0 && *trailer != '\0') + LatHld = 1; + + if (LongHld == 0 && LatHld == 0) { + color = 0; + map_plot (w, + max_x, + max_y, + (long)x_long_cord, + (long)y_lat_cord, + (unsigned char)color, + 0, + destination_pixmap, + draw_filled); + } else if (LongHld == 0 && LatHld == -1) { + dos_labels = (int)TRUE; + map_plot (w, + max_x, + max_y, + (long)x_long_cord, + (long)y_lat_cord, + (unsigned char)color, + 0, + destination_pixmap, + draw_filled); + } + + if (color && !dos_labels) { + trailer = Buffer; + for (k = strlen (trailer) - 1; k >= 0; k--) + trailer[k] = (char)((int)trailer[k] - 27); + + while (*trailer) { + LongHld = (long)( (int)(*(unsigned char *)trailer) * 16); + trailer++; + LatHld = (long)( (int)(*(unsigned char *)trailer) * 8); + trailer++; + LongHld += (long)((*(unsigned char *)trailer >> 3) & 0xf); + LatHld += (*trailer) & 7l; + trailer++; + LatHld = ((double)LatHld * 360000.0) / points_per_degree; + LongHld = ((double)LongHld * 360000.0) / points_per_degree; + x_long_cord = LongHld + left_boundary; + y_lat_cord = LatHld + top_boundary; + map_plot (w, + max_x, + max_y, + (long)x_long_cord, + (long)y_lat_cord, + (unsigned char)color, + 0, + destination_pixmap, + draw_filled); + } + } + } + } else { + LongHld = strtol (Buffer, &trailer, 0); + if (trailer) { + if (*trailer == ',' || *trailer == ' ') { + if (LongHld == 0) + strncpy (map_version, "ASCII", 4); + + trailer++; + dos_flag = (int)strtol (trailer, &trailer, 0); + if (dos_flag == -1) + dos_labels = (int)TRUE; + + if (dos_flag == 0 && *trailer != '\0') { + strncpy (map_version, "Line", 4); + goto process; + } + color = (int)LongHld; + } + } else + strncpy (map_version, "Comp", 4); + } + strcpy (Buffer, ptr); + } + } else { // Windows map... + last_behavior = object_behavior; + (void)fread (&vector_start, 1, 1, f); + (void)fread (&object_behavior, 1, 1, f); // Fill Color? + if (strcmp (map_type, "COMP") == 0) { + short temp_short; + long LatOffset, LongOffset; + LatOffset = (long)(top_boundary - top_boundary % 6000); + LongOffset = (long)(left_boundary - left_boundary % 6000); + (void)fread (&temp_short, 2, 1, f); + x_long_cord = (ntohs (temp_short) * 10 + LongOffset); + (void)fread (&temp_short, 2, 1, f); + y_lat_cord = (ntohs (temp_short) * 10 + LatOffset); + } else { + (void)fread (&temp, 4, 1, f); + x_long_cord = ntohl (temp); + if (strcmp (map_version, "2.00") != 0) + x_long_cord *= 10; + + (void)fread (&temp, 4, 1, f); + y_lat_cord = ntohl (temp); + if (strcmp (map_version, "2.00") != 0) + y_lat_cord *= 10; + } + if (alert_color && last_behavior & 0x80 && (int)vector_start == 0xff) { + map_plot (w, + max_x, + max_y, + (long)x_long_cord, + (long)y_lat_cord, + '\0', + (long)alert_color, + destination_pixmap, + draw_filled); + //special_fill = TRUE; + } + map_plot (w, + max_x, + max_y, + (long)x_long_cord, + (long)y_lat_cord, + vector_start, + (long)object_behavior, + destination_pixmap, + draw_filled); + } + } + if (alert_color) + map_plot (w, + max_x, + max_y, + 0, + 0, + '\0', + special_fill ? (long)0xfd : (long)alert_color, + destination_pixmap, + draw_filled); + else + map_plot (w, + max_x, + max_y, + 0, + 0, + (unsigned char)0xff, + 0, + destination_pixmap, + draw_filled); + + (void)XSetForeground (XtDisplay (w), gc, colors[20]); + line_width = 2; + (void)XSetLineAttributes (XtDisplay (w), gc, line_width, LineSolid, CapButt,JoinMiter); + + + // Here is the map label section of the code for both DOS & Windows-type maps + if (map_labels) { + /* read labels */ + for (count = 0l; count < total_labels && !feof (f); count++) { + //DOS-Type Map Labels + embedded_object = 0; + if (strcmp (map_type, "DOS ") == 0) { // Handle DOS-type map labels/embedded objects + char *trailer; + (void)fgets (&Buffer[strlen (Buffer)],(int)sizeof (Buffer) - (strlen (Buffer)), f); + for (; (ptr = strpbrk (Buffer, "\r\n")) != NULL;strcpy (Buffer, ptr)) { + *ptr = '\0'; + label_type[0] = (char)0x08; + for (ptr++; *ptr == '\r' || *ptr == '\n'; ptr++) ; + trailer = strchr (Buffer, ','); + if (trailer && strncmp (Buffer, "0", 1) != 0) { + *trailer = '\0'; + trailer++; + strcpy (label_text, Buffer); + + // Check for '#' or '$' as the first character of the label. + // If found, we have an embedded symbol and colored text to display. + symbol_table = ' '; + symbol_id = ' '; + symbol_color = '0'; + if ( (label_text[0] == '$') || (label_text[0] == '#') ) { + // We found an embedded map object + embedded_object = 1; // Set the flag + if (label_text[0] == '$') { // Old format: $xC + symbol_table = '/'; + symbol_id = label_text[1]; + symbol_color = label_text[2]; + strcpy( label_text, Buffer+3 ); // Take the object out of the label text + } + else { // Could be in new or old format with a leading '#' character + symbol_table = label_text[1]; + if (symbol_table == '/' || symbol_table == '\\') { // New format: #/xC + symbol_id = label_text[2]; + symbol_color = label_text[3]; + strcpy( label_text, Buffer+4 ); // Take the object out of the label text + } + else { // Old format: #xC + symbol_table = '\\'; + symbol_id = label_text[1]; + symbol_color = label_text[2]; + strcpy( label_text, Buffer+3 ); // Take the object out of the label text + } + } + if (debug_level & 512) + fprintf(stderr,"Found embedded object: %c %c %c %s\n",symbol_table,symbol_id,symbol_color,label_text); + } + + + label_length = (int)strlen (label_text); + label_y_cord = (unsigned long) (-strtod (trailer, &trailer) * 360000) + 32400000; + trailer++; + label_x_cord = (unsigned long) (-strtod (trailer, &trailer) * 360000) + 64800000; + trailer++; + label_mag = (int)strtol (trailer, &trailer, 0) * 20; + if ((label_type[0] & 0x80) == '\0') /* left of coords */ + x = ((label_x_cord - x_long_offset) / scale_x) - (label_length * 6); + else /* right of coords */ + x = ((label_x_cord - x_long_offset) / scale_x); + + y = ((label_y_cord - y_lat_offset) / scale_y); + if (x > (0) && (x < (int)screen_width)) { + if (y > (0) && (y < (int)screen_height)) { + /*fprintf(stderr,"Label mag %d mag %d\n",label_mag,(scale_x*2)-1); */ + //if (label_mag > (int)((scale_x * 2) - 1) || label_mag == 0) + if (label_mag > (int)((scale_x) - 1) || label_mag == 0) { + if (embedded_object) { + // NOTE: 0x21 is the first color for the area object or "DOS" colors + draw_label_text (w, x+10, y+5, label_length,colors[0x21 + symbol_color],label_text); + symbol(w,0,symbol_table,symbol_id,' ',pixmap,1,x-10,y-10,' '); + } + else { + draw_label_text (w, x, y, label_length,colors[(int)(label_type[0] & 0x7f)],label_text); + } + } + } + } + } + } + } else { // Handle Windows-type map labels/embedded objects + int rotation = 0; + char rotation_factor[5]; + + // Windows-Type Map Labels + char label_type_1[2], label_type_2[2]; + + // Snag first two bytes of label + (void)fread (label_type_1, 1, 1, f); + (void)fread (label_type_2, 1, 1, f); + + if (label_type_2[0] == '\0') { // Found a label + + // Found text label + (void)fread (&temp, 4, 1, f); /* x */ + label_x_cord = ntohl (temp); + if (strcmp (map_version, "2.00") != 0) + label_x_cord *= 10; + + (void)fread (&temp, 4, 1, f); /* y */ + label_y_cord = ntohl (temp); + if (strcmp (map_version, "2.00") != 0) + label_y_cord *= 10; + + (void)fread (&temp_mag, 2, 1, f); /* mag */ + label_mag = (int)ntohs (temp_mag); + if (strcmp (map_version, "2.00") != 0) + label_mag *= 10; + + if (strcmp (map_type, "COMP") == 0) { + for (i = 0; i < 32; i++) { + (void)fread (&label_text[i], 1, 1, f); + if (label_text[i] == '\0') { + break; + } + } + label_text[32] = '\0'; // Make sure we have a terminator + } + else { + (void)fread (label_text, 32, 1, f); /* text */ + label_text[32] = '\0'; // Make sure we have a terminator + } + + + // Special strings like: "#123" are rotation factors for labels + // in degrees. This is not documented in the windows-type map + // format documents that I could find. + if (label_text[0] == '#') { + int i,j; + if (debug_level & 512) + fprintf(stderr,"%s\n",label_text); + + // Save the rotation factor in "rotation" + for ( i=1; i<4; i++ ) + rotation_factor[i-1] = label_text[i]; + rotation_factor[3] = '\0'; + rotation = atoi(rotation_factor); + + // Take rotation factor out of label string + for ( i=4, j=0; i < (int)(strlen(label_text)+1); i++,j++) + label_text[j] = label_text[i]; + + //fprintf(stderr,"Windows label: %s, rotation factor: %d\n",label_text, rotation); + } + + + label_length = (int)strlen (label_text); + + for (i = (label_length - 1); i > 0; i--) { + if (label_text[i] == ' ') + label_text[i] = '\0'; + else + break; + } + + label_length = (int)strlen (label_text); + /*fprintf(stderr,"labelin:%s\n",label_text); */ + + if ((label_type_1[0] & 0x80) == '\0') { + /* left of coords */ + x = ((label_x_cord - x_long_offset) / scale_x) - (label_length * 6); + x = 0; // ?????? + } else { + /* right of coords */ + x = ((label_x_cord - x_long_offset) / scale_x); + } + + y = ((label_y_cord - y_lat_offset) / scale_y); + + if (x > (0) && (x < (int)screen_width)) { + if (y > (0) && (y < (int)screen_height)) { + /*fprintf(stderr,"Label mag %d mag %d\n",label_mag,(scale_x*2)-1); */ + //if (label_mag > (int)((scale_x * 2) - 1) || label_mag == 0) + if (label_mag > (int)((scale_x) - 1) || label_mag == 0) { + // Note: We're not drawing the labels in the right colors + if (rotation == 0) { // Non-rotated label + // draw_label_text (w, + // x, + // y, + // label_length, + // colors[(int)(label_type_1[0] & 0x7f)], + // label_text); + draw_rotated_label_text (w, + -90.0, + x, + y, + label_length, + colors[(int)(label_type_1[0] & 0x7f)], + label_text); + } + else { // Rotated label + draw_rotated_label_text (w, + rotation, + x, + y, + label_length, + colors[(int)(label_type_1[0] & 0x7f)], + label_text); + } + } + } + } + } else if (label_type_2[0] == '\1' && label_type_1[0] == '\0'){ // Found an embedded object + + //fprintf(stderr,"Found windows embedded symbol\n"); + + /* label is an embedded symbol */ + (void)fread (&temp, 4, 1, f); + label_x_cord = ntohl (temp); + if (strcmp (map_version, "2.00") != 0) + label_x_cord *= 10; + + (void)fread (&temp, 4, 1, f); + label_y_cord = ntohl (temp); + if (strcmp (map_version, "2.00") != 0) + label_y_cord *= 10; + + (void)fread (&temp_mag, 2, 1, f); + label_mag = (int)ntohs (temp_mag); + if (strcmp (map_version, "2.00") != 0) + label_mag *= 10; + + (void)fread (&label_symbol_del, 1, 1, f); // Snag symbol table char + (void)fread (&label_symbol_char, 1, 1, f); // Snag symbol char + (void)fread (&label_text_color, 1, 1, f); // Snag text color (should be 1-9, others should default to black) + if (label_text_color < '1' && label_text_color > '9') + label_text_color = '0'; // Default to black + + x = ((label_x_cord - x_long_offset) / scale_x); + y = ((label_y_cord - y_lat_offset) / scale_y); + + // Read the label text portion + if (strcmp (map_type, "COMP") == 0) { + for (i = 0; i < 32; i++) { + (void)fread (&label_text[i], 1, 1, f); + if (label_text[i] == '\0') + break; + } + } + else { + (void)fread (label_text, 29, 1, f); + } + + // NOTE: 0x21 is the first color for the area object or "DOS" colors + draw_label_text (w, x+10, y+5, strlen(label_text),colors[0x21 + label_text_color],label_text); + symbol(w,0,label_symbol_del,label_symbol_char,' ',pixmap,1,x-10,y-10,' '); + + if (debug_level & 512) + fprintf(stderr,"Windows map, embedded object: %c %c %c %s\n", + label_symbol_del,label_symbol_char,label_text_color,label_text); + } + else { + if (debug_level & 512) + fprintf(stderr,"Weird label in Windows map, neither a plain label nor an object: %d %d\n", + label_type_1[0],label_type_2[0]); + } + } + } + } // if (map_labels) + } + (void)fclose (f); + } + else + fprintf(stderr,"Couldn't open file: %s\n", file); + } + diff -c -r -N xastir-1.2.0/src/map_geo.c xastir-1.2.0-p/src/map_geo.c *** xastir-1.2.0/src/map_geo.c 1969-12-31 19:00:00.000000000 -0500 --- xastir-1.2.0-p/src/map_geo.c 2003-06-21 13:45:03.000000000 -0400 *************** *** 0 **** --- 1,1220 ---- + /* -*- c-basic-indent: 4; indent-tabs-mode: nil -*- + * $Id: map_geo.c,v 1.1 2003/06/21 17:45:03 alan Exp $ + * + * XASTIR, Amateur Station Tracking and Information Reporting + * Copyright (C) 1999,2000 Frank Giannandrea + * Copyright (C) 2000-2003 The Xastir Group + * + * 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-1307, USA. + * + * Look at the README for more information on the program. + * + * + * Please see separate copyright notice attached to the + * SHPRingDir_2d() function in this file. + * + */ + #include "config.h" + #include "snprintf.h" + + #include + #include + #include + #include + #include + #include + #include + #include + + // Needed for Solaris + #include + + #include + #include + #include + + #ifdef HAVE_X11_XPM_H + #include + #ifdef HAVE_LIBXPM // if we have both, prefer the extra library + #undef HAVE_XM_XPMI_H + #endif // HAVE_LIBXPM + #endif // HAVE_X11_XPM_H + + #ifdef HAVE_XM_XPMI_H + #include + #endif // HAVE_XM_XPMI_H + + #include + + #include + + #include "xastir.h" + #include "maps.h" + #include "alert.h" + #include "util.h" + #include "main.h" + #include "datum.h" + #include "draw_symbols.h" + #include "rotated.h" + #include "color.h" + #include "xa_config.h" + + #define CHECKMALLOC(m) if (!m) { fprintf(stderr, "***** Malloc Failed *****\n"); exit(0); } + + #ifdef HAVE_IMAGEMAGICK + #if TIME_WITH_SYS_TIME + # include + # include + #else // TIME_WITH_SYS_TIME + # if HAVE_SYS_TIME_H + # include + # else // HAVE_SYS_TIME_H + # include + # endif // HAVE_SYS_TIME_H + #endif // TIME_WITH_SYS_TIME + #undef RETSIGTYPE + /* JMT - stupid ImageMagick */ + #define XASTIR_PACKAGE_BUGREPORT PACKAGE_BUGREPORT + #undef PACKAGE_BUGREPORT + #define XASTIR_PACKAGE_NAME PACKAGE_NAME + #undef PACKAGE_NAME + #define XASTIR_PACKAGE_STRING PACKAGE_STRING + #undef PACKAGE_STRING + #define XASTIR_PACKAGE_TARNAME PACKAGE_TARNAME + #undef PACKAGE_TARNAME + #define XASTIR_PACKAGE_VERSION PACKAGE_VERSION + #undef PACKAGE_VERSION + #include + #undef PACKAGE_BUGREPORT + #define PACKAGE_BUGREPORT XASTIR_PACKAGE_BUGREPORT + #undef XASTIR_PACKAGE_BUGREPORT + #undef PACKAGE_NAME + #define PACKAGE_NAME XASTIR_PACKAGE_NAME + #undef XASTIR_PACKAGE_NAME + #undef PACKAGE_STRING + #define PACKAGE_STRING XASTIR_PACKAGE_STRING + #undef XASTIR_PACKAGE_STRING + #undef PACKAGE_TARNAME + #define PACKAGE_TARNAME XASTIR_PACKAGE_TARNAME + #undef XASTIR_PACKAGE_TARNAME + #undef PACKAGE_VERSION + #define PACKAGE_VERSION XASTIR_PACKAGE_VERSION + #undef XASTIR_PACKAGE_VERSION + #endif // HAVE_IMAGEMAGICK + + #ifdef HAVE_LIBCURL + #include + #include + #include + + struct FtpFile { + char *filename; + FILE *stream; + }; + #endif + + extern int npoints; /* tsk tsk tsk -- globals */ + extern int mag; + + + /********************************************************** + * draw_geo_image_map() + * + * If we have found a ".geo" file, we read it here and plot + * the graphic image into the current viewport. + * We check first to see whether the map should be plotted + * and skip it if it's not in our viewport. These images + * are expected to be aligned in the lat/lon directions + * (not rotated) and rectangular. + **********************************************************/ + + void draw_geo_image_map (Widget w, + char *dir, + char *filenm, + alert_entry *alert, + u_char alert_color, + int destination_pixmap, + int draw_filled) { + uid_t user_id; + struct passwd *user_info; + char username[20]; + char file[MAX_FILENAME+1]; // Complete path/name of image file + FILE *f; // Filehandle of image file + char line[MAX_FILENAME]; // One line from GEO file + char fileimg[MAX_FILENAME+1]; // Ascii name of image file, read from GEO file + XpmAttributes atb; // Map attributes after map's read into an XImage + tiepoint tp[2]; // Calibration points for map, read in from .geo file + int n_tp; // Temp counter for number of tiepoints read + float temp_long, temp_lat; + register long map_c_T, map_c_L; // map delta NW edge coordinates, DNN: these should be signed + register long tp_c_dx, tp_c_dy; // tiepoint coordinate differences + // DK7IN-- + int test; // temporary debugging + + unsigned long c_x_min, c_y_min;// top left coordinates of map inside screen + unsigned long c_y_max; // bottom right coordinates of map inside screen + double c_x; // Xastir coordinates 1/100 sec, 0 = 180°W + double c_y; // Xastir coordinates 1/100 sec, 0 = 90°N + double c_y_a; // coordinates correction for Transverse Mercator + + long map_y_0; // map pixel pointer prior to TM adjustment + register long map_x, map_y; // map pixel pointers, DNN: this was a float, chg to long + long map_x_min, map_x_max; // map boundaries for in screen part of map + long map_y_min, map_y_max; // + long map_x_ctr; // half map width in pixel + long map_y_ctr; // half map height in pixel + // long x; + int map_seen, map_act, map_done; + double corrfact; + + long map_c_yc; // map center, vert coordinate + long map_c_xc; // map center, hor coordinate + double map_c_dx, map_c_dy; // map coordinates increment (pixel width) + double c_dx; // adjusted map pixel width + + long scr_x, scr_y; // screen pixel plot positions + long scr_xp, scr_yp; // previous screen plot positions + int scr_dx, scr_dy; // increments in screen plot positions + long scr_x_mc; // map center in screen units + + long scr_c_xr; + + double dist; // distance from equator in nm + double ew_ofs; // distance from map center in nm + + long scale_xa; // adjusted for topo maps + double scale_x_nm; // nm per Xastir coordinate unit + long scale_x0; // at widest map area + + #ifdef HAVE_IMAGEMAGICK + char local_filename[MAX_FILENAME]; + ExceptionInfo exception; + Image *image; + ImageInfo *image_info; + PixelPacket *pixel_pack; + PixelPacket temp_pack; + IndexPacket *index_pack; + int l; + XColor my_colors[256]; + #ifdef HAVE_LIBCURL + CURL *curl; + CURLcode res; + char curlerr[CURL_ERROR_SIZE]; + struct FtpFile ftpfile; + #else + #ifdef HAVE_WGET + char tempfile[MAX_FILENAME]; + #endif // HAVE_WGET + #endif + char gamma[16]; + struct { + float r_gamma; + float g_gamma; + float b_gamma; + int gamma_flag; + int contrast; + int negate; + int equalize; + int normalize; + char level[32]; + char modulate[32]; + } imagemagick_options = { 1.0, 1.0, 1.0, 0, 0, -1, 0, 0, "", "" }; + double left, right, top, bottom, map_width, map_height; + //N0VH + // double lat_center = 0; + // double long_center = 0; + // Terraserver variables + double top_n=0, left_e=0, bottom_n=0, right_e=0, map_top_n=0, map_left_e=0; + int z, url_n=0, url_e=0, t_zoom=16, t_scale=12800; + char zstr[8]; + #else // HAVE_IMAGEMAGICK + XImage *xi; // Temp XImage used for reading in current image + #endif // HAVE_IMAGEMAGICK + + int terraserver_flag = 0; + int toposerver_flag = 0; + char map_it[MAX_FILENAME]; + int geo_image_width = 0; // Image width from GEO file + int geo_image_height = 0; // Image height from GEO file + char geo_datum[8+1]; // WGS-84 etc. + char geo_projection[8+1]; // TM, UTM, GK, LATLON etc. + int map_proj; + + //#define TIMING_DEBUG + #ifdef TIMING_DEBUG + time_mark(1); + #endif // TIMING_DEBUG + + // Get user info + user_id=getuid(); + user_info=getpwuid(user_id); + // Get my login name + strcpy(username,user_info->pw_name); + + xastir_snprintf(file, sizeof(file), "%s/%s", dir, filenm); + + // Read the .geo file to find out map filename and tiepoint info + n_tp = 0; + geo_datum[0] = '\0'; + geo_projection[0] = '\0'; + f = fopen (file, "r"); + if (f != NULL) { + while (!feof (f)) { + (void)get_line (f, line, MAX_FILENAME); + if (strncasecmp (line, "FILENAME", 8) == 0) { + (void)sscanf (line + 9, "%s", fileimg); + if (fileimg[0] != '/' ) { // not absolute path + // make it relative to the .geo file + char temp[MAX_FILENAME]; + strncpy(temp, file, MAX_FILENAME); // grab .geo file name + temp[MAX_FILENAME-1] = '\0'; + (void)get_map_dir(temp); // leaves just the path and trailing / + if (strlen(temp) < (MAX_FILENAME - 1 - strlen(fileimg))) + strcat(temp, fileimg); + strcpy(fileimg, temp); + } + } + if (strncasecmp (line, "URL", 3) == 0) + (void)sscanf (line + 4, "%s", fileimg); + + if (n_tp < 2) { // Only take the first two tiepoints + if (strncasecmp (line, "TIEPOINT", 8) == 0) { + (void)sscanf (line + 9, "%d %d %f %f",&tp[n_tp].img_x,&tp[n_tp].img_y,&temp_long,&temp_lat); + // Convert tiepoints from lat/lon to Xastir coordinates + tp[n_tp].x_long = 64800000l + (360000.0 * temp_long); + tp[n_tp].y_lat = 32400000l + (360000.0 * (-temp_lat)); + n_tp++; + } + } + + if (strncasecmp (line, "IMAGESIZE", 9) == 0) + (void)sscanf (line + 10, "%d %d",&geo_image_width,&geo_image_height); + + if (strncasecmp (line, "DATUM", 5) == 0) + (void)sscanf (line + 6, "%8s",geo_datum); + + if (strncasecmp (line, "PROJECTION", 10) == 0) + (void)sscanf (line + 11, "%8s",geo_projection); // ignores leading and trailing space (nice!) + + if (strncasecmp (line, "TERRASERVER", 11) == 0) + terraserver_flag = 1; + + if (strncasecmp (line, "TOPOSERVER", 10) == 0) + toposerver_flag = 1; + + + #ifdef HAVE_IMAGEMAGICK + if (strncasecmp(line, "GAMMA", 5) == 0) + imagemagick_options.gamma_flag = sscanf(line + 6, "%f,%f,%f", + &imagemagick_options.r_gamma, + &imagemagick_options.g_gamma, + &imagemagick_options.b_gamma); + if (strncasecmp(line, "CONTRAST", 8) == 0) + (void)sscanf(line + 9, "%d", &imagemagick_options.contrast); + if (strncasecmp(line, "NEGATE", 6) == 0) + (void)sscanf(line + 7, "%d", &imagemagick_options.negate); + if (strncasecmp(line, "EQUALIZE", 8) == 0) + imagemagick_options.equalize = 1; + if (strncasecmp(line, "NORMALIZE", 9) == 0) + imagemagick_options.normalize = 1; + #if (MagickLibVersion >= 0x0539) + if (strncasecmp(line, "LEVEL", 5) == 0) { + strncpy(imagemagick_options.level, line + 6, 31); + imagemagick_options.level[31] = '\0'; + } + #endif // MagickLibVersion >= 0x0539 + if (strncasecmp(line, "MODULATE", 8) == 0) { + strncpy(imagemagick_options.modulate, line + 9, 31); + imagemagick_options.modulate[31] = '\0'; + } + #endif // HAVE_IMAGEMAGICK + } + (void)fclose (f); + } + else { + fprintf(stderr,"Couldn't open file: %s\n", file); + return; + } + + // DK7IN: I'm experimenting with the adjustment of topo maps with + // Transverse Mercator projection. Those maps have equal scaling + // in distance while we use equal scaling in degrees. + + // For now I use the map center as central meridian (I think that + // is ok for mapblast), that will change with UTM and Gauss-Krueger + + // I have introduced new entries in the geo file for that... + // I first adjust the x scaling depending on the latitude + // Then I move points in y direction depending on the offset from + // the central meridian. I hope I get that right with those + // approximations. I have the correct formulas, but that will + // be very computing intensive and result in slow map loading... + + // if (geo_datum[0] != '\0') + // fprintf(stderr,"Map Datum: %s\n",geo_datum); // not used now... + + if (geo_projection[0] == '\0') + strcpy(geo_projection,"LatLon"); // default + //fprintf(stderr,"Map Projection: %s\n",geo_projection); + (void)to_upper(geo_projection); + if (strcmp(geo_projection,"TM") == 0) + map_proj = 1; // Transverse Mercator + else + map_proj = 0; // Lat/Lon, default + + + #ifdef HAVE_IMAGEMAGICK + if (terraserver_flag || toposerver_flag) { + //http://terraservice.net/download.ashx?t=1&s=10&x=2742&y=26372&z=10&w=820&h=480 + if (scale_y <= 4) { + t_zoom = 10; // 1m + t_scale = 200; + } + else if (scale_y <= 8) { + t_zoom = 11; // 2m + t_scale = 400; + } + else if (scale_y <= 16) { + t_zoom = 12; // 4m + t_scale = 800; + } + else if (scale_y <= 32) { + t_zoom = 13; // 8m + t_scale = 1600; + } + else if (scale_y <= 64) { + t_zoom = 14; // 16m + t_scale = 3200; + } + else if (scale_y <= 128) { + t_zoom = 15; // 32m + t_scale = 6400; + } + else { + t_zoom = 16; // 64m + t_scale = 12800; + } + + top = -((y_lat_offset - 32400000l) / 360000.0); + left = (x_long_offset - 64800000l) / 360000.0; + ll_to_utm(gDatum[D_NAD_83_CONUS].ellipsoid, top, left, &top_n, &left_e, zstr, sizeof(zstr) ); + sscanf(zstr, "%d", &z); + + bottom = -(((y_lat_offset + (screen_height * scale_y)) - 32400000l) / 360000.0); + right = ((x_long_offset + (screen_width * scale_x)) - 64800000l) / 360000.0; + ll_to_utm(gDatum[D_NAD_83_CONUS].ellipsoid, bottom, right, &bottom_n, &right_e, zstr, sizeof(zstr) ); + + map_top_n = (int)((top_n / t_scale) + 1) * t_scale; + map_left_e = (int)((left_e / t_scale) + 0) * t_scale; + utm_to_ll(gDatum[D_NAD_83_CONUS].ellipsoid, map_top_n, map_left_e, zstr, &top, &left); + + geo_image_height = (map_top_n - bottom_n) * 200 / t_scale; + geo_image_width = (right_e - map_left_e) * 200 / t_scale; + map_width = right - left; + map_height = top - bottom; + + tp[0].img_x = 0; + tp[0].img_y = 0; + tp[0].x_long = 64800000l + (360000.0 * left); + tp[0].y_lat = 32400000l + (360000.0 * (-top)); + + tp[1].img_x = geo_image_width - 1; + tp[1].img_y = geo_image_height - 1; + tp[1].x_long = 64800000l + (360000.0 * right); + tp[1].y_lat = 32400000l + (360000.0 * (-bottom)); + + url_n = (int)(top_n / t_scale); // The request URL does not use the + url_e = (int)(left_e / t_scale); // N/E of the map corner + + xastir_snprintf(fileimg, sizeof(fileimg), + // "http://terraservice.net/download.ashx?t=%d\046s=%d\046x=%d\046y=%d\046z=%d\046w=%d\046h=%d", + "http://terraserver-usa.net/download.ashx?t=%d\046s=%d\046x=%d\046y=%d\046z=%d\046w=%d\046h=%d", + (toposerver_flag) ? 2 : 1, + t_zoom, + url_e, + url_n, + z, + geo_image_width, + geo_image_height); + } + #endif // HAVE_IMAGEMAGICK + + // + // DK7IN: we should check what we got from the geo file + // we use geo_image_width, but it might not be initialised... + // and it's wrong if the '\n' is missing a the end... + + /* + * Here are the corners of our viewport, using the Xastir + * coordinate system. Notice that Y is upside down: + * + * left edge of view = x_long_offset + * right edge of view = x_long_offset + (screen_width * scale_x) + * top edge of view = y_lat_offset + * bottom edge of view = y_lat_offset + (screen_height * scale_y) + * + * The corners of our map will soon be (after translating the + * tiepoints to the corners if they're not already there): + * + * left edge of map = tp[0].x_long in Xastir format + * right edge of map = tp[1].x_long + * top edge of map = tp[0].y_lat + * bottom edge of map = tp[1].y_lat + * + */ + map_c_L = tp[0].x_long - x_long_offset; // map left coordinate + map_c_T = tp[0].y_lat - y_lat_offset; // map top coordinate + + tp_c_dx = (long)(tp[1].x_long - tp[0].x_long);// Width between tiepoints + tp_c_dy = (long)(tp[1].y_lat - tp[0].y_lat); // Height between tiepoints + + + // Check for tiepoints being in wrong relation to one another + if (tp_c_dx < 0) tp_c_dx = -tp_c_dx; // New width between tiepoints + if (tp_c_dy < 0) tp_c_dy = -tp_c_dy; // New height between tiepoints + + + if (debug_level & 512) { + fprintf(stderr,"X tiepoint width: %ld\n", tp_c_dx); + fprintf(stderr,"Y tiepoint width: %ld\n", tp_c_dy); + } + + // Calculate step size per pixel + map_c_dx = ((double) tp_c_dx / abs(tp[1].img_x - tp[0].img_x)); + map_c_dy = ((double) tp_c_dy / abs(tp[1].img_y - tp[0].img_y)); + + // Scaled screen step size for use with XFillRectangle below + scr_dx = (int) (map_c_dx / scale_x) + 1; + scr_dy = (int) (map_c_dy / scale_y) + 1; + + if (debug_level & 512) { + fprintf(stderr,"\nImage: %s\n", file); + fprintf(stderr,"Image size %d %d\n", geo_image_width, geo_image_height); + fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n", map_c_L, map_c_T, map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y)); + } + + // calculate top left map corner from tiepoints + if (tp[0].img_x != 0) { + tp[0].x_long -= (tp[0].img_x * map_c_dx); // map left edge longitude + map_c_L = tp[0].x_long - x_long_offset; // delta ?? + tp[0].img_x = 0; + if (debug_level & 512) + fprintf(stderr,"Translated tiepoint_0 x: %d\t%lu\n", tp[0].img_x, tp[0].x_long); + } + if (tp[0].img_y != 0) { + tp[0].y_lat -= (tp[0].img_y * map_c_dy); // map top edge latitude + map_c_T = tp[0].y_lat - y_lat_offset; + tp[0].img_y = 0; + if (debug_level & 512) + fprintf(stderr,"Translated tiepoint_0 y: %d\t%lu\n", tp[0].img_y, tp[0].y_lat); + } + + // By this point, geo_image_width & geo_image_height have to + // have been initialized to something. + + if ( (geo_image_width == 0) || (geo_image_height == 0) ) { + + if ( (strncasecmp ("http", fileimg, 4) == 0) + || (strncasecmp ("ftp", fileimg, 3) == 0)) { + // what to do for remote files... hmm... -cbell + } else { + + #ifdef HAVE_IMAGEMAGICK + GetExceptionInfo(&exception); + image_info=CloneImageInfo((ImageInfo *) NULL); + (void) strcpy(image_info->filename, fileimg); + if (debug_level & 16) { + fprintf(stderr,"Copied %s into image info.\n", file); + fprintf(stderr,"image_info got: %s\n", image_info->filename); + fprintf(stderr,"Entered ImageMagick code.\n"); + fprintf(stderr,"Attempting to open: %s\n", image_info->filename); + } + + // We do a test read first to see if the file exists, so we + // don't kill Xastir in the ReadImage routine. + f = fopen (image_info->filename, "r"); + if (f == NULL) { + fprintf(stderr,"File %s could not be read\n",image_info->filename); + return; + } + (void)fclose (f); + + image = PingImage(image_info, &exception); + + if (image == (Image *) NULL) { + MagickWarning(exception.severity, exception.reason, exception.description); + //fprintf(stderr,"MagickWarning\n"); + return; + } + + if (debug_level & 16) + fprintf(stderr,"Color depth is %i \n", (int)image->depth); + + geo_image_width = image->magick_columns; + geo_image_height = image->magick_rows; + + // close and clean up imagemagick + + if (image) + DestroyImage(image); + if (image_info) + DestroyImageInfo(image_info); + #endif // HAVE_IMAGEMAGICK + } + } + + // fprintf(stderr, "Geo: %s: size %ux%u.\n",file, geo_image_width, geo_image_height); + // if that did not generate a valid size, bail out... + if ( (geo_image_width == 0) || (geo_image_height == 0) ) { + fprintf(stderr,"*** Skipping '%s', IMAGESIZE tag missing or incorrect. ***\n",file); + fprintf(stderr,"Perhaps no XPM or ImageMagick library support is installed?\n"); + return; + } + // calculate bottom right map corner from tiepoints + // map size is geo_image_width / geo_image_height + if (tp[1].img_x != (geo_image_width - 1) ) { + tp[1].img_x = geo_image_width - 1; + tp[1].x_long = tp[0].x_long + (tp[1].img_x * map_c_dx); // right + if (debug_level & 512) + fprintf(stderr,"Translated tiepoint_1 x: %d\t%lu\n", tp[1].img_x, tp[1].x_long); + } + if (tp[1].img_y != (geo_image_height - 1) ) { + tp[1].img_y = geo_image_height - 1; + tp[1].y_lat = tp[0].y_lat + (tp[1].img_y * map_c_dy); // bottom + if (debug_level & 512) + fprintf(stderr,"Translated tiepoint_1 y: %d\t%lu\n", tp[1].img_y, tp[1].y_lat); + } + + + // Check whether we're indexing or drawing the map + if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS) + || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) { + xastir_snprintf(map_it, sizeof(map_it), langcode ("BBARSTA039"), filenm); + } + else { + xastir_snprintf(map_it, sizeof(map_it), langcode ("BBARSTA028"), filenm); + } + statusline(map_it,0); // Loading/Indexing ... + + + // Check whether we're indexing or drawing the map + if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS) + || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) { + + // We're indexing only. Save the extents in the index. + if (terraserver_flag || toposerver_flag) { + // Force the extents to the edges of the earth for the + // index file. + index_update_xastir(filenm, // Filename only + 64800000l, // Bottom + 0l, // Top + 0l, // Left + 129600000l); // Right + } + else { + index_update_xastir(filenm, // Filename only + tp[1].y_lat, // Bottom + tp[0].y_lat, // Top + tp[0].x_long, // Left + tp[1].x_long); // Right + } + + return; // Done indexing this file + } + + + // Check whether map is inside our current view + // bottom top left right + if (!map_visible (tp[1].y_lat, tp[0].y_lat, tp[0].x_long, tp[1].x_long)) { + if (debug_level & 16) { + fprintf(stderr,"Map not in current view, skipping: %s\n", file); + fprintf(stderr,"\nImage: %s\n", file); + fprintf(stderr,"Image size %d %d\n", geo_image_width, geo_image_height); + fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n", map_c_L, map_c_T, map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y)); + } + return; /* Skip this map */ + } else if (debug_level & 16) { + fprintf(stderr,"Loading imagemap: %s\n", file); + fprintf(stderr,"\nImage: %s\n", file); + fprintf(stderr,"Image size %d %d\n", geo_image_width, geo_image_height); + fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n", map_c_L, map_c_T, map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y)); + } + + + atb.valuemask = 0; + + + // Best here would be to add the process ID or user ID to the filename + // (to keep the filename distinct for different users), and to check + // the timestamp on the map file. If it's older than xx minutes, go + // get another one. Make sure to delete the temp files when closing + // Xastir. It'd probably be good to check for old files and delete + // them when starting Xastir as well. + + // Check to see if we have to use "wget" to go get an internet map + if ( (strncasecmp ("http", fileimg, 4) == 0) + || (strncasecmp ("ftp", fileimg, 3) == 0) + || (terraserver_flag) + || (toposerver_flag) ) { + #ifdef HAVE_IMAGEMAGICK + char *ext; + + if (debug_level & 16) + fprintf(stderr,"ftp or http file: %s\n", fileimg); + + if (terraserver_flag || toposerver_flag) + ext = "jpg"; + else + ext = get_map_ext(fileimg); // Use extension to determine image type + + xastir_snprintf(local_filename, sizeof(local_filename), "/var/tmp/xastir_%s_map.%s", + username,ext); + + #ifdef HAVE_LIBCURL + curl = curl_easy_init(); + + if (curl) { + + /* verbose debug is keen */ + // curl_easy_setopt(curl, CURLOPT_VERBOSE, TRUE); + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curlerr); + + /* write function */ + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_fwrite); + + /* download from fileimg */ + curl_easy_setopt(curl, CURLOPT_URL, fileimg); + + /* save as local_filename */ + ftpfile.filename = local_filename; + ftpfile.stream = NULL; + curl_easy_setopt(curl, CURLOPT_FILE, &ftpfile); + + res = curl_easy_perform(curl); + + curl_easy_cleanup(curl); + + if (CURLE_OK != res) { + fprintf(stderr, "curl told us %d\n", res); + fprintf(stderr, "curlerr is %s\n", curlerr); + } + + if (ftpfile.stream) + fclose(ftpfile.stream); + + // Return if we had trouble + if (CURLE_OK != res) { + return; + } + + } else { + fprintf(stderr,"Couldn't download the geo or Terraserver image\n"); + return; + } + + + #else + #ifdef HAVE_WGET + xastir_snprintf(tempfile, sizeof(tempfile), + "%s --server-response --timestamping --tries=1 --timeout=30 --output-document=%s \'%s\' 2> /dev/null\n", + WGET_PATH, + local_filename, + fileimg); + + if (debug_level & 16) + fprintf(stderr,"%s",tempfile); + + //fprintf(stderr,"Getting file\n"); + if ( system(tempfile) ) { // Go get the file + fprintf(stderr,"Couldn't download the geo or Terraserver image\n"); + return; + } + #else // HAVE_WGET + fprintf(stderr,"libcurl or 'wget' not installed. Can't download image\n"); + #endif // HAVE_WGET + #endif // HAVE_LIBCURL + + // Set permissions on the file so that any user can overwrite it. + chmod(local_filename, 0666); + + // We now re-use the "file" variable. It'll hold the + //name of the map file now instead of the .geo file. + strcpy(file,local_filename); // Tell ImageMagick where to find it + #endif // HAVE_IMAGEMAGICK + + } else { + //fprintf(stderr,"Not ftp or http file\n"); + + // We now re-use the "file" variable. It'll hold the + //name of the map file now instead of the .geo file. + strcpy (file, fileimg); + } + + //fprintf(stderr,"File = %s\n",file); + + + // The status line is not updated yet, probably 'cuz we're too busy + // getting the map in this thread and aren't redrawing? + + + #ifdef HAVE_IMAGEMAGICK + GetExceptionInfo(&exception); + image_info=CloneImageInfo((ImageInfo *) NULL); + (void) strcpy(image_info->filename, file); + if (debug_level & 16) { + fprintf(stderr,"Copied %s into image info.\n", file); + fprintf(stderr,"image_info got: %s\n", image_info->filename); + fprintf(stderr,"Entered ImageMagick code.\n"); + fprintf(stderr,"Attempting to open: %s\n", image_info->filename); + } + + // We do a test read first to see if the file exists, so we + // don't kill Xastir in the ReadImage routine. + f = fopen (image_info->filename, "r"); + if (f == NULL) { + fprintf(stderr,"File %s could not be read\n",image_info->filename); + return; + } + (void)fclose (f); + + image = ReadImage(image_info, &exception); + + if (image == (Image *) NULL) { + MagickWarning(exception.severity, exception.reason, exception.description); + //fprintf(stderr,"MagickWarning\n"); + return; + } + + if (debug_level & 16) + fprintf(stderr,"Color depth is %i \n", (int)image->depth); + + if (image->colorspace != RGBColorspace) { + puts("TBD: I don't think we can deal with colorspace != RGB"); + if (image) + DestroyImage(image); + if (image_info) + DestroyImageInfo(image_info); + return; + } + + atb.width = image->columns; + atb.height = image->rows; + + + // gamma setup + if (imagemagick_options.gamma_flag == 0 || + imagemagick_options.gamma_flag == 1) { + if (imagemagick_options.gamma_flag == 0) // if not set in file, set to 1.0 + imagemagick_options.r_gamma = 1.0; + + imagemagick_options.gamma_flag = 1; // set flag to do gamma + + imagemagick_options.r_gamma += imagemagick_gamma_adjust; + + if (imagemagick_options.r_gamma > 0.95 && imagemagick_options.r_gamma < 1.05) + imagemagick_options.gamma_flag = 0; // don't bother if near 1.0 + else if (imagemagick_options.r_gamma < 0.1) + imagemagick_options.r_gamma = 0.1; // 0.0 is black and negative is really wacky + + xastir_snprintf(gamma, sizeof(gamma), "%.1f", imagemagick_options.r_gamma); + } + else if (imagemagick_options.gamma_flag == 3) { + // No checking if you specify 3 channel gamma correction, so you can try negative + // numbers, etc. if you wish. + imagemagick_options.gamma_flag = 1; // set flag to do gamma + imagemagick_options.r_gamma += imagemagick_gamma_adjust; + imagemagick_options.g_gamma += imagemagick_gamma_adjust; + imagemagick_options.b_gamma += imagemagick_gamma_adjust; + xastir_snprintf(gamma, sizeof(gamma), "%.1f,%.1f,%.1f", + imagemagick_options.r_gamma, + imagemagick_options.g_gamma, + imagemagick_options.b_gamma); + } + else + imagemagick_options.gamma_flag = 0; + + if (imagemagick_options.gamma_flag) { + if (debug_level & 16) + fprintf(stderr,"gamma=%s\n", gamma); + GammaImage(image, gamma); + } + + if (imagemagick_options.contrast != 0) { + if (debug_level & 16) + fprintf(stderr,"contrast=%d\n", imagemagick_options.contrast); + ContrastImage(image, imagemagick_options.contrast); + } + + if (imagemagick_options.negate != -1) { + if (debug_level & 16) + fprintf(stderr,"negate=%d\n", imagemagick_options.negate); + NegateImage(image, imagemagick_options.negate); + } + + if (imagemagick_options.equalize) { + if (debug_level & 16) + puts("equalize"); + EqualizeImage(image); + } + + if (imagemagick_options.normalize) { + if (debug_level & 16) + puts("normalize"); + NormalizeImage(image); + } + + #if (MagickLibVersion >= 0x0539) + if (imagemagick_options.level[0] != '\0') { + if (debug_level & 16) + fprintf(stderr,"level=%s\n", imagemagick_options.level); + LevelImage(image, imagemagick_options.level); + } + #endif // MagickLibVersion >= 0x0539 + + if (imagemagick_options.modulate[0] != '\0') { + if (debug_level & 16) + fprintf(stderr,"modulate=%s\n", imagemagick_options.modulate); + ModulateImage(image, imagemagick_options.modulate); + } + + // If were are drawing to a low bpp display (typically < 8bpp) + // try to reduce the number of colors in an image. + // This may take some time, so it would be best to do ahead of + // time if it is a static image. + #if (MagickLibVersion < 0x0540) + if (visual_type == NOT_TRUE_NOR_DIRECT && GetNumberColors(image, NULL) > 128) { + #else // MagickLib >= 540 + if (visual_type == NOT_TRUE_NOR_DIRECT && GetNumberColors(image, NULL, &exception) > 128) { + #endif // MagickLib Version + + if (image->storage_class == PseudoClass) { + #if (MagickLibVersion < 0x0549) + CompressColormap(image); // Remove duplicate colors + #else // MagickLib >= 0x0549 + CompressImageColormap(image); // Remove duplicate colors + #endif // MagickLibVersion < 0x0549 + } + + // Quantize down to 128 will go here... + } + + pixel_pack = GetImagePixels(image, 0, 0, image->columns, image->rows); + if (!pixel_pack) { + puts("pixel_pack == NULL!!!"); + if (image) + DestroyImage(image); + if (image_info) + DestroyImageInfo(image_info); + return; + } + + index_pack = GetIndexes(image); + if (image->storage_class == PseudoClass && !index_pack) { + puts("PseudoClass && index_pack == NULL!!!"); + if (image) + DestroyImage(image); + if (image_info) + DestroyImageInfo(image_info); + return; + } + + if (image->storage_class == PseudoClass && image->colors <= 256) { + for (l = 0; l < (int)image->colors; l++) { + // Need to check how to do this for ANY image, as ImageMagick can read in all sorts + // of image files + temp_pack = image->colormap[l]; + if (debug_level & 16) + fprintf(stderr,"Colormap color is %i %i %i \n", + temp_pack.red, temp_pack.green, temp_pack.blue); + + // Here's a tricky bit: PixelPacket entries are defined as Quantum's. Quantum + // is defined in /usr/include/magick/image.h as either an unsigned short or an + // unsigned char, depending on what "configure" decided when ImageMagick was installed. + // We can determine which by looking at MaxRGB or QuantumDepth. + // + if (QuantumDepth == 16) { // Defined in /usr/include/magick/image.h + if (debug_level & 16) + fprintf(stderr,"Color quantum is [0..65535]\n"); + my_colors[l].red = temp_pack.red; + my_colors[l].green = temp_pack.green; + my_colors[l].blue = temp_pack.blue; + } + else { // QuantumDepth = 8 + if (debug_level & 16) + fprintf(stderr,"Color quantum is [0..255]\n"); + my_colors[l].red = temp_pack.red << 8; + my_colors[l].green = temp_pack.green << 8; + my_colors[l].blue = temp_pack.blue << 8; + } + + // Get the color allocated on < 8bpp displays. pixel color is written to my_colors.pixel + if (visual_type == NOT_TRUE_NOR_DIRECT) + XAllocColor(XtDisplay(w), cmap, &my_colors[l]); + else + pack_pixel_bits(my_colors[l].red, my_colors[l].green, my_colors[l].blue, + &my_colors[l].pixel); + + if (debug_level & 16) + fprintf(stderr,"Color allocated is %li %i %i %i \n", my_colors[l].pixel, + my_colors[l].red, my_colors[l].blue, my_colors[l].green); + } + } + + #ifdef TIMING_DEBUG + time_mark(0); + #endif // TIMING_DEBUG + + if (debug_level & 16) { + fprintf(stderr,"Image size %d %d\n", atb.width, atb.height); + #if (MagickLibVersion < 0x0540) + fprintf(stderr,"Unique colors = %d\n", GetNumberColors(image, NULL)); + #else // MagickLibVersion < 0x0540 + fprintf(stderr,"Unique colors = %ld\n", GetNumberColors(image, NULL, &exception)); + #endif // MagickLibVersion < 0x0540 + fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n", map_c_L, map_c_T, + map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y)); + + #if (MagickLibVersion < 0x0540) + fprintf(stderr,"is Gray Image = %i\n", IsGrayImage(image)); + fprintf(stderr,"is Monochrome Image = %i\n", IsMonochromeImage(image)); + //fprintf(stderr,"is Opaque Image = %i\n", IsOpaqueImage(image)); + //fprintf(stderr,"is PseudoClass = %i\n", image->storage_class == PseudoClass); + #else // MagickLibVersion < 0x0540 + fprintf(stderr,"is Gray Image = %i\n", IsGrayImage( image, &exception )); + fprintf(stderr,"is Monochrome Image = %i\n", IsMonochromeImage( image, &exception )); + //fprintf(stderr,"is Opaque Image = %i\n", IsOpaqueImage( image, &exception )); + //fprintf(stderr,"is PseudoClass = %i\n", image->storage_class == PseudoClass); + #endif // MagickLibVersion < 0x0540 + + fprintf(stderr,"image matte is %i\n", image->matte); + fprintf(stderr,"Colorspace = %i\n", image->colorspace); + if (image->colorspace == UndefinedColorspace) + fprintf(stderr,"Class Type = Undefined\n"); + else if (image->colorspace == RGBColorspace) + fprintf(stderr,"Class Type = RGBColorspace\n"); + else if (image->colorspace == GRAYColorspace) + fprintf(stderr,"Class Type = GRAYColorspace\n"); + else if (image->colorspace == sRGBColorspace) + fprintf(stderr,"Class Type = sRGBColorspace\n"); + } + + #else // HAVE_IMAGEMAGICK + + // We don't have ImageMagick libs compiled in, so use the + // XPM library instead. + + /* XpmReadFileToImage is the call we wish to avoid if at all + * possible. On large images this can take quite a while. We + * check above to see whether the image is inside our viewport, + * and if not we skip loading the image. + */ + if (! XpmReadFileToImage (XtDisplay (w), file, &xi, NULL, &atb) == XpmSuccess) { + fprintf(stderr,"ERROR loading %s\n", file); + if (xi) + XDestroyImage (xi); + return; + } + if (debug_level & 16) { + fprintf(stderr,"Image size %d %d\n", (int)atb.width, (int)atb.height); + fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n", map_c_L, map_c_T, map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y)); + } + + #endif // HAVE_IMAGEMAGICK + + // draw the image from the file out to the map screen + + // Get the border values for the X and Y for loops used + // for the XFillRectangle call later. + + map_c_yc = (tp[0].y_lat + tp[1].y_lat) / 2; // vert center of map as reference + map_y_ctr = (long)(atb.height / 2 +0.499); + scale_x0 = get_x_scale(0,map_c_yc,scale_y); // reference scaling at vert map center + + map_c_xc = (tp[0].x_long + tp[1].x_long) / 2; // hor center of map as reference + map_x_ctr = (long)(atb.width / 2 +0.499); + scr_x_mc = (map_c_xc - x_long_offset) / scale_x; // screen coordinates of map center + + // calculate map pixel range in y direction that falls into screen area + c_y_max = 0ul; + map_y_min = map_y_max = 0l; + for (map_y_0 = 0, c_y = tp[0].y_lat; map_y_0 < (long)atb.height; map_y_0++, c_y += map_c_dy) { + scr_y = (c_y - y_lat_offset) / scale_y; // current screen position + if (scr_y > 0) { + if (scr_y < screen_height) { + map_y_max = map_y_0; // update last map pixel in y + c_y_max = (unsigned long)c_y;// bottom map inside screen coordinate + } else + break; // done, reached bottom screen border + } else { // pixel is above screen + map_y_min = map_y_0; // update first map pixel in y + } + } + // fprintf(stderr,"map top: %ld bottom: %ld\n",tp[0].y_lat,tp[1].y_lat); + c_y_min = (unsigned long)(tp[0].y_lat + map_y_min * map_c_dy); // top map inside screen coordinate + + // // find the y coordinate nearest to the equator + // c_y = 90*60*60*100; // Equator + // if ((c_y_min>c_y && c_y_max>c_y) || (c_y_min abs(c_y_max-c_y)) + // c_y = c_y_max; // north + // else + // c_y = c_y_min; // south + // } + // scale_x0 = get_x_scale(0,(long)c_y,scale_y); // calc widest map area in x + + // if (map_proj != 1) { + // calculate map pixel range in x direction that falls into screen area + map_x_min = map_x_max = 0l; + for (map_x = 0, c_x = tp[0].x_long; map_x < (long)atb.width; map_x++, c_x += map_c_dx) { + scr_x = (c_x - x_long_offset)/ scale_x; // current screen position + if (scr_x > 0) { + if (scr_x < screen_width) + map_x_max = map_x; // update last map pixel in x + else + break; // done, reached right screen border + } else { // pixel is left from screen + map_x_min = map_x; // update first map pixel in x + } + } + c_x_min = (unsigned long)(tp[0].x_long + map_x_min * map_c_dx); // left map inside screen coordinate + // } + // for (scr_y = scr_y_min; scr_y <= scr_y_max;scr_y++) { // screen lines + // } + + test = 1; // DK7IN: debuging + scr_yp = -1; + scr_c_xr = x_long_offset + screen_width * scale_x; + c_dx = map_c_dx; // map pixel width + scale_xa = scale_x0; // the compiler likes it ;-) + + // for (map_y_0 = 0, c_y = tp[0].y_lat; map_y_0 < (long)atb.height; map_y_0++, c_y += map_c_dy) { + // scr_y = (c_y - y_lat_offset) / scale_y; // current screen position + + map_done = 0; + map_act = 0; + map_seen = 0; + scr_y = screen_height - 1; + + #ifdef TIMING_DEBUG + time_mark(0); + #endif // TIMING_DEBUG + // loop over map pixel rows + for (map_y_0 = map_y_min, c_y = (double)c_y_min; + (map_y_0 <= map_y_max) || (map_proj == 1 && !map_done && scr_y < screen_height); + map_y_0++, c_y += map_c_dy) { + scr_y = (c_y - y_lat_offset) / scale_y; + if (scr_y != scr_yp) { // don't do a row twice + scr_yp = scr_y; // remember as previous y + if (map_proj == 1) { // Transverse Mercator correction in x + scale_xa = get_x_scale(0,(long)c_y,scale_y); // recalc scale_x for current y + c_dx = map_c_dx * scale_xa / scale_x0; // adjusted map pixel width + + map_x_min = map_x_ctr - (map_c_xc - x_long_offset) / c_dx; + if (map_x_min < 0) + map_x_min = 0; + c_x_min = map_c_xc - (map_x_ctr - map_x_min) * c_dx; + map_x_max = map_x_ctr - (map_c_xc - scr_c_xr) / c_dx; + if (map_x_max > (long)atb.width) + map_x_max = atb.width; + scr_dx = (int) (c_dx / scale_x) + 1; // at least 1 pixel wide + } + + // if (c_y == (double)c_y_min) { // first call + // fprintf(stderr,"map: min %ld ctr %ld max %ld, c_dx %ld, c_x_min %ld, c_y_min %ld\n",map_x_min,map_x_ctr,map_x_max,(long)c_dx,c_x_min,c_y_min); + // } + scr_xp = -1; + // loop over map pixel columns + map_act = 0; + scale_x_nm = calc_dscale_x(0,(long)c_y) / 1852.0; // nm per Xastir coordinate + for (map_x = map_x_min, c_x = (double)c_x_min; map_x <= map_x_max; map_x++, c_x += c_dx) { + scr_x = (c_x - x_long_offset) / scale_x; + if (scr_x != scr_xp) { // don't do a pixel twice + scr_xp = scr_x; // remember as previous x + if (map_proj == 1) { // Transverse Mercator correction in y + // DK7IN-- + dist = (90*60 - (c_y / 6000.0)); // equator distance in nm + // ?? 180W discontinuity! not done yet + ew_ofs = (c_x - (double)map_c_xc) * scale_x_nm; // EW offset from center in nm + //corrfact = (map_y_0 - map_y_ctr)/(2*map_y_ctr); // 0..50% + //corrfact = fabs(ew_ofs/dist)*3.0; + //corrfact = 1.0-1.0*(0.5*map_y_0 / map_y_ctr); + corrfact = 1.0; + c_y_a = (fabs(dist) - sqrt((double)(dist*dist - ew_ofs*ew_ofs)))*6000.0; // in Xastir units + if (dist < 0) // S + map_y = map_y_0 + (long)(corrfact*c_y_a / map_c_dy); // coord per pixel + else // N + map_y = map_y_0 - (long)(corrfact*c_y_a / map_c_dy); + // if (test < 10) { + // fprintf(stderr,"dist: %ldkm, ew_ofs: %ldkm, dy: %ldkm\n",(long)(1.852*dist),(long)(1.852*ew_ofs),(long)(1.852*c_y_a/6000.0)); + // fprintf(stderr," corrfact: %f, mapy0: %ld, mapy: %ld\n",corrfact,map_y_0,map_y); + // test++; + // } + } else { + map_y = map_y_0; + } + + if (map_y >= 0 && map_y <= tp[1].img_y) { // check map boundaries in y direction + map_seen = 1; + map_act = 1; // detects blank screen rows (end of map) + + // DK7IN-- + + //----- copy pixel from map to screen --------------------- + // if (c_y == (double)c_y_min && (scr_x < 5 || (c_x == (double)c_x_min))) { // first call + // fprintf(stderr,"map: x %ld y %ld scr: x %ld y %ld dx %d, dy %d\n",map_x,map_y,scr_x,scr_y,scr_dx,scr_dy); + // fprintf(stderr,"color: %ld\n",XGetPixel (xi, map_x, map_y)); + // // 65529 + // } + + // now copy a pixel from the map image to the screen + #ifdef HAVE_IMAGEMAGICK + l = map_x + map_y * image->columns; + if (image->storage_class == PseudoClass) { + XSetForeground(XtDisplay(w), gc, my_colors[index_pack[l]].pixel); + } + else { + pack_pixel_bits(pixel_pack[l].red, + pixel_pack[l].green, + pixel_pack[l].blue, + &my_colors[0].pixel); + XSetForeground(XtDisplay(w), gc, my_colors[0].pixel); + } + #else // HAVE_IMAGEMAGICK + (void)XSetForeground (XtDisplay (w), gc, XGetPixel (xi, map_x, map_y)); + #endif // HAVE_IMAGEMAGICK + (void)XFillRectangle (XtDisplay (w),pixmap,gc,scr_x,scr_y,scr_dx,scr_dy); + } // check map boundaries in y direction + } + } // loop over map pixel columns + if (map_seen && !map_act) + map_done = 1; + } + } // loop over map pixel rows + + #ifdef HAVE_IMAGEMAGICK + if (image) + DestroyImage(image); + if (image_info) + DestroyImageInfo(image_info); + #else // HAVE_IMAGEMAGICK + if (xi) + XDestroyImage (xi); + #endif // HAVE_IMAGEMAGICK + + #ifdef TIMING_DEBUG + time_mark(0); + #endif // TIMING_DEBUG + } + diff -c -r -N xastir-1.2.0/src/map_gnis.c xastir-1.2.0-p/src/map_gnis.c *** xastir-1.2.0/src/map_gnis.c 1969-12-31 19:00:00.000000000 -0500 --- xastir-1.2.0-p/src/map_gnis.c 2003-06-21 13:45:20.000000000 -0400 *************** *** 0 **** --- 1,1208 ---- + /* -*- c-basic-indent: 4; indent-tabs-mode: nil -*- + * $Id: map_gnis.c,v 1.1 2003/06/21 17:45:20 alan Exp $ + * + * XASTIR, Amateur Station Tracking and Information Reporting + * Copyright (C) 1999,2000 Frank Giannandrea + * Copyright (C) 2000-2003 The Xastir Group + * + * 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-1307, USA. + * + * Look at the README for more information on the program. + * + * + * Please see separate copyright notice attached to the + * SHPRingDir_2d() function in this file. + * + */ + #include "config.h" + #include "snprintf.h" + + #include + #include + #include + #include + #include + #include + #include + #include + + // Needed for Solaris + #include + + #include + #include + #include + + #ifdef HAVE_X11_XPM_H + #include + #ifdef HAVE_LIBXPM // if we have both, prefer the extra library + #undef HAVE_XM_XPMI_H + #endif // HAVE_LIBXPM + #endif // HAVE_X11_XPM_H + + #ifdef HAVE_XM_XPMI_H + #include + #endif // HAVE_XM_XPMI_H + + #include + + #include + + #include "xastir.h" + #include "maps.h" + #include "alert.h" + #include "util.h" + #include "main.h" + #include "datum.h" + #include "draw_symbols.h" + #include "rotated.h" + #include "color.h" + #include "xa_config.h" + + #define CHECKMALLOC(m) if (!m) { fprintf(stderr, "***** Malloc Failed *****\n"); exit(0); } + + //NOTE: This function has a problem if a non-gnis file is labeled + //with a ".gnis" extension. It causes a segfault in Xastir. More + //error checking needs to be done in order to prevent this. + + // draw_gnis_map() + // + // Allows drawing a background map of labels for the viewport. + // Example format: + // "WA","Abbey View Memorial Park","cemetery","Snohomish","53","061","474647N","1221650W","47.77972","-122.28056","","","","","420","","Edmonds East" + // + // These types of files are available from http://geonames.usgs.gov/ + // under "Download State Gazetteer Data - Available Via Anonymous FTP". + // A typical filename would be: "WA.deci.gz". Do not get the other + // types of files which are columnar. The files that we parse are + // comma-delimited and have quotes around each field. + + // Some of the files have quotes around some fields, but not others, + // and some have an extreme amount of spaces at the end of each + // line. Some also have spaces, after a field but before a comma. + // + // Another difference just found: Some files have quotes around all + // fields, some have quotes around only some. We need to handle + // this gracefully. + // + void draw_gnis_map (Widget w, + char *dir, + char *filenm, + alert_entry *alert, + u_char alert_color, + int destination_pixmap, + int draw_filled) + { + char file[MAX_FILENAME]; // Complete path/name of GNIS file + FILE *f; // Filehandle of GNIS file + char line[MAX_FILENAME]; // One line of text from file + char *i, *j, *k; + char state[50]; + char name[200]; + char type[100]; + char county[100]; + char latitude[15]; + char longitude[15]; + char population[15]; + char lat_dd[3]; + char lat_mm[3]; + char lat_ss[3]; + char lat_dir[2]; + char long_dd[4]; + char long_mm[3]; + char long_ss[3]; + char long_dir[2]; + char lat_str[15]; + char long_str[15]; + int temp1; + long coord_lon, coord_lat; + long min_lat, min_lon, max_lat, max_lon; + int ok; + long x,y; + char symbol_table, symbol_id, symbol_over; + unsigned long bottom_extent = 0l; + unsigned long top_extent = 0l; + unsigned long left_extent = 0l; + unsigned long right_extent = 0l; + char status_text[MAX_FILENAME]; + + + //fprintf(stderr,"draw_gnis_map starting: %s/%s\n",dir,filenm); + + xastir_snprintf(file, sizeof(file), "%s/%s", dir, filenm); + + // Screen view + min_lat = y_lat_offset + (long)(screen_height * scale_y); + max_lat = y_lat_offset; + min_lon = x_long_offset; + max_lon = x_long_offset + (long)(screen_width * scale_x); + + + // The map extents in the map index are checked in draw_map to + // see whether we should draw the map at all. + + + // Update the statusline for this map name + // Check whether we're indexing or drawing the map + if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS) + || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) { + xastir_snprintf(status_text, sizeof(status_text), langcode ("BBARSTA039"), filenm); + } + else { + xastir_snprintf(status_text, sizeof(status_text), langcode ("BBARSTA028"), filenm); + } + statusline(status_text,0); // Loading/Indexing ... + + + // Attempt to open the file + f = fopen (file, "r"); + if (f != NULL) { + while (!feof (f)) { // Loop through entire file + + if ( get_line (f, line, MAX_FILENAME) ) { // Snag one line of data + if (strlen(line) > 0) { + + //NOTE: We handle running off the end of "line" + //via the "continue" statement. Skip the line + //if we don't find enough parameters while + //parsing. + + // Find State feature resides in + i = index(line,','); // Find ',' after state field + + if (i == NULL) { // Comma not found + continue; // Skip this line + } + + i[0] = '\0'; + strncpy(state,line,49); + clean_string(state); + + //NOTE: It'd be nice to take the part after the comma and put it before the rest + // of the text someday, i.e. "Cassidy, Lake". + + // Find Name + j = index(i+1, ','); // Find ',' after Name. Note that there may be commas in the name. + + if (j == NULL) { // Comma not found + continue; // Skip this line + } + + while ( (j != NULL) && (j[1] != '\"') ) { + k = j; + j = index(k+1, ','); + } + + if (j == NULL) { // Comma not found + continue; // Skip this line + } + + j[0] = '\0'; + strncpy(name,i+1,199); + clean_string(name); + + // Find Type + i = index(j+1, ','); + + if (i == NULL) { // Comma not found + continue; // Skip this line + } + + i[0] = '\0'; + strncpy(type,j+1,99); + clean_string(type); + + // Find County // Can there be commas in the county name? + j = index(i+1, ','); + + if (j == NULL) { // Comma not found + continue; // Skip this line + } + + j[0] = '\0'; + strncpy(county,i+1,99); + clean_string(county); + + // Find ? + i = index(j+1, ','); + + if (i == NULL) { // Comma not found + continue; // Skip this line + } + + i[0] = '\0'; + + // Find ? + j = index(i+1, ','); + + if (j == NULL) { // Comma not found + continue; // Skip this line + } + + j[0] = '\0'; + + // Find latitude (DDMMSSN) + i = index(j+1, ','); + + if (i == NULL) { // Comma not found + continue; // Skip this line + } + + i[0] = '\0'; + strncpy(latitude,j+1,14); + clean_string(latitude); + + // Find longitude (DDDMMSSW) + j = index(i+1, ','); + + if (j == NULL) { // Comma not found + continue; // Skip this line + } + + j[0] = '\0'; + strncpy(longitude,i+1,14); + clean_string(longitude); + + // Find another latitude + i = index(j+1, ','); + + if (i == NULL) { // Comma not found + continue; // Skip this line + } + + i[0] = '\0'; + + // Find another longitude + j = index(i+1, ','); + + if (j == NULL) { // Comma not found + continue; // Skip this line + } + + j[0] = '\0'; + + // Find ? + i = index(j+1, ','); + + if (i == NULL) { // Comma not found + continue; // Skip this line + } + + i[0] = '\0'; + + // Find ? + j = index(i+1, ','); + + if (j == NULL) { // Comma not found + continue; // Skip this line + } + + j[0] = '\0'; + + // Find ? + i = index(j+1, ','); + + if (i == NULL) { // Comma not found + continue; // Skip this line + } + + i[0] = '\0'; + + // Find ? + j = index(i+1, ','); + + if (j == NULL) { // Comma not found + continue; // Skip this line + } + + j[0] = '\0'; + + // Find altitude + i = index(j+1, ','); + + if (i == NULL) { // Comma not found + continue; // Skip this line + } + + i[0] = '\0'; + + // Find population + j = index(i+1, ','); + + if (j == NULL) { // Comma not found + continue; // Skip this line + } + + if ( j != NULL ) { + j[0] = '\0'; + strncpy(population,i+1,14); + } else { + strncpy(population,"0",14); + } + clean_string(population); + + lat_dd[0] = latitude[0]; + lat_dd[1] = latitude[1]; + lat_dd[2] = '\0'; + + lat_mm[0] = latitude[2]; + lat_mm[1] = latitude[3]; + lat_mm[2] = '\0'; + + lat_ss[0] = latitude[4]; + lat_ss[1] = latitude[5]; + lat_ss[2] = '\0'; + + lat_dir[0] = latitude[6]; + lat_dir[1] = '\0'; + + long_dd[0] = longitude[0]; + long_dd[1] = longitude[1]; + long_dd[2] = longitude[2]; + long_dd[3] = '\0'; + + long_mm[0] = longitude[3]; + long_mm[1] = longitude[4]; + long_mm[2] = '\0'; + + long_ss[0] = longitude[5]; + long_ss[1] = longitude[6]; + long_ss[2] = '\0'; + + long_dir[0] = longitude[7]; + long_dir[1] = '\0'; + + // Now must convert from DD MM SS format to DD MM.MM format so that we + // can run it through our conversion routine to Xastir coordinates. + (void)sscanf(lat_ss, "%d", &temp1); + temp1 = (int)((temp1 / 60.0) * 100 + 0.5); // Poor man's rounding + xastir_snprintf(lat_str, sizeof(lat_str), "%s%s.%02d%s", lat_dd, + lat_mm, temp1, lat_dir); + coord_lat = convert_lat_s2l(lat_str); + + (void)sscanf(long_ss, "%d", &temp1); + temp1 = (int)((temp1 / 60.0) * 100 + 0.5); // Poor man's rounding + xastir_snprintf(long_str, sizeof(long_str), "%s%s.%02d%s", long_dd, + long_mm, temp1, long_dir); + coord_lon = convert_lon_s2l(long_str); + + + // Save the min/max extents of the file. We + // should really initially set the extents to + // the min/max for the Xastir coordinate system, + // but in practice zeroes should work just as + // well. + if ((coord_lat > (long)bottom_extent) || (bottom_extent == 0l)) + bottom_extent = coord_lat; + if ((coord_lat < (long)top_extent) || (top_extent == 0l)) + top_extent = coord_lat; + if ((coord_lon < (long)left_extent) || (left_extent == 0l)) + left_extent = coord_lon; + if ((coord_lon > (long)right_extent) || (right_extent == 0l)) + right_extent = coord_lon; + + + // Check whether we're indexing the map + if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS) + || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) { + // Do nothing, we're indexing, not drawing + } + // Now check whether this lat/lon is within our viewport. If it + // is, draw a text label at that location. + else if (coord_lon >= min_lon && coord_lon <= max_lon + && coord_lat <= min_lat && coord_lat >= max_lat) { + + if (debug_level & 16) { + fprintf(stderr,"%s\t%s\t%s\t%s\t%s\t%s\t\t", + state, name, type, county, latitude, longitude); + fprintf(stderr,"%s %s %s %s\t%s %s %s %s\t\t", + lat_dd, lat_mm, lat_ss, lat_dir, long_dd, long_mm, long_ss, long_dir); + fprintf(stderr,"%s\t%s\n", lat_str, long_str); + } + + // Convert to screen coordinates. Careful + // here! The format conversions you'll need + // if you try to compress this into two + // lines will get you into trouble. + x = coord_lon - x_long_offset; + y = coord_lat - y_lat_offset; + x = x / scale_x; + y = y / scale_y; + + ok = 1; + if (x > 16000) ok = 0; // Skip this point + if (x < -16000) ok = 0; // Skip this point + if (y > 16000) ok = 0; // Skip this point + if (y < -16000) ok = 0; // Skip this point + + /* set default symbol */ + symbol_table = '/'; + symbol_id = '.'; /* small x */ + symbol_over = ' '; + + if (strcasecmp(type,"airport") == 0) { + symbol_id = '^'; + if (scale_y > 100) + ok = 0; + } + else if (strcasecmp(type,"arch") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"area") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"arroyo") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"bar") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"basin") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"bay") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"beach") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"bench") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"bend") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"bridge") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"building") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"canal") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"cape") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"cave") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"cemetery") == 0) { + symbol_table = '\\'; + symbol_id = '+'; + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"census") == 0) { + /* if (scale_y > 50)*/ /* Census divisions */ + ok = 0; + } + else if (strcasecmp(type,"channel") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"church") == 0) { + symbol_table = '\\'; + symbol_id = '+'; + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"civil") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"cliff") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"crater") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"crossing") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"dam") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"falls") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"flat") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"forest") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"gap") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"geyser") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"glacier") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"gut") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"harbor") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"hospital") == 0) { + symbol_id = 'h'; + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"island") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"isthmus") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"lake") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"lava") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"levee") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"locale") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"military") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"mine") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"oilfield") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"other") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"park") == 0) { + symbol_table = '\\'; + symbol_id = ';'; + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"pillar") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"plain") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"po") == 0) { + symbol_id = ']'; + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"ppl") == 0) { + symbol_id = '/'; + if (scale_y > 20000) // Don't draw cities at zoom higher than 20,000 + ok = 0; + else if (scale_y > 4000) { // Don't draw cities of less than 20,000 + if (atoi(population) < 50000) { + ok = 0; + } + } + else if (scale_y > 1500) { // Don't draw cities of less than 10,000 + if (atoi(population) < 20000) { + ok = 0; + } + } + else if (scale_y > 750) { // Don't draw cities of less than 5,000 + if (atoi(population) < 10000) { + ok = 0; + } + } + else if (scale_y > 200) { // Don't draw cities of less than 1,000 + if (atoi(population) < 1000) { + ok = 0; + //fprintf(stderr,"Name: %s\tPopulation: %s\n",name,population); + } + } + } + else if (strcasecmp(type,"range") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"rapids") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"reserve") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"reservoir") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"ridge") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"school") == 0) { + symbol_id = 'K'; + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"sea") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"slope") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"spring") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"stream") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"summit") == 0) { + if (scale_y > 100) + ok = 0; + } + else if (strcasecmp(type,"swamp") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"trail") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"tower") == 0) { + symbol_id = 'r'; + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"tunnel") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"valley") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"well") == 0) { + if (scale_y > 50) + ok = 0; + } + else if (strcasecmp(type,"woods") == 0) { + if (scale_y > 50) + ok = 0; + } + else { + fprintf(stderr,"Something unusual found, Type:%s\tState:%s\tCounty:%s\tName:%s\n", + type,state,county,name); + } + + if (ok == 1) { // If ok to draw it + symbol(w, 0, symbol_table, symbol_id, symbol_over, pixmap, 1, x-10, y-10, ' '); + draw_nice_string(w, pixmap, 0, x+10, y+5, (char*)name, 0xf, 0x10, strlen(name)); + } + + } + else { + //fprintf(stderr,"Not in viewport. Coordinates: %ld %ld\n",coord_lat,coord_lon); + //fprintf(stderr,"Min/Max Lat: %ld %ld\n",min_lat,max_lat); + //fprintf(stderr,"Min/Max Lon: %ld %ld\n",min_lon,max_lon); + } + } + } + } // End of while + (void)fclose (f); + + + // Check whether we're indexing the map + if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS) + || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) { + + // We're indexing only. Save the extents in the index. + index_update_xastir(filenm, // Filename only + bottom_extent, // Bottom + top_extent, // Top + left_extent, // Left + right_extent); // Right + } + } + else { + fprintf(stderr,"Couldn't open file: %s\n", file); + return; + } + if (debug_level & 16) + fprintf(stderr,"Exiting draw_gnis_map\n"); + } + + + + + + // Search for a placename among GNIS files + // + // We need to search a file in the map directory that has the filename + // STATE.gis, where STATE is from the "state" variable passed to us. + // Search for the placename/county/state/type that the user requested. + // Once found, center the map on that location or bring up a response + // dialog that asks whether one wants to go there, and that dialog + // provides info about the place found, with a possible selection + // out of a list of matches. + // Might also need to place a label at that position on the map in + // case that GNIS file isn't currently selected. + // + int locate_place( Widget w, char *name_in, char *state_in, char *county_in, + char *quad_in, char *type_in, char *filename_in, int follow_case, int get_match ) { + char file[MAX_FILENAME]; // Complete path/name of GNIS file + FILE *f; // Filehandle of GNIS file + char line[MAX_FILENAME]; // One line of text from file + char *i, *j, *k; + char state[50]; + char state_in2[50]; + char name[200]; + char name_in2[50]; + char type[100]; + char type_in2[50]; + char county[100]; + char county_in2[50]; + char quad[100]; + char quad_in2[100]; + char latitude[15]; + char longitude[15]; + char population[15]; + char lat_dd[3]; + char lat_mm[3]; + char lat_ss[3]; + char lat_dir[2]; + char long_dd[4]; + char long_mm[3]; + char long_ss[3]; + char long_dir[2]; + char lat_str[15]; + char long_str[15]; + int temp1; + long coord_lon, coord_lat; + int ok; + struct stat file_status; + + + strcpy(file,filename_in); + if (debug_level & 16) + fprintf(stderr,"File: %s\n",file); + + + strcpy(name_in2,name_in); + strcpy(state_in2,state_in); + strcpy(county_in2,county_in); + strcpy(quad_in2,quad_in); + strcpy(type_in2,type_in); + + + // Convert State/Province to upper-case always (they're + // always upper-case in the GNIS files from USGS. + to_upper(state_in2); + + + if (debug_level & 16) + fprintf(stderr,"Name:%s\tState:%s\tCounty:%s\tQuad:%s\tType:%s\n", + name_in,state_in2,county_in,quad_in,type_in); + + + // If "Match Case" togglebutton is not set, convert the + // rest of the keys to upper-case. + if (!follow_case) { + to_upper(name_in2); + to_upper(county_in2); + to_upper(quad_in2); + to_upper(type_in2); + } + + + // Check status of the file + if (stat(file, &file_status) < 0) { + popup_message( langcode("POPEM00028"), filename_in ); + return(0); + } + // Check for regular file + if (!S_ISREG(file_status.st_mode)) { + popup_message( langcode("POPEM00028"), filename_in ); + return(0); + } + // Attempt to open the file + f = fopen (file, "r"); + if (f != NULL) { + while (!feof (f)) { // Loop through entire file + if ( get_line (f, line, MAX_FILENAME) ) { // Snag one line of data + if (strlen(line) > 0) { + + + //NOTE: How do we handle running off the end of "line" while using "index"? + // Short lines here can cause segfaults. + + + // Find State feature resides in + i = index(line,','); // Find ',' after state + + if (i == NULL) { // Comma not found + continue; // Skip line + } + + i[0] = '\0'; + strncpy(state,line+1,49); + // state[strlen(state)-1] = '\0'; + clean_string(state); + + //NOTE: It'd be nice to take the part after the comma and put it before the rest + // of the text someday, i.e. "Cassidy, Lake". + // Find Name + j = index(i+1, ','); // Find ',' after Name. Note that there may be commas in the name. + + if (j == NULL) { // Comma not found + continue; // Skip line + } + + while ( (j != NULL) && (j[1] != '\"') ) { + k = j; + j = index(k+1, ','); + } + + if (j == NULL) { // Comma not found + continue; // Skip line + } + + j[0] = '\0'; + strncpy(name,i+2,199); + // name[strlen(name)-1] = '\0'; + clean_string(name); + + // Find Type + i = index(j+1, ','); + + if (i == NULL) { // Comma not found + continue; // Skip line + } + + i[0] = '\0'; + strncpy(type,j+2,99); + // type[strlen(type)-1] = '\0'; + clean_string(type); + + // Find County // Can there be commas in the county name? + j = index(i+1, ','); + + if (j == NULL) { // Comma not found + continue; // Skip line + } + + j[0] = '\0'; + strncpy(county,i+2,99); + // county[strlen(county)-1] = '\0'; + clean_string(county); + + // Find ? + i = index(j+1, ','); + + if (i == NULL) { // Comma not found + continue; // Skip line + } + + i[0] = '\0'; + + // Find ? + j = index(i+1, ','); + + if (j == NULL) { // Comma not found + continue; // Skip line + } + + j[0] = '\0'; + + // Find latitude (DDMMSSN) + i = index(j+1, ','); + + if (i == NULL) { // Comma not found + continue; // Skip line + } + + i[0] = '\0'; + strncpy(latitude,j+2,14); + // latitude[strlen(latitude)-1] = '\0'; + clean_string(latitude); + + // Find longitude (DDDMMSSW) + j = index(i+1, ','); + + if (j == NULL) { // Comma not found + continue; // Skip line + } + + j[0] = '\0'; + strncpy(longitude,i+2,14); + // longitude[strlen(longitude)-1] = '\0'; + clean_string(longitude); + + // Find another latitude + i = index(j+1, ','); + + if (i == NULL) { // Comma not found + continue; // Skip line + } + + i[0] = '\0'; + + // Find another longitude + j = index(i+1, ','); + + if (j == NULL) { // Comma not found + continue; // Skip line + } + + j[0] = '\0'; + + // Find ? + i = index(j+1, ','); + + if (i == NULL) { // Comma not found + continue; // Skip line + } + + i[0] = '\0'; + + // Find ? + j = index(i+1, ','); + + if (j == NULL) { // Comma not found + continue; // Skip line + } + + j[0] = '\0'; + + // Find ? + i = index(j+1, ','); + + if (i == NULL) { // Comma not found + continue; // Skip line + } + + i[0] = '\0'; + + // Find ? + j = index(i+1, ','); + + if (j == NULL) { // Comma not found + continue; // Skip line + } + + j[0] = '\0'; + + // Find altitude + i = index(j+1, ','); + + if (i == NULL) { // Comma not found + continue; // Skip line + } + + i[0] = '\0'; + + // Find population + j = index(i+1, ','); + + if (j == NULL) { // Comma not found + continue; // Skip line + } + + j[0] = '\0'; + strncpy(population,i+2,14); + // population[strlen(population)-1] = '\0'; + clean_string(population); + + // Find quad name (last field) + i = index(j+1, '"'); + + if (i == NULL) { // Comma not found + continue; // Skip line + } + + i[0] = '\0'; + strncpy(quad,j+2,14); + // quad[strlen(quad)] = '\0'; + clean_string(quad); + + + // If "Match Case" togglebutton is not set, convert + // the data to upper-case before we do our compare. + if (!follow_case) { + to_upper(name); + to_upper(state); + to_upper(county); + to_upper(quad); + to_upper(type); + } + + + // Still need to code for the "Match Exact" togglebutton. + + + // Now compare the input variables with those we've + // parsed. If a match, bring up a list of items which + // match. + // + ok = 1; + if (get_match) { // Looking for exact match + if (name_in2[0] != '\0') + if (strcmp(name,name_in2) != 0) + ok = 0; + if (state_in2[0] != '\0') + if (strcmp(state,state_in2) != 0) + ok = 0; + if (county_in2[0] != '\0') + if (strcmp(county,county_in2) != 0) + ok = 0; + if (quad_in2[0] != '\0') + if (strcmp(quad,quad_in2) != 0) + ok = 0; + if (type_in2[0] != '\0') + if (strcmp(type,type_in2) != 0) + ok = 0; + } + else { // Look for substring in file, not exact match + if (name_in2[0] != '\0') + if (strstr(name,name_in2) == NULL) + ok = 0; + if (state_in2[0] != '\0') + if (strstr(state,state_in2) == NULL) + ok = 0; + if (county_in2[0] != '\0') + if (strstr(county,county_in2) == NULL) + ok = 0; + if (quad_in2[0] != '\0') + if (strstr(quad,quad_in2) == NULL) + ok = 0; + if (type_in2[0] != '\0') + if (strstr(type,type_in2) == NULL) + ok = 0; + } + + + if (ok) { + if (debug_level & 16) + fprintf(stderr,"Match: %s,%s,%s,%s\n",name,state,county,type); + + popup_message( langcode("POPEM00029"), name ); + + lat_dd[0] = latitude[0]; + lat_dd[1] = latitude[1]; + lat_dd[2] = '\0'; + + lat_mm[0] = latitude[2]; + lat_mm[1] = latitude[3]; + lat_mm[2] = '\0'; + + lat_ss[0] = latitude[4]; + lat_ss[1] = latitude[5]; + lat_ss[2] = '\0'; + + lat_dir[0] = latitude[6]; + lat_dir[1] = '\0'; + + long_dd[0] = longitude[0]; + long_dd[1] = longitude[1]; + long_dd[2] = longitude[2]; + long_dd[3] = '\0'; + + long_mm[0] = longitude[3]; + long_mm[1] = longitude[4]; + long_mm[2] = '\0'; + + long_ss[0] = longitude[5]; + long_ss[1] = longitude[6]; + long_ss[2] = '\0'; + + long_dir[0] = longitude[7]; + long_dir[1] = '\0'; + + // Now must convert from DD MM SS format to DD MM.MM format so that we + // can run it through our conversion routine to Xastir coordinates. + (void)sscanf(lat_ss, "%d", &temp1); + temp1 = (int)((temp1 / 60.0) * 100 + 0.5); // Poor man's rounding + xastir_snprintf(lat_str, sizeof(lat_str), "%s%s.%02d%s", lat_dd, + lat_mm, temp1, lat_dir); + coord_lat = convert_lat_s2l(lat_str); + + (void)sscanf(long_ss, "%d", &temp1); + temp1 = (int)((temp1 / 60.0) * 100 + 0.5); // Poor man's rounding + xastir_snprintf(long_str, sizeof(long_str), "%s%s.%02d%s", long_dd, + long_mm, temp1, long_dir); + coord_lon = convert_lon_s2l(long_str); + set_map_position(w, coord_lat, coord_lon); + return(1); // We found a match + } + } + } + } + } else { + popup_message( langcode("POPEM00028"), filename_in ); + } + + return(0); // We didn't find a match + } + + + + diff -c -r -N xastir-1.2.0/src/map_pdb.c xastir-1.2.0-p/src/map_pdb.c *** xastir-1.2.0/src/map_pdb.c 1969-12-31 19:00:00.000000000 -0500 --- xastir-1.2.0-p/src/map_pdb.c 2003-06-19 21:43:06.000000000 -0400 *************** *** 0 **** --- 1,534 ---- + /* -*- c-basic-indent: 4; indent-tabs-mode: nil -*- + * $Id$ + * + * XASTIR, Amateur Station Tracking and Information Reporting + * Copyright (C) 1999,2000 Frank Giannandrea + * Copyright (C) 2000-2003 The Xastir Group + * + * 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-1307, USA. + * + * Look at the README for more information on the program. + * + * + * Please see separate copyright notice attached to the + * SHPRingDir_2d() function in this file. + * + */ + #include "config.h" + #include "snprintf.h" + + #include + #include + #include + #include + #include + #include + #include + #include + + // Needed for Solaris + #include + + #include + #include + #include + + #ifdef HAVE_X11_XPM_H + #include + #ifdef HAVE_LIBXPM // if we have both, prefer the extra library + #undef HAVE_XM_XPMI_H + #endif // HAVE_LIBXPM + #endif // HAVE_X11_XPM_H + + #ifdef HAVE_XM_XPMI_H + #include + #endif // HAVE_XM_XPMI_H + + #include + + #include + + #include "xastir.h" + #include "maps.h" + #include "alert.h" + #include "util.h" + #include "main.h" + #include "datum.h" + #include "draw_symbols.h" + #include "rotated.h" + #include "color.h" + #include "xa_config.h" + + #define CHECKMALLOC(m) if (!m) { fprintf(stderr, "***** Malloc Failed *****\n"); exit(0); } + + #define DOS_HDR_LINES 8 + #define GRID_MORE 5000 + + extern int npoints; /* tsk tsk tsk -- globals */ + extern int mag; + + + // Note: There are long's in the pdb_hdr that are not being used. + // If they were, the ntohl() function would need to be used in order + // to make sure they were represented correctly on big-endian and + // little-endian machines. Same goes for short's, make sure ntohs() + // is used in all cases. + // + // Also Note: It looks like all the values in the data structures are + // unsigned, we may have to explicitly define the long's as well. -KD6ZWR + // + void draw_palm_image_map(Widget w, + char *dir, + char *filenm, + alert_entry *alert, + u_char alert_color, + int destination_pixmap, + int draw_filled) { + + // Do NOT change any of these structs. They have to match the + // structs that the palm maps were made with. + #pragma pack(1) + struct { + char name[32]; + short file_attributes; + short version; // 2: No placeholder bytes in file, 3: w/bytes + long creation_date; + long modification_date; + long backup_date; + long modification_number; + long app_info; + long sort_info; + char database_type[4]; + char creator_type[4]; + long unique_id_seed; + long next_record_list; + short number_of_records; + } pdb_hdr; + + struct { + long record_data_offset; + char category; + char id[3]; + } prl; + + // Two placeholder bytes where were added in version 3. We + // skip these below automatically using the fseek calls and the + // record offsets. + //struct { + // short placeholder; + //} pdb_ph; + + struct { + long left_bounds; + long right_bounds; + long top_bounds; + long bottom_bounds; + char menu_name[12]; + short granularity; + char sort_order; + char fill[33]; + } pmf_hdr; + + struct { + char type; + char sub_type; + short minimum_zoom; + } record_hdr; + + struct { + unsigned short next_vector; + unsigned short left_bounds; + unsigned short right_bounds; + unsigned short top_bounds; + unsigned short bottom_bounds; + unsigned short line_start_x; + unsigned short line_start_y; + } vector_hdr; + + struct { + unsigned char next_x; + unsigned char next_y; + } vector_point; + + struct { + unsigned short next_label; + unsigned short start_x; + unsigned short start_y; + char symbol_set; + char symbol_char; + char color; + char treatment; + short fill; + char text[20]; + } label_record; + + FILE *fn; + char filename[MAX_FILENAME]; + int records, record_count, count; + int scale; + long map_left, map_right, map_top, map_bottom, max_x, max_y; + long record_ptr; + long line_x, line_y; + int vector; + char status_text[MAX_FILENAME]; + + + xastir_snprintf(filename, sizeof(filename), "%s/%s", dir, filenm); + + if ((fn = fopen(filename, "r")) != NULL) { + + if (debug_level & 16) + fprintf(stderr,"opened file: %s\n", filename); + + fread(&pdb_hdr, sizeof(pdb_hdr), 1, fn); + + if (strncmp(pdb_hdr.database_type, "map1", 4) != 0 + || strncmp(pdb_hdr.creator_type, "pAPR", 4) != 0) { + fprintf(stderr,"Not Palm OS Map: %s\n", filename); + fclose(fn); + return; + } + + records = ntohs(pdb_hdr.number_of_records); + + fread(&prl, sizeof(prl), 1, fn); + + if (debug_level & 512) { + fprintf(stderr,"Palm Map: %s, %d records, offset: %8x\n", + pdb_hdr.name, + records, + (unsigned int)ntohl(prl.record_data_offset)); + } + + // Save the current pointer into the file + record_ptr = (long)ftell(fn); + // record_ptr should now be point to the next record list in + // the sequence (if there is another one). + + // Point to the map file header corresponding to the record + // list we just read in & snag it. + fseek(fn, ntohl(prl.record_data_offset), SEEK_SET); + fread(&pmf_hdr, sizeof(pmf_hdr), 1, fn); + + scale = ntohs(pmf_hdr.granularity); + map_left = ntohl(pmf_hdr.left_bounds); + map_right = ntohl(pmf_hdr.right_bounds); + map_top = ntohl(pmf_hdr.top_bounds); + map_bottom = ntohl(pmf_hdr.bottom_bounds); + + if (debug_level & 512) { + fprintf(stderr,"\tLeft %ld, Right %ld, Top %ld, Bottom %ld, %s, Scale %d, %d\n", + map_left, + map_right, + map_top, + map_bottom, + pmf_hdr.menu_name, + scale, + pmf_hdr.sort_order); + } + + // DNN: multipy by 10; pocketAPRS corners in tenths of seconds, + // internal map in hundredths of seconds (was "scale" which was wrong, + // scale is not used for the map corners) + // Multipy now so we don't have to do it for every use below... + map_left = map_left * 10; + map_right = map_right * 10; + map_top = map_top * 10; + map_bottom = map_bottom * 10; + + + // Check whether we're indexing or drawing the map + if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS) + || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) { + + // We're indexing only. Save the extents in the index. + index_update_xastir(filenm, // Filename only + map_bottom, // Bottom + map_top, // Top + map_left, // Left + map_right); // Right + + fclose(fn); + return; // Done indexing this file + } + + + if (map_onscreen(map_left, map_right, map_top, map_bottom)) { + + + // Update the statusline for this map name + // Check whether we're indexing or drawing the map + if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS) + || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) { + xastir_snprintf(status_text, sizeof(status_text), langcode ("BBARSTA039"), filenm); + } + else { + xastir_snprintf(status_text, sizeof(status_text), langcode ("BBARSTA028"), filenm); + } + statusline(status_text,0); // Loading/Indexing ... + + + max_x = (long)(screen_width + MAX_OUTBOUND); + max_y = (long)(screen_height + MAX_OUTBOUND); + + /* read vectors */ + for (record_count = 2; record_count <= records; record_count++) { + + // Point to the next record list header & snag it + fseek(fn, record_ptr, SEEK_SET); + fread(&prl, sizeof(prl), 1, fn); + + if (debug_level & 512) { + fprintf(stderr,"\tRecord %d, offset: %8x\n", + record_count, + (unsigned int)ntohl(prl.record_data_offset)); + } + + // Save a pointer to the next record list header + record_ptr = (long)ftell(fn); + + // Point to the next map file header & snag it + fseek(fn, ntohl(prl.record_data_offset), SEEK_SET); + fread(&record_hdr, sizeof(record_hdr), 1, fn); + + if (debug_level & 512) { + fprintf(stderr,"\tType %d, Sub %d, Zoom %d\n", + record_hdr.type, + record_hdr.sub_type, + (unsigned short) ntohs(record_hdr.minimum_zoom)); + } + + if (record_hdr.type > 0 && record_hdr.type < 16) { + + vector = True; + + while (vector && fread(&vector_hdr, sizeof(vector_hdr), 1, fn)) { + + count = (unsigned short) ntohs(vector_hdr.next_vector); + + if (count && !(count&1)) { + line_x = (long)ntohs(vector_hdr.line_start_x); + line_y = (long)ntohs(vector_hdr.line_start_y); + + if (debug_level & 512) { + fprintf(stderr,"\tvector %d, left %d, right %d, top %d, bottom %d, start x %ld, start y %ld\n", + count, + (unsigned short) ntohs(vector_hdr.left_bounds), + (unsigned short) ntohs(vector_hdr.right_bounds), + (unsigned short) ntohs(vector_hdr.top_bounds), + (unsigned short) ntohs(vector_hdr.bottom_bounds), + line_x, + line_y); + } + + // DNN: Only line_x and line_y are scaled, + // not map_left and map_top + map_plot (w, + max_x, + max_y, + map_left + (line_x * scale), + map_top + (line_y * scale), + record_hdr.type, // becomes the color choice + 0, + destination_pixmap, + draw_filled); + + for (count -= sizeof(vector_hdr); count > 0; count -= sizeof(vector_point)) { + + fread(&vector_point, sizeof(vector_point), 1, fn); + + if (debug_level & 512) { + fprintf(stderr,"\tnext x %d, next y %d\n", + vector_point.next_x, + vector_point.next_y); + } + + line_x += vector_point.next_x - 127; + line_y += vector_point.next_y - 127; + + // DNN: Only line_x and line_y are scaled, + // not map_left and map_top + map_plot (w, + max_x, + max_y, + map_left + (line_x * scale), + map_top + (line_y * scale), + record_hdr.type, + 0, + destination_pixmap, + draw_filled); + } + + // DNN: Only line_x and line_y are scaled, + // not map_left and map_top + map_plot (w, + max_x, + max_y, + map_left + (line_x * scale), + map_top + (line_y * scale), + 0, // Color 0 + 0, + destination_pixmap, + draw_filled); + } + else { + vector = False; + } + } + } + else if ( (record_hdr.type == 0) // We have a label + && map_labels) { // and we wish to draw it + long label_x_cord; + long label_y_cord; + int label_length; + int label; + long label_mag; + long x; + long y; + int i; + int color; + + + label_mag = (long) ntohs(record_hdr.minimum_zoom); + + // DNN: Multiplication by 4 looks reasonable on the map I + // checked, be my guest to come up with a better value... + // For the map I used the behaviour mimics the + // behaviour on pocketAPRS when the labels show up + label_mag *= 4; + + label = True; + + while (label && fread(&label_record, sizeof(label_record), 1, fn)) { + + count = ntohs(label_record.next_label); + + if (count && !(count&1)) { + line_x = (long)ntohs(vector_hdr.line_start_x); + line_y = (long)ntohs(vector_hdr.line_start_y); + + if (debug_level & 512) { + fprintf(stderr,"\t%d, %d, %d, %d, %d, %d, 0x%x, %s\n", + ntohs(label_record.next_label), + ntohs(label_record.start_x), + ntohs(label_record.start_y), + label_record.symbol_set, + label_record.symbol_char, + label_record.color, + label_record.treatment, + label_record.text); + } + + label_x_cord = map_left + + (((long) ntohs(label_record.start_x)) * scale); + label_y_cord = map_top + + (((long) ntohs(label_record.start_y)) * scale); + + // DNN: Skip empty labels + if(label_record.text[0] != '\0') { + label_record.text[19] = '\0'; // Make sure we have a terminator + label_length = (int)strlen (label_record.text); + + for (i = (label_length - 1); i > 0; i--) { + if (label_record.text[i] == ' ') + label_record.text[i] = '\0'; + else + break; + } + + label_length = (int)strlen (label_record.text); + + // DNN: todo: treatment: + // bit 7: inverse + // bit 6: draw beneath map line data + // bit 5,4: 00 = left, 01 = center, 10 = right + // bit 3,2,1,0: typeface 0 = normal, 1 = bold, + // 2 = large, 3 = extra large + // + // For now KISS, just put it on the map. + + x = ((label_x_cord - x_long_offset) / scale_x); + + /* examine bits 4 and 5 of treatment */ + if((label_record.treatment & 0x30) == 0x00) { + /* left of coords */ + x = x - (label_length * 6); + } + else if((label_record.treatment & 0x30) == 0x10) { + /* center */ + x = x - (label_length * 3); + } + else { + /* right of coords */ + x = ((label_x_cord - x_long_offset) / scale_x); + } + + y = ((label_y_cord - y_lat_offset) / scale_y); + + // Color selection + switch (label_record.color) { + case 0: + color = 0x08; // black + break; + case 1: + color = 0x07; // darkgray + break; + case 2: + color = 0x14; // lightgray + break; + case 3: + color = 0x0f; // white + break; + default: + color = 0x08; // black + break; + } + + if (label_mag > (int)((scale_x) - 1) || label_mag == 0) { + if (x > (0) && (x < (int)screen_width)) { + if (y > (0) && (y < (int)screen_height)) { + draw_rotated_label_text (w, + -90.0, + x, + y, + label_length, + colors[color], + label_record.text); + } + } + } + } + /* Label has a symbol */ + if(label_record.symbol_char != '\0') { + // DNN: Not implemented (yet) + } + } + else { + label = False; + } + } + } // End of while + } + } + + fclose(fn); + + if (debug_level & 16) + fprintf(stderr,"Closed file\n"); + } + else { + fprintf(stderr,"Couldn't open file: %s\n", filename); + } + } diff -c -r -N xastir-1.2.0/src/maps.c xastir-1.2.0-p/src/maps.c *** xastir-1.2.0/src/maps.c 2003-06-06 20:04:09.000000000 -0400 --- xastir-1.2.0-p/src/maps.c 2003-06-21 13:44:46.000000000 -0400 *************** *** 1,5 **** /* -*- c-basic-indent: 4; indent-tabs-mode: nil -*- ! * $Id: maps.c,v 1.290 2003/06/07 00:04:09 we7u Exp $ * * XASTIR, Amateur Station Tracking and Information Reporting * Copyright (C) 1999,2000 Frank Giannandrea --- 1,5 ---- /* -*- c-basic-indent: 4; indent-tabs-mode: nil -*- ! * $Id: maps.c,v 1.293 2003/06/21 17:44:46 alan Exp $ * * XASTIR, Amateur Station Tracking and Information Reporting * Copyright (C) 1999,2000 Frank Giannandrea *************** *** 104,129 **** #include - #ifdef HAVE_LIBGEOTIFF - //#include "cpl_csv.h" - #include "xtiffio.h" - #include "geotiffio.h" - #include "geo_normalize.h" - #include "projects.h" - #endif // HAVE_LIBGEOTIFF - - #ifdef HAVE_LIBSHP - #ifdef HAVE_SHAPEFIL_H - #include - #else - #ifdef HAVE_LIBSHP_SHAPEFIL_H - #include - #else - #error HAVE_LIBSHP defined but no corresponding include defined - #endif // HAVE_LIBSHP_SHAPEFIL_H - #endif // HAVE_SHAPEFIL_H - #endif // HAVE_LIBSHP - #ifdef HAVE_LIBCURL #include #include --- 104,109 ---- *************** *** 146,155 **** #include "color.h" #include "xa_config.h" - #define DOS_HDR_LINES 8 - #define GRID_MORE 5000 - - #define CHECKMALLOC(m) if (!m) { fprintf(stderr, "***** Malloc Failed *****\n"); exit(0); } --- 126,131 ---- *************** *** 181,230 **** int doing_snapshot = 0; - - typedef struct { - int img_x; - int img_y; - unsigned long x_long; - unsigned long y_lat; - } tiepoint; - - int mag; int npoints; /* number of points in a line */ - /* MAP pointers */ - - map_vectors *map_vectors_ptr; - text_label *map_text_label_ptr; - symbol_label *map_symbol_label_ptr; - - /* MAP counters */ - - long vectors_num; - long text_label_num; - long object_label_num; - float geotiff_map_intensity = 0.65; // Geotiff map color intensity, set from Maps->Geotiff Map Intensity float imagemagick_gamma_adjust = 0.0; // Additional imagemagick map gamma correction, set from Maps->Adjust Gamma // Storage for the index file timestamp time_t map_index_timestamp; - extern int index_retrieve(char *filename, unsigned long *bottom, - unsigned long *top, unsigned long *left, unsigned long *right, - int *map_layer, int *draw_filled, int *auto_maps); - static int map_onscreen_index(char *filename); - extern void index_update_directory(char *directory); - extern void index_update_accessed(char *filename); - - int grid_size = 0; - - - void maps_init(void) { init_critical_section( &print_properties_dialog_lock ); --- 157,174 ---- *************** *** 470,689 **** /********************************************************** - * map_plot() - * - * Plots vectors on the map. If "color" is non-zero, - * then it draws filled polygons in the color of - * "object_behavior"? Weird. - **********************************************************/ - void map_plot (Widget w, long max_x, long max_y, long x_long_cord, - long y_lat_cord, unsigned char color, long object_behavior, - int destination_pixmap, int draw_filled) { - - static int redraw_check; - static XPoint points[MAX_MAP_POINTS]; - static unsigned char last_color = (unsigned char)0; - static unsigned char last_behavior = (unsigned char)0, first_behavior = (unsigned char)0; - long x, y; - int draw_ok; - unsigned char line_behavior, fill_color; - char warning[200]; - - /* don't ever go over MAX_MAP_POINTS have a bad map not a crashed program */ - if (npoints > MAX_MAP_POINTS) { - xastir_snprintf(warning, sizeof(warning), "Warning line point count overflow: map_plot\b\n"); - XtAppWarning (app_context, warning); - npoints = MAX_MAP_POINTS; - } - - /* if map_color_levels are on see if we should draw the line? */ - draw_ok = 0; - if (map_color_levels) // Decide which colors to display at this zoom level - switch (color) { - case (0x01): - case (0x14): - case (0x18): - if (mag < 100) - draw_ok = 1; - break; - case (0x15): - case (0x19): - if (mag < 600) - draw_ok = 1; - break; - case (0x16): - if (mag < 800) - draw_ok = 1; - break; - default: - draw_ok = 1; - break; - } - else // Display all colors - draw_ok = 1; - - if (draw_ok) { - x = ((x_long_cord - x_long_offset) / scale_x); - y = ((y_lat_cord - y_lat_offset) / scale_y); - if (x < -MAX_OUTBOUND) - x = -MAX_OUTBOUND; - - if (y < -MAX_OUTBOUND) - y = -MAX_OUTBOUND; - - if (x > max_x) - x = max_x; - - if (y > max_y) - y = max_y; - - if (debug_level & 16) - fprintf(stderr," MAP Plot - max_x: %ld, max_y: %ld, x: %ld, y: %ld, color: %d, behavior: %lx, points: %d\n", - max_x, max_y, x, y, (int)color, (unsigned long)object_behavior, npoints); - - if ( (last_color != color) || (color == (unsigned char)0xff) ) { - if (npoints && (last_color != (unsigned char)0xff) ) { - line_behavior = last_behavior; - if (last_behavior & 0x80) { - if (color) { - fill_color = (last_behavior & ~0x80) + (unsigned char)0x60; - if (fill_color > (unsigned char)0x69) - fill_color = (unsigned char)0x60; - } else - fill_color = (unsigned char)object_behavior; - - - // Here's where we draw filled areas using fill_color. - - (void)XSetForeground (XtDisplay (w), gc, colors[(int)fill_color]); - - switch (destination_pixmap) { - - case DRAW_TO_PIXMAP: - // We must be drawing maps 'cuz this is the pixmap we use for it. - if (map_color_fill && draw_filled) { - - if (npoints >= 3) { - (void)XFillPolygon(XtDisplay(w), - pixmap, - gc, - points, - npoints, - Nonconvex, - CoordModeOrigin); - } - else { - fprintf(stderr, - "map_plot:Too few points:%d, Skipping XFillPolygon()", - npoints); - } - } - break; - - case DRAW_TO_PIXMAP_ALERTS: - fprintf(stderr,"You're calling the wrong routine to draw weather alerts!\n"); - break; - - case DRAW_TO_PIXMAP_FINAL: - // We must be drawing symbols/tracks 'cuz this is the pixmap we use for it. - - if (npoints >= 3) { - (void)XFillPolygon(XtDisplay(w), - pixmap_final, - gc, - points, - npoints, - Nonconvex, - CoordModeOrigin); - } - else { - fprintf(stderr, - "map_plot:Too few points:%d, Skipping XFillPolygon()", - npoints); - } - break; - } - - line_behavior = first_behavior; - } - if (line_behavior & 0x01) - (void)XSetLineAttributes (XtDisplay (w), gc, 2, LineSolid, CapButt,JoinMiter); - else - (void)XSetLineAttributes (XtDisplay (w), gc, 1, LineSolid, CapButt,JoinMiter); - - if (color == (unsigned char)0x56) - (void)XSetLineAttributes (XtDisplay (w), gc, 10, LineSolid, CapButt,JoinMiter); - - // Set the color for drawing lines/borders - (void)XSetForeground (XtDisplay (w), gc, colors[(int)last_color]); - - switch (destination_pixmap) { - - case DRAW_TO_PIXMAP_FINAL: - (void)XDrawLines (XtDisplay (w), pixmap_final, gc, points, npoints,CoordModeOrigin); - break; - - case DRAW_TO_PIXMAP: - (void)XDrawLines (XtDisplay (w), pixmap, gc, points, npoints,CoordModeOrigin); - break; - - case DRAW_TO_PIXMAP_ALERTS: - fprintf(stderr,"You're calling the wrong routine to draw weather alerts!\n"); - break; - } - - npoints = 0; - - /* check to see if we have been away from the screen too long */ - if (redraw_check > 1000) { - redraw_check = 0; - XmUpdateDisplay (XtParent (da)); - } - redraw_check++; - } - last_color = color; - if (color == (unsigned char)0xff) { - npoints = 0; - first_behavior = (unsigned char)object_behavior; - } - points[npoints].x = (short)x; - points[npoints].y = (short)y; - if ( (points[npoints].x > (-MAX_OUTBOUND)) - && (points[npoints].x < (short)max_x) - && (points[npoints].y > (-MAX_OUTBOUND)) - && (points[npoints].y < (short)max_y) - && (color != (unsigned char)0) ) - - npoints++; - - last_behavior = (unsigned char)object_behavior; - return; - } - points[npoints].x = (short)x; - points[npoints].y = (short)y; - last_behavior = (unsigned char)object_behavior; - - if (points[npoints].x != points[npoints - 1].x || points[npoints].y != points[npoints - 1].y) { - if (last_behavior & 0x80) - npoints++; - - else if (points[npoints].x > (-MAX_OUTBOUND) - && points[npoints].x < (short)max_x - && points[npoints].y > (-MAX_OUTBOUND) - && points[npoints].y < (short)max_y) - npoints++; - - } - } else { - npoints = 0; - } - } /* map_plot */ - - - - - - /********************************************************** * get_map_ext() * * Returns the extension for the filename. We use this to --- 414,419 ---- *************** *** 731,825 **** - - - /********************************************************** - * get_alt_fgd_path() - * - * Used to search for .fgd in ../metadata subdir, as it is - * layed out on a USGS CDROM. - **********************************************************/ - void get_alt_fgd_path(char *fullpath, int fullpath_length) { - int len; - int i, j = 0; - char *dir = fullpath; - char fname[MAX_FILENAME]; - - // Split up into directory and filename - len = (int)strlen (fullpath); - for (i = len; i >= 0; i--) { - if (fullpath[i] == '/') { - dir = &fullpath[i]; - break; - } - } - for (++i; i <= len; i++) { - fname[j++] = fullpath[i]; // Grab the filename - if (fullpath[i] == '\0') - break; - } - - // We have the filename now. dir now points to - // the '/' at the end of the path. - - // Now do it again to knock off the "data" subdirectory - // from the end. - dir[0] = '\0'; // Terminate the current string, wiping out the '/' character - len = (int)strlen (fullpath); // Length of the new shortened string - for (i = len; i >= 0; i--) { - if (fullpath[i] == '/') { - dir = &fullpath[i + 1]; // Dir now points to one past the '/' character - break; - } - } - for (++i; i <= len; i++) { - if (fullpath[i] == '\0') - break; - } - - // Add "metadata/" into the path - xastir_snprintf(dir, fullpath_length, "metadata/%s", fname); - //fprintf(stderr,"FGD Directory: %s\n", fullpath); - } - - - - - - /********************************************************** - * get_alt_fgd_path2() - * - * Used to search for .fgd in Metadata subdir. This function - * is no longer used. - **********************************************************/ - void get_alt_fgd_path2(char *fullpath, int fullpath_length) { - int len; - int i, j = 0; - char *dir = fullpath; - char fname[MAX_FILENAME]; - - // Split up into directory and filename - len = (int)strlen (fullpath); - for (i = len; i >= 0; i--) { - if (fullpath[i] == '/') { - dir = &fullpath[i + 1]; - break; - } - } - for (++i; i <= len; i++) { - fname[j++] = fullpath[i]; - if (fullpath[i] == '\0') - break; - } - - // Add "Metadata/" into the path - xastir_snprintf(dir, fullpath_length, "Metadata/%s", fname); - } - - - - - /*********************************************************** * map_visible() * --- 461,466 ---- *************** *** 1157,10907 **** - #ifdef HAVE_LIBSHP - /******************************************************************* - * create_shapefile_map() - * - * Do we have a need for storing date/ time/ speed/ course/ - * altitude/ heard-direct for each point? Altitude could be stored - * in the Z space. If we store a station's trail as an SHPT_POINT - * file, then we can associate a bunch of info with each point: - * date/time, altitude, course, speed, status/comments, path, port, - * heard-direct, weather data, etc. We could also dynamically - * change the number of fields based on what we have a need to - * store, using field-names to determine what's stored in each file. - * - * shapefile_name is the path/name of the map file we wish to create - * (without the extension). - * - * type = SHPT_POINT, SHPT_ARC, SHPT_POLYGON, - * SHPT_MULTIPOINT, etc. - * - * quantity equals the number of vertices we have. - * - * padfx/padfy/padfz are the vertices themselves, in double format. - *******************************************************************/ - void create_shapefile_map(char *dir, char *shapefile_name, int type, - int quantity, double *padfx, double *padfy, double *padfz, - int add_timestamp) { - - SHPHandle my_shp_handle; - SHPObject *my_object; - DBFHandle my_dbf_handle; - char timedatestring[101]; - int index; - int max_objects = 1; - char credit_string[] = "Created by Xastir, http://www.xastir.org"; - char temp_shapefile_name[MAX_FILENAME]; - - - if (debug_level & 16) { - fprintf(stderr,"create_shapefile_map\n"); - fprintf(stderr,"%s %s %d %d %d\n", - dir, - shapefile_name, - type, - quantity, - add_timestamp); - } - if (quantity == 0) { - // No reason to make a map if we don't have any points. - return; - } - // Get the time/datestamp - get_timestamp(timedatestring); - if (add_timestamp) { // Prepend a timestamp to the filename - int ii; - xastir_snprintf(temp_shapefile_name, - sizeof(temp_shapefile_name), - "%s%s_%s", - dir, - timedatestring, - shapefile_name); - - // Change spaces to underlines - for (ii = 0; ii < strlen(temp_shapefile_name); ii++) { - if (temp_shapefile_name[ii] == ' ') { - temp_shapefile_name[ii] = '_'; - } - } - } - else { // Use the filename directly, no timestamp - xastir_snprintf(temp_shapefile_name, - sizeof(temp_shapefile_name), - "%s%s", - dir, - shapefile_name); - } ! if (debug_level & 16) ! fprintf(stderr, "Creating file %s\n", temp_shapefile_name); ! ! // Create empty .shp/.shx/.dbf files ! // ! my_shp_handle = SHPCreate(temp_shapefile_name, type); ! my_dbf_handle = DBFCreate(temp_shapefile_name); ! // Check whether we were able to open these handles ! if ((my_shp_handle == NULL) || (my_dbf_handle == NULL)) { ! // Probably write-protected directory ! fprintf(stderr, "Could not create shapefile %s\n", ! temp_shapefile_name); ! return; ! } ! // Create the different fields we'll use to store the ! // attributes: ! // ! // Add a credits field and set the length. Field 0. ! DBFAddField(my_dbf_handle, "Credits", FTString, strlen(credit_string) + 1, 0); ! // ! // Add a date/time field and set the length. Field 1. ! DBFAddField(my_dbf_handle, "DateTime", FTString, strlen(timedatestring) + 1, 0); ! // Note that if were passed additional parameters that went ! // along with the lat/long/altitude points, we could write those ! // into the DBF file in the loop below. We would have to change ! // from a polygon to a point filetype though. ! // Populate the files with objects and attributes. Perform this ! // loop once for each object. ! // ! for (index = 0; index < max_objects; index++) { - // Create a temporary object from the vertices - my_object = SHPCreateSimpleObject( type, - quantity, - padfx, - padfy, - padfz); - // Write out the vertices - SHPWriteObject( my_shp_handle, - -1, - my_object); - // Destroy the temporary object - SHPDestroyObject(my_object); - // Note that with the current setup the below really only get - // written into the file once. Check it with dbfinfo/dbfdump. ! // Write the credits attributes ! DBFWriteStringAttribute( my_dbf_handle, ! index, ! 0, ! credit_string); ! // Write the time/date string ! DBFWriteStringAttribute( my_dbf_handle, ! index, ! 1, ! timedatestring); ! } ! // Close the .shp/.shx/.dbf files ! SHPClose(my_shp_handle); ! DBFClose(my_dbf_handle); ! } ! // Function which creates a Shapefile map from an APRS trail. ! // ! // Navigate through the linked list of TrackRow structs to pick out ! // the lat/long and write them into arrays of floats. We then pass ! // those arrays to create_shapefile_map(). ! // ! void create_map_from_trail(char *call_sign) { ! DataRow *p_station; ! // Find the station in our database. Count the number of points ! // for that station first, then allocate some arrays to hold ! // that quantity of points. Stuff the lat/long into the arrays ! // and then call create_shapefile_map(). ! // ! if (search_station_name(&p_station, call_sign, 1)) { ! int count; ! int ii; ! TrackRow *ptr; ! char temp[MAX_FILENAME]; ! char temp2[MAX_FILENAME]; ! double *x; ! double *y; ! double *z; ! ! ! count = 0; ! ptr = p_station->oldest_trackpoint; ! while (ptr != NULL) { ! count++; ! ptr = ptr->next; ! } ! ! //fprintf(stderr, "Quantity of points: %d\n", count); ! ! if (count == 0) { ! // No reason to make a map if we don't have any points ! // in the track list. ! return; ! } ! ! // We know how many points are in the linked list. Allocate ! // arrays to hold the values. ! x = (double *) malloc( count * sizeof(double) ); ! y = (double *) malloc( count * sizeof(double) ); ! z = (double *) malloc( count * sizeof(double) ); ! CHECKMALLOC(x); ! CHECKMALLOC(y); ! CHECKMALLOC(z); ! ! // Fill in the values. We need to convert from Xastir ! // coordinate system to lat/long doubles as we go. ! ptr = p_station->oldest_trackpoint; ! ii = 0; ! while ((ptr != NULL) && (ii < count) ) { ! ! // Convert from Xastir coordinates to lat/long ! ! // Convert to string ! convert_lon_l2s(ptr->trail_long_pos, temp, sizeof(temp), CONVERT_DEC_DEG); ! // Convert to double and stuff into array of doubles ! (void)sscanf(temp, "%lf", &x[ii]); ! // If longitude string contains "W", make the final ! // result negative. ! if (index(temp, 'W')) ! x[ii] = x[ii] * -1.0; ! ! // Convert to string ! convert_lat_l2s(ptr->trail_lat_pos, temp, sizeof(temp), CONVERT_DEC_DEG); ! // Convert to double and stuff into array of doubles ! (void)sscanf(temp, "%lf", &y[ii]); ! // If latitude string contains "S", make the final ! // result negative. ! if (index(temp, 'S')) ! y[ii] = y[ii] * -1.0; - z[ii] = ptr->altitude; // Altitude (meters), undefined=-99999 ! ptr = ptr->next; ! ii++; ! } ! // Create a Shapefile from the APRS trail. Write it into ! // "/maps/GPS" and add a date/timestamp to the end. ! // ! // Create directory name ("maps/GPS/") ! xastir_snprintf(temp, sizeof(temp), ! "%s/GPS/", ! get_data_base_dir("maps")); ! ! // Create filename ! xastir_snprintf(temp2, sizeof(temp2), ! "%s%s", ! call_sign, ! "_APRS_Trail_Red"); ! ! create_shapefile_map( ! temp, ! temp2, ! SHPT_ARC, ! count, ! x, ! y, ! z, ! 1); // Add a timestamp to the front of the filename ! // Free the storage that we malloc'ed ! free(x); ! free(y); ! free(z); ! } ! else { // Couldn't find the station of interest } ! } - // Code borrowed from Shapelib which determines whether a ring is CW - // or CCW. Thanks to Frank Warmerdam for permitting us to use this - // under the GPL license! Per e-mail of 04/29/2003 between Frank - // and Curt, WE7U. Frank gave permission for us to use _any_ - // portion of Shapelib inside the GPL'ed Xastir program. - // - // Test Ring for Clockwise/Counter-Clockwise (fill or hole ring) - // - // Return 1 for Clockwise (fill ring) - // Return -1 for Counter-Clockwise (hole ring) - // Return 0 for error/indeterminate (shouldn't get this!) - // - int shape_ring_direction ( SHPObject *psObject, int Ring ) { - int nVertStart; - int nVertCount; - int iVert; - float dfSum; - int result; ! ! nVertStart = psObject->panPartStart[Ring]; - if( Ring == psObject->nParts-1 ) - nVertCount = psObject->nVertices - psObject->panPartStart[Ring]; - else - nVertCount = psObject->panPartStart[Ring+1] - - psObject->panPartStart[Ring]; ! dfSum = 0.0; ! for( iVert = nVertStart; iVert < nVertStart+nVertCount-1; iVert++ ) ! { ! dfSum += psObject->padfX[iVert] * psObject->padfY[iVert+1] ! - psObject->padfY[iVert] * psObject->padfX[iVert+1]; ! } - dfSum += psObject->padfX[iVert] * psObject->padfY[nVertStart] - - psObject->padfY[iVert] * psObject->padfX[nVertStart]; ! if (dfSum < 0.0) ! result = 1; ! else if (dfSum > 0.0) ! result = -1; ! else ! result = 0; - return(result); - } ! ! /********************************************************** ! * draw_shapefile_map() ! * ! * This function handles both weather-alert shapefiles (from the ! * NOAA site) and shapefiles used as maps (from a number of ! * sources). ! * ! * If destination_pixmap equals INDEX_CHECK_TIMESTAMPS or ! * INDEX_NO_TIMESTAMPS, then we are indexing the file (finding the ! * extents) instead of drawing it. ! * ! * The current implementation can draw Polygon, PolyLine, and Point ! * Shapefiles, but only from a few sources (NOAA, Mapshots.com, and ! * ESRI/GeographyNetwork.com). We don't handle some of the more ! * esoteric formats. We now handle the "hole" drawing in polygon ! * shapefiles, where one direction around the ring means a fill, and ! * the other direction means a hole in the polygon. ! * ! * Note that we must currently hard-code the file-recognition ! * portion and the file-drawing portion, because every new source of ! * Shapefiles has a different format, and the fields and field ! * definitions can all change between them. ! * ! * If alert is NULL, draw every shape that fits the screen. If ! * non-NULL, draw only the shape that matches the zone number. ! * ! * Here's what I get for the County_Warning_Area Shapefile: ! * ! * ! * Info for shapefiles/county_warning_areas/w_24ja01.shp ! * 4 Columns, 121 Records in file ! * WFO string (3,0) ! * CWA string (3,0) ! * LON float (18,5) ! * LAT float (18,5) ! * Info for shapefiles/county_warning_areas/w_24ja01.shp ! * Polygon(5), 121 Records in file ! * File Bounds: ( 0, 0) ! * ( 179.7880249, 71.39809418) ! * ! * From the NOAA web pages: ! ! Zone Alert Maps: (polygon) (such as z_16mr01.shp) ! ---------------- ! field name type width,dec description ! STATE character 2 [ss] State abbrev (US Postal Standard) ! ZONE character 3 [zzz] Zone number, from WSOM C-11 ! CWA character 3 County Warning Area, from WSOM C-47 ! NAME character 254 Zone name, from WSOM C-11 ! STATE_ZONE character 5 [sszzz] state+("00"+zone.trim).right(3)) ! TIME_ZONE character 2 [tt] Time Zone, 2 chars if split ! FE_AREA character 2 [aa] Cardinal area of state (occasional) ! LON numeric 10,5 Longitude of centroid [decimal degrees] ! LAT numeric 9,5 Latitude of centroid [decimal degrees] ! ! ! NOTE: APRS weather alerts have these sorts of codes in them: ! AL_C001 ! AUTAUGACOUNTY ! MS_C075 ! LAUDERDALE&NEWTONCOUNTIES ! KY_C009 ! EDMONSON ! MS_CLARKE ! MS_C113 ! MN_Z076 ! PIKECOUNTY ! ATTALACOUNTY ! ST.LUCIECOUNTY ! CW_AGLD ! ! The strings in the shapefiles are mixed-case, and it appears that the NAME field would ! have the county name, in case state_zone-number format was not used. We can use the ! STATE_ZONE filed for a match unless it is a non-standard form, in which case we'll need ! to look through the NAME field, and perhaps chop off the "SS_" state portion first. ! ! ! County Warning Areas: (polygon) ! --------------------- ! field name type width,dec description ! WFO character 3 WFO Identifier (name of CWA) ! CWA character 3 CWA Identifier (same as WFO) ! LON numeric 10,5 Longitude of centroid [decimal degrees] ! LAT numeric 9,5 Latitude of centroid [decimal degrees] ! ! Coastal and Offshore Marine Areas: (polygon) ! ---------------------------------- ! field name type width,dec description ! ID character 6 Marine Zone Identifier ! WFO character 3 Assigned WFO (Office Identifier) ! NAME character 250 Name of Marine Zone ! LON numeric 10,5 Longitude of Centroid [decimal degrees] ! LAT numeric 9,5 Latitude of Centroid [decimal degrees] ! WFO_AREA character 200 "Official Area of Responsibility", from WSOM D51/D52 ! ! Road Maps: (polyline) ! ---------- ! field name type width,dec description ! STFIPS numeric 2,0 State FIPS Code ! CTFIPS numeric 3,0 County FIPS Code ! MILES numeric 6,2 length [mi] ! KILOMETERS numeric 6,2 length [km] ! TOLL numeric 1,0 ! SURFACE numeric 1,0 Surface type ! LANES numeric 2,0 Number of lanes ! FEAT_CLASS numeric 2,0 ! CLASS character 30 ! SIGN1 character 6 Primary Sign Route ! SIGN2 character 6 Secondary Sign Route ! SIGN3 character 6 Alternate Sign Route ! DESCRIPT character 35 Name of road (sparse) ! SPEEDLIM numeric 16,0 ! SECONDS numeric 16,2 ! ! Lakes (lk17de98.shp): ! --------------------- ! field name type width,dec description ! NAME string (40,0) ! FEATURE string (40,0) ! LON float (10,5) ! LAT float (9,5) ! ! ! USGS Quads Overlay (24kgrid.shp) from ! http://data.geocomm.com/quadindex/ ! ---------------------------------- ! field name type width,dec Example ! NAME string (30,0) Lummi Bay OE W ! STATE string (2,0) WA ! LAT string (6,0) 48.750 ! LON string (8,0) -122.750 ! MRC string (8,0) 48122-G7 ! ! ! // Need to figure out which type of alert it is, select the corresponding shapefile, ! // then store the shapefile AND the alert_tag in the alert_list[i].filename list? ! // and draw the map. Add an item to alert_list structure to keep track? ! ! // The last parameter denotes loading into pixmap_alerts instead of pixmap or pixmap_final ! // Here's the old APRS-type map call: ! //map_search (w, alert_scan, alert, &alert_count,(int)(alert_status[i + 2] == DATA_VIA_TNC || alert_status[i + 2] == DATA_VIA_LOCAL), DRAW_TO_PIXMAP_ALERTS); - // Check the zone name(s) to see which Shapefile(s) to use. ! switch (zone[4]) { ! case ('C'): // County File (c_16my01.shp) ! break; ! case ('A'): // County Warning File (w_24ja01.shp) ! break; ! case ('Z'): // Zone File (z_16mr01.shp, z_16my01.shp, mz24ja01.shp, oz09de99.shp) ! break; ! } ! ! ! **********************************************************/ ! void draw_shapefile_map (Widget w, ! char *dir, ! char *filenm, ! alert_entry * alert, ! char alert_color, ! int destination_pixmap, ! int draw_filled) { ! ! DBFHandle hDBF; ! SHPObject *object; ! static XPoint points[MAX_MAP_POINTS]; ! char file[MAX_FILENAME]; /* Complete path/name of image file */ ! char warning_text[MAX_FILENAME*2]; ! int *panWidth, i, fieldcount, recordcount, structure, ring; ! char ftype[15]; ! int nWidth, nDecimals; ! SHPHandle hSHP; ! int nShapeType, nEntities; ! double adfBndsMin[4], adfBndsMax[4]; ! char sType [15]= ""; ! unsigned long my_lat, my_long; ! long x,y; ! int ok, index; ! int polygon_hole_flag; ! int *polygon_hole_storage; ! GC gc_temp = NULL; ! XGCValues gc_temp_values; ! Region region[3]; ! int temp_region1; ! int temp_region2; ! int temp_region3; ! int gps_flag = 0; ! char gps_label[100]; ! int gps_color = 0x0c; ! int road_flag = 0; ! int lake_flag = 0; ! int river_flag = 0; ! int railroad_flag = 0; ! int path_flag = 0; ! int city_flag = 0; ! int quad_overlay_flag = 0; ! int mapshots_labels_flag = 0; ! int weather_alert_flag = 0; ! char *filename; // filename itself w/o directory ! char search_param1[10]; ! int search_field1 = 0; ! char search_param2[10]; ! int search_field2 = -1; ! int found_shape = -1; ! int start_record; ! int end_record; ! int ok_to_draw = 0; ! int high_water_mark_i = 0; ! int high_water_mark_index = 0; ! char quad_label[100]; ! char status_text[MAX_FILENAME]; ! ! typedef struct _label_string { ! char label[50]; ! int found; ! struct _label_string *next; ! } label_string; ! ! label_string *label_ptr = NULL; ! label_string *ptr2 = NULL; ! ! ! //fprintf(stderr,"*** Alert color: %d ***\n",alert_color); ! ! // We don't draw the shapes if alert_color == -1 ! if (alert_color != -1) ! ok_to_draw++; ! ! search_param1[0] = '\0'; ! search_param2[0] = '\0'; ! xastir_snprintf(file, sizeof(file), "%s/%s", dir, filenm); ! //fprintf(stderr,"draw_shapefile_map:start:%s\n",file); ! filename = filenm; ! i = strlen(filenm); ! while ( (filenm[i] != '/') && (i >= 0) ) ! filename = &filenm[i--]; ! //fprintf(stderr,"draw_shapefile_map:filename:%s\ttitle:%s\n",filename,alert->title); ! ! if (alert) ! weather_alert_flag++; ! ! // Check for maps/GPS directory. We set up the labels and ! // colors differently for these types of files. ! if (strstr(filenm,"GPS")) { // We're in the maps/GPS directory ! gps_flag++; ! } ! ! // Open the .dbf file for reading. This has the textual ! // data (attributes) associated with each shape. ! hDBF = DBFOpen( file, "rb" ); ! if ( hDBF == NULL ) { ! if (debug_level & 16) ! fprintf(stderr,"draw_shapefile_map: DBFOpen(%s,\"rb\") failed.\n", file ); ! return; ! } ! if (debug_level & 16) ! fprintf(stderr,"\n---------------------------------------------\nInfo for %s\n",filenm); ! fieldcount = DBFGetFieldCount(hDBF); ! if (fieldcount == (int)NULL) { ! DBFClose( hDBF ); // Clean up open file descriptors ! return; // Should have at least one field ! ! } ! recordcount = DBFGetRecordCount(hDBF); ! if (recordcount == (int)NULL) { ! DBFClose( hDBF ); // Clean up open file descriptors ! return; // Should have at least one record ! } ! if (debug_level & 16) ! fprintf(stderr,"%d Columns, %d Records in file\n", fieldcount, recordcount); ! panWidth = (int *) malloc( fieldcount * sizeof(int) ); ! CHECKMALLOC(panWidth); ! // Make sure to free(panWidth) everywhere we return from!!! ! ! // If we're doing weather alerts and index is not filled in yet ! if (weather_alert_flag && (alert->index == -1) ) { ! ! // For weather alerts: ! // Need to figure out from the initial characters of the filename which ! // type of file we're using, then compute the fields we're looking for. ! // After we know that, need to look in the DBF file for a match. Once ! // we find a match, we can open up the SHX/SHP files, go straight to ! // the shape we want, and draw it. ! switch (filenm[0]) { ! ! case 'c': // County File ! // County, c_ files: WI_C037 ! // STATE CWA COUNTYNAME ! // AL BMX Morgan ! // Need fields 0/1: ! search_field1 = 0; // STATE ! search_field2 = 3; // FIPS ! xastir_snprintf(search_param1,sizeof(search_param1),"%c%c", ! alert->title[0], ! alert->title[1]); ! xastir_snprintf(search_param2,sizeof(search_param2),"%c%c%c", ! alert->title[4], ! alert->title[5], ! alert->title[6]); ! break; ! ! case 'w': // County Warning Area File ! // County Warning Area, w_ files: CW_ATAE ! // WFO CWA ! // TAE TAE ! // Need field 0 ! search_field1 = 0; // WFO ! search_field2 = -1; ! xastir_snprintf(search_param1,sizeof(search_param1),"%c%c%c", ! alert->title[4], ! alert->title[5], ! alert->title[6]); ! break; ! ! case 'o': // Offshore Marine Area File ! // Offshore Marine Zones, oz files: AN_Z081 ! // ID WFO NAME ! // ANZ081 MPC Gulf of Maine ! // Need field 0 ! search_field1 = 0; // ID ! search_field2 = -1; ! xastir_snprintf(search_param1,sizeof(search_param1),"%c%c%c%c%c%c", ! alert->title[0], ! alert->title[1], ! alert->title[3], ! alert->title[4], ! alert->title[5], ! alert->title[6]); ! break; ! ! case 'm': // Marine Area File ! // Marine Zones, mz?????? files: PK_Z120 ! // ID WFO NAME ! // PKZ120 AJK Area 1B. Southeast Alaska, ! // Need field 0 ! search_field1 = 0; // ID ! search_field2 = -1; ! xastir_snprintf(search_param1,sizeof(search_param1),"%c%c%c%c%c%c", ! alert->title[0], ! alert->title[1], ! alert->title[3], ! alert->title[4], ! alert->title[5], ! alert->title[6]); ! break; ! ! case 'z': // Zone File ! default: ! // Weather alert zones, z_ files: KS_Z033 ! // STATE_ZONE ! // AK225 ! // Need field 4 ! search_field1 = 4; // STATE_ZONE ! search_field2 = -1; ! xastir_snprintf(search_param1,sizeof(search_param1),"%c%c%c%c%c", ! alert->title[0], ! alert->title[1], ! alert->title[4], ! alert->title[5], ! alert->title[6]); ! break; ! } ! ! //fprintf(stderr,"Search_param1: %s,\t",search_param1); ! //fprintf(stderr,"Search_param2: %s\n",search_param2); ! } ! ! for (i=0; i < fieldcount; i++) { ! char szTitle[12]; ! ! switch (DBFGetFieldInfo(hDBF, i, szTitle, &nWidth, &nDecimals)) { ! case FTString: ! strcpy(ftype, "string");; ! break; - case FTInteger: - strcpy(ftype, "integer"); - break; ! case FTDouble: ! strcpy(ftype, "float"); ! break; ! case FTInvalid: ! strcpy(ftype, "invalid/unsupported"); ! break; ! default: ! strcpy(ftype, "unknown"); ! break; } ! // Check for quad overlay type of map ! if (strstr(filename,"24kgrid")) { // USGS Quad overlay file ! quad_overlay_flag++; ! } ! // Check the filename for mapshots.com filetypes to see what ! // type of file we may be dealing with. ! if (strncasecmp(filename,"tgr",3) == 0) { // Found Mapshots or GeographyNetwork file ! if (strstr(filename,"lpt")) { // Point file ! mapshots_labels_flag++; ! if (debug_level & 16) { ! fprintf(stderr,"*** Found point file ***\n"); ! break; ! } ! else ! break; ! } ! else if (strstr(filename,"plc")) { // Designated Places: Arlington ! city_flag++; ! mapshots_labels_flag++; ! if (debug_level & 16) { ! fprintf(stderr,"*** Found (Designated Places) ***\n"); ! break; ! } ! else ! break; ! } ! else if (strstr(filename,"ctycu")) { // County Boundaries: WA, Snohomish ! if (debug_level & 16) { ! fprintf(stderr,"*** Found county (mapshots county) ***\n"); ! break; ! } ! else ! break; ! } ! else if (strstr(filename,"lkA")) { // Roads ! road_flag++; ! mapshots_labels_flag++; ! if (debug_level & 16) { ! fprintf(stderr,"*** Found some roads (mapshots roads) ***\n"); ! break; ! } ! else ! break; ! } ! else if (strstr(filename,"lkB")) { // Railroads ! railroad_flag++; ! mapshots_labels_flag++; ! if (debug_level & 16) { ! fprintf(stderr,"*** Found some railroads (mapshots railroads) ***\n"); ! break; ! } ! else ! break; ! } ! else if (strstr(filename,"lkC")) { // Paths/etc. Pipelines? Transmission lines? ! path_flag++; ! if (debug_level & 16) { ! fprintf(stderr,"*** Found some paths (mapshots paths/etc) ***\n"); ! break; ! } ! else ! break; ! } ! else if (strstr(filename,"lkH")) { // Rivers/Streams/Lakes/Glaciers ! river_flag++; ! mapshots_labels_flag++; ! if (debug_level & 16) { ! fprintf(stderr,"*** Found water (mapshots rivers/streams/lakes/glaciers) ***\n"); ! break; ! } ! else ! break; ! } ! else if (strstr(filename,"urb")) { // Urban areas: Seattle, WA ! if (debug_level & 16) { ! fprintf(stderr,"*** Found (mapshots urban areas) ***\n"); ! break; ! } ! else ! break; ! } ! else if (strstr(filename,"wat")) { // Bodies of water, creeks/lakes/glaciers ! lake_flag++; ! mapshots_labels_flag++; ! if (debug_level & 16) { ! fprintf(stderr,"*** Found some water (mapshots bodies of water, creeks/lakes/glaciers) ***\n"); ! break; ! } ! else ! break; ! } ! } ! // Attempt to guess which type of shapefile we're dealing ! // with, and how we should draw it. ! // If debug is on, we want to print out every field, otherwise ! // break once we've made our guess on the type of shapefile. ! if (debug_level & 16) ! fprintf(stderr,"%15.15s\t%15s (%d,%d)\n", szTitle, ftype, nWidth, nDecimals); ! ! if (strncasecmp(szTitle, "SPEEDLIM", 8) == 0) { ! // sewroads shapefile? ! road_flag++; ! if (debug_level & 16) ! fprintf(stderr,"*** Found some roads (SPEEDLIM*) ***\n"); ! else ! break; ! } ! else if (strncasecmp(szTitle, "US_RIVS_ID", 10) == 0) { ! // which shapefile? ! river_flag++; ! if (debug_level & 16) ! fprintf(stderr,"*** Found some rivers (US_RIVS_ID*) ***\n"); ! else ! break; ! } ! else if (strcasecmp(szTitle, "FEATURE") == 0) { ! char *attr_str; ! int j; ! for (j=0; j < recordcount; j++) { ! if (fieldcount >= (i+1)) { ! attr_str = (char*)DBFReadStringAttribute(hDBF, j, i); ! if (strncasecmp(attr_str, "LAKE", 4) == 0) { ! // NOAA Lakes and Water Bodies (lk17de98) shapefile ! lake_flag++; ! if (debug_level & 16) ! fprintf(stderr,"*** Found some lakes (FEATURE == LAKE*) ***\n"); ! break; ! } ! else if (strstr(attr_str, "Highway") != NULL || ! strstr(attr_str, "highway") != NULL || ! strstr(attr_str, "HIGHWAY") != NULL) { ! // NOAA Interstate Highways of the US (in011502) shapefile ! // NOAA Major Roads of the US (rd011802) shapefile ! road_flag++; ! if (debug_level & 16) ! fprintf(stderr,"*** Found some roads (FEATURE == *HIGHWAY*) ***\n"); ! break; ! } ! } ! } ! if (!(debug_level & 16) && (lake_flag || road_flag)) ! break; ! } ! else if (strcasecmp(szTitle, "LENGTH") == 0 || ! strcasecmp(szTitle, "RR") == 0 || ! strcasecmp(szTitle, "HUC") == 0 || ! strcasecmp(szTitle, "TYPE") == 0 || ! strcasecmp(szTitle, "SEGL") == 0 || ! strcasecmp(szTitle, "PMILE") == 0 || ! strcasecmp(szTitle, "ARBSUM") == 0 || ! strcasecmp(szTitle, "PNAME") == 0 || ! strcasecmp(szTitle, "OWNAME") == 0 || ! strcasecmp(szTitle, "PNMCD") == 0 || ! strcasecmp(szTitle, "OWNMCD") == 0 || ! strcasecmp(szTitle, "DSRR") == 0 || ! strcasecmp(szTitle, "DSHUC") == 0 || ! strcasecmp(szTitle, "USDIR") == 0) { ! // NOAA Rivers of the US (rv14fe02) shapefile ! // NOAA Rivers of the US Subset (rt14fe02) shapefile ! river_flag++; ! if (river_flag >= 14) { ! if (debug_level & 16) ! fprintf(stderr,"*** Found some rivers (NOAA Rivers of the US or Subset) ***\n"); ! else ! break; ! } ! } ! } - // Search for specific record if we're doing alerts - if (weather_alert_flag && (alert->index == -1) ) { - int done = 0; - char *string1; - char *string2; - // Step through all records - for( i = 0; i < recordcount && !done; i++ ) { - char *ptr; - switch (filenm[0]) { - case 'c': // County File - // Remember that there's only one place for - // internal storage of the DBF string. This is - // why this code is organized with two "if" - // statements. - if (fieldcount >= (search_field1 + 1) ) { - string1 = (char *)DBFReadStringAttribute(hDBF,i,search_field1); - if (!strncasecmp(search_param1,string1,2)) { - //fprintf(stderr,"Found state\n"); - if (fieldcount >= (search_field2 + 1) ) { - string2 = (char *)DBFReadStringAttribute(hDBF,i,search_field2); - ptr = string2; - ptr += 2; // Skip past first two characters of FIPS code - if (!strncasecmp(search_param2,ptr,3)) { - //fprintf(stderr,"Found it! %s\tShape: %d\n",string1,i); - done++; - found_shape = i; - } - } - } - } - break; - case 'w': // County Warning Area File - if (fieldcount >= (search_field1 + 1) ) { - string1 = (char *)DBFReadStringAttribute(hDBF,i,search_field1); - if ( !strncasecmp(search_param1,string1,strlen(string1)) - && (strlen(string1) != 0) ) { - //fprintf(stderr,"Found it! %s\tShape: %d\n",string1,i); - done++; - found_shape = i; - } - } - break; - case 'o': // Offshore Marine Area File - if (fieldcount >= (search_field1 + 1) ) { - string1 = (char *)DBFReadStringAttribute(hDBF,i,search_field1); - if ( !strncasecmp(search_param1,string1,strlen(string1)) - && (strlen(string1) != 0) ) { - //fprintf(stderr,"Found it! %s\tShape: %d\n",string1,i); - done++; - found_shape = i; - } - } - break; - case 'm': // Marine Area File - if (fieldcount >= (search_field1 + 1) ) { - string1 = (char *)DBFReadStringAttribute(hDBF,i,search_field1); - if ( !strncasecmp(search_param1,string1,strlen(string1)) - && (strlen(string1) != 0) ) { - //fprintf(stderr,"Found it! %s\tShape: %d\n",string1,i); - done++; - found_shape = i; - } - } - break; - case 'z': // Zone File - if (fieldcount >= (search_field1 + 1) ) { - string1 = (char *)DBFReadStringAttribute(hDBF,i,search_field1); - if ( !strncasecmp(search_param1,string1,strlen(string1)) - && (strlen(string1) != 0) ) { - //fprintf(stderr,"Found it! %s\tShape: %d\n",string1,i); - done++; - found_shape = i; - } - } - default: - break; - } - } - alert->index = found_shape; // Fill it in 'cuz we just found it - } - else if (weather_alert_flag) { - // We've been here before and we already know the index into the - // file to fetch this particular shape. - found_shape = alert->index; - } - //fprintf(stderr,"Found shape: %d\n", found_shape); - if (debug_level & 16) - fprintf(stderr,"Calling SHPOpen()\n"); ! // Open the .shx/.shp files for reading. ! // These are the index and the vertice files. ! hSHP = SHPOpen( file, "rb" ); ! if( hSHP == NULL ) { ! fprintf(stderr,"draw_shapefile_map: SHPOpen(%s,\"rb\") failed.\n", file ); ! DBFClose( hDBF ); // Clean up open file descriptors ! ! // Free up any malloc's that we did ! if (panWidth) ! free(panWidth); ! return; } - // Get the extents of the map file - SHPGetInfo( hSHP, &nEntities, &nShapeType, adfBndsMin, adfBndsMax ); - // Check whether we're indexing or drawing the map - if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS) - || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) { - xastir_snprintf(status_text, sizeof(status_text), langcode ("BBARSTA039"), filenm); - statusline(status_text,0); // Indexing ... ! // We're indexing only. Save the extents in the index. ! index_update_ll(filenm, // Filename only ! adfBndsMin[1], // Bottom ! adfBndsMax[1], // Top ! adfBndsMin[0], // Left ! adfBndsMax[0]); // Right ! ! DBFClose( hDBF ); // Clean up open file descriptors ! SHPClose( hSHP ); ! ! // Free up any malloc's that we did ! if (panWidth) ! free(panWidth); ! return; // Done indexing this file ! } ! else { ! xastir_snprintf(status_text, sizeof(status_text), langcode ("BBARSTA028"), filenm); ! statusline(status_text,0); // Loading ... } ! ! ! switch ( nShapeType ) { ! case SHPT_POINT: ! strcpy(sType,"Point"); ! break; - case SHPT_ARC: - strcpy(sType,"Polyline"); - break; - case SHPT_POLYGON: - strcpy(sType,"Polygon"); - break; - case SHPT_MULTIPOINT: - fprintf(stderr,"Multi-Point Shapefile format not implemented: %s\n",file); - strcpy(sType,"MultiPoint"); - DBFClose( hDBF ); // Clean up open file descriptors - SHPClose( hSHP ); - - // Free up any malloc's that we did - if (panWidth) - free(panWidth); - return; // Multipoint type. Not implemented yet. - break; ! default: ! DBFClose( hDBF ); // Clean up open file descriptors ! SHPClose( hSHP ); ! ! // Free up any malloc's that we did ! if (panWidth) ! free(panWidth); ! return; // Unknown type. Don't know how to process it. ! break; } - if (debug_level & 16) - fprintf(stderr,"%s(%d), %d Records in file\n",sType,nShapeType,nEntities); - if (debug_level & 16) - fprintf(stderr,"File Bounds: (%15.10g,%15.10g)\n\t(%15.10g,%15.10g)\n", - adfBndsMin[0], adfBndsMin[1], adfBndsMax[0], adfBndsMax[1] ); - // Check the bounding box for this shapefile. If none of the - // file is within our viewport, we can skip the entire file. - if (debug_level & 16) - fprintf(stderr,"Calling map_visible_lat_lon on the entire shapefile\n"); ! if (! map_visible_lat_lon( adfBndsMin[1], // Bottom ! adfBndsMax[1], // Top ! adfBndsMin[0], // Left ! adfBndsMax[0], // Right ! file) ) { // Error text if failure ! if (debug_level & 16) ! fprintf(stderr,"No shapes within viewport. Skipping file...\n"); ! DBFClose( hDBF ); // Clean up open file descriptors ! SHPClose( hSHP ); - // Free up any malloc's that we did - if (panWidth) - free(panWidth); - return; // The file contains no shapes in our viewport - } - // Update the statusline for this map name - // Check whether we're indexing or drawing the map - if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS) - || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) { - xastir_snprintf(status_text, sizeof(status_text), langcode ("BBARSTA039"), filenm); - } - else { - xastir_snprintf(status_text, sizeof(status_text), langcode ("BBARSTA028"), filenm); - } - statusline(status_text,0); // Loading/Indexing ... - - - // Set a default line width for all maps. This will most likely - // be modified for particular maps in later code. - (void)XSetLineAttributes(XtDisplay(w), gc, 0, LineSolid, CapButt,JoinMiter); - - - // NOTE: Setting the color here and in the "else" may not stick if we do more - // complex drawing further down like a SteelBlue lake with a black boundary, - // or if we have labels turned on which resets our color to black. - if (weather_alert_flag) { - char xbm_path[MAX_FILENAME]; - int _w, _h, _xh, _yh; - int ret_val; - - // This GC is used for weather alerts (writing to the - // pixmap: pixmap_alerts) and _was_ used for beam_heading - // rays, but no longer is. - (void)XSetForeground (XtDisplay (w), gc_tint, colors[(int)alert_color]); - - // N7TAP: No more tinting as that would change the color of the alert, losing that information. - (void)XSetFunction(XtDisplay(w), gc_tint, GXcopy); - /* - Options are: - GXclear 0 (Don't use) - GXand src AND dst (Darker colors, black can result from overlap) - GXandReverse src AND (NOT dst) (Darker colors) - GXcopy src (Don't use) - GXandInverted (NOT src) AND dst (Pretty colors) - GXnoop dst (Don't use) - GXxor src XOR dst (Don't use, overlapping areas cancel each other out) - GXor src OR dst (More pastel colors, too bright?) - GXnor (NOT src) AND (NOT dst) (Darker colors, very readable) - GXequiv (NOT src) XOR dst (Bright, very readable) - GXinvert (NOT dst) (Don't use) - GXorReverse src OR (NOT dst) (Bright, not as readable as others) - GXcopyInverted (NOT src) (Don't use) - GXorInverted (NOT src) OR dst (Bright, not very readable) - GXnand (NOT src) OR (NOT dst) (Bright, not very readable) - GXset 1 (Don't use) - */ - - if (strncasecmp(alert->alert_tag, "FLOOD", 5) == 0) - xastir_snprintf(xbm_path, sizeof(xbm_path), "%s/%s", SYMBOLS_DIR, "flood.xbm"); - else if (strncasecmp(alert->alert_tag, "SNOW", 4) == 0) - xastir_snprintf(xbm_path, sizeof(xbm_path), "%s/%s", SYMBOLS_DIR, "snow.xbm"); - else if (strncasecmp(alert->alert_tag, "TORNDO", 6) == 0) - xastir_snprintf(xbm_path, sizeof(xbm_path), "%s/%s", SYMBOLS_DIR, "tornado.xbm"); - else if (strncasecmp(alert->alert_tag, "WIND", 4) == 0) - xastir_snprintf(xbm_path, sizeof(xbm_path), "%s/%s", SYMBOLS_DIR, "wind.xbm"); - else if (strncasecmp(alert->alert_tag, "WINTER_STORM", 12) == 0) - xastir_snprintf(xbm_path, sizeof(xbm_path), "%s/%s", SYMBOLS_DIR, "wntr_strm.xbm"); - else if (strncasecmp(alert->alert_tag, "WINTER_WEATHER", 14) == 0) - xastir_snprintf(xbm_path, sizeof(xbm_path), "%s/%s", SYMBOLS_DIR, "winter_wx.xbm"); - else - xastir_snprintf(xbm_path, sizeof(xbm_path), "%s/%s", SYMBOLS_DIR, "alert.xbm"); - - (void)XSetLineAttributes(XtDisplay(w), gc_tint, 0, LineSolid, CapButt,JoinMiter); - XFreePixmap(XtDisplay(w), pixmap_wx_stipple); - ret_val = XReadBitmapFile(XtDisplay(w), DefaultRootWindow(XtDisplay(w)), - xbm_path, &_w, &_h, &pixmap_wx_stipple, &_xh, &_yh); ! if (ret_val != 0) { ! fprintf(stderr,"Bitmap not found: %s\n",xbm_path); ! exit(1); ! } ! (void)XSetStipple(XtDisplay(w), gc_tint, pixmap_wx_stipple); ! } ! else { ! // Are these actually used anymore by the code? Colors get set later ! // when we know more about what we're dealing with. ! if (lake_flag || river_flag) ! (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x1a]); // Steel Blue ! else if (path_flag) ! (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x08]); // black ! else if (railroad_flag) ! (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x01]); // purple ! else if (city_flag) ! (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x0e]); // yellow ! else ! (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x08]); // black } - // Now that we have the file open, we can read out the structures. - // We can handle Point, PolyLine and Polygon shapefiles at the moment. - if (weather_alert_flag) { // We're drawing _one_ weather alert shape - if (found_shape != -1) { // Found the record - start_record = found_shape; - end_record = found_shape + 1; - } - else { // Didn't find the record - start_record = 0; - end_record = 0; - } - } - else { // Draw an entire Shapefile map - start_record = 0; - end_record = nEntities; - } ! // Here's where we actually iterate through the entire file, drawing ! // each structure as we find it. ! for (structure = start_record; structure < end_record; structure++) { ! int skip_it = 0; ! int skip_label = 0; ! // Have had segfaults before at the SHPReadObject() call ! // when the Shapefile was corrupted. ! //fprintf(stderr,"Before SHPReadObject:%d\n",structure); - object = SHPReadObject( hSHP, structure ); // Note that each structure can have multiple rings ! //fprintf(stderr,"After SHPReadObject\n"); - if (object == NULL) - continue; // Skip this iteration, go on to the next ! // Fill in the boundary variables in the alert record. We use ! // this info in load_alert_maps() to determine which alerts are ! // within our view, without having to open up the shapefiles to ! // get this info (faster). ! if (weather_alert_flag) { ! alert->top_boundary = object->dfYMax; ! alert->left_boundary = object->dfXMin; ! alert->bottom_boundary = object->dfYMin; ! alert->right_boundary = object->dfXMax; ! } - // Here we check the bounding box for this shape against our - // current viewport. If we can't see it, don't draw it. ! if (debug_level & 16) ! fprintf(stderr,"Calling map_visible_lat_lon on a shape\n"); - // Set up some warning text just in case the map has a - // problem. - xastir_snprintf(warning_text, - sizeof(warning_text), - "File:%s, Structure:%d", - file, - structure); ! //fprintf(stderr,"%s\n",warning_text); - if ( map_visible_lat_lon( object->dfYMin, // Bottom - object->dfYMax, // Top - object->dfXMin, // Left - object->dfXMax, // Right - warning_text) ) { // Error text if failure ! const char *temp; ! char temp2[100]; ! int jj; ! int x0 = 0; // Used for computing label rotation ! int x1 = 0; ! int y0 = 0; ! int y1 = 0; - if (debug_level & 16) { - fprintf(stderr,"Shape %d is visible, drawing it.", structure); - fprintf(stderr," Parts in shape: %d\n", object->nParts ); // Number of parts in this structure - } ! if (alert) ! alert->flags[0] = 'Y'; ! if (debug_level & 16) { ! // Print the field contents ! for (jj = 0; jj < fieldcount; jj++) { ! if (fieldcount >= (jj + 1) ) { ! temp = DBFReadStringAttribute( hDBF, structure, jj ); ! if (temp != NULL) { ! fprintf(stderr,"%s, ", temp); ! } ! } ! } ! fprintf(stderr,"\n"); ! fprintf(stderr,"Done with field contents\n"); ! } ! switch ( nShapeType ) { ! case SHPT_POINT: ! // We hit this case once for each point shape in ! // the file, iff that shape is within our ! // viewport. ! if (debug_level & 16) ! fprintf(stderr,"Found Point Shapefile\n"); - // Read each point, place a label there, and an optional symbol - //object->padfX - //object->padfY - //object->padfZ - - // if ( mapshots_labels_flag - // && map_labels - // && (fieldcount >= 3) ) { - - if (1) { // Need a bracket so we can define - // some local variables. - const char *temp = NULL; - int ok = 1; - int temp_ok; - - // If labels are enabled and we have enough - // fields in the .dbf file, read the label. - if (map_labels && fieldcount >= 1) { - // Snag the label from the .dbf file - temp = DBFReadStringAttribute( hDBF, structure, 0 ); - } ! // Convert point to Xastir coordinates ! temp_ok = convert_to_xastir_coordinates(&my_long, ! &my_lat, ! (float)object->padfX[0], ! (float)object->padfY[0]); ! //fprintf(stderr,"%ld %ld\n", my_long, my_lat); ! ! if (!temp_ok) { ! fprintf(stderr,"draw_shapefile_map: Problem converting from lat/lon\n"); ! ok = 0; ! x = 0; ! y = 0; ! } ! else { ! // Convert to screen coordinates. Careful ! // here! The format conversions you'll need ! // if you try to compress this into two ! // lines will get you into trouble. ! x = my_long - x_long_offset; ! y = my_lat - y_lat_offset; ! x = x / scale_x; ! y = y / scale_y; ! ! if (x > 16000) ok = 0; // Skip this point ! if (x < -16000) ok = 0; // Skip this point ! if (y > 16000) ok = 0; // Skip this point ! if (y < -16000) ok = 0; // Skip this point ! } - if (ok == 1) { - char symbol_table = '/'; - char symbol_id = '.'; /* small x */ - char symbol_over = ' '; - - // Fine-tuned the location here so that - // the middle of the 'X' would be at the - // proper pixel. - symbol(w, 0, symbol_table, symbol_id, symbol_over, pixmap, 1, x-10, y-10, ' '); - - // Fine-tuned this string so that it is - // to the right of the 'X' and aligned - // nicely. - if (map_labels) { - draw_nice_string(w, pixmap, 0, x+10, y+5, (char*)temp, 0xf, 0x10, strlen(temp)); - //(void)draw_label_text ( w, x, y, strlen(temp), colors[0x08], (char *)temp); - //(void)draw_rotated_label_text (w, 90, x+10, y, strlen(temp), colors[0x08], (char *)temp); - } - } - } - break; ! case SHPT_ARC: ! // We hit this case once for each polyline shape ! // in the file, iff at least part of that shape ! // is within our viewport. - if (debug_level & 16) - fprintf(stderr,"Found Polylines\n"); ! // Draw the PolyLines themselves: - // Default in case we forget to set the line - // width later: - (void)XSetLineAttributes (XtDisplay (w), gc, 0, LineSolid, CapButt,JoinMiter); - - index = 0; // Index into our own points array. - // Tells how many points we've - // collected so far. - - // Read the vertices for each line - for (ring = 0; ring < object->nVertices; ring++ ) { - int temp_ok; - - ok = 1; - - //fprintf(stderr,"\t%d:%g %g\t", ring, object->padfX[ring], object->padfY[ring] ); - // Convert to Xastir coordinates - temp_ok = convert_to_xastir_coordinates(&my_long, - &my_lat, - (float)object->padfX[ring], - (float)object->padfY[ring]); - //fprintf(stderr,"%ld %ld\n", my_long, my_lat); - - if (!temp_ok) { - fprintf(stderr,"draw_shapefile_map: Problem converting from lat/lon\n"); - ok = 0; - x = 0; - y = 0; - } - else { - // Convert to screen coordinates. Careful - // here! The format conversions you'll need - // if you try to compress this into two - // lines will get you into trouble. - x = my_long - x_long_offset; - y = my_lat - y_lat_offset; - x = x / scale_x; - y = y / scale_y; - - - // Save the endpoints of the first line - // segment for later use in label rotation - if (ring == 0) { - // Save the first set of screen coordinates - x0 = (int)x; - y0 = (int)y; - } - else if (ring == 1) { - // Save the second set of screen coordinates - x1 = (int)x; - y1 = (int)y; - } - - // XDrawLines uses 16-bit unsigned integers - // (shorts). Make sure we stay within the - // limits. - if (x > 16000) ok = 0; // Skip this point - if (x < -16000) ok = 0; // Skip this point - if (y > 16000) ok = 0; // Skip this point - if (y < -16000) ok = 0; // Skip this point - } - - if (ok == 1) { - points[index].x = (short)x; - points[index].y = (short)y; - //fprintf(stderr,"%d %d\t", points[index].x, points[index].y); - index++; - } - if (index > high_water_mark_index) - high_water_mark_index = index; ! if (index >= MAX_MAP_POINTS) { ! index = MAX_MAP_POINTS - 1; ! fprintf(stderr,"Trying to overrun the points array: SHPT_ARC, index=%d\n",index); ! } ! } ! ! // Set up width and zoom level for roads ! if (road_flag) { ! int lanes = 0; ! int dashed_line = 0; ! ! if ( mapshots_labels_flag && (fieldcount >= 9) ) { ! const char *temp; ! ! temp = DBFReadStringAttribute( hDBF, structure, 8 ); // CFCC Field ! switch (temp[1]) { ! case '1': // A1? = Primary road or interstate highway ! lanes = 4; ! (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x04]); // brown ! break; ! case '2': // A2? = Primary road w/o limited access, US highways ! lanes = 3; ! (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x08]); // black ! break; ! case '3': // A3? = Secondary road & connecting road, state highways ! if (map_color_levels && scale_y > 256) ! skip_label++; ! lanes = 2; ! (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x08]); // black ! switch (temp[2]) { ! case '1': ! case '2': ! case '3': ! case '4': ! case '5': ! case '6': ! break; ! case '7': ! case '8': ! default: ! if (map_color_levels && scale_y > 128) ! skip_label++; ! break; ! } ! break; ! case '4': // A4? = Local, neighborhood & rural roads, city streets ! // Skip the road if we're above this zoom level ! if (map_color_levels && scale_y > 96) ! skip_it++; ! // Skip labels above this zoom level to keep things uncluttered ! if (map_color_levels && scale_y > 16) ! skip_label++; ! lanes = 1; ! (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x28]); // gray35 ! break; ! case '5': // A5? = Vehicular trail passable only by 4WD vehicle ! // Skip the road if we're above this zoom level ! if (map_color_levels && scale_y > 64) ! skip_it++; ! if (map_color_levels && scale_y > 16) ! skip_label++; ! lanes = 1; ! dashed_line++; ! (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x28]); // gray35 ! break; ! case '6': // A6? = Cul-de-sac, traffic circles, access ramp, ! // service drive, ferry crossing ! switch (temp[2]) { ! case '5': // Ferry crossing ! lanes = 2; ! dashed_line++; ! (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x08]); // black ! break; ! default: ! lanes = 1; ! // Skip the road if we're above this zoom level ! if (map_color_levels && scale_y > 64) ! skip_it++; ! if (map_color_levels && scale_y > 16) ! skip_label++; ! (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x28]); // gray35 ! break; ! } ! ! break; ! case '7': // A7? = Walkway or pedestrian trail, stairway, ! // alley, driveway or service road ! // Skip the road if we're above this zoom level ! if (map_color_levels && scale_y > 64) ! skip_it++; ! if (map_color_levels && scale_y > 16) ! skip_label++; ! lanes = 1; ! dashed_line++; ! ! switch (temp[2]) { ! case '1': // Walkway or trail for pedestrians ! case '2': // Stairway or stepped road for pedestrians ! (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x0c]); // red ! break; ! default: ! (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x28]); // gray35 ! break; ! } ! ! break; ! default: ! lanes = 1; ! (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x28]); // gray35 ! break; ! } ! } ! else { // Must not be a mapshots or ESRI Tiger map ! if (fieldcount >= 7) { // Need at least 7 fields if we're snagging #6, else segfault ! lanes = DBFReadIntegerAttribute( hDBF, structure, 6 ); ! ! // In case we guess wrong on the ! // type of file and the lanes are ! // really out of bounds: ! if (lanes < 1 || lanes > 10) { ! //fprintf(stderr,"lanes = %d\n",lanes); ! lanes = 1; ! } ! } ! (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x28]); // gray35 ! } ! ! if (lanes != (int)NULL) { ! if (dashed_line) { ! (void)XSetLineAttributes (XtDisplay (w), gc, 1, LineOnOffDash, CapButt,JoinMiter); ! } ! else { ! (void)XSetLineAttributes (XtDisplay (w), gc, lanes, LineSolid, CapButt,JoinMiter); ! } ! } ! else { ! (void)XSetLineAttributes (XtDisplay (w), gc, 1, LineSolid, CapButt,JoinMiter); ! } ! } ! ! // Set up width and zoom levels for water ! else if (river_flag || lake_flag) { ! int lanes = 0; ! int dashed_line = 0; ! int glacier_flag = 0; ! ! if ( mapshots_labels_flag && (fieldcount >= 9) ) { ! const char *temp; ! ! temp = DBFReadStringAttribute( hDBF, structure, 8 ); // CFCC Field ! switch (temp[1]) { ! case '0': // H0? = Water feature/shoreline ! if (map_color_levels && scale_y > 16) ! skip_label++; ! lanes = 0; ! ! switch (temp[2]) { ! case '2': // Intermittent ! dashed_line++; ! break; ! default: ! break; ! } ! ! break; ! case '1': ! if (map_color_levels && scale_y > 128) ! skip_label++; ! switch (temp[2]) { ! case '0': ! if (map_color_levels && scale_y > 16) ! skip_label++; ! lanes = 1; ! break; ! case '1': ! if (map_color_levels && scale_y > 16) ! skip_label++; ! lanes = 1; ! break; ! case '2': ! if (map_color_levels && scale_y > 16) ! skip_label++; ! lanes = 1; ! dashed_line++; ! break; ! case '3': ! if (map_color_levels && scale_y > 16) ! skip_label++; ! lanes = 1; ! break; ! default: ! if (map_color_levels && scale_y > 16) ! skip_label++; ! lanes = 1; ! break; ! } ! break; ! case '2': ! if (map_color_levels && scale_y > 16) ! skip_label++; ! lanes = 1; ! ! switch (temp[2]) { ! case '2': // Intermittent ! dashed_line++; ! break; ! default: ! break; ! } ! ! break; ! case '3': ! if (map_color_levels && scale_y > 16) ! skip_label++; ! lanes = 1; ! ! switch (temp[2]) { ! case '2': // Intermittent ! dashed_line++; ! break; ! default: ! break; ! } ! ! break; ! case '4': ! if (map_color_levels && scale_y > 16) ! skip_label++; ! lanes = 1; ! ! switch (temp[2]) { ! case '2': // Intermittent ! dashed_line++; ! break; ! default: ! break; ! } ! ! break; ! case '5': ! if (map_color_levels && scale_y > 16) ! skip_label++; ! lanes = 1; ! break; ! case '6': ! if (map_color_levels && scale_y > 16) ! skip_label++; ! lanes = 1; ! break; ! case '7': // Nonvisible stuff. Don't draw these ! skip_it++; ! skip_label++; ! break; ! case '8': ! if (map_color_levels && scale_y > 16) ! skip_label++; ! lanes = 1; ! ! switch (temp[2]) { ! case '1': // Glacier ! glacier_flag++; ! break; ! default: ! break; ! } ! ! break; ! default: ! if (map_color_levels && scale_y > 16) ! skip_label++; ! lanes = 1; ! break; ! } ! if (dashed_line) { ! (void)XSetLineAttributes (XtDisplay (w), gc, lanes, LineOnOffDash, CapButt,JoinMiter); ! } ! else { ! (void)XSetLineAttributes (XtDisplay (w), gc, lanes, LineSolid, CapButt,JoinMiter); ! } ! } ! else { // We don't know how wide to make it, not a mapshots or ESRI Tiger maps ! if (dashed_line) { ! (void)XSetLineAttributes (XtDisplay (w), gc, 0, LineOnOffDash, CapButt,JoinMiter); ! } ! else { ! (void)XSetLineAttributes (XtDisplay (w), gc, 0, LineSolid, CapButt,JoinMiter); ! } ! } ! if (glacier_flag) ! (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x0f]); // white ! else ! (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x1a]); // Steel Blue ! } // End of river_flag/lake_flag code ! ! else { // Set default line width, use whatever color is already defined by this point. ! (void)XSetLineAttributes (XtDisplay (w), gc, 0, LineSolid, CapButt,JoinMiter); ! } ! ! ! //WE7U ! // I'd like to be able to change the color of each GPS track for ! // each team in the field. It'll help to differentiate the tracks ! // where they happen to cross. ! ! if (gps_flag) { ! int jj; ! int done = 0; ! ! ! // Fill in the label we'll use later ! xastir_snprintf(gps_label, ! sizeof(gps_label), ! filename); ! ! // Knock off the "_Color.shp" portion of the ! // label. Find the last underline character ! // and change it to an end-of-string. ! jj = strlen(gps_label); ! while ( !done && (jj > 0) ) { ! if (gps_label[jj] == '_') { ! gps_label[jj] = '\0'; // Terminate it here ! done++; ! } ! jj--; ! } ! ! ! // Check for a color in the filename: i.e. ! // "Team2_Track_Red.shp" ! if (strstr(filenm,"_Red.shp")) { ! gps_color = 0x0c; // Red ! } ! else if (strstr(filenm,"_Green.shp")) { ! // gps_color = 0x64; // ForestGreen ! gps_color = 0x23; // Area Green Hi ! } ! else if (strstr(filenm,"_Black.shp")) { ! gps_color = 0x08; // black ! } ! else if (strstr(filenm,"_White.shp")) { ! gps_color = 0x0f; // white ! } ! else if (strstr(filenm,"_Orange.shp")) { ! // gps_color = 0x06; // orange ! // gps_color = 0x19; // orange2 ! // gps_color = 0x41; // DarkOrange3 (good medium orange) ! gps_color = 0x62; // orange3 (brighter) ! } ! else if (strstr(filenm,"_Blue.shp")) { ! gps_color = 0x03; // cyan ! } ! else if (strstr(filenm,"_Yellow.shp")) { ! gps_color = 0x0e; // yellow ! } ! else if (strstr(filenm,"_Purple.shp")) { ! gps_color = 0x0b; // mediumorchid ! } ! else { // Default color ! gps_color = 0x0c; // Red ! } ! ! // Set the color for the arc's ! (void)XSetForeground(XtDisplay(w), gc, colors[gps_color]); ! ! // Make the track nice and wide: Easy to ! // see. ! // (void)XSetLineAttributes (XtDisplay (w), gc, 3, LineSolid, CapButt,JoinMiter); ! (void)XSetLineAttributes (XtDisplay (w), gc, 3, LineOnOffDash, CapButt,JoinMiter); ! // (void)XSetLineAttributes (XtDisplay (w), gc, 3, LineDoubleDash, CapButt,JoinMiter); ! } ! ! ! if (ok_to_draw && !skip_it) { ! (void)XDrawLines(XtDisplay(w), pixmap, gc, points, index, CoordModeOrigin); ! } ! ! ! // Figure out and draw the labels for PolyLines. Note that we later ! // determine whether we want to draw the label at all. Move all ! // code possible below that decision point to keep everything fast. ! // Don't do unnecessary calculations if we're not going to draw the ! // label. ! ! // We're done with drawing the arc's. Draw the ! // labels in this next section. ! // ! temp = ""; ! if ( !skip_label ! && !skip_it ! && map_labels ! && road_flag) { ! char a[2],b[2],c[2]; ! ! if ( (mapshots_labels_flag) && (fieldcount >= 8) ) { ! char temp3[3]; ! char temp4[31]; ! char temp5[5]; ! char temp6[3]; ! ! temp = DBFReadStringAttribute( hDBF, structure, 4 ); ! xastir_snprintf(temp3,sizeof(temp3),"%s",temp); ! temp = DBFReadStringAttribute( hDBF, structure, 5 ); ! xastir_snprintf(temp4,sizeof(temp4),"%s",temp); ! temp = DBFReadStringAttribute( hDBF, structure, 6 ); ! xastir_snprintf(temp5,sizeof(temp5),"%s",temp); ! temp = DBFReadStringAttribute( hDBF, structure, 7 ); ! xastir_snprintf(temp6,sizeof(temp6),"%s",temp); ! ! // Take care to not insert spaces if ! // some of the strings are empty. ! if (strlen(temp3) != 0) strcpy(a," "); ! else a[0] = '\0'; ! if (strlen(temp4) != 0) strcpy(b," "); ! else b[0] = '\0'; ! if (strlen(temp5) != 0) strcpy(c," "); ! else c[0] = '\0'; ! ! xastir_snprintf(temp2,sizeof(temp2),"%s%s%s%s%s%s%s", ! temp3,a,temp4,b,temp5,c,temp6); ! temp = temp2; ! } ! else if (fieldcount >=10) { // Need at least 10 fields if we're snagging #9, else segfault ! // For roads, we need to use SIGN1 if it exists, else use DESCRIP if it exists. ! temp = DBFReadStringAttribute( hDBF, structure, 9 ); // SIGN1 ! } ! if ( (temp == NULL) || (strlen(temp) == 0) ) { ! if (fieldcount >=13) // Need at least 13 fields if we're snagging #12, else segfault ! temp = DBFReadStringAttribute( hDBF, structure, 12 ); // DESCRIP ! else ! temp = NULL; ! } ! } ! else if (!skip_label ! && map_labels ! && !skip_it ! && (lake_flag || river_flag) ) { ! ! if ( mapshots_labels_flag && river_flag && (fieldcount >= 8) ) { ! char temp3[3]; ! char temp4[31]; ! char temp5[5]; ! char temp6[3]; ! ! ! temp = DBFReadStringAttribute( hDBF, structure, 4 ); ! xastir_snprintf(temp3,sizeof(temp3),"%s",temp); ! temp = DBFReadStringAttribute( hDBF, structure, 5 ); ! xastir_snprintf(temp4,sizeof(temp4),"%s",temp); ! temp = DBFReadStringAttribute( hDBF, structure, 6 ); ! xastir_snprintf(temp5,sizeof(temp5),"%s",temp); ! temp = DBFReadStringAttribute( hDBF, structure, 7 ); ! xastir_snprintf(temp6,sizeof(temp6),"%s",temp); ! xastir_snprintf(temp2,sizeof(temp2),"%s %s %s %s", ! temp3,temp4,temp5,temp6); ! temp = temp2; ! } ! else if (mapshots_labels_flag && lake_flag && (fieldcount >= 4) ) { ! temp = DBFReadStringAttribute( hDBF, structure, 3 ); ! } ! else if (fieldcount >=14) { // Need at least 14 fields if we're snagging #13, else segfault ! temp = DBFReadStringAttribute( hDBF, structure, 13 ); // PNAME (rivers) ! } ! else ! temp = NULL; ! } ! ! ! // First we need to convert over to using the ! // temp2 variable, which is changeable. Make ! // temp point to it. temp may already be ! // pointing to the temp2 variable. ! ! if (temp != temp2) { ! // temp points to an unchangeable string ! ! if (temp != NULL) { // NOAA interstates file has a NULL at this point ! strncpy(temp2,temp,sizeof(temp2)); // Copy the string so we can change it ! temp = temp2; // Point temp to it (for later use) ! } ! else { ! temp2[0] = '\0'; ! } ! } ! else { // We're already set to work on temp2! ! } ! ! ! if ( map_labels && gps_flag ) { ! // We're drawing GPS info. Use gps_label, ! // overriding anything set before. ! xastir_snprintf(temp2, ! sizeof(temp2), ! "%s", ! gps_label); ! } ! ! ! // Change "United States Highway 2" into "US 2" ! // Look for substring at start of string ! if ( strstr(temp2,"United States Highway") == temp2 ) { ! int index; ! // Convert to "US" ! temp2[1] = 'S'; // Add an 'S' ! index = 2; ! while (temp2[index+19] != '\0') { ! temp2[index] = temp2[index+19]; ! index++; ! } ! temp2[index] = '\0'; ! } ! else { // Change "State Highway 204" into "State 204" ! // Look for substring at start of string ! if ( strstr(temp2,"State Highway") == temp2 ) { ! int index; ! // Convert to "State" ! index = 5; ! while (temp2[index+8] != '\0') { ! temp2[index] = temp2[index+8]; ! index++; ! } ! temp2[index] = '\0'; ! } ! else { // Change "State Route 2" into "State 2" ! // Look for substring at start of string ! if ( strstr(temp2,"State Route") == temp2 ) { ! int index; ! // Convert to "State" ! index = 5; ! while (temp2[index+6] != '\0') { ! temp2[index] = temp2[index+6]; ! index++; ! } ! temp2[index] = '\0'; ! } ! } ! } ! ! if ( (temp != NULL) ! && (strlen(temp) != 0) ! && map_labels ! && !skip_it ! && !skip_label ) { ! int temp_ok; ! ! ok = 1; ! ! // Convert to Xastir coordinates ! temp_ok = convert_to_xastir_coordinates(&my_long, ! &my_lat, ! (float)object->padfX[0], ! (float)object->padfY[0]); ! //fprintf(stderr,"%ld %ld\n", my_long, my_lat); ! ! if (!temp_ok) { ! fprintf(stderr,"draw_shapefile_map: Problem converting from lat/lon\n"); ! ok = 0; ! x = 0; ! y = 0; ! } ! else { ! // Convert to screen coordinates. Careful ! // here! The format conversions you'll need ! // if you try to compress this into two ! // lines will get you into trouble. ! x = my_long - x_long_offset; ! y = my_lat - y_lat_offset; ! x = x / scale_x; ! y = y / scale_y; ! ! if (x > 16000) ok = 0; // Skip this point ! if (x < -16000) ok = 0; // Skip this point ! if (y > 16000) ok = 0; // Skip this point ! if (y < -16000) ok = 0; // Skip this point ! } ! ! if (ok == 1 && ok_to_draw) { ! int new_label = 1; ! int mod_number; ! ! // Set up the mod_number, which is used ! // below to determine how many of each ! // identical label are skipped at each ! // zoom level. ! if (scale_y <= 2) ! mod_number = 1; ! else if (scale_y <= 4) ! mod_number = 3; ! else if (scale_y <= 8) ! mod_number = 5; ! else if (scale_y <= 16) ! mod_number = 10; ! else if (scale_y <= 32) ! mod_number = 15; ! else ! mod_number = 20; ! ! // Check whether we've written out this string ! // already: Look for a match in our linked list ! ! // The problem with this method is that we might get strings ! // "written" at the extreme top or right edge of the display, which ! // means the strings wouldn't be visible, but Xastir thinks that it ! // wrote the string out visibly. To partially counteract this I've ! // set it up to write only some of the identical strings. This ! // still doesn't help in the cases where a street only comes in from ! // the top or right and doesn't have an intersection with another ! // street (and therefore another label) within the view. ! ! ptr2 = label_ptr; ! while (ptr2 != NULL) { // Step through the list ! if (strcasecmp(ptr2->label,temp) == 0) { // Found a match ! //fprintf(stderr,"Found a match!\t%s\n",temp); ! new_label = 0; ! ptr2->found = ptr2->found + 1; // Increment the "found" quantity ! ! // We change this "mod" number based on zoom level, so that long ! // strings don't overwrite each other, and so that we don't get too ! // many or too few labels drawn. This will cause us to skip ! // intersections (the tiger files appear to have a label at each ! // intersection). Between rural and urban areas, this method might ! // not work well. Urban areas have few intersections, so we'll get ! // fewer labels drawn. ! // A better method might be to check the screen location for each ! // one and only write the strings if they are far enough apart, and ! // only count a string as written if the start of it is onscreen and ! // the angle is correct for it to be written on the screen. ! ! // Draw a number of labels ! // appropriate for the zoom ! // level. ! if ( ((ptr2->found - 1) % mod_number) != 0 ) ! skip_label++; ! ptr2 = NULL; // End the loop ! } ! else { ! ptr2 = ptr2->next; ! } ! } ! if (!skip_label) { // Draw the string ! ! // Compute the label rotation angle ! float diff_X = (int)x1 - x0; ! float diff_Y = (int)y1 - y0; ! float angle = 0.0; // Angle for the beginning of this polyline ! ! if (diff_X == 0.0) { // Avoid divide by zero errors ! diff_X = 0.0000001; ! } ! angle = atan( diff_X / diff_Y ); // Compute in radians ! // Convert to degrees ! angle = angle / (2.0 * M_PI ); ! angle = angle * 360.0; ! ! // Change to fit our rotate label function's idea of angle ! angle = 360.0 - angle; ! ! //fprintf(stderr,"Y: %f\tX: %f\tAngle: %f ==> ",diff_Y,diff_X,angle); ! ! if ( angle > 90.0 ) {angle += 180.0;} ! if ( angle >= 360.0 ) {angle -= 360.0;} ! ! //fprintf(stderr,"%f\t%s\n",angle,temp); ! ! // (void)draw_label_text ( w, x, y, strlen(temp), colors[0x08], (char *)temp); ! if (gps_flag) { ! (void)draw_rotated_label_text (w, ! //(int)angle, ! -90, // Horizontal, easiest to read ! x, ! y, ! strlen(temp), ! colors[gps_color], ! (char *)temp); ! } ! else { ! (void)draw_rotated_label_text(w, ! (int)angle, ! x, ! y, ! strlen(temp), ! colors[0x08], ! (char *)temp); ! } ! } ! if (new_label) { ! ! // Create a new record for this string ! // and add it to the head of the list. ! // Make sure to "free" this linked ! // list. ! //fprintf(stderr,"Creating a new record: %s\n",temp); ! ptr2 = (label_string *)malloc(sizeof(label_string)); ! xastir_snprintf(ptr2->label,sizeof(ptr2->label),"%s",temp); ! ptr2->found = 1; ! ptr2->next = label_ptr; ! label_ptr = ptr2; ! //if (label_ptr->next == NULL) ! // fprintf(stderr,"only one record\n"); ! } ! } ! } ! break; ! ! ! ! case SHPT_POLYGON: ! ! if (debug_level & 16) ! fprintf(stderr,"Found Polygons\n"); ! ! // Each polygon can be made up of multiple ! // rings, and each ring has multiple points that ! // define it. We hit this case once for each ! // polygon shape in the file, iff at least part ! // of that shape is within our viewport. ! ! // We now handle the "hole" drawing in polygon shapefiles, where ! // clockwise direction around the ring means a fill, and CCW means a ! // hole in the polygon. ! // ! // Possible implementations: ! // ! // 1) Snag an algorithm for a polygon "fill" function from ! // somewhere, but add a piece that will check for being inside a ! // "hole" polygon and just not draw while traversing it (change the ! // pen color to transparent over the holes?). ! // SUMMARY: How to do this? ! // ! // 2) Draw to another layer, then copy only the filled pixels to ! // their final destination pixmap. ! // SUMMARY: Draw polygons once, then a copy operation. ! // ! // 3) Separate area: Draw polygon. Copy from other map layer into ! // holes, then copy the result back. ! // SUMMARY: How to determine outline? ! // ! // 4) Use clip-masks to prevent drawing over the hole areas: Draw ! // to another 1-bit pixmap or region. This area can be the size of ! // the max shape extents. Filled = 1. Holes = 0. Use that pixmap ! // as a clip-mask to draw the polygons again onto the final pixmap. ! // SUMMARY: We end up drawing the shape twice! ! // ! // MODIFICATION: Draw a filled rectangle onto the map pixmap using ! // the clip-mask to control where it actually gets drawn. ! // SUMMARY: Only end up drawing the shape once. ! // ! // 5) Inverted clip-mask: Draw just the holes to a separate pixmap: ! // Create a pixmap filled with 1's (XFillRectangle & GXset). Draw ! // the holes and use GXinvert to draw zero's to the mask where the ! // holes go. Use this as a clip-mask to draw the filled areas of ! // the polygon to the map pixmap. ! // SUMMARY: Faster than methods 1-4? ! // ! // 6) Use Regions to do the same method as #5 but with more ease. ! // Create a polygon Region, then create a Region for each hole and ! // subtract the hole from the polygon Region. Once we have a ! // complete polygon + holes, use that as the clip-mask for drawing ! // the real polygon. Use XSetRegion() on the GC to set this up. We ! // might have to do offsets as well so that the region maps properly ! // to our map pixmap when we draw the final polygon to it. ! // SUMMARY: Should be faster than methods 1-5. ! // ! // 7) Do method 6 but instead of drawing a polygon region, draw a ! // rectangle region first, then knock holes in it. Use that region ! // as the clip-mask for the XFillPolygon() later by calling ! // XSetRegion() on the GC. We don't really need a polygon region ! // for a clip-mask. A rectangle with holes in it will work just as ! // well and should be faster overall. We might have to do offsets ! // as well so that the region maps properly to our map pixmap when ! // we draw the final polygon to it. ! // SUMMARY: This might be the fastest method of the ones listed, if ! // drawing a rectangle region is faster than drawing a polygon ! // region. We draw the polygon once here instead of twice, and each ! // hole only once. The only added drawing time would be the ! // creation of the rectangle region, which should be fairly fast, ! // and the subtracting of the hole regions from it. ! // ! // ! // Shapefiles also allow identical points to be next to each other ! // in the vertice list. We should look for that and get rid of ! // duplicate vertices. ! ! ! //if (object->nParts > 1) ! //fprintf(stderr,"Number of parts: %d\n", object->nParts); ! ! ! // Unfortunately, for Polygon shapes we must make one pass through ! // the entire set of rings to see if we have any "hole" rings (as ! // opposed to "fill" rings). If we have any "hole" rings, we must ! // handle the drawing of the Shape quite differently. ! // ! // Read the vertices for each ring in the Shape. Test whether we ! // have a hole ring. If so, save the ring index away for the next ! // step when we actually draw the shape. ! ! polygon_hole_flag = 0; ! ! // Allocate storage for a flag for each ring in ! // this Shape. ! // !!Remember to free this storage later!! ! polygon_hole_storage = (int *)malloc(object->nParts*sizeof(int)); ! ! // Run through the entire shape (all rings of it) once. Create an ! // array of flags that specify whether each ring is a fill or a ! // hole. If any holes found, set the global polygon_hole_flag as ! // well. ! ! for (ring = 0; ring < object->nParts; ring++ ) { ! ! // Testing for fill or hole ring. This will ! // determine how we ultimately draw the ! // entire shape. ! // ! switch ( shape_ring_direction( object, ring) ) { ! case 0: // Error in trying to compute whether fill or hole ! fprintf(stderr,"Error in computing fill/hole ring\n"); ! case 1: // It's a fill ring ! // Do nothing for these two cases ! // except clear the flag in our ! // storage ! polygon_hole_storage[ring] = 0; ! break; ! case -1: // It's a hole ring ! // Add it to our list of hole rings ! // here and set a flag. That way we ! // won't have to run through ! // SHPRingDir_2d again in the next ! // loop. ! polygon_hole_flag++; ! polygon_hole_storage[ring] = 1; ! // fprintf(stderr, "Ring %d/%d is a polygon hole\n", ! // ring, ! // object->nParts); ! break; ! } ! } ! // We're done with the initial run through the vertices of all ! // rings. We now know which rings are fills and which are holes and ! // have recorded the data. ! ! ! ! //WE7U3 ! // Speedup: If not draw_filled, then don't go ! // through the math and region code. Set the ! // flag to zero so that we won't do all the math ! // and the regions. ! if (!map_color_fill || !draw_filled) ! polygon_hole_flag = 0; ! ! if (polygon_hole_flag) { ! XRectangle rectangle; ! long width, height; ! double top_ll, left_ll, bottom_ll, right_ll; ! int temp_ok; ! ! ! // fprintf(stderr, "%s:Found %d hole rings in shape %d\n", ! // file, ! // polygon_hole_flag, ! // structure); ! ! //WE7U3 ! //////////////////////////////////////////////////////////////////////// ! ! // Now that we know which are fill/hole rings, worry about drawing ! // each ring of the Shape: ! // ! // 1) Create a filled rectangle region, probably the size of the ! // Shape extents, and at the same screen coordinates as the entire ! // shape would normally be drawn. ! // ! // 2) Create a region for each hole ring and subtract these new ! // regions one at a time from the rectangle region created above. ! // ! // 3) When the "swiss-cheese" rectangle region is complete, draw ! // only the filled polygons onto the map pixmap using the ! // swiss-cheese rectangle region as the clip-mask. Use a temporary ! // GC for this operation, as I can't find a way to remove a ! // clip-mask from a GC. We may have to use offsets to make this ! // work properly. ! ! ! // Create three regions and rotate between ! // them, due to the XSubtractRegion() ! // needing three parameters. If we later ! // find that two of the parameters can be ! // repeated, we can simplify our code. ! // We'll rotate through them mod 3. ! ! temp_region1 = 0; ! ! // Create empty region ! region[temp_region1] = XCreateRegion(); ! ! // Draw a rectangular clip-mask inside the ! // Region. Use the same extents as the full ! // Shape. ! ! // Set up the real sizes from the Shape ! // extents. ! top_ll = object->dfYMax; ! left_ll = object->dfXMin; ! bottom_ll = object->dfYMin; ! right_ll = object->dfXMax; ! ! // Convert point to Xastir coordinates: ! temp_ok = convert_to_xastir_coordinates(&my_long, ! &my_lat, ! left_ll, ! top_ll); ! //fprintf(stderr,"%ld %ld\n", my_long, my_lat); ! ! if (!temp_ok) { ! fprintf(stderr,"draw_shapefile_map: Problem converting from lat/lon\n"); ! ok = 0; ! x = 0; ! y = 0; ! } ! else { ! // Convert to screen coordinates. Careful ! // here! The format conversions you'll need ! // if you try to compress this into two ! // lines will get you into trouble. ! x = my_long - x_long_offset; ! y = my_lat - y_lat_offset; ! x = x / scale_x; ! y = y / scale_y; ! ! // Here we check for really wacko points that will cause problems ! // with the X drawing routines, and fix them. ! if (x > 1700l) x = 1700l; ! if (x < 0l) x = 0l; ! if (y > 1700l) y = 1700l; ! if (y < 0l) y = 0l; ! } ! ! // Convert points to Xastir coordinates ! temp_ok = convert_to_xastir_coordinates(&my_long, ! &my_lat, ! right_ll, ! bottom_ll); ! //fprintf(stderr,"%ld %ld\n", my_long, my_lat); ! ! if (!temp_ok) { ! fprintf(stderr,"draw_shapefile_map: Problem converting from lat/lon\n"); ! ok = 0; ! width = 0; ! height = 0; ! } ! else { ! // Convert to screen coordinates. Careful ! // here! The format conversions you'll need ! // if you try to compress this into two ! // lines will get you into trouble. ! width = my_long - x_long_offset; ! height = my_lat - y_lat_offset; ! width = width / scale_x; ! height = height / scale_y; ! ! // Here we check for really wacko points that will cause problems ! // with the X drawing routines, and fix them. ! if (width > 1700l) width = 1700l; ! if (width < 1l) width = 1l; ! if (height > 1700l) height = 1700l; ! if (height < 1l) height = 1l; ! } ! ! //TODO ! // We can run into trouble here because we only have 16-bit values ! // to work with. If we're zoomed in and the Shape is large in ! // comparison to the screen, we'll easily exceed these numbers. ! // Perhaps we'll need to work with something other than screen ! // coordinates? Perhaps truncating the values will be adequate. ! ! rectangle.x = (short) x; ! rectangle.y = (short) y; ! rectangle.width = (unsigned short) width; ! rectangle.height = (unsigned short) height; ! ! //fprintf(stderr,"*** Rectangle: %d,%d %dx%d\n", rectangle.x, rectangle.y, rectangle.width, rectangle.height); ! ! // Create the initial region containing a ! // filled rectangle. ! XUnionRectWithRegion(&rectangle, ! region[temp_region1], ! region[temp_region1]); ! ! // Create a region for each set of hole ! // vertices (CCW rotation of the vertices) ! // and subtract each from the rectangle ! // region. ! for (ring = 0; ring < object->nParts; ring++ ) { ! int endpoint; ! int on_screen; ! ! ! if (polygon_hole_storage[ring] == 1) { ! // It's a hole polygon. Cut the ! // hole out of our rectangle region. ! int num_vertices = 0; ! int nVertStart; ! ! ! nVertStart = object->panPartStart[ring]; ! ! if( ring == object->nParts-1 ) ! num_vertices = object->nVertices ! - object->panPartStart[ring]; ! else ! num_vertices = object->panPartStart[ring+1] ! - object->panPartStart[ring]; ! ! //TODO ! // Snag the vertices and put them into the "points" array, ! // converting to screen coordinates as we go, then subtracting the ! // starting point, so that the regions remain small? ! // ! // We could either subtract the starting point of each shape from ! // each point, or take the hit on region size and just use the full ! // screen size (or whatever part of it the shape required plus the ! // area from the starting point to 0,0). ! ! ! if ( (ring+1) < object->nParts) ! endpoint = object->panPartStart[ring+1]; ! //else endpoint = object->nVertices; ! else ! endpoint = object->panPartStart[0] + object->nVertices; ! //fprintf(stderr,"Endpoint %d\n", endpoint); ! //fprintf(stderr,"Vertices: %d\n", endpoint - object->panPartStart[ring]); ! ! i = 0; // i = Number of points to draw for one ring ! on_screen = 0; ! // index = ptr into the shapefile's array of points ! for (index = object->panPartStart[ring]; index < endpoint; ) { ! int temp_ok; ! ! ! // Get vertice and convert to Xastir coordinates ! temp_ok = convert_to_xastir_coordinates(&my_long, ! &my_lat, ! (float)object->padfX[index], ! (float)object->padfY[index]); ! ! //fprintf(stderr,"%lu %lu\t", my_long, my_lat); ! ! if (!temp_ok) { ! fprintf(stderr,"draw_shapefile_map: Problem converting from lat/lon\n"); ! ok = 0; ! x = 0; ! y = 0; ! } ! else { ! // Convert to screen coordinates. Careful ! // here! The format conversions you'll need ! // if you try to compress this into two ! // lines will get you into trouble. ! x = my_long - x_long_offset; ! y = my_lat - y_lat_offset; ! x = x / scale_x; ! y = y / scale_y; ! ! //fprintf(stderr,"%ld %ld\t\t", x, y); ! ! // Here we check for really ! // wacko points that will ! // cause problems with the X ! // drawing routines, and fix ! // them. Increment ! // on_screen if any of the ! // points might be on ! // screen. ! if (x > 1700l) ! x = 1700l; ! else if (x < 0l) ! x = 0l; ! else on_screen++; ! ! if (y > 1700l) ! y = 1700l; ! else if (y < 0l) ! y = 0l; ! else on_screen++; ! ! points[i].x = (short)x; ! points[i].y = (short)y; ! ! if (on_screen) { ! // fprintf(stderr,"%d x:%d y:%d\n", ! // i, ! // points[i].x, ! // points[i].y); ! } ! i++; ! } ! index++; ! ! if (index > high_water_mark_index) ! high_water_mark_index = index; ! ! if (index > endpoint) { ! index = endpoint; ! fprintf(stderr,"Trying to run past the end of shapefile array: index=%d\n",index); ! } ! } // End of converting vertices for a ring ! ! ! // Create and subtract the region ! // only if it might be on screen. ! if (on_screen) { ! temp_region2 = (temp_region1 + 1) % 3; ! temp_region3 = (temp_region1 + 2) % 3; ! ! // Create empty regions. ! region[temp_region2] = XCreateRegion(); ! region[temp_region3] = XCreateRegion(); ! ! // Draw the hole polygon ! if (num_vertices >= 3) { ! region[temp_region2] = XPolygonRegion(points, ! num_vertices, ! WindingRule); ! } ! else { ! fprintf(stderr, ! "draw_shapefile_map:XPolygonRegion with too few vertices:%d\n", ! num_vertices); ! } ! ! // Subtract region2 from region1 and ! // put the result into region3. ! //fprintf(stderr, "Subtracting region\n"); ! XSubtractRegion(region[temp_region1], ! region[temp_region2], ! region[temp_region3]); ! ! // Get rid of the two regions we no ! // longer need ! XDestroyRegion(region[temp_region1]); ! XDestroyRegion(region[temp_region2]); ! ! // Indicate the final result region for ! // the next iteration or the exit of the ! // loop. ! temp_region1 = temp_region3; ! } ! } ! } ! ! // region[temp_region1] now contains a ! // clip-mask of the original polygon with ! // holes cut out of it (swiss-cheese ! // rectangle). ! ! // Create temporary GC. It looks like we ! // don't need this to create the regions, ! // but we'll need it when we draw the filled ! // polygons onto the map pixmap using the ! // final region as a clip-mask. ! ! // Offsets? ! // XOffsetRegion ! ! // gc_temp_values.function = GXcopy; ! gc_temp = XCreateGC(XtDisplay(w), ! XtWindow(w), ! 0, ! &gc_temp_values); ! ! // Set the clip-mask into the GC. This GC ! // is now ruined for other purposes, so ! // destroy it when we're done drawing this ! // one shape. ! XSetRegion(XtDisplay(w), gc_temp, region[temp_region1]); ! XDestroyRegion(region[temp_region1]); ! } ! //WE7U3 ! //////////////////////////////////////////////////////////////////////// ! ! ! // Read the vertices for each ring in this Shape ! for (ring = 0; ring < object->nParts; ring++ ) { ! int endpoint; ! int glacier_flag = 0; ! const char *temp; ! ! ! if (lake_flag || river_flag) { ! if ( mapshots_labels_flag && (fieldcount >= 3) ) { ! temp = DBFReadStringAttribute( hDBF, structure, 2 ); // CFCC Field ! switch (temp[1]) { ! case '8': // Special water feature ! switch(temp[2]) { ! case '1': ! glacier_flag++; // Found a glacier ! break; ! default: ! break; ! } ! break; ! default: ! break; ! } ! } ! } ! ! //fprintf(stderr,"Ring: %d\t\t", ring); ! ! if ( (ring+1) < object->nParts) ! endpoint = object->panPartStart[ring+1]; ! //else endpoint = object->nVertices; ! else ! endpoint = object->panPartStart[0] + object->nVertices; ! ! //fprintf(stderr,"Endpoint %d\n", endpoint); ! //fprintf(stderr,"Vertices: %d\n", endpoint - object->panPartStart[ring]); ! ! i = 0; // i = Number of points to draw for one ring ! // index = ptr into the shapefile's array of points ! for (index = object->panPartStart[ring]; index < endpoint; ) { ! int temp_ok; ! ! ok = 1; ! ! //fprintf(stderr,"\t%d:%g %g\t", index, object->padfX[index], object->padfY[index] ); ! ! // Get vertice and convert to Xastir coordinates ! temp_ok = convert_to_xastir_coordinates(&my_long, ! &my_lat, ! (float)object->padfX[index], ! (float)object->padfY[index]); ! ! //fprintf(stderr,"%lu %lu\t", my_long, my_lat); ! ! if (!temp_ok) { ! fprintf(stderr,"draw_shapefile_map: Problem converting from lat/lon\n"); ! ok = 0; ! x = 0; ! y = 0; ! } ! else { ! // Convert to screen coordinates. Careful ! // here! The format conversions you'll need ! // if you try to compress this into two ! // lines will get you into trouble. ! x = my_long - x_long_offset; ! y = my_lat - y_lat_offset; ! x = x / scale_x; ! y = y / scale_y; ! ! //fprintf(stderr,"%ld %ld\t\t", x, y); ! ! // Here we check for really wacko points that will cause problems ! // with the X drawing routines, and fix them. ! if (x > 15000l) x = 15000l; ! if (x < -15000l) x = -15000l; ! if (y > 15000l) y = 15000l; ! if (y < -15000l) y = -15000l; ! ! points[i].x = (short)x; ! points[i].y = (short)y; ! i++; // Number of points to draw ! ! if (i > high_water_mark_i) ! high_water_mark_i = i; ! ! ! if (i >= MAX_MAP_POINTS) { ! i = MAX_MAP_POINTS - 1; ! fprintf(stderr,"Trying to run past the end of our internal points array: i=%d\n",i); ! } ! ! //fprintf(stderr,"%d %d\t", points[i].x, points[i].y); ! ! index++; ! ! if (index > high_water_mark_index) ! high_water_mark_index = index; ! ! if (index > endpoint) { ! index = endpoint; ! fprintf(stderr,"Trying to run past the end of shapefile array: index=%d\n",index); ! } ! } ! } ! ! if ( (i >= 3) ! && (ok_to_draw) ! && ( !draw_filled || !map_color_fill || (draw_filled && polygon_hole_storage[ring] == 0) ) ) { ! // We have a polygon to draw! ! ! //WE7U3 ! if ((!draw_filled || !map_color_fill) && polygon_hole_storage[ring] == 1) { ! // We have a hole drawn as unfilled. ! // Draw as a black dashed line. ! (void)XSetForeground(XtDisplay(w), gc, colors[0x08]); // black for border ! (void)XSetLineAttributes (XtDisplay (w), gc, 0, LineOnOffDash, CapButt,JoinMiter); ! (void)XDrawLines(XtDisplay(w), pixmap, gc, points, i, CoordModeOrigin); ! (void)XSetLineAttributes (XtDisplay (w), gc, 0, LineSolid, CapButt,JoinMiter); ! } ! else if (quad_overlay_flag) { ! (void)XDrawLines(XtDisplay(w), pixmap, gc, points, i, CoordModeOrigin); ! } ! else if (glacier_flag) { ! (void)XSetForeground(XtDisplay(w), gc, colors[0x0f]); // white ! if (map_color_fill && draw_filled) { ! ! if (polygon_hole_flag) { ! (void)XSetForeground(XtDisplay(w), gc_temp, colors[0x0f]); // white ! ! if (i >= 3) { ! (void)XFillPolygon(XtDisplay(w), ! pixmap, ! gc_temp, ! points, ! i, ! Nonconvex, ! CoordModeOrigin); ! } ! else { ! fprintf(stderr, ! "draw_shapefile_map:Too few points:%d, Skipping XFillPolygon()", ! npoints); ! } ! } ! else { ! if (i >= 3) { ! (void)XFillPolygon(XtDisplay(w), ! pixmap, ! gc, ! points, ! i, ! Nonconvex, ! CoordModeOrigin); ! } ! else { ! fprintf(stderr, ! "draw_shapefile_map:Too few points:%d, Skipping XFillPolygon()", ! npoints); ! } ! } ! } ! (void)XDrawLines(XtDisplay(w), pixmap, gc, points, i, CoordModeOrigin); ! } ! else if (lake_flag) { ! (void)XSetForeground(XtDisplay(w), gc, colors[0x1a]); // Steel Blue ! if (map_color_fill && draw_filled) { ! ! if (polygon_hole_flag) { ! (void)XSetForeground(XtDisplay(w), gc_temp, colors[0x1a]); // Steel Blue ! ! if (i >= 3) { ! (void)XFillPolygon(XtDisplay(w), ! pixmap, ! gc_temp, ! points, ! i, ! Nonconvex, ! CoordModeOrigin); ! } ! else { ! fprintf(stderr, ! "draw_shapefile_map:Too few points:%d, Skipping XFillPolygon()", ! npoints); ! } ! } ! else { ! if (i >= 3) { ! (void)XFillPolygon(XtDisplay(w), ! pixmap, ! gc, ! points, ! i, ! Nonconvex, ! CoordModeOrigin); ! } ! else { ! fprintf(stderr, ! "draw_shapefile_map:Too few points:%d, Skipping XFillPolygon()", ! npoints); ! } ! } ! ! // (void)XSetForeground(XtDisplay(w), gc, colors[0x08]); // black for border ! } ! (void)XDrawLines(XtDisplay(w), pixmap, gc, points, i, CoordModeOrigin); ! } ! else if (river_flag) { ! (void)XSetForeground(XtDisplay(w), gc, colors[0x1a]); // Steel Blue ! if (map_color_fill && draw_filled) { ! ! if (polygon_hole_flag) { ! (void)XSetForeground(XtDisplay(w), gc_temp, colors[0x1a]); // Steel Blue ! ! if (i >= 3) { ! (void)XFillPolygon(XtDisplay(w), ! pixmap, ! gc_temp, ! points, ! i, ! Nonconvex, ! CoordModeOrigin); ! } ! else { ! fprintf(stderr, ! "draw_shapefile_map:Too few points:%d, Skipping XFillPolygon()", ! npoints); ! } ! } ! else { ! if (i >= 3) { ! (void)XFillPolygon(XtDisplay(w), ! pixmap, ! gc, ! points, ! i, ! Nonconvex, ! CoordModeOrigin); ! } ! else { ! fprintf(stderr, ! "draw_shapefile_map:Too few points:%d, Skipping XFillPolygon()", ! npoints); ! } ! } ! ! } ! else { ! (void)XDrawLines(XtDisplay(w), pixmap, gc, points, i, CoordModeOrigin); ! } ! } ! else if (weather_alert_flag) { ! (void)XSetFillStyle(XtDisplay(w), gc_tint, FillStippled); ! // We skip the hole/fill thing for these? ! ! if (i >= 3) { ! (void)XFillPolygon(XtDisplay(w), ! pixmap_alerts, ! gc_tint, ! points, ! i, ! Nonconvex, ! CoordModeOrigin); ! } ! else { ! fprintf(stderr, ! "draw_shapefile_map:Too few points:%d, Skipping XFillPolygon()", ! npoints); ! } ! ! (void)XSetFillStyle(XtDisplay(w), gc_tint, FillSolid); ! (void)XDrawLines(XtDisplay(w), pixmap_alerts, gc_tint, points, i, CoordModeOrigin); ! } ! else if (map_color_fill && draw_filled) { // Land masses? ! if (polygon_hole_flag) { ! if (city_flag) ! (void)XSetForeground(XtDisplay(w), gc_temp, GetPixelByName(w,"RosyBrown")); // RosyBrown, duh ! else ! (void)XSetForeground(XtDisplay(w), gc_temp, colors[0xff]); // grey ! ! if (i >= 3) { ! (void)XFillPolygon(XtDisplay(w), ! pixmap, ! gc_temp, ! points, ! i, ! Nonconvex, ! CoordModeOrigin); ! } ! else { ! fprintf(stderr, ! "draw_shapefile_map:Too few points:%d, Skipping XFillPolygon()", ! npoints); ! } ! } ! else { ! if (city_flag) ! (void)XSetForeground(XtDisplay(w), gc, GetPixelByName(w,"RosyBrown")); // RosyBrown, duh ! else ! (void)XSetForeground(XtDisplay(w), gc, colors[0xff]); // grey ! ! if (i >= 3) { ! (void)XFillPolygon(XtDisplay (w), ! pixmap, ! gc, ! points, ! i, ! Nonconvex, ! CoordModeOrigin); ! } ! else { ! fprintf(stderr, ! "draw_shapefile_map:Too few points:%d, Skipping XFillPolygon()", ! npoints); ! } ! } ! ! (void)XSetForeground(XtDisplay(w), gc, colors[0x08]); // black for border ! ! // Draw a thicker border for city boundaries ! if (city_flag) { ! if (scale_y <= 64) { ! (void)XSetLineAttributes(XtDisplay(w), gc, 2, LineSolid, CapButt,JoinMiter); ! } ! else if (scale_y <= 128) { ! (void)XSetLineAttributes(XtDisplay(w), gc, 1, LineSolid, CapButt,JoinMiter); ! } ! else { ! (void)XSetLineAttributes(XtDisplay(w), gc, 0, LineSolid, CapButt,JoinMiter); ! } ! ! (void)XSetForeground(XtDisplay(w), gc, colors[0x14]); // lightgray for border ! } ! else { ! (void)XSetForeground(XtDisplay(w), gc, colors[0x08]); // black for border ! } ! ! (void)XDrawLines(XtDisplay(w), pixmap, gc, points, i, CoordModeOrigin); ! } ! else { // Use whatever color is defined by this point. ! (void)XSetLineAttributes(XtDisplay(w), gc, 0, LineSolid, CapButt,JoinMiter); ! (void)XDrawLines(XtDisplay(w), pixmap, gc, points, i, CoordModeOrigin); ! } ! } ! } ! ! // Free the storage that we allocated to hold ! // the "hole" flags for the shape. ! free(polygon_hole_storage); ! ! if (polygon_hole_flag) { ! //Free the temporary GC that we may have used to ! //draw polygons using the clip-mask: ! XFreeGC(XtDisplay(w), gc_temp); ! } ! ! ! //////////////////////////////////////////////////////////////////////////////////////////////////// ! // Done with drawing shapes, now draw labels ! //////////////////////////////////////////////////////////////////////////////////////////////////// ! ! ! temp = ""; ! ! if (lake_flag) { ! if (map_color_levels && scale_y > 128) ! skip_label++; ! if (mapshots_labels_flag && (fieldcount >= 4) ) ! temp = DBFReadStringAttribute( hDBF, structure, 3 ); ! else if (fieldcount >= 1) ! temp = DBFReadStringAttribute( hDBF, structure, 0 ); // NAME (lakes) ! else ! temp = NULL; ! } ! else if (city_flag) { ! if (map_color_levels && scale_y > 512) ! skip_label++; ! if (mapshots_labels_flag && (fieldcount >= 4) ) ! temp = DBFReadStringAttribute( hDBF, structure, 3 ); // NAME (designated places) ! else ! temp = NULL; ! } ! ! if (quad_overlay_flag) { ! if (fieldcount >= 5) { ! // Use just the last two characters of ! // the quad index. "44072-A3" converts ! // to "A3" ! temp = DBFReadStringAttribute( hDBF, structure, 4 ); ! xastir_snprintf(quad_label, ! sizeof(quad_label), ! "%s ", ! &temp[strlen(temp) - 2]); ! ! // Append the name of the quad ! temp = DBFReadStringAttribute( hDBF, structure, 0 ); ! strcat(quad_label,temp); ! } ! else { ! quad_label[0] = '\0'; ! } ! } ! ! if ( (temp != NULL) ! && (strlen(temp) != 0) ! && map_labels ! && !skip_label ) { ! int temp_ok; ! ! ok = 1; ! ! // Convert to Xastir coordinates: ! // If quad overlay shapefile, need to ! // snag the label coordinates from the DBF ! // file instead. Note that the coordinates ! // are for the bottom right corner of the ! // quad, so we need to shift it left by 7.5' ! // to make the label appear inside the quad ! // (attached to the bottom left corner in ! // this case). ! if (quad_overlay_flag) { ! const char *dbf_temp; ! float lat_f; ! float lon_f; ! ! if (fieldcount >= 4) { ! dbf_temp = DBFReadStringAttribute( hDBF, structure, 2 ); ! sscanf(dbf_temp, "%f", &lat_f); ! dbf_temp = DBFReadStringAttribute( hDBF, structure, 3 ); ! sscanf(dbf_temp, "%f", &lon_f); ! lon_f = lon_f - 0.125; ! } ! else { ! lat_f = 0.0; ! lon_f = 0.0; ! } ! ! //fprintf(stderr,"Lat: %f, Lon: %f\t, Quad: %s\n", lat_f, lon_f, quad_label); ! ! temp_ok = convert_to_xastir_coordinates(&my_long, ! &my_lat, ! (float)lon_f, ! (float)lat_f); ! } ! else { // Not quad overlay, use vertices ! temp_ok = convert_to_xastir_coordinates(&my_long, ! &my_lat, ! (float)object->padfX[0], ! (float)object->padfY[0]); ! } ! //fprintf(stderr,"%ld %ld\n", my_long, my_lat); ! ! if (!temp_ok) { ! fprintf(stderr,"draw_shapefile_map: Problem converting from lat/lon\n"); ! ok = 0; ! x = 0; ! y = 0; ! } ! else { ! // Convert to screen coordinates. Careful ! // here! The format conversions you'll need ! // if you try to compress this into two ! // lines will get you into trouble. ! x = my_long - x_long_offset; ! y = my_lat - y_lat_offset; ! x = x / scale_x; ! y = y / scale_y; ! ! if (x > 16000) ok = 0; // Skip this point ! if (x < -16000) ok = 0; // Skip this point ! if (y > 16000) ok = 0; // Skip this point ! if (y < -16000) ok = 0; // Skip this point ! ! if (ok == 1 && ok_to_draw) { ! if (quad_overlay_flag) { ! draw_nice_string(w, ! pixmap, ! 0, ! x+2, ! y-1, ! (char*)quad_label, ! 0xf, ! 0x10, ! strlen(quad_label)); ! } ! else { ! (void)draw_label_text ( w, ! x, ! y, ! strlen(temp), ! colors[0x08], ! (char *)temp); ! } ! } ! } ! } ! break; ! ! case SHPT_MULTIPOINT: ! // Not implemented. ! fprintf(stderr,"Shapefile Multi-Point format files aren't supported!\n"); ! break; ! ! default: ! // Not implemented. ! fprintf(stderr,"Shapefile format not supported: Subformat unknown (default clause of switch)!\n"); ! break; ! ! } // End of switch ! } ! else { // Shape not currently visible ! if (alert) ! alert->flags[0] = 'N'; ! } ! SHPDestroyObject( object ); // Done with this structure ! } ! ! ! // Free our linked list of strings, if any ! ptr2 = label_ptr; ! while (ptr2 != NULL) { ! label_ptr = ptr2->next; ! //fprintf(stderr,"free: %s\n",ptr2->label); ! free(ptr2); ! ptr2 = label_ptr; ! } ! ! ! DBFClose( hDBF ); ! SHPClose( hSHP ); ! ! // Free up any malloc's that we did ! if (panWidth) ! free(panWidth); ! ! // XmUpdateDisplay (XtParent (da)); ! ! if (debug_level & 16) { ! fprintf(stderr,"High-Mark Index:%d,\tHigh-Mark i:%d\n", ! high_water_mark_index, ! high_water_mark_i); ! } ! } ! // End of draw_shapefile_map() ! ! #endif // HAVE_LIBSHP ! ! ! ! ! ! void Print_properties_destroy_shell(/*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) { ! Widget shell = (Widget) clientData; ! XtPopdown(shell); ! ! begin_critical_section(&print_properties_dialog_lock, "maps.c:Print_properties_destroy_shell" ); ! ! XtDestroyWidget(shell); ! print_properties_dialog = (Widget)NULL; ! ! end_critical_section(&print_properties_dialog_lock, "maps.c:Print_properties_destroy_shell" ); ! ! } ! ! ! ! ! ! // Print_window: Prints the drawing area to a Postscript file. ! // ! void Print_window( Widget widget, XtPointer clientData, XtPointer callData ) { ! ! #ifdef NO_GRAPHICS ! fprintf(stderr,"XPM or ImageMagick support not compiled into Xastir!\n"); ! #else // NO_GRAPHICS ! ! #ifndef HAVE_GV ! fprintf(stderr,"GV support not compiled into Xastir!\n"); ! #else // HAVE_GV ! ! ! char xpm_filename[MAX_FILENAME]; ! char ps_filename[MAX_FILENAME]; ! char mono[50] = ""; ! char invert[50] = ""; ! char rotate[50] = ""; ! char scale[50] = ""; ! char density[50] = ""; ! char command[MAX_FILENAME*2]; ! char temp[100]; ! char format[50] = "-portrait "; ! uid_t user_id; ! struct passwd *user_info; ! char username[20]; ! ! ! // Get user info ! user_id=getuid(); ! user_info=getpwuid(user_id); ! // Get my login name ! strcpy(username,user_info->pw_name); ! ! xastir_snprintf(xpm_filename, sizeof(xpm_filename), "/var/tmp/xastir_%s_print.xpm", ! username); ! xastir_snprintf(ps_filename, sizeof(ps_filename), "/var/tmp/xastir_%s_print.ps", ! username); ! ! busy_cursor(appshell); // Show a busy cursor while we're doing all of this ! ! // Get rid of Print Properties dialog ! Print_properties_destroy_shell(widget, print_properties_dialog, NULL ); ! ! ! if ( debug_level & 512 ) ! fprintf(stderr,"Creating %s\n", xpm_filename ); ! ! xastir_snprintf(temp, sizeof(temp), langcode("PRINT0012") ); ! statusline(temp,1); // Dumping image to file... ! ! if ( !XpmWriteFileFromPixmap(XtDisplay(appshell), // Display *display ! xpm_filename, // char *filename ! pixmap_final, // Pixmap pixmap ! (Pixmap)NULL, // Pixmap shapemask ! NULL ) == XpmSuccess ) { // XpmAttributes *attributes ! fprintf(stderr,"ERROR writing %s\n", xpm_filename ); ! } ! else { // We now have the xpm file created on disk ! ! chmod( xpm_filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH ); ! ! if ( debug_level & 512 ) ! fprintf(stderr,"Convert %s ==> %s\n", xpm_filename, ps_filename ); ! ! ! // Convert it to a postscript file for printing. This depends ! // on the ImageMagick command "convert". ! // ! // Other options to try in the future: ! // -label ! // ! if ( print_auto_scale ) { ! // sprintf(scale, "-geometry 612x792 -page 612x792 "); // "Letter" size at 72 dpi ! // sprintf(scale, "-sample 612x792 -page 612x792 "); // "Letter" size at 72 dpi ! xastir_snprintf(scale, sizeof(scale), "-page 1275x1650+0+0 "); // "Letter" size at 150 dpi ! } ! else ! scale[0] = '\0'; // Empty string ! ! ! if ( print_in_monochrome ) ! xastir_snprintf(mono, sizeof(mono), "-monochrome +dither " ); // Monochrome ! else ! xastir_snprintf(mono, sizeof(mono), "+dither "); // Color ! ! ! if ( print_invert ) ! xastir_snprintf(invert, sizeof(invert), "-negate " ); // Reverse Colors ! else ! invert[0] = '\0'; // Empty string ! ! ! if (debug_level & 512) ! fprintf(stderr,"Width: %ld\tHeight: %ld\n", screen_width, screen_height); ! ! ! if ( print_rotated ) { ! xastir_snprintf(rotate, sizeof(rotate), "-rotate -90 " ); ! xastir_snprintf(format, sizeof(format), "-landscape " ); ! } else if ( print_auto_rotation ) { ! // Check whether the width or the height of the pixmap is greater. ! // If width is greater than height, rotate the image by 270 degrees. ! if (screen_width > screen_height) { ! xastir_snprintf(rotate, sizeof(rotate), "-rotate -90 " ); ! xastir_snprintf(format, sizeof(format), "-landscape " ); ! if (debug_level & 512) ! fprintf(stderr,"Rotating\n"); ! } else { ! rotate[0] = '\0'; // Empty string ! if (debug_level & 512) ! fprintf(stderr,"Not Rotating\n"); ! } ! } else { ! rotate[0] = '\0'; // Empty string ! if (debug_level & 512) ! fprintf(stderr,"Not Rotating\n"); ! } ! ! ! // Higher print densities require more memory and time to process ! xastir_snprintf(density, sizeof(density), "-density %dx%d", print_resolution, ! print_resolution ); ! ! xastir_snprintf(temp, sizeof(temp), langcode("PRINT0013") ); ! statusline(temp,1); // Converting to Postscript... ! ! ! // Filters: ! // Point (ok at higher dpi's) ! // Box (not too bad) ! // Triangle (no) ! // Hermite (no) ! // Hanning (no) ! // Hamming (no) ! // Blackman (better but still not good) ! // Gaussian (no) ! // Quadratic (no) ! // Cubic (no) ! // Catrom (not too bad) ! // Mitchell (no) ! // Lanczos (no) ! // Bessel (no) ! // Sinc (not too bad) ! ! #ifdef HAVE_CONVERT ! xastir_snprintf(command, ! sizeof(command), ! "%s -filter Point %s%s%s%s%s %s %s", ! CONVERT_PATH, ! mono, ! invert, ! rotate, ! scale, ! density, ! xpm_filename, ! ps_filename ); ! if ( debug_level & 512 ) ! fprintf(stderr,"%s\n", command ); ! ! if ( system( command ) != 0 ) { ! fprintf(stderr,"\n\nPrint: Couldn't convert from XPM to PS!\n\n\n"); ! return; ! } ! #endif // HAVE_CONVERT ! ! chmod( ps_filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH ); ! ! // Delete temporary xpm file ! if ( !(debug_level & 512) ) ! unlink( xpm_filename ); ! ! if ( debug_level & 512 ) ! fprintf(stderr,"Printing postscript file %s\n", ps_filename); ! ! // Note: This needs to be changed to "lp" for Solaris. ! // Also need to have a field to configure the printer name. One ! // fill-in field could do both. ! // ! // Since we could be running SUID root, we don't want to be ! // calling "system" anyway. Several problems with it. ! /* ! xastir_snprintf(command, ! sizeof(command), ! "%s -Plp %s", ! LPR_PATH, ! ps_filename ); ! if ( debug_level & 512 ) ! fprintf(stderr,"%s\n", command); ! ! if ( system( command ) != 0 ) { ! fprintf(stderr,"\n\nPrint: Couldn't send to the printer!\n\n\n"); ! return; ! } ! */ ! ! ! #ifdef HAVE_GV ! // Bring up the "gv" postscript viewer ! xastir_snprintf(command, ! sizeof(command), ! // "%s %s-scale -2 -media Letter %s &", ! "%s %s-scale -2 %s &", ! GV_PATH, ! format, ! ps_filename ); ! ! if ( debug_level & 512 ) ! fprintf(stderr,"%s\n", command); ! ! if ( system( command ) != 0 ) { ! fprintf(stderr,"\n\nPrint: Couldn't bring up the gv viewer!\n\n\n"); ! return; ! } ! #endif // HAVE_GV ! ! /* ! if ( !(debug_level & 512) ) ! unlink( ps_filename ); ! */ ! ! if ( debug_level & 512 ) ! fprintf(stderr," Done printing.\n"); ! } ! ! xastir_snprintf(temp, sizeof(temp), langcode("PRINT0014") ); ! statusline(temp,1); // Finished creating print file. ! ! //popup_message( langcode("PRINT0015"), langcode("PRINT0014") ); ! ! #endif // HAVE_GV ! #endif // NO_GRAPHICS ! ! } ! ! ! ! ! ! /* ! * Auto_rotate ! * ! */ ! void Auto_rotate( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) { ! char *which = (char *)clientData; ! XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData; ! ! if(state->set) { ! print_auto_rotation = atoi(which); ! print_rotated = 0; ! XmToggleButtonSetState(rotate_90, FALSE, FALSE); ! } else { ! print_auto_rotation = 0; ! } ! } ! ! ! ! ! ! /* ! * Rotate_90 ! * ! */ ! void Rotate_90( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) { ! char *which = (char *)clientData; ! XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData; ! ! if(state->set) { ! print_rotated = atoi(which); ! print_auto_rotation = 0; ! XmToggleButtonSetState(auto_rotate, FALSE, FALSE); ! } else { ! print_rotated = 0; ! } ! } ! ! ! ! ! ! /* ! * Auto_scale ! * ! */ ! void Auto_scale( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) { ! char *which = (char *)clientData; ! XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData; ! ! if(state->set) { ! print_auto_scale = atoi(which); ! } else { ! print_auto_scale = 0; ! } ! } ! ! ! ! ! ! /* ! * Monochrome ! * ! */ ! void Monochrome( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) { ! char *which = (char *)clientData; ! XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData; ! ! if(state->set) { ! print_in_monochrome = atoi(which); ! } else { ! print_in_monochrome = 0; ! } ! } ! ! ! ! ! ! /* ! * Invert ! * ! */ ! void Invert( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) { ! char *which = (char *)clientData; ! XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData; ! ! if(state->set) { ! print_invert = atoi(which); ! } else { ! print_invert = 0; ! } ! } ! ! ! ! ! ! // Print_properties: Prints the drawing area to a PostScript file ! // ! // Perhaps later: ! // 1) Select an area on the screen to print ! // 2) -label ! // ! void Print_properties( Widget w, XtPointer clientData, XtPointer callData ) { ! static Widget pane, form, button_ok, button_cancel, ! sep, auto_scale, ! // paper_size, paper_size_data, scale, scale_data, blank_background, ! // res_label1, res_label2, res_x, res_y, button_preview, ! monochrome, invert; ! Atom delw; ! ! if (!print_properties_dialog) { ! ! ! begin_critical_section(&print_properties_dialog_lock, "maps.c:Print_properties" ); ! ! ! print_properties_dialog = XtVaCreatePopupShell(langcode("PRINT0001"),xmDialogShellWidgetClass,Global.top, ! XmNdeleteResponse,XmDESTROY, ! XmNdefaultPosition, FALSE, ! NULL); ! ! ! pane = XtVaCreateWidget("Print_properties pane",xmPanedWindowWidgetClass, print_properties_dialog, ! XmNbackground, colors[0xff], ! NULL); ! ! ! form = XtVaCreateWidget("Print_properties form",xmFormWidgetClass, pane, ! XmNfractionBase, 2, ! XmNbackground, colors[0xff], ! XmNautoUnmanage, FALSE, ! XmNshadowThickness, 1, ! NULL); ! ! ! /* ! paper_size = XtVaCreateManagedWidget(langcode("PRINT0002"),xmLabelWidgetClass, form, ! XmNtopAttachment, XmATTACH_FORM, ! XmNtopOffset, 10, ! XmNbottomAttachment, XmATTACH_NONE, ! XmNleftAttachment, XmATTACH_FORM, ! XmNleftOffset, 10, ! XmNrightAttachment, XmATTACH_NONE, ! XmNbackground, colors[0xff], ! NULL); ! XtSetSensitive(paper_size,FALSE); ! ! ! paper_size_data = XtVaCreateManagedWidget("Print_properties paper_size_data", xmTextFieldWidgetClass, form, ! XmNeditable, TRUE, ! XmNcursorPositionVisible, TRUE, ! XmNsensitive, TRUE, ! XmNshadowThickness, 1, ! XmNcolumns, 15, ! XmNwidth, ((15*7)+2), ! XmNmaxLength, 15, ! XmNbackground, colors[0x0f], ! XmNtopAttachment,XmATTACH_FORM, ! XmNtopOffset, 5, ! XmNbottomAttachment,XmATTACH_NONE, ! XmNleftAttachment, XmATTACH_WIDGET, ! XmNleftWidget, paper_size, ! XmNleftOffset, 10, ! XmNrightAttachment,XmATTACH_FORM, ! XmNrightOffset, 10, ! XmNnavigationType, XmTAB_GROUP, ! XmNtraversalOn, TRUE, ! NULL); ! XtSetSensitive(paper_size_data,FALSE); ! */ ! ! ! auto_rotate = XtVaCreateManagedWidget(langcode("PRINT0003"),xmToggleButtonWidgetClass,form, ! // XmNtopAttachment, XmATTACH_WIDGET, ! // XmNtopWidget, paper_size_data, ! // XmNtopOffset, 5, ! XmNtopAttachment, XmATTACH_FORM, ! XmNtopOffset, 10, ! XmNbottomAttachment, XmATTACH_NONE, ! XmNleftAttachment, XmATTACH_FORM, ! XmNleftOffset ,10, ! XmNrightAttachment, XmATTACH_NONE, ! XmNbackground, colors[0xff], ! XmNnavigationType, XmTAB_GROUP, ! XmNtraversalOn, TRUE, ! NULL); ! XtAddCallback(auto_rotate,XmNvalueChangedCallback,Auto_rotate,"1"); ! ! ! rotate_90 = XtVaCreateManagedWidget(langcode("PRINT0004"),xmToggleButtonWidgetClass,form, ! // XmNtopAttachment, XmATTACH_WIDGET, ! // XmNtopWidget, paper_size_data, ! // XmNtopOffset, 5, ! XmNtopAttachment, XmATTACH_FORM, ! XmNtopOffset, 10, ! XmNbottomAttachment, XmATTACH_NONE, ! XmNleftAttachment, XmATTACH_WIDGET, ! XmNleftWidget, auto_rotate, ! XmNleftOffset ,10, ! XmNrightAttachment, XmATTACH_FORM, ! XmNrightOffset, 10, ! XmNbackground, colors[0xff], ! XmNnavigationType, XmTAB_GROUP, ! XmNtraversalOn, TRUE, ! NULL); ! XtAddCallback(rotate_90,XmNvalueChangedCallback,Rotate_90,"1"); ! ! ! auto_scale = XtVaCreateManagedWidget(langcode("PRINT0005"),xmToggleButtonWidgetClass,form, ! XmNtopAttachment, XmATTACH_WIDGET, ! XmNtopWidget, auto_rotate, ! XmNtopOffset, 5, ! XmNbottomAttachment, XmATTACH_NONE, ! XmNleftAttachment, XmATTACH_FORM, ! XmNleftOffset ,10, ! XmNrightAttachment, XmATTACH_NONE, ! XmNbackground, colors[0xff], ! XmNnavigationType, XmTAB_GROUP, ! XmNtraversalOn, TRUE, ! NULL); ! XtAddCallback(auto_scale,XmNvalueChangedCallback,Auto_scale,"1"); ! ! ! /* ! scale = XtVaCreateManagedWidget(langcode("PRINT0006"),xmLabelWidgetClass, form, ! XmNtopAttachment, XmATTACH_WIDGET, ! XmNtopWidget, auto_rotate, ! XmNtopOffset, 10, ! XmNbottomAttachment, XmATTACH_NONE, ! XmNleftAttachment, XmATTACH_WIDGET, ! XmNleftWidget, auto_scale, ! XmNleftOffset, 10, ! XmNrightAttachment, XmATTACH_NONE, ! XmNbackground, colors[0xff], ! NULL); ! XtSetSensitive(scale,FALSE); ! ! ! scale_data = XtVaCreateManagedWidget("Print_properties scale_data", xmTextFieldWidgetClass, form, ! XmNeditable, TRUE, ! XmNcursorPositionVisible, TRUE, ! XmNsensitive, TRUE, ! XmNshadowThickness, 1, ! XmNcolumns, 15, ! XmNwidth, ((15*7)+2), ! XmNmaxLength, 15, ! XmNbackground, colors[0x0f], ! XmNtopAttachment,XmATTACH_WIDGET, ! XmNtopWidget, auto_rotate, ! XmNtopOffset, 5, ! XmNbottomAttachment,XmATTACH_NONE, ! XmNleftAttachment, XmATTACH_WIDGET, ! XmNleftWidget, scale, ! XmNleftOffset, 10, ! XmNrightAttachment,XmATTACH_FORM, ! XmNrightOffset, 10, ! XmNnavigationType, XmTAB_GROUP, ! XmNtraversalOn, TRUE, ! NULL); ! XtSetSensitive(scale_data,FALSE); ! */ ! ! ! /* ! blank_background = XtVaCreateManagedWidget(langcode("PRINT0007"),xmToggleButtonWidgetClass,form, ! XmNtopAttachment, XmATTACH_WIDGET, ! XmNtopWidget, scale_data, ! XmNtopWidget, auto_rotate, ! XmNtopOffset, 5, ! XmNbottomAttachment, XmATTACH_NONE, ! XmNleftAttachment, XmATTACH_FORM, ! XmNleftOffset ,10, ! XmNrightAttachment, XmATTACH_NONE, ! XmNbackground, colors[0xff], ! XmNnavigationType, XmTAB_GROUP, ! XmNtraversalOn, TRUE, ! NULL); ! XtSetSensitive(blank_background,FALSE); ! */ ! ! ! monochrome = XtVaCreateManagedWidget(langcode("PRINT0008"),xmToggleButtonWidgetClass,form, ! XmNtopAttachment, XmATTACH_WIDGET, ! // XmNtopWidget, blank_background, ! XmNtopWidget, auto_scale, ! XmNtopOffset, 5, ! XmNbottomAttachment, XmATTACH_NONE, ! XmNleftAttachment, XmATTACH_FORM, ! XmNleftOffset ,10, ! XmNrightAttachment, XmATTACH_NONE, ! XmNbackground, colors[0xff], ! XmNnavigationType, XmTAB_GROUP, ! XmNtraversalOn, TRUE, ! NULL); ! XtAddCallback(monochrome,XmNvalueChangedCallback,Monochrome,"1"); ! ! ! invert = XtVaCreateManagedWidget(langcode("PRINT0016"),xmToggleButtonWidgetClass,form, ! XmNtopAttachment, XmATTACH_WIDGET, ! XmNtopWidget, monochrome, ! XmNtopOffset, 5, ! XmNbottomAttachment, XmATTACH_NONE, ! XmNleftAttachment, XmATTACH_FORM, ! XmNleftOffset ,10, ! XmNrightAttachment, XmATTACH_NONE, ! XmNbackground, colors[0xff], ! XmNnavigationType, XmTAB_GROUP, ! XmNtraversalOn, TRUE, ! NULL); ! XtAddCallback(invert,XmNvalueChangedCallback,Invert,"1"); ! ! ! /* ! res_label1 = XtVaCreateManagedWidget(langcode("PRINT0009"),xmLabelWidgetClass, form, ! XmNtopAttachment, XmATTACH_WIDGET, ! XmNtopWidget, invert, ! XmNtopOffset, 10, ! XmNbottomAttachment, XmATTACH_NONE, ! XmNleftAttachment, XmATTACH_FORM, ! XmNleftOffset, 10, ! XmNrightAttachment, XmATTACH_NONE, ! XmNbackground, colors[0xff], ! NULL); ! XtSetSensitive(res_label1,FALSE); ! ! ! res_x = XtVaCreateManagedWidget("Print_properties resx_data", xmTextFieldWidgetClass, form, ! XmNeditable, TRUE, ! XmNcursorPositionVisible, TRUE, ! XmNsensitive, TRUE, ! XmNshadowThickness, 1, ! XmNcolumns, 15, ! XmNwidth, ((15*7)+2), ! XmNmaxLength, 15, ! XmNbackground, colors[0x0f], ! XmNtopAttachment,XmATTACH_WIDGET, ! XmNtopWidget, invert, ! XmNtopOffset, 5, ! XmNbottomAttachment,XmATTACH_NONE, ! XmNleftAttachment, XmATTACH_WIDGET, ! XmNleftWidget, res_label1, ! XmNleftOffset, 10, ! XmNrightAttachment,XmATTACH_NONE, ! XmNnavigationType, XmTAB_GROUP, ! XmNtraversalOn, TRUE, ! NULL); ! XtSetSensitive(res_x,FALSE); ! ! ! res_label2 = XtVaCreateManagedWidget("X",xmLabelWidgetClass, form, ! XmNtopAttachment, XmATTACH_WIDGET, ! XmNtopWidget, invert, ! XmNtopOffset, 10, ! XmNbottomAttachment, XmATTACH_NONE, ! XmNleftAttachment, XmATTACH_WIDGET, ! XmNleftWidget, res_x, ! XmNleftOffset, 10, ! XmNrightAttachment, XmATTACH_NONE, ! XmNbackground, colors[0xff], ! NULL); ! XtSetSensitive(res_label2,FALSE); ! ! ! res_y = XtVaCreateManagedWidget("Print_properties res_y_data", xmTextFieldWidgetClass, form, ! XmNeditable, TRUE, ! XmNcursorPositionVisible, TRUE, ! XmNsensitive, TRUE, ! XmNshadowThickness, 1, ! XmNcolumns, 15, ! XmNwidth, ((15*7)+2), ! XmNmaxLength, 15, ! XmNbackground, colors[0x0f], ! XmNtopAttachment,XmATTACH_WIDGET, ! XmNtopWidget, invert, ! XmNtopOffset, 5, ! XmNbottomAttachment,XmATTACH_NONE, ! XmNleftAttachment, XmATTACH_WIDGET, ! XmNleftWidget, res_label2, ! XmNleftOffset, 10, ! XmNrightAttachment,XmATTACH_FORM, ! XmNrightOffset, 10, ! XmNnavigationType, XmTAB_GROUP, ! XmNtraversalOn, TRUE, ! NULL); ! XtSetSensitive(res_y,FALSE); ! */ ! ! ! sep = XtVaCreateManagedWidget("Print_properties sep", xmSeparatorGadgetClass,form, ! XmNorientation, XmHORIZONTAL, ! XmNtopAttachment,XmATTACH_WIDGET, ! // XmNtopWidget, res_y, ! XmNtopWidget, invert, ! XmNtopOffset, 10, ! XmNbottomAttachment,XmATTACH_NONE, ! XmNleftAttachment, XmATTACH_FORM, ! XmNrightAttachment,XmATTACH_FORM, ! XmNbackground, colors[0xff], ! NULL); ! ! ! /* ! button_preview = XtVaCreateManagedWidget(langcode("PRINT0010"),xmPushButtonGadgetClass, form, ! XmNtopAttachment, XmATTACH_WIDGET, ! XmNtopWidget, sep, ! XmNtopOffset, 5, ! XmNbottomAttachment, XmATTACH_FORM, ! XmNbottomOffset, 5, ! XmNleftAttachment, XmATTACH_POSITION, ! XmNleftPosition, 0, ! XmNleftOffset, 5, ! XmNrightAttachment, XmATTACH_POSITION, ! XmNrightPosition, 1, ! XmNrightOffset, 2, ! XmNbackground, colors[0xff], ! XmNnavigationType, XmTAB_GROUP, ! XmNtraversalOn, TRUE, ! NULL); ! XtSetSensitive(button_preview,FALSE); ! */ ! ! ! // button_ok = XtVaCreateManagedWidget(langcode("PRINT0011"),xmPushButtonGadgetClass, form, ! button_ok = XtVaCreateManagedWidget(langcode("PRINT0010"),xmPushButtonGadgetClass, form, ! XmNtopAttachment, XmATTACH_WIDGET, ! XmNtopWidget, sep, ! XmNtopOffset, 5, ! XmNbottomAttachment, XmATTACH_FORM, ! XmNbottomOffset, 5, ! XmNleftAttachment, XmATTACH_POSITION, ! XmNleftPosition, 0, ! XmNleftOffset, 3, ! XmNrightAttachment, XmATTACH_POSITION, ! XmNrightPosition, 1, ! XmNrightOffset, 2, ! XmNbackground, colors[0xff], ! XmNnavigationType, XmTAB_GROUP, ! XmNtraversalOn, TRUE, ! NULL); ! ! ! button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),xmPushButtonGadgetClass, form, ! XmNtopAttachment, XmATTACH_WIDGET, ! XmNtopWidget, sep, ! XmNtopOffset, 5, ! XmNbottomAttachment, XmATTACH_FORM, ! XmNbottomOffset, 5, ! XmNleftAttachment, XmATTACH_POSITION, ! XmNleftPosition, 1, ! XmNleftOffset, 3, ! XmNrightAttachment, XmATTACH_POSITION, ! XmNrightPosition, 2, ! XmNrightOffset, 5, ! XmNbackground, colors[0xff], ! XmNnavigationType, XmTAB_GROUP, ! XmNtraversalOn, TRUE, ! NULL); ! ! ! // XtAddCallback(button_preview, XmNactivateCallback, Print_window, "1" ); ! XtAddCallback(button_ok, XmNactivateCallback, Print_window, "0" ); ! XtAddCallback(button_cancel, XmNactivateCallback, Print_properties_destroy_shell, print_properties_dialog); ! ! ! XmToggleButtonSetState(rotate_90,FALSE,FALSE); ! XmToggleButtonSetState(auto_rotate,TRUE,FALSE); ! ! ! if (print_auto_rotation) ! XmToggleButtonSetState(auto_rotate, TRUE, TRUE); ! else ! XmToggleButtonSetState(auto_rotate, FALSE, TRUE); ! ! ! if (print_rotated) ! XmToggleButtonSetState(rotate_90, TRUE, TRUE); ! else ! XmToggleButtonSetState(rotate_90, FALSE, TRUE); ! ! ! if (print_in_monochrome) ! XmToggleButtonSetState(monochrome, TRUE, FALSE); ! else ! XmToggleButtonSetState(monochrome, FALSE, FALSE); ! ! ! if (print_invert) ! XmToggleButtonSetState(invert, TRUE, FALSE); ! else ! XmToggleButtonSetState(invert, FALSE, FALSE); ! ! ! if (print_auto_scale) ! XmToggleButtonSetState(auto_scale, TRUE, TRUE); ! else ! XmToggleButtonSetState(auto_scale, FALSE, TRUE); ! ! ! // XmTextFieldSetString(paper_size_data,print_paper_size); ! ! ! end_critical_section(&print_properties_dialog_lock, "maps.c:Print_properties" ); ! ! ! pos_dialog(print_properties_dialog); ! ! ! delw = XmInternAtom(XtDisplay(print_properties_dialog),"WM_DELETE_WINDOW", FALSE); ! XmAddWMProtocolCallback(print_properties_dialog, delw, Print_properties_destroy_shell, (XtPointer)print_properties_dialog); ! ! ! XtManageChild(form); ! XtManageChild(pane); ! ! ! XtPopup(print_properties_dialog,XtGrabNone); ! fix_dialog_size(print_properties_dialog); ! ! ! // Move focus to the Cancel button. This appears to highlight the ! // button fine, but we're not able to hit the key to ! // have that default function happen. Note: We _can_ hit the ! // key, and that activates the option. ! // XmUpdateDisplay(print_properties_dialog); ! XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT); ! ! ! } else { ! (void)XRaiseWindow(XtDisplay(print_properties_dialog), XtWindow(print_properties_dialog)); ! } ! } ! ! ! ! ! ! // Create png image (for use in web browsers??). Requires that "convert" ! // from the ImageMagick package be installed on the system. ! // ! static void* snapshot_thread(void *arg) { ! ! #ifndef NO_GRAPHICS ! char xpm_filename[MAX_FILENAME]; ! char png_filename[MAX_FILENAME]; ! #ifdef HAVE_CONVERT ! char command[MAX_FILENAME*2]; ! #endif // HAVE_CONVERT ! uid_t user_id; ! struct passwd *user_info; ! char username[20]; ! ! ! // The pthread_detach() call means we don't care about the ! // return code and won't use pthread_join() later. Makes ! // threading more efficient. ! (void)pthread_detach(pthread_self()); ! ! // Get user info ! user_id=getuid(); ! user_info=getpwuid(user_id); ! // Get my login name ! strcpy(username,user_info->pw_name); ! ! xastir_snprintf(xpm_filename, sizeof(xpm_filename), "/var/tmp/xastir_%s_snap.xpm", ! username); ! xastir_snprintf(png_filename, sizeof(png_filename),"/var/tmp/xastir_%s_snap.png", ! username); ! ! if ( debug_level & 512 ) ! fprintf(stderr,"Creating %s\n", xpm_filename ); ! ! if ( !XpmWriteFileFromPixmap( XtDisplay(appshell), // Display *display ! xpm_filename, // char *filename ! pixmap_final, // Pixmap pixmap ! (Pixmap)NULL, // Pixmap shapemask ! NULL ) == XpmSuccess ) { // XpmAttributes *attributes ! fprintf(stderr,"ERROR writing %s\n", xpm_filename ); ! } ! else { // We now have the xpm file created on disk ! ! chmod( xpm_filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH ); ! ! if ( debug_level & 512 ) ! fprintf(stderr,"Convert %s ==> %s\n", xpm_filename, png_filename ); ! ! #ifdef HAVE_CONVERT ! // Convert it to a png file. This depends on having the ! // ImageMagick command "convert" installed. ! xastir_snprintf(command, ! sizeof(command), ! "%s -quality 100 -colors 256 %s %s", ! CONVERT_PATH, ! xpm_filename, ! png_filename ); ! ! if ( system( command ) != 0 ) { ! // We _may_ have had an error. Check errno to make ! // sure. ! if (errno) { ! fprintf(stderr, "%s\n", strerror(errno)); ! fprintf(stderr, ! "Failed to convert snapshot: %s -> %s\n", ! xpm_filename, ! png_filename); ! } ! else { ! fprintf(stderr, ! "System call return error: convert: %s -> %s\n", ! xpm_filename, ! png_filename); ! } ! } ! else { ! chmod( png_filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH ); ! ! // Delete temporary xpm file ! unlink( xpm_filename ); ! ! if ( debug_level & 512 ) ! fprintf(stderr," Done creating png.\n"); ! } ! #endif // HAVE_CONVERT ! } ! ! #endif // NO_GRAPHICS ! ! // Signify that we're all done and that another snapshot can ! // occur. ! doing_snapshot = 0; ! ! return(NULL); ! } ! ! ! ! ! ! // Starts a separate thread that creates a png image from the ! // current displayed image. ! // ! void Snapshot(void) { ! pthread_t snapshot_thread_id; ! ! ! // Check whether we're already doing a snapshot ! if (doing_snapshot) ! return; ! ! // Time to take another snapshot? ! if (sec_now() < (last_snapshot + 300) ) // New snapshot every five minutes ! return; ! ! doing_snapshot++; ! last_snapshot = sec_now(); // Set up timer for next time ! ! //----- Start New Thread ----- ! ! // Here we start a new thread. We'll communicate with the main ! // thread via global variables. Use mutex locks if there might ! // be a conflict as to when/how we're updating those variables. ! // ! ! if (pthread_create(&snapshot_thread_id, NULL, snapshot_thread, NULL)) { ! fprintf(stderr,"Error creating snapshot thread\n"); ! } ! else { ! // We're off and running with the new thread! ! } ! } ! ! ! ! ! ! // Function to remove double-quote characters and spaces that occur ! // outside of the double-quote characters. ! void clean_string(char *input) { ! char *i; ! char *j; ! ! ! //fprintf(stderr,"|%s|\t",input); ! ! // Remove any double quote characters ! i = index(input,'"'); // Find first quote character, if any ! ! if (i != NULL) { ! j = index(i+1,'"'); // Find second quote character, if any ! ! if (j != NULL) { // Found two quote characters ! j[0] = '\0'; // Terminate the string at the 2nd quote ! strcpy(input,i+1); ! } ! else { // We only found one quote character. What to do? ! // fprintf(stderr,"clean_string: Only one quote found!\n"); ! } ! } ! //fprintf(stderr,"|%s|\n",input); ! ! // Remove leading/trailing spaces? ! } ! ! ! ! ! ! //NOTE: This function has a problem if a non-gnis file is labeled ! //with a ".gnis" extension. It causes a segfault in Xastir. More ! //error checking needs to be done in order to prevent this. ! ! // draw_gnis_map() ! // ! // Allows drawing a background map of labels for the viewport. ! // Example format: ! // "WA","Abbey View Memorial Park","cemetery","Snohomish","53","061","474647N","1221650W","47.77972","-122.28056","","","","","420","","Edmonds East" ! // ! // These types of files are available from http://geonames.usgs.gov/ ! // under "Download State Gazetteer Data - Available Via Anonymous FTP". ! // A typical filename would be: "WA.deci.gz". Do not get the other ! // types of files which are columnar. The files that we parse are ! // comma-delimited and have quotes around each field. ! ! // Some of the files have quotes around some fields, but not others, ! // and some have an extreme amount of spaces at the end of each ! // line. Some also have spaces, after a field but before a comma. ! // ! // Another difference just found: Some files have quotes around all ! // fields, some have quotes around only some. We need to handle ! // this gracefully. ! // ! void draw_gnis_map (Widget w, char *dir, char *filenm, int destination_pixmap) ! { ! char file[MAX_FILENAME]; // Complete path/name of GNIS file ! FILE *f; // Filehandle of GNIS file ! char line[MAX_FILENAME]; // One line of text from file ! char *i, *j, *k; ! char state[50]; ! char name[200]; ! char type[100]; ! char county[100]; ! char latitude[15]; ! char longitude[15]; ! char population[15]; ! char lat_dd[3]; ! char lat_mm[3]; ! char lat_ss[3]; ! char lat_dir[2]; ! char long_dd[4]; ! char long_mm[3]; ! char long_ss[3]; ! char long_dir[2]; ! char lat_str[15]; ! char long_str[15]; ! int temp1; ! long coord_lon, coord_lat; ! long min_lat, min_lon, max_lat, max_lon; ! int ok; ! long x,y; ! char symbol_table, symbol_id, symbol_over; ! unsigned long bottom_extent = 0l; ! unsigned long top_extent = 0l; ! unsigned long left_extent = 0l; ! unsigned long right_extent = 0l; ! char status_text[MAX_FILENAME]; ! ! ! //fprintf(stderr,"draw_gnis_map starting: %s/%s\n",dir,filenm); ! ! xastir_snprintf(file, sizeof(file), "%s/%s", dir, filenm); ! ! // Screen view ! min_lat = y_lat_offset + (long)(screen_height * scale_y); ! max_lat = y_lat_offset; ! min_lon = x_long_offset; ! max_lon = x_long_offset + (long)(screen_width * scale_x); ! ! ! // The map extents in the map index are checked in draw_map to ! // see whether we should draw the map at all. ! ! ! // Update the statusline for this map name ! // Check whether we're indexing or drawing the map ! if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS) ! || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) { ! xastir_snprintf(status_text, sizeof(status_text), langcode ("BBARSTA039"), filenm); ! } ! else { ! xastir_snprintf(status_text, sizeof(status_text), langcode ("BBARSTA028"), filenm); ! } ! statusline(status_text,0); // Loading/Indexing ... ! ! ! // Attempt to open the file ! f = fopen (file, "r"); ! if (f != NULL) { ! while (!feof (f)) { // Loop through entire file ! ! if ( get_line (f, line, MAX_FILENAME) ) { // Snag one line of data ! if (strlen(line) > 0) { ! ! //NOTE: We handle running off the end of "line" ! //via the "continue" statement. Skip the line ! //if we don't find enough parameters while ! //parsing. ! ! // Find State feature resides in ! i = index(line,','); // Find ',' after state field ! ! if (i == NULL) { // Comma not found ! continue; // Skip this line ! } ! ! i[0] = '\0'; ! strncpy(state,line,49); ! clean_string(state); ! ! //NOTE: It'd be nice to take the part after the comma and put it before the rest ! // of the text someday, i.e. "Cassidy, Lake". ! ! // Find Name ! j = index(i+1, ','); // Find ',' after Name. Note that there may be commas in the name. ! ! if (j == NULL) { // Comma not found ! continue; // Skip this line ! } ! ! while ( (j != NULL) && (j[1] != '\"') ) { ! k = j; ! j = index(k+1, ','); ! } ! ! if (j == NULL) { // Comma not found ! continue; // Skip this line ! } ! ! j[0] = '\0'; ! strncpy(name,i+1,199); ! clean_string(name); ! ! // Find Type ! i = index(j+1, ','); ! ! if (i == NULL) { // Comma not found ! continue; // Skip this line ! } ! ! i[0] = '\0'; ! strncpy(type,j+1,99); ! clean_string(type); ! ! // Find County // Can there be commas in the county name? ! j = index(i+1, ','); ! ! if (j == NULL) { // Comma not found ! continue; // Skip this line ! } ! ! j[0] = '\0'; ! strncpy(county,i+1,99); ! clean_string(county); ! ! // Find ? ! i = index(j+1, ','); ! ! if (i == NULL) { // Comma not found ! continue; // Skip this line ! } ! ! i[0] = '\0'; ! ! // Find ? ! j = index(i+1, ','); ! ! if (j == NULL) { // Comma not found ! continue; // Skip this line ! } ! ! j[0] = '\0'; ! ! // Find latitude (DDMMSSN) ! i = index(j+1, ','); ! ! if (i == NULL) { // Comma not found ! continue; // Skip this line ! } ! ! i[0] = '\0'; ! strncpy(latitude,j+1,14); ! clean_string(latitude); ! ! // Find longitude (DDDMMSSW) ! j = index(i+1, ','); ! ! if (j == NULL) { // Comma not found ! continue; // Skip this line ! } ! ! j[0] = '\0'; ! strncpy(longitude,i+1,14); ! clean_string(longitude); ! ! // Find another latitude ! i = index(j+1, ','); ! ! if (i == NULL) { // Comma not found ! continue; // Skip this line ! } ! ! i[0] = '\0'; ! ! // Find another longitude ! j = index(i+1, ','); ! ! if (j == NULL) { // Comma not found ! continue; // Skip this line ! } ! ! j[0] = '\0'; ! ! // Find ? ! i = index(j+1, ','); ! ! if (i == NULL) { // Comma not found ! continue; // Skip this line ! } ! ! i[0] = '\0'; ! ! // Find ? ! j = index(i+1, ','); ! ! if (j == NULL) { // Comma not found ! continue; // Skip this line ! } ! ! j[0] = '\0'; ! ! // Find ? ! i = index(j+1, ','); ! ! if (i == NULL) { // Comma not found ! continue; // Skip this line ! } ! ! i[0] = '\0'; ! ! // Find ? ! j = index(i+1, ','); ! ! if (j == NULL) { // Comma not found ! continue; // Skip this line ! } ! ! j[0] = '\0'; ! ! // Find altitude ! i = index(j+1, ','); ! ! if (i == NULL) { // Comma not found ! continue; // Skip this line ! } ! ! i[0] = '\0'; ! ! // Find population ! j = index(i+1, ','); ! ! if (j == NULL) { // Comma not found ! continue; // Skip this line ! } ! ! if ( j != NULL ) { ! j[0] = '\0'; ! strncpy(population,i+1,14); ! } else { ! strncpy(population,"0",14); ! } ! clean_string(population); ! ! lat_dd[0] = latitude[0]; ! lat_dd[1] = latitude[1]; ! lat_dd[2] = '\0'; ! ! lat_mm[0] = latitude[2]; ! lat_mm[1] = latitude[3]; ! lat_mm[2] = '\0'; ! ! lat_ss[0] = latitude[4]; ! lat_ss[1] = latitude[5]; ! lat_ss[2] = '\0'; ! ! lat_dir[0] = latitude[6]; ! lat_dir[1] = '\0'; ! ! long_dd[0] = longitude[0]; ! long_dd[1] = longitude[1]; ! long_dd[2] = longitude[2]; ! long_dd[3] = '\0'; ! ! long_mm[0] = longitude[3]; ! long_mm[1] = longitude[4]; ! long_mm[2] = '\0'; ! ! long_ss[0] = longitude[5]; ! long_ss[1] = longitude[6]; ! long_ss[2] = '\0'; ! ! long_dir[0] = longitude[7]; ! long_dir[1] = '\0'; ! ! // Now must convert from DD MM SS format to DD MM.MM format so that we ! // can run it through our conversion routine to Xastir coordinates. ! (void)sscanf(lat_ss, "%d", &temp1); ! temp1 = (int)((temp1 / 60.0) * 100 + 0.5); // Poor man's rounding ! xastir_snprintf(lat_str, sizeof(lat_str), "%s%s.%02d%s", lat_dd, ! lat_mm, temp1, lat_dir); ! coord_lat = convert_lat_s2l(lat_str); ! ! (void)sscanf(long_ss, "%d", &temp1); ! temp1 = (int)((temp1 / 60.0) * 100 + 0.5); // Poor man's rounding ! xastir_snprintf(long_str, sizeof(long_str), "%s%s.%02d%s", long_dd, ! long_mm, temp1, long_dir); ! coord_lon = convert_lon_s2l(long_str); ! ! ! // Save the min/max extents of the file. We ! // should really initially set the extents to ! // the min/max for the Xastir coordinate system, ! // but in practice zeroes should work just as ! // well. ! if ((coord_lat > (long)bottom_extent) || (bottom_extent == 0l)) ! bottom_extent = coord_lat; ! if ((coord_lat < (long)top_extent) || (top_extent == 0l)) ! top_extent = coord_lat; ! if ((coord_lon < (long)left_extent) || (left_extent == 0l)) ! left_extent = coord_lon; ! if ((coord_lon > (long)right_extent) || (right_extent == 0l)) ! right_extent = coord_lon; ! ! ! // Check whether we're indexing the map ! if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS) ! || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) { ! // Do nothing, we're indexing, not drawing ! } ! // Now check whether this lat/lon is within our viewport. If it ! // is, draw a text label at that location. ! else if (coord_lon >= min_lon && coord_lon <= max_lon ! && coord_lat <= min_lat && coord_lat >= max_lat) { ! ! if (debug_level & 16) { ! fprintf(stderr,"%s\t%s\t%s\t%s\t%s\t%s\t\t", ! state, name, type, county, latitude, longitude); ! fprintf(stderr,"%s %s %s %s\t%s %s %s %s\t\t", ! lat_dd, lat_mm, lat_ss, lat_dir, long_dd, long_mm, long_ss, long_dir); ! fprintf(stderr,"%s\t%s\n", lat_str, long_str); ! } ! ! // Convert to screen coordinates. Careful ! // here! The format conversions you'll need ! // if you try to compress this into two ! // lines will get you into trouble. ! x = coord_lon - x_long_offset; ! y = coord_lat - y_lat_offset; ! x = x / scale_x; ! y = y / scale_y; ! ! ok = 1; ! if (x > 16000) ok = 0; // Skip this point ! if (x < -16000) ok = 0; // Skip this point ! if (y > 16000) ok = 0; // Skip this point ! if (y < -16000) ok = 0; // Skip this point ! ! /* set default symbol */ ! symbol_table = '/'; ! symbol_id = '.'; /* small x */ ! symbol_over = ' '; ! ! if (strcasecmp(type,"airport") == 0) { ! symbol_id = '^'; ! if (scale_y > 100) ! ok = 0; ! } ! else if (strcasecmp(type,"arch") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"area") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"arroyo") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"bar") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"basin") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"bay") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"beach") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"bench") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"bend") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"bridge") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"building") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"canal") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"cape") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"cave") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"cemetery") == 0) { ! symbol_table = '\\'; ! symbol_id = '+'; ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"census") == 0) { ! /* if (scale_y > 50)*/ /* Census divisions */ ! ok = 0; ! } ! else if (strcasecmp(type,"channel") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"church") == 0) { ! symbol_table = '\\'; ! symbol_id = '+'; ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"civil") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"cliff") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"crater") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"crossing") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"dam") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"falls") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"flat") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"forest") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"gap") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"geyser") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"glacier") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"gut") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"harbor") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"hospital") == 0) { ! symbol_id = 'h'; ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"island") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"isthmus") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"lake") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"lava") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"levee") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"locale") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"military") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"mine") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"oilfield") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"other") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"park") == 0) { ! symbol_table = '\\'; ! symbol_id = ';'; ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"pillar") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"plain") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"po") == 0) { ! symbol_id = ']'; ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"ppl") == 0) { ! symbol_id = '/'; ! if (scale_y > 20000) // Don't draw cities at zoom higher than 20,000 ! ok = 0; ! else if (scale_y > 4000) { // Don't draw cities of less than 20,000 ! if (atoi(population) < 50000) { ! ok = 0; ! } ! } ! else if (scale_y > 1500) { // Don't draw cities of less than 10,000 ! if (atoi(population) < 20000) { ! ok = 0; ! } ! } ! else if (scale_y > 750) { // Don't draw cities of less than 5,000 ! if (atoi(population) < 10000) { ! ok = 0; ! } ! } ! else if (scale_y > 200) { // Don't draw cities of less than 1,000 ! if (atoi(population) < 1000) { ! ok = 0; ! //fprintf(stderr,"Name: %s\tPopulation: %s\n",name,population); ! } ! } ! } ! else if (strcasecmp(type,"range") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"rapids") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"reserve") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"reservoir") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"ridge") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"school") == 0) { ! symbol_id = 'K'; ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"sea") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"slope") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"spring") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"stream") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"summit") == 0) { ! if (scale_y > 100) ! ok = 0; ! } ! else if (strcasecmp(type,"swamp") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"trail") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"tower") == 0) { ! symbol_id = 'r'; ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"tunnel") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"valley") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"well") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else if (strcasecmp(type,"woods") == 0) { ! if (scale_y > 50) ! ok = 0; ! } ! else { ! fprintf(stderr,"Something unusual found, Type:%s\tState:%s\tCounty:%s\tName:%s\n", ! type,state,county,name); ! } ! ! if (ok == 1) { // If ok to draw it ! symbol(w, 0, symbol_table, symbol_id, symbol_over, pixmap, 1, x-10, y-10, ' '); ! draw_nice_string(w, pixmap, 0, x+10, y+5, (char*)name, 0xf, 0x10, strlen(name)); ! } ! ! } ! else { ! //fprintf(stderr,"Not in viewport. Coordinates: %ld %ld\n",coord_lat,coord_lon); ! //fprintf(stderr,"Min/Max Lat: %ld %ld\n",min_lat,max_lat); ! //fprintf(stderr,"Min/Max Lon: %ld %ld\n",min_lon,max_lon); ! } ! } ! } ! } // End of while ! (void)fclose (f); ! ! ! // Check whether we're indexing the map ! if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS) ! || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) { ! ! // We're indexing only. Save the extents in the index. ! index_update_xastir(filenm, // Filename only ! bottom_extent, // Bottom ! top_extent, // Top ! left_extent, // Left ! right_extent); // Right ! } ! } ! else { ! fprintf(stderr,"Couldn't open file: %s\n", file); ! return; ! } ! if (debug_level & 16) ! fprintf(stderr,"Exiting draw_gnis_map\n"); ! } ! ! ! ! ! ! // Search for a placename among GNIS files ! // ! // We need to search a file in the map directory that has the filename ! // STATE.gis, where STATE is from the "state" variable passed to us. ! // Search for the placename/county/state/type that the user requested. ! // Once found, center the map on that location or bring up a response ! // dialog that asks whether one wants to go there, and that dialog ! // provides info about the place found, with a possible selection ! // out of a list of matches. ! // Might also need to place a label at that position on the map in ! // case that GNIS file isn't currently selected. ! // ! int locate_place( Widget w, char *name_in, char *state_in, char *county_in, ! char *quad_in, char *type_in, char *filename_in, int follow_case, int get_match ) { ! char file[MAX_FILENAME]; // Complete path/name of GNIS file ! FILE *f; // Filehandle of GNIS file ! char line[MAX_FILENAME]; // One line of text from file ! char *i, *j, *k; ! char state[50]; ! char state_in2[50]; ! char name[200]; ! char name_in2[50]; ! char type[100]; ! char type_in2[50]; ! char county[100]; ! char county_in2[50]; ! char quad[100]; ! char quad_in2[100]; ! char latitude[15]; ! char longitude[15]; ! char population[15]; ! char lat_dd[3]; ! char lat_mm[3]; ! char lat_ss[3]; ! char lat_dir[2]; ! char long_dd[4]; ! char long_mm[3]; ! char long_ss[3]; ! char long_dir[2]; ! char lat_str[15]; ! char long_str[15]; ! int temp1; ! long coord_lon, coord_lat; ! int ok; ! struct stat file_status; ! ! ! strcpy(file,filename_in); ! if (debug_level & 16) ! fprintf(stderr,"File: %s\n",file); ! ! ! strcpy(name_in2,name_in); ! strcpy(state_in2,state_in); ! strcpy(county_in2,county_in); ! strcpy(quad_in2,quad_in); ! strcpy(type_in2,type_in); ! ! ! // Convert State/Province to upper-case always (they're ! // always upper-case in the GNIS files from USGS. ! to_upper(state_in2); ! ! ! if (debug_level & 16) ! fprintf(stderr,"Name:%s\tState:%s\tCounty:%s\tQuad:%s\tType:%s\n", ! name_in,state_in2,county_in,quad_in,type_in); ! ! ! // If "Match Case" togglebutton is not set, convert the ! // rest of the keys to upper-case. ! if (!follow_case) { ! to_upper(name_in2); ! to_upper(county_in2); ! to_upper(quad_in2); ! to_upper(type_in2); ! } ! ! ! // Check status of the file ! if (stat(file, &file_status) < 0) { ! popup_message( langcode("POPEM00028"), filename_in ); ! return(0); ! } ! // Check for regular file ! if (!S_ISREG(file_status.st_mode)) { ! popup_message( langcode("POPEM00028"), filename_in ); ! return(0); ! } ! // Attempt to open the file ! f = fopen (file, "r"); ! if (f != NULL) { ! while (!feof (f)) { // Loop through entire file ! if ( get_line (f, line, MAX_FILENAME) ) { // Snag one line of data ! if (strlen(line) > 0) { ! ! ! //NOTE: How do we handle running off the end of "line" while using "index"? ! // Short lines here can cause segfaults. ! ! ! // Find State feature resides in ! i = index(line,','); // Find ',' after state ! ! if (i == NULL) { // Comma not found ! continue; // Skip line ! } ! ! i[0] = '\0'; ! strncpy(state,line+1,49); ! // state[strlen(state)-1] = '\0'; ! clean_string(state); ! ! //NOTE: It'd be nice to take the part after the comma and put it before the rest ! // of the text someday, i.e. "Cassidy, Lake". ! // Find Name ! j = index(i+1, ','); // Find ',' after Name. Note that there may be commas in the name. ! ! if (j == NULL) { // Comma not found ! continue; // Skip line ! } ! ! while ( (j != NULL) && (j[1] != '\"') ) { ! k = j; ! j = index(k+1, ','); ! } ! ! if (j == NULL) { // Comma not found ! continue; // Skip line ! } ! ! j[0] = '\0'; ! strncpy(name,i+2,199); ! // name[strlen(name)-1] = '\0'; ! clean_string(name); ! ! // Find Type ! i = index(j+1, ','); ! ! if (i == NULL) { // Comma not found ! continue; // Skip line ! } ! ! i[0] = '\0'; ! strncpy(type,j+2,99); ! // type[strlen(type)-1] = '\0'; ! clean_string(type); ! ! // Find County // Can there be commas in the county name? ! j = index(i+1, ','); ! ! if (j == NULL) { // Comma not found ! continue; // Skip line ! } ! ! j[0] = '\0'; ! strncpy(county,i+2,99); ! // county[strlen(county)-1] = '\0'; ! clean_string(county); ! ! // Find ? ! i = index(j+1, ','); ! ! if (i == NULL) { // Comma not found ! continue; // Skip line ! } ! ! i[0] = '\0'; ! ! // Find ? ! j = index(i+1, ','); ! ! if (j == NULL) { // Comma not found ! continue; // Skip line ! } ! ! j[0] = '\0'; ! ! // Find latitude (DDMMSSN) ! i = index(j+1, ','); ! ! if (i == NULL) { // Comma not found ! continue; // Skip line ! } ! ! i[0] = '\0'; ! strncpy(latitude,j+2,14); ! // latitude[strlen(latitude)-1] = '\0'; ! clean_string(latitude); ! ! // Find longitude (DDDMMSSW) ! j = index(i+1, ','); ! ! if (j == NULL) { // Comma not found ! continue; // Skip line ! } ! ! j[0] = '\0'; ! strncpy(longitude,i+2,14); ! // longitude[strlen(longitude)-1] = '\0'; ! clean_string(longitude); ! ! // Find another latitude ! i = index(j+1, ','); ! ! if (i == NULL) { // Comma not found ! continue; // Skip line ! } ! ! i[0] = '\0'; ! ! // Find another longitude ! j = index(i+1, ','); ! ! if (j == NULL) { // Comma not found ! continue; // Skip line ! } ! ! j[0] = '\0'; ! ! // Find ? ! i = index(j+1, ','); ! ! if (i == NULL) { // Comma not found ! continue; // Skip line ! } ! ! i[0] = '\0'; ! ! // Find ? ! j = index(i+1, ','); ! ! if (j == NULL) { // Comma not found ! continue; // Skip line ! } ! ! j[0] = '\0'; ! ! // Find ? ! i = index(j+1, ','); ! ! if (i == NULL) { // Comma not found ! continue; // Skip line ! } ! ! i[0] = '\0'; ! ! // Find ? ! j = index(i+1, ','); ! ! if (j == NULL) { // Comma not found ! continue; // Skip line ! } ! ! j[0] = '\0'; ! ! // Find altitude ! i = index(j+1, ','); ! ! if (i == NULL) { // Comma not found ! continue; // Skip line ! } ! ! i[0] = '\0'; ! ! // Find population ! j = index(i+1, ','); ! ! if (j == NULL) { // Comma not found ! continue; // Skip line ! } ! ! j[0] = '\0'; ! strncpy(population,i+2,14); ! // population[strlen(population)-1] = '\0'; ! clean_string(population); ! ! // Find quad name (last field) ! i = index(j+1, '"'); ! ! if (i == NULL) { // Comma not found ! continue; // Skip line ! } ! ! i[0] = '\0'; ! strncpy(quad,j+2,14); ! // quad[strlen(quad)] = '\0'; ! clean_string(quad); ! ! ! // If "Match Case" togglebutton is not set, convert ! // the data to upper-case before we do our compare. ! if (!follow_case) { ! to_upper(name); ! to_upper(state); ! to_upper(county); ! to_upper(quad); ! to_upper(type); ! } ! ! ! // Still need to code for the "Match Exact" togglebutton. ! ! ! // Now compare the input variables with those we've ! // parsed. If a match, bring up a list of items which ! // match. ! // ! ok = 1; ! if (get_match) { // Looking for exact match ! if (name_in2[0] != '\0') ! if (strcmp(name,name_in2) != 0) ! ok = 0; ! if (state_in2[0] != '\0') ! if (strcmp(state,state_in2) != 0) ! ok = 0; ! if (county_in2[0] != '\0') ! if (strcmp(county,county_in2) != 0) ! ok = 0; ! if (quad_in2[0] != '\0') ! if (strcmp(quad,quad_in2) != 0) ! ok = 0; ! if (type_in2[0] != '\0') ! if (strcmp(type,type_in2) != 0) ! ok = 0; ! } ! else { // Look for substring in file, not exact match ! if (name_in2[0] != '\0') ! if (strstr(name,name_in2) == NULL) ! ok = 0; ! if (state_in2[0] != '\0') ! if (strstr(state,state_in2) == NULL) ! ok = 0; ! if (county_in2[0] != '\0') ! if (strstr(county,county_in2) == NULL) ! ok = 0; ! if (quad_in2[0] != '\0') ! if (strstr(quad,quad_in2) == NULL) ! ok = 0; ! if (type_in2[0] != '\0') ! if (strstr(type,type_in2) == NULL) ! ok = 0; ! } ! ! ! if (ok) { ! if (debug_level & 16) ! fprintf(stderr,"Match: %s,%s,%s,%s\n",name,state,county,type); ! ! popup_message( langcode("POPEM00029"), name ); ! ! lat_dd[0] = latitude[0]; ! lat_dd[1] = latitude[1]; ! lat_dd[2] = '\0'; ! ! lat_mm[0] = latitude[2]; ! lat_mm[1] = latitude[3]; ! lat_mm[2] = '\0'; ! ! lat_ss[0] = latitude[4]; ! lat_ss[1] = latitude[5]; ! lat_ss[2] = '\0'; ! ! lat_dir[0] = latitude[6]; ! lat_dir[1] = '\0'; ! ! long_dd[0] = longitude[0]; ! long_dd[1] = longitude[1]; ! long_dd[2] = longitude[2]; ! long_dd[3] = '\0'; ! ! long_mm[0] = longitude[3]; ! long_mm[1] = longitude[4]; ! long_mm[2] = '\0'; ! ! long_ss[0] = longitude[5]; ! long_ss[1] = longitude[6]; ! long_ss[2] = '\0'; ! ! long_dir[0] = longitude[7]; ! long_dir[1] = '\0'; ! ! // Now must convert from DD MM SS format to DD MM.MM format so that we ! // can run it through our conversion routine to Xastir coordinates. ! (void)sscanf(lat_ss, "%d", &temp1); ! temp1 = (int)((temp1 / 60.0) * 100 + 0.5); // Poor man's rounding ! xastir_snprintf(lat_str, sizeof(lat_str), "%s%s.%02d%s", lat_dd, ! lat_mm, temp1, lat_dir); ! coord_lat = convert_lat_s2l(lat_str); ! ! (void)sscanf(long_ss, "%d", &temp1); ! temp1 = (int)((temp1 / 60.0) * 100 + 0.5); // Poor man's rounding ! xastir_snprintf(long_str, sizeof(long_str), "%s%s.%02d%s", long_dd, ! long_mm, temp1, long_dir); ! coord_lon = convert_lon_s2l(long_str); ! set_map_position(w, coord_lat, coord_lon); ! return(1); // We found a match ! } ! } ! } ! } ! } else { ! popup_message( langcode("POPEM00028"), filename_in ); ! } ! ! return(0); // We didn't find a match ! } ! ! ! ! ! ! /********************************************************** ! * draw_geo_image_map() ! * ! * If we have found a ".geo" file, we read it here and plot ! * the graphic image into the current viewport. ! * We check first to see whether the map should be plotted ! * and skip it if it's not in our viewport. These images ! * are expected to be aligned in the lat/lon directions ! * (not rotated) and rectangular. ! **********************************************************/ ! ! void draw_geo_image_map (Widget w, char *dir, char *filenm, int destination_pixmap) { ! uid_t user_id; ! struct passwd *user_info; ! char username[20]; ! char file[MAX_FILENAME+1]; // Complete path/name of image file ! FILE *f; // Filehandle of image file ! char line[MAX_FILENAME]; // One line from GEO file ! char fileimg[MAX_FILENAME+1]; // Ascii name of image file, read from GEO file ! XpmAttributes atb; // Map attributes after map's read into an XImage ! tiepoint tp[2]; // Calibration points for map, read in from .geo file ! int n_tp; // Temp counter for number of tiepoints read ! float temp_long, temp_lat; ! register long map_c_T, map_c_L; // map delta NW edge coordinates, DNN: these should be signed ! register long tp_c_dx, tp_c_dy; // tiepoint coordinate differences ! // DK7IN-- ! int test; // temporary debugging ! ! unsigned long c_x_min, c_y_min;// top left coordinates of map inside screen ! unsigned long c_y_max; // bottom right coordinates of map inside screen ! double c_x; // Xastir coordinates 1/100 sec, 0 = 180°W ! double c_y; // Xastir coordinates 1/100 sec, 0 = 90°N ! double c_y_a; // coordinates correction for Transverse Mercator ! ! long map_y_0; // map pixel pointer prior to TM adjustment ! register long map_x, map_y; // map pixel pointers, DNN: this was a float, chg to long ! long map_x_min, map_x_max; // map boundaries for in screen part of map ! long map_y_min, map_y_max; // ! long map_x_ctr; // half map width in pixel ! long map_y_ctr; // half map height in pixel ! // long x; ! int map_seen, map_act, map_done; ! double corrfact; ! ! long map_c_yc; // map center, vert coordinate ! long map_c_xc; // map center, hor coordinate ! double map_c_dx, map_c_dy; // map coordinates increment (pixel width) ! double c_dx; // adjusted map pixel width ! ! long scr_x, scr_y; // screen pixel plot positions ! long scr_xp, scr_yp; // previous screen plot positions ! int scr_dx, scr_dy; // increments in screen plot positions ! long scr_x_mc; // map center in screen units ! ! long scr_c_xr; ! ! double dist; // distance from equator in nm ! double ew_ofs; // distance from map center in nm ! ! long scale_xa; // adjusted for topo maps ! double scale_x_nm; // nm per Xastir coordinate unit ! long scale_x0; // at widest map area ! ! #ifdef HAVE_IMAGEMAGICK ! char local_filename[MAX_FILENAME]; ! ExceptionInfo exception; ! Image *image; ! ImageInfo *image_info; ! PixelPacket *pixel_pack; ! PixelPacket temp_pack; ! IndexPacket *index_pack; ! int l; ! XColor my_colors[256]; ! #ifdef HAVE_LIBCURL ! CURL *curl; ! CURLcode res; ! char curlerr[CURL_ERROR_SIZE]; ! struct FtpFile ftpfile; ! #else ! #ifdef HAVE_WGET ! char tempfile[MAX_FILENAME]; ! #endif // HAVE_WGET ! #endif ! char gamma[16]; ! struct { ! float r_gamma; ! float g_gamma; ! float b_gamma; ! int gamma_flag; ! int contrast; ! int negate; ! int equalize; ! int normalize; ! char level[32]; ! char modulate[32]; ! } imagemagick_options = { 1.0, 1.0, 1.0, 0, 0, -1, 0, 0, "", "" }; ! double left, right, top, bottom, map_width, map_height; ! //N0VH ! // double lat_center = 0; ! // double long_center = 0; ! // Terraserver variables ! double top_n=0, left_e=0, bottom_n=0, right_e=0, map_top_n=0, map_left_e=0; ! int z, url_n=0, url_e=0, t_zoom=16, t_scale=12800; ! char zstr[8]; ! #else // HAVE_IMAGEMAGICK ! XImage *xi; // Temp XImage used for reading in current image ! #endif // HAVE_IMAGEMAGICK ! ! int terraserver_flag = 0; ! int toposerver_flag = 0; ! char map_it[MAX_FILENAME]; ! int geo_image_width = 0; // Image width from GEO file ! int geo_image_height = 0; // Image height from GEO file ! char geo_datum[8+1]; // WGS-84 etc. ! char geo_projection[8+1]; // TM, UTM, GK, LATLON etc. ! int map_proj; ! ! //#define TIMING_DEBUG ! #ifdef TIMING_DEBUG ! time_mark(1); ! #endif // TIMING_DEBUG ! ! // Get user info ! user_id=getuid(); ! user_info=getpwuid(user_id); ! // Get my login name ! strcpy(username,user_info->pw_name); ! ! xastir_snprintf(file, sizeof(file), "%s/%s", dir, filenm); ! ! // Read the .geo file to find out map filename and tiepoint info ! n_tp = 0; ! geo_datum[0] = '\0'; ! geo_projection[0] = '\0'; ! f = fopen (file, "r"); ! if (f != NULL) { ! while (!feof (f)) { ! (void)get_line (f, line, MAX_FILENAME); ! if (strncasecmp (line, "FILENAME", 8) == 0) { ! (void)sscanf (line + 9, "%s", fileimg); ! if (fileimg[0] != '/' ) { // not absolute path ! // make it relative to the .geo file ! char temp[MAX_FILENAME]; ! strncpy(temp, file, MAX_FILENAME); // grab .geo file name ! temp[MAX_FILENAME-1] = '\0'; ! (void)get_map_dir(temp); // leaves just the path and trailing / ! if (strlen(temp) < (MAX_FILENAME - 1 - strlen(fileimg))) ! strcat(temp, fileimg); ! strcpy(fileimg, temp); ! } ! } ! if (strncasecmp (line, "URL", 3) == 0) ! (void)sscanf (line + 4, "%s", fileimg); ! ! if (n_tp < 2) { // Only take the first two tiepoints ! if (strncasecmp (line, "TIEPOINT", 8) == 0) { ! (void)sscanf (line + 9, "%d %d %f %f",&tp[n_tp].img_x,&tp[n_tp].img_y,&temp_long,&temp_lat); ! // Convert tiepoints from lat/lon to Xastir coordinates ! tp[n_tp].x_long = 64800000l + (360000.0 * temp_long); ! tp[n_tp].y_lat = 32400000l + (360000.0 * (-temp_lat)); ! n_tp++; ! } ! } ! ! if (strncasecmp (line, "IMAGESIZE", 9) == 0) ! (void)sscanf (line + 10, "%d %d",&geo_image_width,&geo_image_height); ! ! if (strncasecmp (line, "DATUM", 5) == 0) ! (void)sscanf (line + 6, "%8s",geo_datum); ! ! if (strncasecmp (line, "PROJECTION", 10) == 0) ! (void)sscanf (line + 11, "%8s",geo_projection); // ignores leading and trailing space (nice!) ! ! if (strncasecmp (line, "TERRASERVER", 11) == 0) ! terraserver_flag = 1; ! ! if (strncasecmp (line, "TOPOSERVER", 10) == 0) ! toposerver_flag = 1; ! ! ! #ifdef HAVE_IMAGEMAGICK ! if (strncasecmp(line, "GAMMA", 5) == 0) ! imagemagick_options.gamma_flag = sscanf(line + 6, "%f,%f,%f", ! &imagemagick_options.r_gamma, ! &imagemagick_options.g_gamma, ! &imagemagick_options.b_gamma); ! if (strncasecmp(line, "CONTRAST", 8) == 0) ! (void)sscanf(line + 9, "%d", &imagemagick_options.contrast); ! if (strncasecmp(line, "NEGATE", 6) == 0) ! (void)sscanf(line + 7, "%d", &imagemagick_options.negate); ! if (strncasecmp(line, "EQUALIZE", 8) == 0) ! imagemagick_options.equalize = 1; ! if (strncasecmp(line, "NORMALIZE", 9) == 0) ! imagemagick_options.normalize = 1; ! #if (MagickLibVersion >= 0x0539) ! if (strncasecmp(line, "LEVEL", 5) == 0) { ! strncpy(imagemagick_options.level, line + 6, 31); ! imagemagick_options.level[31] = '\0'; ! } ! #endif // MagickLibVersion >= 0x0539 ! if (strncasecmp(line, "MODULATE", 8) == 0) { ! strncpy(imagemagick_options.modulate, line + 9, 31); ! imagemagick_options.modulate[31] = '\0'; ! } ! #endif // HAVE_IMAGEMAGICK ! } ! (void)fclose (f); ! } ! else { ! fprintf(stderr,"Couldn't open file: %s\n", file); ! return; ! } ! ! // DK7IN: I'm experimenting with the adjustment of topo maps with ! // Transverse Mercator projection. Those maps have equal scaling ! // in distance while we use equal scaling in degrees. ! ! // For now I use the map center as central meridian (I think that ! // is ok for mapblast), that will change with UTM and Gauss-Krueger ! ! // I have introduced new entries in the geo file for that... ! // I first adjust the x scaling depending on the latitude ! // Then I move points in y direction depending on the offset from ! // the central meridian. I hope I get that right with those ! // approximations. I have the correct formulas, but that will ! // be very computing intensive and result in slow map loading... ! ! // if (geo_datum[0] != '\0') ! // fprintf(stderr,"Map Datum: %s\n",geo_datum); // not used now... ! ! if (geo_projection[0] == '\0') ! strcpy(geo_projection,"LatLon"); // default ! //fprintf(stderr,"Map Projection: %s\n",geo_projection); ! (void)to_upper(geo_projection); ! if (strcmp(geo_projection,"TM") == 0) ! map_proj = 1; // Transverse Mercator ! else ! map_proj = 0; // Lat/Lon, default ! ! ! #ifdef HAVE_IMAGEMAGICK ! if (terraserver_flag || toposerver_flag) { ! //http://terraservice.net/download.ashx?t=1&s=10&x=2742&y=26372&z=10&w=820&h=480 ! if (scale_y <= 4) { ! t_zoom = 10; // 1m ! t_scale = 200; ! } ! else if (scale_y <= 8) { ! t_zoom = 11; // 2m ! t_scale = 400; ! } ! else if (scale_y <= 16) { ! t_zoom = 12; // 4m ! t_scale = 800; ! } ! else if (scale_y <= 32) { ! t_zoom = 13; // 8m ! t_scale = 1600; ! } ! else if (scale_y <= 64) { ! t_zoom = 14; // 16m ! t_scale = 3200; ! } ! else if (scale_y <= 128) { ! t_zoom = 15; // 32m ! t_scale = 6400; ! } ! else { ! t_zoom = 16; // 64m ! t_scale = 12800; ! } ! ! top = -((y_lat_offset - 32400000l) / 360000.0); ! left = (x_long_offset - 64800000l) / 360000.0; ! ll_to_utm(gDatum[D_NAD_83_CONUS].ellipsoid, top, left, &top_n, &left_e, zstr, sizeof(zstr) ); ! sscanf(zstr, "%d", &z); ! ! bottom = -(((y_lat_offset + (screen_height * scale_y)) - 32400000l) / 360000.0); ! right = ((x_long_offset + (screen_width * scale_x)) - 64800000l) / 360000.0; ! ll_to_utm(gDatum[D_NAD_83_CONUS].ellipsoid, bottom, right, &bottom_n, &right_e, zstr, sizeof(zstr) ); ! ! map_top_n = (int)((top_n / t_scale) + 1) * t_scale; ! map_left_e = (int)((left_e / t_scale) + 0) * t_scale; ! utm_to_ll(gDatum[D_NAD_83_CONUS].ellipsoid, map_top_n, map_left_e, zstr, &top, &left); ! ! geo_image_height = (map_top_n - bottom_n) * 200 / t_scale; ! geo_image_width = (right_e - map_left_e) * 200 / t_scale; ! map_width = right - left; ! map_height = top - bottom; ! ! tp[0].img_x = 0; ! tp[0].img_y = 0; ! tp[0].x_long = 64800000l + (360000.0 * left); ! tp[0].y_lat = 32400000l + (360000.0 * (-top)); ! ! tp[1].img_x = geo_image_width - 1; ! tp[1].img_y = geo_image_height - 1; ! tp[1].x_long = 64800000l + (360000.0 * right); ! tp[1].y_lat = 32400000l + (360000.0 * (-bottom)); ! ! url_n = (int)(top_n / t_scale); // The request URL does not use the ! url_e = (int)(left_e / t_scale); // N/E of the map corner ! ! xastir_snprintf(fileimg, sizeof(fileimg), ! // "http://terraservice.net/download.ashx?t=%d\046s=%d\046x=%d\046y=%d\046z=%d\046w=%d\046h=%d", ! "http://terraserver-usa.net/download.ashx?t=%d\046s=%d\046x=%d\046y=%d\046z=%d\046w=%d\046h=%d", ! (toposerver_flag) ? 2 : 1, ! t_zoom, ! url_e, ! url_n, ! z, ! geo_image_width, ! geo_image_height); ! } ! #endif // HAVE_IMAGEMAGICK ! ! // ! // DK7IN: we should check what we got from the geo file ! // we use geo_image_width, but it might not be initialised... ! // and it's wrong if the '\n' is missing a the end... ! ! /* ! * Here are the corners of our viewport, using the Xastir ! * coordinate system. Notice that Y is upside down: ! * ! * left edge of view = x_long_offset ! * right edge of view = x_long_offset + (screen_width * scale_x) ! * top edge of view = y_lat_offset ! * bottom edge of view = y_lat_offset + (screen_height * scale_y) ! * ! * The corners of our map will soon be (after translating the ! * tiepoints to the corners if they're not already there): ! * ! * left edge of map = tp[0].x_long in Xastir format ! * right edge of map = tp[1].x_long ! * top edge of map = tp[0].y_lat ! * bottom edge of map = tp[1].y_lat ! * ! */ ! map_c_L = tp[0].x_long - x_long_offset; // map left coordinate ! map_c_T = tp[0].y_lat - y_lat_offset; // map top coordinate ! ! tp_c_dx = (long)(tp[1].x_long - tp[0].x_long);// Width between tiepoints ! tp_c_dy = (long)(tp[1].y_lat - tp[0].y_lat); // Height between tiepoints ! ! ! // Check for tiepoints being in wrong relation to one another ! if (tp_c_dx < 0) tp_c_dx = -tp_c_dx; // New width between tiepoints ! if (tp_c_dy < 0) tp_c_dy = -tp_c_dy; // New height between tiepoints ! ! ! if (debug_level & 512) { ! fprintf(stderr,"X tiepoint width: %ld\n", tp_c_dx); ! fprintf(stderr,"Y tiepoint width: %ld\n", tp_c_dy); ! } ! ! // Calculate step size per pixel ! map_c_dx = ((double) tp_c_dx / abs(tp[1].img_x - tp[0].img_x)); ! map_c_dy = ((double) tp_c_dy / abs(tp[1].img_y - tp[0].img_y)); ! ! // Scaled screen step size for use with XFillRectangle below ! scr_dx = (int) (map_c_dx / scale_x) + 1; ! scr_dy = (int) (map_c_dy / scale_y) + 1; ! ! if (debug_level & 512) { ! fprintf(stderr,"\nImage: %s\n", file); ! fprintf(stderr,"Image size %d %d\n", geo_image_width, geo_image_height); ! fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n", map_c_L, map_c_T, map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y)); ! } ! ! // calculate top left map corner from tiepoints ! if (tp[0].img_x != 0) { ! tp[0].x_long -= (tp[0].img_x * map_c_dx); // map left edge longitude ! map_c_L = tp[0].x_long - x_long_offset; // delta ?? ! tp[0].img_x = 0; ! if (debug_level & 512) ! fprintf(stderr,"Translated tiepoint_0 x: %d\t%lu\n", tp[0].img_x, tp[0].x_long); ! } ! if (tp[0].img_y != 0) { ! tp[0].y_lat -= (tp[0].img_y * map_c_dy); // map top edge latitude ! map_c_T = tp[0].y_lat - y_lat_offset; ! tp[0].img_y = 0; ! if (debug_level & 512) ! fprintf(stderr,"Translated tiepoint_0 y: %d\t%lu\n", tp[0].img_y, tp[0].y_lat); ! } ! ! // By this point, geo_image_width & geo_image_height have to ! // have been initialized to something. ! ! if ( (geo_image_width == 0) || (geo_image_height == 0) ) { ! ! if ( (strncasecmp ("http", fileimg, 4) == 0) ! || (strncasecmp ("ftp", fileimg, 3) == 0)) { ! // what to do for remote files... hmm... -cbell ! } else { ! ! #ifdef HAVE_IMAGEMAGICK ! GetExceptionInfo(&exception); ! image_info=CloneImageInfo((ImageInfo *) NULL); ! (void) strcpy(image_info->filename, fileimg); ! if (debug_level & 16) { ! fprintf(stderr,"Copied %s into image info.\n", file); ! fprintf(stderr,"image_info got: %s\n", image_info->filename); ! fprintf(stderr,"Entered ImageMagick code.\n"); ! fprintf(stderr,"Attempting to open: %s\n", image_info->filename); ! } ! ! // We do a test read first to see if the file exists, so we ! // don't kill Xastir in the ReadImage routine. ! f = fopen (image_info->filename, "r"); ! if (f == NULL) { ! fprintf(stderr,"File %s could not be read\n",image_info->filename); ! return; ! } ! (void)fclose (f); ! ! image = PingImage(image_info, &exception); ! ! if (image == (Image *) NULL) { ! MagickWarning(exception.severity, exception.reason, exception.description); ! //fprintf(stderr,"MagickWarning\n"); ! return; ! } ! ! if (debug_level & 16) ! fprintf(stderr,"Color depth is %i \n", (int)image->depth); ! ! geo_image_width = image->magick_columns; ! geo_image_height = image->magick_rows; ! ! // close and clean up imagemagick ! ! if (image) ! DestroyImage(image); ! if (image_info) ! DestroyImageInfo(image_info); ! #endif // HAVE_IMAGEMAGICK ! } ! } ! ! // fprintf(stderr, "Geo: %s: size %ux%u.\n",file, geo_image_width, geo_image_height); ! // if that did not generate a valid size, bail out... ! if ( (geo_image_width == 0) || (geo_image_height == 0) ) { ! fprintf(stderr,"*** Skipping '%s', IMAGESIZE tag missing or incorrect. ***\n",file); ! fprintf(stderr,"Perhaps no XPM or ImageMagick library support is installed?\n"); ! return; ! } ! // calculate bottom right map corner from tiepoints ! // map size is geo_image_width / geo_image_height ! if (tp[1].img_x != (geo_image_width - 1) ) { ! tp[1].img_x = geo_image_width - 1; ! tp[1].x_long = tp[0].x_long + (tp[1].img_x * map_c_dx); // right ! if (debug_level & 512) ! fprintf(stderr,"Translated tiepoint_1 x: %d\t%lu\n", tp[1].img_x, tp[1].x_long); ! } ! if (tp[1].img_y != (geo_image_height - 1) ) { ! tp[1].img_y = geo_image_height - 1; ! tp[1].y_lat = tp[0].y_lat + (tp[1].img_y * map_c_dy); // bottom ! if (debug_level & 512) ! fprintf(stderr,"Translated tiepoint_1 y: %d\t%lu\n", tp[1].img_y, tp[1].y_lat); ! } ! ! ! // Check whether we're indexing or drawing the map ! if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS) ! || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) { ! xastir_snprintf(map_it, sizeof(map_it), langcode ("BBARSTA039"), filenm); ! } ! else { ! xastir_snprintf(map_it, sizeof(map_it), langcode ("BBARSTA028"), filenm); ! } ! statusline(map_it,0); // Loading/Indexing ... ! ! ! // Check whether we're indexing or drawing the map ! if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS) ! || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) { ! ! // We're indexing only. Save the extents in the index. ! if (terraserver_flag || toposerver_flag) { ! // Force the extents to the edges of the earth for the ! // index file. ! index_update_xastir(filenm, // Filename only ! 64800000l, // Bottom ! 0l, // Top ! 0l, // Left ! 129600000l); // Right ! } ! else { ! index_update_xastir(filenm, // Filename only ! tp[1].y_lat, // Bottom ! tp[0].y_lat, // Top ! tp[0].x_long, // Left ! tp[1].x_long); // Right ! } ! ! return; // Done indexing this file ! } ! ! ! // Check whether map is inside our current view ! // bottom top left right ! if (!map_visible (tp[1].y_lat, tp[0].y_lat, tp[0].x_long, tp[1].x_long)) { ! if (debug_level & 16) { ! fprintf(stderr,"Map not in current view, skipping: %s\n", file); ! fprintf(stderr,"\nImage: %s\n", file); ! fprintf(stderr,"Image size %d %d\n", geo_image_width, geo_image_height); ! fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n", map_c_L, map_c_T, map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y)); ! } ! return; /* Skip this map */ ! } else if (debug_level & 16) { ! fprintf(stderr,"Loading imagemap: %s\n", file); ! fprintf(stderr,"\nImage: %s\n", file); ! fprintf(stderr,"Image size %d %d\n", geo_image_width, geo_image_height); ! fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n", map_c_L, map_c_T, map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y)); ! } ! ! ! atb.valuemask = 0; ! ! ! // Best here would be to add the process ID or user ID to the filename ! // (to keep the filename distinct for different users), and to check ! // the timestamp on the map file. If it's older than xx minutes, go ! // get another one. Make sure to delete the temp files when closing ! // Xastir. It'd probably be good to check for old files and delete ! // them when starting Xastir as well. ! ! // Check to see if we have to use "wget" to go get an internet map ! if ( (strncasecmp ("http", fileimg, 4) == 0) ! || (strncasecmp ("ftp", fileimg, 3) == 0) ! || (terraserver_flag) ! || (toposerver_flag) ) { ! #ifdef HAVE_IMAGEMAGICK ! char *ext; ! ! if (debug_level & 16) ! fprintf(stderr,"ftp or http file: %s\n", fileimg); ! ! if (terraserver_flag || toposerver_flag) ! ext = "jpg"; ! else ! ext = get_map_ext(fileimg); // Use extension to determine image type ! ! xastir_snprintf(local_filename, sizeof(local_filename), "/var/tmp/xastir_%s_map.%s", ! username,ext); ! ! #ifdef HAVE_LIBCURL ! curl = curl_easy_init(); ! ! if (curl) { ! ! /* verbose debug is keen */ ! // curl_easy_setopt(curl, CURLOPT_VERBOSE, TRUE); ! curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curlerr); ! ! /* write function */ ! curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_fwrite); ! ! /* download from fileimg */ ! curl_easy_setopt(curl, CURLOPT_URL, fileimg); ! ! /* save as local_filename */ ! ftpfile.filename = local_filename; ! ftpfile.stream = NULL; ! curl_easy_setopt(curl, CURLOPT_FILE, &ftpfile); ! ! res = curl_easy_perform(curl); ! ! curl_easy_cleanup(curl); ! ! if (CURLE_OK != res) { ! fprintf(stderr, "curl told us %d\n", res); ! fprintf(stderr, "curlerr is %s\n", curlerr); ! } ! ! if (ftpfile.stream) ! fclose(ftpfile.stream); ! ! // Return if we had trouble ! if (CURLE_OK != res) { ! return; ! } ! ! } else { ! fprintf(stderr,"Couldn't download the geo or Terraserver image\n"); ! return; ! } ! ! ! #else ! #ifdef HAVE_WGET ! xastir_snprintf(tempfile, sizeof(tempfile), ! "%s --server-response --timestamping --tries=1 --timeout=30 --output-document=%s \'%s\' 2> /dev/null\n", ! WGET_PATH, ! local_filename, ! fileimg); ! ! if (debug_level & 16) ! fprintf(stderr,"%s",tempfile); ! ! //fprintf(stderr,"Getting file\n"); ! if ( system(tempfile) ) { // Go get the file ! fprintf(stderr,"Couldn't download the geo or Terraserver image\n"); ! return; ! } ! #else // HAVE_WGET ! fprintf(stderr,"libcurl or 'wget' not installed. Can't download image\n"); ! #endif // HAVE_WGET ! #endif // HAVE_LIBCURL ! ! // Set permissions on the file so that any user can overwrite it. ! chmod(local_filename, 0666); ! ! // We now re-use the "file" variable. It'll hold the ! //name of the map file now instead of the .geo file. ! strcpy(file,local_filename); // Tell ImageMagick where to find it ! #endif // HAVE_IMAGEMAGICK ! ! } else { ! //fprintf(stderr,"Not ftp or http file\n"); ! ! // We now re-use the "file" variable. It'll hold the ! //name of the map file now instead of the .geo file. ! strcpy (file, fileimg); ! } ! ! //fprintf(stderr,"File = %s\n",file); ! ! ! // The status line is not updated yet, probably 'cuz we're too busy ! // getting the map in this thread and aren't redrawing? ! ! ! #ifdef HAVE_IMAGEMAGICK ! GetExceptionInfo(&exception); ! image_info=CloneImageInfo((ImageInfo *) NULL); ! (void) strcpy(image_info->filename, file); ! if (debug_level & 16) { ! fprintf(stderr,"Copied %s into image info.\n", file); ! fprintf(stderr,"image_info got: %s\n", image_info->filename); ! fprintf(stderr,"Entered ImageMagick code.\n"); ! fprintf(stderr,"Attempting to open: %s\n", image_info->filename); ! } ! ! // We do a test read first to see if the file exists, so we ! // don't kill Xastir in the ReadImage routine. ! f = fopen (image_info->filename, "r"); ! if (f == NULL) { ! fprintf(stderr,"File %s could not be read\n",image_info->filename); ! return; ! } ! (void)fclose (f); ! ! image = ReadImage(image_info, &exception); ! ! if (image == (Image *) NULL) { ! MagickWarning(exception.severity, exception.reason, exception.description); ! //fprintf(stderr,"MagickWarning\n"); ! return; ! } ! ! if (debug_level & 16) ! fprintf(stderr,"Color depth is %i \n", (int)image->depth); ! ! if (image->colorspace != RGBColorspace) { ! puts("TBD: I don't think we can deal with colorspace != RGB"); ! if (image) ! DestroyImage(image); ! if (image_info) ! DestroyImageInfo(image_info); ! return; ! } ! ! atb.width = image->columns; ! atb.height = image->rows; ! ! ! // gamma setup ! if (imagemagick_options.gamma_flag == 0 || ! imagemagick_options.gamma_flag == 1) { ! if (imagemagick_options.gamma_flag == 0) // if not set in file, set to 1.0 ! imagemagick_options.r_gamma = 1.0; ! ! imagemagick_options.gamma_flag = 1; // set flag to do gamma ! ! imagemagick_options.r_gamma += imagemagick_gamma_adjust; ! ! if (imagemagick_options.r_gamma > 0.95 && imagemagick_options.r_gamma < 1.05) ! imagemagick_options.gamma_flag = 0; // don't bother if near 1.0 ! else if (imagemagick_options.r_gamma < 0.1) ! imagemagick_options.r_gamma = 0.1; // 0.0 is black and negative is really wacky ! ! xastir_snprintf(gamma, sizeof(gamma), "%.1f", imagemagick_options.r_gamma); ! } ! else if (imagemagick_options.gamma_flag == 3) { ! // No checking if you specify 3 channel gamma correction, so you can try negative ! // numbers, etc. if you wish. ! imagemagick_options.gamma_flag = 1; // set flag to do gamma ! imagemagick_options.r_gamma += imagemagick_gamma_adjust; ! imagemagick_options.g_gamma += imagemagick_gamma_adjust; ! imagemagick_options.b_gamma += imagemagick_gamma_adjust; ! xastir_snprintf(gamma, sizeof(gamma), "%.1f,%.1f,%.1f", ! imagemagick_options.r_gamma, ! imagemagick_options.g_gamma, ! imagemagick_options.b_gamma); ! } ! else ! imagemagick_options.gamma_flag = 0; ! ! if (imagemagick_options.gamma_flag) { ! if (debug_level & 16) ! fprintf(stderr,"gamma=%s\n", gamma); ! GammaImage(image, gamma); ! } ! ! if (imagemagick_options.contrast != 0) { ! if (debug_level & 16) ! fprintf(stderr,"contrast=%d\n", imagemagick_options.contrast); ! ContrastImage(image, imagemagick_options.contrast); ! } ! ! if (imagemagick_options.negate != -1) { ! if (debug_level & 16) ! fprintf(stderr,"negate=%d\n", imagemagick_options.negate); ! NegateImage(image, imagemagick_options.negate); ! } ! ! if (imagemagick_options.equalize) { ! if (debug_level & 16) ! puts("equalize"); ! EqualizeImage(image); ! } ! ! if (imagemagick_options.normalize) { ! if (debug_level & 16) ! puts("normalize"); ! NormalizeImage(image); ! } ! ! #if (MagickLibVersion >= 0x0539) ! if (imagemagick_options.level[0] != '\0') { ! if (debug_level & 16) ! fprintf(stderr,"level=%s\n", imagemagick_options.level); ! LevelImage(image, imagemagick_options.level); ! } ! #endif // MagickLibVersion >= 0x0539 ! ! if (imagemagick_options.modulate[0] != '\0') { ! if (debug_level & 16) ! fprintf(stderr,"modulate=%s\n", imagemagick_options.modulate); ! ModulateImage(image, imagemagick_options.modulate); ! } ! ! // If were are drawing to a low bpp display (typically < 8bpp) ! // try to reduce the number of colors in an image. ! // This may take some time, so it would be best to do ahead of ! // time if it is a static image. ! #if (MagickLibVersion < 0x0540) ! if (visual_type == NOT_TRUE_NOR_DIRECT && GetNumberColors(image, NULL) > 128) { ! #else // MagickLib >= 540 ! if (visual_type == NOT_TRUE_NOR_DIRECT && GetNumberColors(image, NULL, &exception) > 128) { ! #endif // MagickLib Version ! ! if (image->storage_class == PseudoClass) { ! #if (MagickLibVersion < 0x0549) ! CompressColormap(image); // Remove duplicate colors ! #else // MagickLib >= 0x0549 ! CompressImageColormap(image); // Remove duplicate colors ! #endif // MagickLibVersion < 0x0549 ! } ! ! // Quantize down to 128 will go here... ! } ! ! pixel_pack = GetImagePixels(image, 0, 0, image->columns, image->rows); ! if (!pixel_pack) { ! puts("pixel_pack == NULL!!!"); ! if (image) ! DestroyImage(image); ! if (image_info) ! DestroyImageInfo(image_info); ! return; ! } ! ! index_pack = GetIndexes(image); ! if (image->storage_class == PseudoClass && !index_pack) { ! puts("PseudoClass && index_pack == NULL!!!"); ! if (image) ! DestroyImage(image); ! if (image_info) ! DestroyImageInfo(image_info); ! return; ! } ! ! if (image->storage_class == PseudoClass && image->colors <= 256) { ! for (l = 0; l < (int)image->colors; l++) { ! // Need to check how to do this for ANY image, as ImageMagick can read in all sorts ! // of image files ! temp_pack = image->colormap[l]; ! if (debug_level & 16) ! fprintf(stderr,"Colormap color is %i %i %i \n", ! temp_pack.red, temp_pack.green, temp_pack.blue); ! ! // Here's a tricky bit: PixelPacket entries are defined as Quantum's. Quantum ! // is defined in /usr/include/magick/image.h as either an unsigned short or an ! // unsigned char, depending on what "configure" decided when ImageMagick was installed. ! // We can determine which by looking at MaxRGB or QuantumDepth. ! // ! if (QuantumDepth == 16) { // Defined in /usr/include/magick/image.h ! if (debug_level & 16) ! fprintf(stderr,"Color quantum is [0..65535]\n"); ! my_colors[l].red = temp_pack.red; ! my_colors[l].green = temp_pack.green; ! my_colors[l].blue = temp_pack.blue; ! } ! else { // QuantumDepth = 8 ! if (debug_level & 16) ! fprintf(stderr,"Color quantum is [0..255]\n"); ! my_colors[l].red = temp_pack.red << 8; ! my_colors[l].green = temp_pack.green << 8; ! my_colors[l].blue = temp_pack.blue << 8; ! } ! ! // Get the color allocated on < 8bpp displays. pixel color is written to my_colors.pixel ! if (visual_type == NOT_TRUE_NOR_DIRECT) ! XAllocColor(XtDisplay(w), cmap, &my_colors[l]); ! else ! pack_pixel_bits(my_colors[l].red, my_colors[l].green, my_colors[l].blue, ! &my_colors[l].pixel); ! ! if (debug_level & 16) ! fprintf(stderr,"Color allocated is %li %i %i %i \n", my_colors[l].pixel, ! my_colors[l].red, my_colors[l].blue, my_colors[l].green); ! } ! } ! ! #ifdef TIMING_DEBUG ! time_mark(0); ! #endif // TIMING_DEBUG ! ! if (debug_level & 16) { ! fprintf(stderr,"Image size %d %d\n", atb.width, atb.height); ! #if (MagickLibVersion < 0x0540) ! fprintf(stderr,"Unique colors = %d\n", GetNumberColors(image, NULL)); ! #else // MagickLibVersion < 0x0540 ! fprintf(stderr,"Unique colors = %ld\n", GetNumberColors(image, NULL, &exception)); ! #endif // MagickLibVersion < 0x0540 ! fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n", map_c_L, map_c_T, ! map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y)); ! ! #if (MagickLibVersion < 0x0540) ! fprintf(stderr,"is Gray Image = %i\n", IsGrayImage(image)); ! fprintf(stderr,"is Monochrome Image = %i\n", IsMonochromeImage(image)); ! //fprintf(stderr,"is Opaque Image = %i\n", IsOpaqueImage(image)); ! //fprintf(stderr,"is PseudoClass = %i\n", image->storage_class == PseudoClass); ! #else // MagickLibVersion < 0x0540 ! fprintf(stderr,"is Gray Image = %i\n", IsGrayImage( image, &exception )); ! fprintf(stderr,"is Monochrome Image = %i\n", IsMonochromeImage( image, &exception )); ! //fprintf(stderr,"is Opaque Image = %i\n", IsOpaqueImage( image, &exception )); ! //fprintf(stderr,"is PseudoClass = %i\n", image->storage_class == PseudoClass); ! #endif // MagickLibVersion < 0x0540 ! ! fprintf(stderr,"image matte is %i\n", image->matte); ! fprintf(stderr,"Colorspace = %i\n", image->colorspace); ! if (image->colorspace == UndefinedColorspace) ! fprintf(stderr,"Class Type = Undefined\n"); ! else if (image->colorspace == RGBColorspace) ! fprintf(stderr,"Class Type = RGBColorspace\n"); ! else if (image->colorspace == GRAYColorspace) ! fprintf(stderr,"Class Type = GRAYColorspace\n"); ! else if (image->colorspace == sRGBColorspace) ! fprintf(stderr,"Class Type = sRGBColorspace\n"); ! } ! ! #else // HAVE_IMAGEMAGICK ! ! // We don't have ImageMagick libs compiled in, so use the ! // XPM library instead. ! ! /* XpmReadFileToImage is the call we wish to avoid if at all ! * possible. On large images this can take quite a while. We ! * check above to see whether the image is inside our viewport, ! * and if not we skip loading the image. ! */ ! if (! XpmReadFileToImage (XtDisplay (w), file, &xi, NULL, &atb) == XpmSuccess) { ! fprintf(stderr,"ERROR loading %s\n", file); ! if (xi) ! XDestroyImage (xi); ! return; ! } ! if (debug_level & 16) { ! fprintf(stderr,"Image size %d %d\n", (int)atb.width, (int)atb.height); ! fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n", map_c_L, map_c_T, map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y)); ! } ! ! #endif // HAVE_IMAGEMAGICK ! ! // draw the image from the file out to the map screen ! ! // Get the border values for the X and Y for loops used ! // for the XFillRectangle call later. ! ! map_c_yc = (tp[0].y_lat + tp[1].y_lat) / 2; // vert center of map as reference ! map_y_ctr = (long)(atb.height / 2 +0.499); ! scale_x0 = get_x_scale(0,map_c_yc,scale_y); // reference scaling at vert map center ! ! map_c_xc = (tp[0].x_long + tp[1].x_long) / 2; // hor center of map as reference ! map_x_ctr = (long)(atb.width / 2 +0.499); ! scr_x_mc = (map_c_xc - x_long_offset) / scale_x; // screen coordinates of map center ! ! // calculate map pixel range in y direction that falls into screen area ! c_y_max = 0ul; ! map_y_min = map_y_max = 0l; ! for (map_y_0 = 0, c_y = tp[0].y_lat; map_y_0 < (long)atb.height; map_y_0++, c_y += map_c_dy) { ! scr_y = (c_y - y_lat_offset) / scale_y; // current screen position ! if (scr_y > 0) { ! if (scr_y < screen_height) { ! map_y_max = map_y_0; // update last map pixel in y ! c_y_max = (unsigned long)c_y;// bottom map inside screen coordinate ! } else ! break; // done, reached bottom screen border ! } else { // pixel is above screen ! map_y_min = map_y_0; // update first map pixel in y ! } ! } ! // fprintf(stderr,"map top: %ld bottom: %ld\n",tp[0].y_lat,tp[1].y_lat); ! c_y_min = (unsigned long)(tp[0].y_lat + map_y_min * map_c_dy); // top map inside screen coordinate ! ! // // find the y coordinate nearest to the equator ! // c_y = 90*60*60*100; // Equator ! // if ((c_y_min>c_y && c_y_max>c_y) || (c_y_min abs(c_y_max-c_y)) ! // c_y = c_y_max; // north ! // else ! // c_y = c_y_min; // south ! // } ! // scale_x0 = get_x_scale(0,(long)c_y,scale_y); // calc widest map area in x ! ! // if (map_proj != 1) { ! // calculate map pixel range in x direction that falls into screen area ! map_x_min = map_x_max = 0l; ! for (map_x = 0, c_x = tp[0].x_long; map_x < (long)atb.width; map_x++, c_x += map_c_dx) { ! scr_x = (c_x - x_long_offset)/ scale_x; // current screen position ! if (scr_x > 0) { ! if (scr_x < screen_width) ! map_x_max = map_x; // update last map pixel in x ! else ! break; // done, reached right screen border ! } else { // pixel is left from screen ! map_x_min = map_x; // update first map pixel in x ! } ! } ! c_x_min = (unsigned long)(tp[0].x_long + map_x_min * map_c_dx); // left map inside screen coordinate ! // } ! // for (scr_y = scr_y_min; scr_y <= scr_y_max;scr_y++) { // screen lines ! // } ! ! test = 1; // DK7IN: debuging ! scr_yp = -1; ! scr_c_xr = x_long_offset + screen_width * scale_x; ! c_dx = map_c_dx; // map pixel width ! scale_xa = scale_x0; // the compiler likes it ;-) ! ! // for (map_y_0 = 0, c_y = tp[0].y_lat; map_y_0 < (long)atb.height; map_y_0++, c_y += map_c_dy) { ! // scr_y = (c_y - y_lat_offset) / scale_y; // current screen position ! ! map_done = 0; ! map_act = 0; ! map_seen = 0; ! scr_y = screen_height - 1; ! ! #ifdef TIMING_DEBUG ! time_mark(0); ! #endif // TIMING_DEBUG ! // loop over map pixel rows ! for (map_y_0 = map_y_min, c_y = (double)c_y_min; ! (map_y_0 <= map_y_max) || (map_proj == 1 && !map_done && scr_y < screen_height); ! map_y_0++, c_y += map_c_dy) { ! scr_y = (c_y - y_lat_offset) / scale_y; ! if (scr_y != scr_yp) { // don't do a row twice ! scr_yp = scr_y; // remember as previous y ! if (map_proj == 1) { // Transverse Mercator correction in x ! scale_xa = get_x_scale(0,(long)c_y,scale_y); // recalc scale_x for current y ! c_dx = map_c_dx * scale_xa / scale_x0; // adjusted map pixel width ! ! map_x_min = map_x_ctr - (map_c_xc - x_long_offset) / c_dx; ! if (map_x_min < 0) ! map_x_min = 0; ! c_x_min = map_c_xc - (map_x_ctr - map_x_min) * c_dx; ! map_x_max = map_x_ctr - (map_c_xc - scr_c_xr) / c_dx; ! if (map_x_max > (long)atb.width) ! map_x_max = atb.width; ! scr_dx = (int) (c_dx / scale_x) + 1; // at least 1 pixel wide ! } ! ! // if (c_y == (double)c_y_min) { // first call ! // fprintf(stderr,"map: min %ld ctr %ld max %ld, c_dx %ld, c_x_min %ld, c_y_min %ld\n",map_x_min,map_x_ctr,map_x_max,(long)c_dx,c_x_min,c_y_min); ! // } ! scr_xp = -1; ! // loop over map pixel columns ! map_act = 0; ! scale_x_nm = calc_dscale_x(0,(long)c_y) / 1852.0; // nm per Xastir coordinate ! for (map_x = map_x_min, c_x = (double)c_x_min; map_x <= map_x_max; map_x++, c_x += c_dx) { ! scr_x = (c_x - x_long_offset) / scale_x; ! if (scr_x != scr_xp) { // don't do a pixel twice ! scr_xp = scr_x; // remember as previous x ! if (map_proj == 1) { // Transverse Mercator correction in y ! // DK7IN-- ! dist = (90*60 - (c_y / 6000.0)); // equator distance in nm ! // ?? 180W discontinuity! not done yet ! ew_ofs = (c_x - (double)map_c_xc) * scale_x_nm; // EW offset from center in nm ! //corrfact = (map_y_0 - map_y_ctr)/(2*map_y_ctr); // 0..50% ! //corrfact = fabs(ew_ofs/dist)*3.0; ! //corrfact = 1.0-1.0*(0.5*map_y_0 / map_y_ctr); ! corrfact = 1.0; ! c_y_a = (fabs(dist) - sqrt((double)(dist*dist - ew_ofs*ew_ofs)))*6000.0; // in Xastir units ! if (dist < 0) // S ! map_y = map_y_0 + (long)(corrfact*c_y_a / map_c_dy); // coord per pixel ! else // N ! map_y = map_y_0 - (long)(corrfact*c_y_a / map_c_dy); ! // if (test < 10) { ! // fprintf(stderr,"dist: %ldkm, ew_ofs: %ldkm, dy: %ldkm\n",(long)(1.852*dist),(long)(1.852*ew_ofs),(long)(1.852*c_y_a/6000.0)); ! // fprintf(stderr," corrfact: %f, mapy0: %ld, mapy: %ld\n",corrfact,map_y_0,map_y); ! // test++; ! // } ! } else { ! map_y = map_y_0; ! } ! ! if (map_y >= 0 && map_y <= tp[1].img_y) { // check map boundaries in y direction ! map_seen = 1; ! map_act = 1; // detects blank screen rows (end of map) ! ! // DK7IN-- ! ! //----- copy pixel from map to screen --------------------- ! // if (c_y == (double)c_y_min && (scr_x < 5 || (c_x == (double)c_x_min))) { // first call ! // fprintf(stderr,"map: x %ld y %ld scr: x %ld y %ld dx %d, dy %d\n",map_x,map_y,scr_x,scr_y,scr_dx,scr_dy); ! // fprintf(stderr,"color: %ld\n",XGetPixel (xi, map_x, map_y)); ! // // 65529 ! // } ! ! // now copy a pixel from the map image to the screen ! #ifdef HAVE_IMAGEMAGICK ! l = map_x + map_y * image->columns; ! if (image->storage_class == PseudoClass) { ! XSetForeground(XtDisplay(w), gc, my_colors[index_pack[l]].pixel); ! } ! else { ! pack_pixel_bits(pixel_pack[l].red, ! pixel_pack[l].green, ! pixel_pack[l].blue, ! &my_colors[0].pixel); ! XSetForeground(XtDisplay(w), gc, my_colors[0].pixel); ! } ! #else // HAVE_IMAGEMAGICK ! (void)XSetForeground (XtDisplay (w), gc, XGetPixel (xi, map_x, map_y)); ! #endif // HAVE_IMAGEMAGICK ! (void)XFillRectangle (XtDisplay (w),pixmap,gc,scr_x,scr_y,scr_dx,scr_dy); ! } // check map boundaries in y direction ! } ! } // loop over map pixel columns ! if (map_seen && !map_act) ! map_done = 1; ! } ! } // loop over map pixel rows ! ! #ifdef HAVE_IMAGEMAGICK ! if (image) ! DestroyImage(image); ! if (image_info) ! DestroyImageInfo(image_info); ! #else // HAVE_IMAGEMAGICK ! if (xi) ! XDestroyImage (xi); ! #endif // HAVE_IMAGEMAGICK ! ! #ifdef TIMING_DEBUG ! time_mark(0); ! #endif // TIMING_DEBUG ! } ! ! ! ! ! ! /********************************************************** ! * draw_tiger_map() ! * N0VH ! **********************************************************/ ! #ifdef HAVE_IMAGEMAGICK ! void draw_tiger_map (Widget w) { ! uid_t user_id; ! struct passwd *user_info; ! char username[20]; ! char file[MAX_FILENAME]; // Complete path/name of image file ! FILE *f; // Filehandle of image file ! char fileimg[MAX_FILENAME]; // Ascii name of image file, read from GEO file ! char tigertmp[MAX_FILENAME*2]; // Used for putting together the tigermap query ! XpmAttributes atb; // Map attributes after map's read into an XImage ! tiepoint tp[2]; // Calibration points for map, read in from .geo file ! register long map_c_T, map_c_L; // map delta NW edge coordinates, DNN: these should be signed ! register long tp_c_dx, tp_c_dy; // tiepoint coordinate differences ! unsigned long c_x_min, c_y_min;// top left coordinates of map inside screen ! unsigned long c_y_max; // bottom right coordinates of map inside screen ! double c_x; // Xastir coordinates 1/100 sec, 0 = 180°W ! double c_y; // Xastir coordinates 1/100 sec, 0 = 90°N ! ! long map_y_0; // map pixel pointer prior to TM adjustment ! register long map_x, map_y; // map pixel pointers, DNN: this was a float, chg to long ! long map_x_min, map_x_max; // map boundaries for in screen part of map ! long map_y_min, map_y_max; // ! long map_x_ctr; // half map width in pixel ! long map_y_ctr; // half map height in pixel ! int map_seen, map_act, map_done; ! ! long map_c_yc; // map center, vert coordinate ! long map_c_xc; // map center, hor coordinate ! double map_c_dx, map_c_dy; // map coordinates increment (pixel width) ! double c_dx; // adjusted map pixel width ! ! long scr_x, scr_y; // screen pixel plot positions ! long scr_xp, scr_yp; // previous screen plot positions ! int scr_dx, scr_dy; // increments in screen plot positions ! long scr_x_mc; // map center in screen units ! ! long scr_c_xr; ! ! long scale_xa; // adjusted for topo maps ! double scale_x_nm; // nm per Xastir coordinate unit ! long scale_x0; // at widest map area ! ! char local_filename[MAX_FILENAME]; ! ExceptionInfo exception; ! Image *image; ! ImageInfo *image_info; ! PixelPacket *pixel_pack; ! PixelPacket temp_pack; ! IndexPacket *index_pack; ! int l; ! XColor my_colors[256]; ! #ifdef HAVE_LIBCURL ! CURL *curl; ! CURLcode res; ! char curlerr[CURL_ERROR_SIZE]; ! struct FtpFile ftpfile; ! #else ! #ifdef HAVE_WGET ! char tempfile[MAX_FILENAME]; ! #endif // HAVE_WGET ! #endif ! double left, right, top, bottom, map_width, map_height; ! double lat_center = 0; ! double long_center = 0; ! ! char map_it[MAX_FILENAME]; ! char tmpstr[100]; ! int geo_image_width; // Image width from GEO file ! int geo_image_height; // Image height from GEO file ! ! ! xastir_snprintf(map_it, sizeof(map_it), langcode ("BBARSTA028"), "tigermap"); ! statusline(map_it,0); // Loading ... ! ! ! // Get user info ! user_id=getuid(); ! user_info=getpwuid(user_id); ! // Get my login name ! strcpy(username,user_info->pw_name); ! ! // Tiepoint for upper left screen corner ! // ! tp[0].img_x = 0; // Pixel Coordinates ! tp[0].img_y = 0; // Pixel Coordinates ! tp[0].x_long = x_long_offset; // Xastir Coordinates ! tp[0].y_lat = y_lat_offset; // Xastir Coordinates ! ! // Tiepoint for lower right screen corner ! // ! tp[1].img_x = screen_width - 1; // Pixel Coordinates ! tp[1].img_y = screen_height - 1; // Pixel Coordinates ! ! tp[1].x_long = x_long_offset + (( screen_width) * scale_x); // Xastir Coordinates ! tp[1].y_lat = y_lat_offset + ((screen_height) * scale_y); // Xastir Coordinates ! ! left = (double)((x_long_offset - 64800000l )/360000.0); // Lat/long Coordinates ! top = (double)(-((y_lat_offset - 32400000l )/360000.0)); // Lat/long Coordinates ! right = (double)(((x_long_offset + ((screen_width) * scale_x) ) - 64800000l)/360000.0);//Lat/long Coordinates ! bottom = (double)(-(((y_lat_offset + ((screen_height) * scale_y) ) - 32400000l)/360000.0));//Lat/long Coordinates ! ! map_width = right - left; // Lat/long Coordinates ! map_height = top - bottom; // Lat/long Coordinates ! ! geo_image_width = screen_width; ! geo_image_height = screen_height; ! ! long_center = (left + right)/2.0l; ! lat_center = (top + bottom)/2.0l; ! ! // Example query to the census map server.... ! /* xastir_snprintf(fileimg, sizeof(fileimg), ! "\'http://tiger.census.gov/cgi-bin/mapper/map.gif?on=CITIES&on=GRID&on=counties&on=majroads&on=places&&on=interstate&on=states&on=ushwy&on=statehwy&lat=%f\046lon=%f\046wid=%f\046ht=%f\046iwd=%i\046iht=%i\'",\ ! lat_center, long_center, map_width, map_height, tp[1].img_x + 1, tp[1].img_y + 1); */ ! ! xastir_snprintf(tigertmp, sizeof(tigertmp), "http://tiger.census.gov/cgi-bin/mapper/map.gif?"); ! ! if (tiger_show_grid) ! strcat(tigertmp, "&on=GRID"); ! else ! strcat(tigertmp, "&off=GRID"); ! ! if (tiger_show_counties) ! strcat(tigertmp, "&on=counties"); ! else ! strcat(tigertmp, "&off=counties"); ! ! if (tiger_show_cities) ! strcat(tigertmp, "&on=CITIES"); ! else ! strcat(tigertmp, "&off=CITIES"); ! ! if (tiger_show_places) ! strcat(tigertmp, "&on=places"); ! else ! strcat(tigertmp, "&off=places"); ! ! if (tiger_show_majroads) ! strcat(tigertmp, "&on=majroads"); ! else ! strcat(tigertmp, "&off=majroads"); ! ! if (tiger_show_streets) ! strcat(tigertmp, "&on=streets"); ! // Don't turn streets off since this will automagically show up as you zoom in. ! ! if (tiger_show_railroad) ! strcat(tigertmp, "&on=railroad"); ! else ! strcat(tigertmp, "&off=railroad"); ! ! if (tiger_show_states) ! strcat(tigertmp, "&on=states"); ! else ! strcat(tigertmp, "&off=states"); ! ! if (tiger_show_interstate) ! strcat(tigertmp, "&on=interstate"); ! else ! strcat(tigertmp, "&off=interstate"); ! ! if (tiger_show_ushwy) ! strcat(tigertmp, "&on=ushwy"); ! else ! strcat(tigertmp, "&off=ushwy"); ! ! if (tiger_show_statehwy) ! strcat(tigertmp, "&on=statehwy"); ! else ! strcat(tigertmp, "&off=statehwy"); ! ! if (tiger_show_water) ! strcat(tigertmp, "&on=water"); ! else ! strcat(tigertmp, "&off=water"); ! ! if (tiger_show_lakes) ! strcat(tigertmp, "&on=shorelin"); ! else ! strcat(tigertmp, "&off=shorelin"); ! ! if (tiger_show_misc) ! strcat(tigertmp, "&on=miscell"); ! else ! strcat(tigertmp, "&off=miscell"); ! ! xastir_snprintf(tmpstr, sizeof(tmpstr), "&lat=%f\046lon=%f\046", lat_center, long_center); ! strcat (tigertmp, tmpstr); ! xastir_snprintf(tmpstr, sizeof(tmpstr), "wid=%f\046ht=%f\046", map_width, map_height); ! strcat (tigertmp, tmpstr); ! xastir_snprintf(tmpstr, sizeof(tmpstr), "iwd=%i\046iht=%i", tp[1].img_x + 1, tp[1].img_y + 1); ! strcat (tigertmp, tmpstr); ! xastir_snprintf(fileimg, sizeof(fileimg), tigertmp); ! ! if (debug_level & 512) { ! fprintf(stderr,"left side is %f\n", left); ! fprintf(stderr,"right side is %f\n", right); ! fprintf(stderr,"top is %f\n", top); ! fprintf(stderr,"bottom is %f\n", bottom); ! fprintf(stderr,"lat center is %f\n", lat_center); ! fprintf(stderr,"long center is %f\n", long_center); ! fprintf(stderr,"screen width is %li\n", screen_width); ! fprintf(stderr,"screen height is %li\n", screen_height); ! fprintf(stderr,"map width is %f\n", map_width); ! fprintf(stderr,"map height is %f\n", map_height); ! fprintf(stderr,"fileimg is %s\n", fileimg); ! fprintf(stderr,"ftp or http file: %s\n", fileimg); ! } ! ! xastir_snprintf(local_filename, sizeof(local_filename), "/var/tmp/xastir_%s_map.%s", username,"gif"); ! ! #ifdef HAVE_LIBCURL ! curl = curl_easy_init(); ! ! if (curl) { ! ! /* verbose debug is keen */ ! // curl_easy_setopt(curl, CURLOPT_VERBOSE, TRUE); ! curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curlerr); ! ! /* write function */ ! curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_fwrite); ! ! /* download from fileimg */ ! curl_easy_setopt(curl, CURLOPT_URL, fileimg); ! ! /* save as local_filename */ ! ftpfile.filename = local_filename; ! ftpfile.stream = NULL; ! curl_easy_setopt(curl, CURLOPT_FILE, &ftpfile); ! ! res = curl_easy_perform(curl); ! ! curl_easy_cleanup(curl); ! ! if (CURLE_OK != res) { ! fprintf(stderr, "curl told us %d\n", res); ! fprintf(stderr, "curlerr is %s\n", curlerr); ! } ! ! if (ftpfile.stream) ! fclose(ftpfile.stream); ! ! // Return if we had trouble ! if (CURLE_OK != res) { ! return; ! } ! ! } else { ! fprintf(stderr,"Couldn't download the Tigermap image\n"); ! return; ! } ! #else ! #ifdef HAVE_WGET ! xastir_snprintf(tempfile, sizeof(tempfile), ! "%s --server-response --timestamping --tries=1 --timeout=%d --output-document=%s \'%s\' 2> /dev/null\n", ! WGET_PATH, ! tigermap_timeout, ! local_filename, ! fileimg); ! ! if (debug_level & 512) ! fprintf(stderr,"%s",tempfile); ! ! if (system(tempfile)) { // Go get the file ! fprintf(stderr,"Couldn't download the Tigermap image\n"); ! return; ! } ! #else // HAVE_WGET ! fprintf(stderr,"libcurl or 'wget' not installed. Can't download image\n"); ! #endif // HAVE_WGET ! #endif // HAVE_LIBCURL ! ! ! ! // For debugging the MagickError/MagickWarning segfaults. ! //system("cat /dev/null >/var/tmp/xastir_hacker_map.gif"); ! ! ! // Set permissions on the file so that any user can overwrite it. ! chmod(local_filename, 0666); ! ! strcpy(file,local_filename); // Tell ImageMagick where to find it ! ! GetExceptionInfo(&exception); ! ! image_info=CloneImageInfo((ImageInfo *) NULL); ! (void) strcpy(image_info->filename, file); ! ! if (debug_level & 512) { ! fprintf(stderr,"Copied %s into image info.\n", file); ! fprintf(stderr,"image_info got: %s\n", image_info->filename); ! fprintf(stderr,"Entered ImageMagick code.\n"); ! fprintf(stderr,"Attempting to open: %s\n", image_info->filename); ! } ! ! // We do a test read first to see if the file exists, so we ! // don't kill Xastir in the ReadImage routine. ! f = fopen (image_info->filename, "r"); ! if (f == NULL) { ! if (debug_level & 512) ! fprintf(stderr,"File could not be read\n"); ! return; ! } ! (void)fclose (f); ! ! image = ReadImage(image_info, &exception); ! ! if (image == (Image *) NULL) { ! MagickWarning(exception.severity, exception.reason, exception.description); ! //fprintf(stderr,"MagickWarning\n"); ! return; ! } ! ! if (debug_level & 512) ! fprintf(stderr,"Color depth is %i \n", (int)image->depth); ! ! if (image->colorspace != RGBColorspace) { ! puts("TBD: I don't think we can deal with colorspace != RGB"); ! if (image) ! DestroyImage(image); ! if (image_info) ! DestroyImageInfo(image_info); ! return; ! } ! ! atb.valuemask = 0; ! atb.width = image->columns; ! atb.height = image->rows; ! ! // Code to mute the image so it's not as bright. ! if (tigermap_intensity != 100) { ! char tempstr[30]; ! ! if (debug_level & 512) ! fprintf(stderr,"level=%s\n", tempstr); ! ! xastir_snprintf(tempstr, sizeof(tempstr), "%d, 100, 100", tigermap_intensity); ! ModulateImage(image, tempstr); ! } ! ! // If were are drawing to a low bpp display (typically < 8bpp) ! // try to reduce the number of colors in an image. ! // This may take some time, so it would be best to do ahead of ! // time if it is a static image. ! #if (MagickLibVersion < 0x0540) ! if (visual_type == NOT_TRUE_NOR_DIRECT && GetNumberColors(image, NULL) > 128) { ! #else // MagickLib >= 540 ! if (visual_type == NOT_TRUE_NOR_DIRECT && GetNumberColors(image, NULL, &exception) > 128) { ! #endif // MagickLib Version ! ! if (image->storage_class == PseudoClass) { ! #if (MagickLibVersion < 0x0549) ! CompressColormap(image); // Remove duplicate colors ! #else // MagickLib >= 0x0549 ! CompressImageColormap(image); // Remove duplicate colors ! #endif // MagickLibVersion < 0x0549 ! } ! ! // Quantize down to 128 will go here... ! } ! ! pixel_pack = GetImagePixels(image, 0, 0, image->columns, image->rows); ! if (!pixel_pack) { ! puts("pixel_pack == NULL!!!"); ! if (image) ! DestroyImage(image); ! if (image_info) ! DestroyImageInfo(image_info); ! return; ! } ! ! index_pack = GetIndexes(image); ! if (image->storage_class == PseudoClass && !index_pack) { ! puts("PseudoClass && index_pack == NULL!!!"); ! if (image) ! DestroyImage(image); ! if (image_info) ! DestroyImageInfo(image_info); ! return; ! } ! ! if (image->storage_class == PseudoClass && image->colors <= 256) { ! for (l = 0; l < (int)image->colors; l++) { ! // Need to check how to do this for ANY image, as ImageMagick can read in all sorts ! // of image files ! temp_pack = image->colormap[l]; ! if (debug_level & 512) ! fprintf(stderr,"Colormap color is %i %i %i \n", ! temp_pack.red, temp_pack.green, temp_pack.blue); ! ! // Here's a tricky bit: PixelPacket entries are defined as Quantum's. Quantum ! // is defined in /usr/include/magick/image.h as either an unsigned short or an ! // unsigned char, depending on what "configure" decided when ImageMagick was installed. ! // We can determine which by looking at MaxRGB or QuantumDepth. ! // ! if (QuantumDepth == 16) { // Defined in /usr/include/magick/image.h ! if (debug_level & 512) ! fprintf(stderr,"Color quantum is [0..65535]\n"); ! my_colors[l].red = temp_pack.red; ! my_colors[l].green = temp_pack.green; ! my_colors[l].blue = temp_pack.blue; ! } ! else { // QuantumDepth = 8 ! if (debug_level & 512) ! fprintf(stderr,"Color quantum is [0..255]\n"); ! my_colors[l].red = temp_pack.red << 8; ! my_colors[l].green = temp_pack.green << 8; ! my_colors[l].blue = temp_pack.blue << 8; ! } ! ! // Get the color allocated on < 8bpp displays. pixel color is written to my_colors.pixel ! if (visual_type == NOT_TRUE_NOR_DIRECT) ! XAllocColor(XtDisplay(w), cmap, &my_colors[l]); ! else ! pack_pixel_bits(my_colors[l].red, my_colors[l].green, my_colors[l].blue, ! &my_colors[l].pixel); ! ! if (debug_level & 512) ! fprintf(stderr,"Color allocated is %li %i %i %i \n", my_colors[l].pixel, ! my_colors[l].red, my_colors[l].blue, my_colors[l].green); ! } ! } ! /* ! * Here are the corners of our viewport, using the Xastir ! * coordinate system. Notice that Y is upside down: ! * ! * left edge of view = x_long_offset ! * right edge of view = x_long_offset + (screen_width * scale_x) ! * top edge of view = y_lat_offset ! * bottom edge of view = y_lat_offset + (screen_height * scale_y) ! * ! * The corners of our map will soon be (after translating the ! * tiepoints to the corners if they're not already there): ! * ! * left edge of map = tp[0].x_long in Xastir format ! * right edge of map = tp[1].x_long ! * top edge of map = tp[0].y_lat ! * bottom edge of map = tp[1].y_lat ! * ! */ ! map_c_L = tp[0].x_long - x_long_offset; // map left coordinate ! map_c_T = tp[0].y_lat - y_lat_offset; // map top coordinate ! ! tp_c_dx = (long)(tp[1].x_long - tp[0].x_long);// Width between tiepoints ! tp_c_dy = (long)(tp[1].y_lat - tp[0].y_lat); // Height between tiepoints ! ! ! // Check for tiepoints being in wrong relation to one another ! if (tp_c_dx < 0) ! tp_c_dx = -tp_c_dx; // New width between tiepoints ! if (tp_c_dy < 0) ! tp_c_dy = -tp_c_dy; // New height between tiepoints ! ! // Calculate step size per pixel ! map_c_dx = ((double) tp_c_dx / abs(tp[1].img_x - tp[0].img_x)); ! map_c_dy = ((double) tp_c_dy / abs(tp[1].img_y - tp[0].img_y)); ! ! // Scaled screen step size for use with XFillRectangle below ! scr_dx = (int) (map_c_dx / scale_x) + 1; ! scr_dy = (int) (map_c_dy / scale_y) + 1; ! ! // calculate top left map corner from tiepoints ! if (tp[0].img_x != 0) { ! tp[0].x_long -= (tp[0].img_x * map_c_dx); // map left edge longitude ! map_c_L = tp[0].x_long - x_long_offset; // delta ?? ! tp[0].img_x = 0; ! if (debug_level & 512) ! fprintf(stderr,"Translated tiepoint_0 x: %d\t%lu\n", tp[0].img_x, tp[0].x_long); ! } ! if (tp[0].img_y != 0) { ! tp[0].y_lat -= (tp[0].img_y * map_c_dy); // map top edge latitude ! map_c_T = tp[0].y_lat - y_lat_offset; ! tp[0].img_y = 0; ! if (debug_level & 512) ! fprintf(stderr,"Translated tiepoint_0 y: %d\t%lu\n", tp[0].img_y, tp[0].y_lat); ! } ! ! // calculate bottom right map corner from tiepoints ! // map size is geo_image_width / geo_image_height ! if (tp[1].img_x != (geo_image_width - 1) ) { ! tp[1].img_x = geo_image_width - 1; ! tp[1].x_long = tp[0].x_long + (tp[1].img_x * map_c_dx); // right ! if (debug_level & 512) ! fprintf(stderr,"Translated tiepoint_1 x: %d\t%lu\n", tp[1].img_x, tp[1].x_long); ! } ! if (tp[1].img_y != (geo_image_height - 1) ) { ! tp[1].img_y = geo_image_height - 1; ! tp[1].y_lat = tp[0].y_lat + (tp[1].img_y * map_c_dy); // bottom ! if (debug_level & 512) ! fprintf(stderr,"Translated tiepoint_1 y: %d\t%lu\n", tp[1].img_y, tp[1].y_lat); ! } ! ! if (debug_level & 512) { ! fprintf(stderr,"X tiepoint width: %ld\n", tp_c_dx); ! fprintf(stderr,"Y tiepoint width: %ld\n", tp_c_dy); ! fprintf(stderr,"Loading imagemap: %s\n", file); ! fprintf(stderr,"\nImage: %s\n", file); ! fprintf(stderr,"Image size %d %d\n", geo_image_width, geo_image_height); ! fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n", ! map_c_L, map_c_T, map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y)); ! fprintf(stderr,"Image size %d %d\n", atb.width, atb.height); ! #if (MagickLibVersion < 0x0540) ! fprintf(stderr,"Unique colors = %d\n", GetNumberColors(image, NULL)); ! #else // MagickLib < 540 ! fprintf(stderr,"Unique colors = %ld\n", GetNumberColors(image, NULL, &exception)); ! #endif // MagickLib < 540 ! fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n", map_c_L, map_c_T, ! map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y)); ! fprintf(stderr,"image matte is %i\n", image->matte); ! } // debug_level & 512 ! ! // draw the image from the file out to the map screen ! ! // Get the border values for the X and Y for loops used ! // for the XFillRectangle call later. ! ! map_c_yc = (tp[0].y_lat + tp[1].y_lat) / 2; // vert center of map as reference ! map_y_ctr = (long)(atb.height / 2 +0.499); ! scale_x0 = get_x_scale(0,map_c_yc,scale_y); // reference scaling at vert map center ! ! map_c_xc = (tp[0].x_long + tp[1].x_long) / 2; // hor center of map as reference ! map_x_ctr = (long)(atb.width / 2 +0.499); ! scr_x_mc = (map_c_xc - x_long_offset) / scale_x; // screen coordinates of map center ! ! // calculate map pixel range in y direction that falls into screen area ! c_y_max = 0ul; ! map_y_min = map_y_max = 0l; ! for (map_y_0 = 0, c_y = tp[0].y_lat; map_y_0 < (long)atb.height; map_y_0++, c_y += map_c_dy) { ! scr_y = (c_y - y_lat_offset) / scale_y; // current screen position ! if (scr_y > 0) { ! if (scr_y < screen_height) { ! map_y_max = map_y_0; // update last map pixel in y ! c_y_max = (unsigned long)c_y;// bottom map inside screen coordinate ! } else ! break; // done, reached bottom screen border ! } else { // pixel is above screen ! map_y_min = map_y_0; // update first map pixel in y ! } ! } ! c_y_min = (unsigned long)(tp[0].y_lat + map_y_min * map_c_dy); // top map inside screen coordinate ! ! map_x_min = map_x_max = 0l; ! for (map_x = 0, c_x = tp[0].x_long; map_x < (long)atb.width; map_x++, c_x += map_c_dx) { ! scr_x = (c_x - x_long_offset)/ scale_x; // current screen position ! if (scr_x > 0) { ! if (scr_x < screen_width) ! map_x_max = map_x; // update last map pixel in x ! else ! break; // done, reached right screen border ! } else { // pixel is left from screen ! map_x_min = map_x; // update first map pixel in x ! } ! } ! c_x_min = (unsigned long)(tp[0].x_long + map_x_min * map_c_dx); // left map inside screen coordinate ! ! scr_yp = -1; ! scr_c_xr = x_long_offset + screen_width * scale_x; ! c_dx = map_c_dx; // map pixel width ! scale_xa = scale_x0; // the compiler likes it ;-) ! ! map_done = 0; ! map_act = 0; ! map_seen = 0; ! scr_y = screen_height - 1; ! ! // loop over map pixel rows ! for (map_y_0 = map_y_min, c_y = (double)c_y_min; (map_y_0 <= map_y_max); map_y_0++, c_y += map_c_dy) { ! scr_y = (c_y - y_lat_offset) / scale_y; ! if (scr_y != scr_yp) { // don't do a row twice ! scr_yp = scr_y; // remember as previous y ! scr_xp = -1; ! // loop over map pixel columns ! map_act = 0; ! scale_x_nm = calc_dscale_x(0,(long)c_y) / 1852.0; // nm per Xastir coordinate ! for (map_x = map_x_min, c_x = (double)c_x_min; map_x <= map_x_max; map_x++, c_x += c_dx) { ! scr_x = (c_x - x_long_offset) / scale_x; ! if (scr_x != scr_xp) { // don't do a pixel twice ! scr_xp = scr_x; // remember as previous x ! map_y = map_y_0; ! ! if (map_y >= 0 && map_y <= tp[1].img_y) { // check map boundaries in y direction ! map_seen = 1; ! map_act = 1; // detects blank screen rows (end of map) ! ! // now copy a pixel from the map image to the screen ! l = map_x + map_y * image->columns; ! if (image->storage_class == PseudoClass) { ! XSetForeground(XtDisplay(w), gc, my_colors[index_pack[l]].pixel); ! } ! else { ! pack_pixel_bits(pixel_pack[l].red, ! pixel_pack[l].green, ! pixel_pack[l].blue, ! &my_colors[0].pixel); ! XSetForeground(XtDisplay(w), gc, my_colors[0].pixel); ! } ! (void)XFillRectangle (XtDisplay (w),pixmap,gc,scr_x,scr_y,scr_dx,scr_dy); ! } // check map boundaries in y direction ! } ! } // loop over map pixel columns ! if (map_seen && !map_act) ! map_done = 1; ! } ! } // loop over map pixel rows ! ! if (image) ! DestroyImage(image); ! if (image_info) ! DestroyImageInfo(image_info); ! } ! #endif //HAVE_IMAGEMAGICK ! ///////////////////////////////////////////// End of Tigermap code /////////////////////////////////////// ! ! ! ! ! ! #ifdef HAVE_LIBGEOTIFF ! /*********************************************************** ! * read_fgd_file() ! * ! * Read in the "*.fgd" file associated with the geoTIFF ! * file. Get the corner points from it and return. If ! * no fgd file exists for this map, return a 0. ! ***********************************************************/ ! int read_fgd_file ( char* tif_filename, ! float* f_west_bounding, ! float* f_east_bounding, ! float* f_north_bounding, ! float* f_south_bounding) ! { ! char fgd_file[MAX_FILENAME];/* Complete path/name of .fgd file */ ! FILE *fgd; /* Filehandle of .fgd file */ ! char line[MAX_FILENAME]; /* One line from .fgd file */ ! int length; ! char *ptr; /* Substring pointer */ ! int num_coordinates = 0; ! ! ! /* Read the .fgd file to find corners of the map neat-line */ ! strcpy( fgd_file, tif_filename); ! length = strlen(fgd_file); ! ! /* Change the extension to ".fgd" */ ! fgd_file[length-3] = 'f'; ! fgd_file[length-2] = 'g'; ! fgd_file[length-1] = 'd'; ! ! if (debug_level & 512) ! fprintf(stderr,"%s\n",fgd_file); ! ! /* ! * Search for the WEST/EAST/NORTH/SOUTH BOUNDING COORDINATES ! * in the .fgd file. ! */ ! fgd = fopen (fgd_file, "r"); ! ! // Try an alternate path (../metadata/ subdirectory) if the first path didn't work ! // This allows working with USGS maps directly from CDROM ! if (fgd == NULL) { ! get_alt_fgd_path(fgd_file, sizeof(fgd_file) ); ! ! if (debug_level & 512) ! fprintf(stderr,"%s\n",fgd_file); ! ! fgd = fopen (fgd_file, "r"); ! } ! ! if (fgd != NULL) ! { ! while ( ( !feof (fgd) ) && ( num_coordinates < 4 ) ) ! { ! get_line (fgd, line, MAX_FILENAME); ! ! if (*f_west_bounding == 0.0) ! { ! if ( ( (ptr = strstr(line, "WEST BOUNDING COORDINATE:") ) != NULL) ! || ( (ptr = strstr(line, "West_Bounding_Coordinate:") ) != NULL) ) ! { ! sscanf (ptr + 25, " %f", f_west_bounding); ! if (debug_level & 512) ! fprintf(stderr,"West Bounding: %f\n",*f_west_bounding); ! num_coordinates++; ! } ! } ! ! else if (*f_east_bounding == 0.0) ! { ! if ( ( (ptr = strstr(line, "EAST BOUNDING COORDINATE:") ) != NULL) ! || ( (ptr = strstr(line, "East_Bounding_Coordinate:") ) != NULL) ) ! { ! sscanf (ptr + 25, " %f", f_east_bounding); ! if (debug_level & 512) ! fprintf(stderr,"East Bounding: %f\n",*f_east_bounding); ! num_coordinates++; ! } ! } ! ! else if (*f_north_bounding == 0.0) ! { ! if ( ( (ptr = strstr(line, "NORTH BOUNDING COORDINATE:") ) != NULL) ! || ( (ptr = strstr(line, "North_Bounding_Coordinate:") ) != NULL) ) ! { ! sscanf (ptr + 26, " %f", f_north_bounding); ! if (debug_level & 512) ! fprintf(stderr,"North Bounding: %f\n",*f_north_bounding); ! num_coordinates++; ! } ! } ! ! else if (*f_south_bounding == 0.0) ! { ! if ( ( (ptr = strstr(line, "SOUTH BOUNDING COORDINATE:") ) != NULL) ! || ( (ptr = strstr(line, "South_Bounding_Coordinate:") ) != NULL) ) ! { ! sscanf (ptr + 26, " %f", f_south_bounding); ! if (debug_level & 512) ! fprintf(stderr,"South Bounding: %f\n",*f_south_bounding); ! num_coordinates++; ! } ! } ! ! } ! fclose (fgd); ! } ! else ! { ! if (debug_level & 512) ! fprintf(stderr,"Couldn't open '.fgd' file, assuming no map collar to chop %s\n", ! tif_filename); ! return(0); ! } ! ! ! /* ! * We should now have exactly four bounding coordinates. ! * These specify the map neat-line corners. We can use ! * them to chop off the white collar from around the map. ! */ ! if (num_coordinates != 4) ! { ! fprintf(stderr,"Couldn't find 4 bounding coordinates in '.fgd' file, map %s\n", ! tif_filename); ! return(0); ! } ! ! ! if (debug_level & 512) { ! fprintf(stderr,"%f %f %f %f\n", ! *f_south_bounding, ! *f_north_bounding, ! *f_west_bounding, ! *f_east_bounding); ! } ! ! return(1); /* Successful */ ! } ! ! ! ! ! ! // Check the "GTIFProj4*" functions to see if we can use ! // datum.c instead for any of them. These calls are all in ! // draw_geotiff_image_map(). It looks like they deal with ! // converting from pixels to coordinates and vice-versa, so we ! // probably still need them. Perhaps we can borrow the code for ! // that and do it ourselves, to get rid of the extra library? ! ! /*********************************************************** ! * draw_geotiff_image_map() ! * ! * Here's where we handle geoTIFF files, such as USGS DRG ! * topo maps. The .fgd file gives us the lat/lon of the map ! * neat-line corners for USGS maps. We use this info to ! * chop off the white map border. If no .fgd file is present, ! * we assume there is no map collar to be cropped and display ! * every pixel. ! * We also translate from the map datum to WGS84. We use ! * libgeotiff/libtiff/libproj for these operations. ! ! * TODO: ! * Provide support for datums other than NAD27/NAD83/WGS84. ! * Libproj doesn't currently support many datums. ! * ! * Provide support for handling different map projections. ! * Perhaps by reprojecting the map data and storing it on ! * disk in another format. ! * ! * Select 'o', 'f', 'k', or 'c' maps based on zoom level. ! * Might also put some hysteresis in this so that it keeps ! * the current type of map through one extra zoom each way. ! * 'c': Good from x256 to x064. ! * 'f': Good from x128 to x032. Not very readable at x128. ! * 'k': Good from x??? to x???. ! * 'o': Good from x064 to x004. Not very readable at x64. ! ***********************************************************/ ! void draw_geotiff_image_map (Widget w, char *dir, char *filenm, int destination_pixmap) { ! char file[MAX_FILENAME]; /* Complete path/name of image file */ ! TIFF *tif = (TIFF *) 0; /* Filehandle for tiff image file */ ! GTIF *gtif = (GTIF *) 0; /* GeoKey-level descriptor */ ! /* enum { VERSION = 0, MAJOR, MINOR }; */ ! int versions[3]; ! uint32 width; /* Width of the image */ ! uint32 height; /* Height of the image */ ! uint16 bitsPerSample; /* Should be 8 for USGS DRG's */ ! uint16 samplesPerPixel = 1; /* Should be 1 for USGS DRG's. Some maps ! don't have this tag so we default to 1 */ ! uint32 rowsPerStrip; /* Should be 1 for USGS DRG's */ ! uint16 planarConfig; /* Should be 1 for USGS DRG's */ ! uint16 photometric; /* DRGs are RGB (2) */ ! int bytesPerRow; /* Bytes per scanline row of tiff file */ ! GTIFDefn defn; /* Stores geotiff details */ ! u_char *imageMemory; /* Fixed pointer to same memory area */ ! uint32 row; /* My row counter for the loop */ ! int num_colors; /* Number of colors in the geotiff colormap */ ! uint16 *red_orig, *green_orig, *blue_orig; /* Used for storing geotiff colors */ ! XColor my_colors[256]; /* Used for translating colormaps */ ! unsigned long west_bounding = 0; ! unsigned long east_bounding = 0; ! unsigned long north_bounding = 0; ! unsigned long south_bounding = 0; ! float f_west_bounding = 0.0; ! float f_east_bounding = 0.0; ! float f_north_bounding = 0.0; ! float f_south_bounding = 0.0; ! ! unsigned long west_bounding_wgs84 = 0; ! unsigned long east_bounding_wgs84 = 0; ! unsigned long north_bounding_wgs84 = 0; ! unsigned long south_bounding_wgs84 = 0; ! ! float f_NW_x_bounding; ! float f_NW_y_bounding; ! float f_NE_x_bounding; ! float f_NE_y_bounding; ! float f_SW_x_bounding; ! float f_SW_y_bounding; ! float f_SE_x_bounding; ! float f_SE_y_bounding; ! ! unsigned long NW_x_bounding_wgs84 = 0; ! unsigned long NW_y_bounding_wgs84 = 0; ! double f_NW_x_bounding_wgs84 = 0.0; ! double f_NW_y_bounding_wgs84 = 0.0; ! ! unsigned long NE_x_bounding_wgs84 = 0; ! unsigned long NE_y_bounding_wgs84 = 0; ! double f_NE_x_bounding_wgs84 = 0.0; ! double f_NE_y_bounding_wgs84 = 0.0; ! ! unsigned long SW_x_bounding_wgs84 = 0; ! unsigned long SW_y_bounding_wgs84 = 0; ! double f_SW_x_bounding_wgs84 = 0.0; ! double f_SW_y_bounding_wgs84 = 0.0; ! ! unsigned long SE_x_bounding_wgs84 = 0; ! unsigned long SE_y_bounding_wgs84 = 0; ! double f_SE_x_bounding_wgs84 = 0.0; ! double f_SE_y_bounding_wgs84 = 0.0; ! ! int NW_x = 0; /* Store pixel values for map neat-line */ ! int NW_y = 0; /* ditto */ ! int NE_x = 0; /* ditto */ ! int NE_y = 0; /* ditto */ ! int SW_x = 0; /* ditto */ ! int SW_y = 0; /* ditto */ ! int SE_x = 0; /* ditto */ ! int SE_y = 0; /* ditto */ ! int left_crop; /* Pixel cropping value */ ! int right_crop; /* Pixel cropping value */ ! int top_crop; /* Pixel cropping value */ ! int bottom_crop; /* Pixel cropping value */ ! double xxx, yyy; /* LFM: needs more accuracy here */ ! register long sxx, syy; /* X Y screen plot positions */ ! float steph; ! register float stepw; ! int stepwc, stephc; ! char map_it[MAX_FILENAME]; /* Used to hold filename for status line */ ! int have_fgd; /* Tells where we have an associated *.fgd file */ ! //short datum; ! char *datum_name; /* Points to text name of datum */ ! //double *GeoTie; ! int crop_it = 0; /* Flag which tells whether the image should be cropped */ ! ! register uint32 column; ! ! float xastir_left_x_increment; ! float left_x_increment; ! float xastir_left_y_increment; ! float left_y_increment; ! float xastir_right_x_increment; ! float right_x_increment; ! float xastir_right_y_increment; ! float right_y_increment; ! float xastir_top_y_increment; ! float top_y_increment; ! float xastir_bottom_y_increment; ! float bottom_y_increment; ! float xastir_avg_y_increment; ! float avg_y_increment; ! int row_offset; ! register unsigned long current_xastir_left; ! unsigned long current_xastir_right; ! register uint32 current_left; ! uint32 current_right; ! uint32 current_line_width; ! register unsigned long xastir_current_y; ! register uint32 column_offset; ! register unsigned long xastir_current_x; ! double *PixelScale; ! int have_PixelScale; ! uint16 qty; ! int SkipRows; ! unsigned long view_min_x, view_max_x; ! unsigned long view_min_y, view_max_y; ! ! register unsigned long xastir_total_y; ! int NW_line_offset; ! int NE_line_offset; ! int NW_xastir_x_offset; ! int NE_xastir_x_offset; ! int NW_xastir_y_offset; ! int NW_x_offset; ! int NE_x_offset; ! float xastir_avg_left_right_y_increment; ! register float total_avg_y_increment; ! unsigned long view_left_minus_pixel_width; ! unsigned long view_top_minus_pixel_height; ! ! ! ! if (debug_level & 16) ! fprintf(stderr,"%s/%s\n", dir, filenm); ! ! ! xastir_snprintf(file, sizeof(file), "%s/%s", dir, filenm); ! ! /* Check whether we have an associated *.fgd file. This ! * file contains the neat-line corner points for USGS DRG ! * maps, which allows us to chop off the map collar. ! */ ! have_fgd = read_fgd_file( file, ! &f_west_bounding, ! &f_east_bounding, ! &f_north_bounding, ! &f_south_bounding ); ! ! /* ! * If we are able to read the fgd file then we have the lat/lon ! * corner points in floating point variables. If there isn't ! * an fgd file then we must get the info from the geotiff ! * tags themselves and we assume that there's no map collar to ! * chop off. ! */ ! ! ! /* ! * What we NEED to do (implemented a bit later in this function ! * in order to support geotiff files created with other map ! * datums, is to open up the geotiff file and get the map datum ! * used for the data. Then convert the corner points to WGS84 ! * and check to see whether the image is inside our viewport. ! * Some USGS geotiff maps have map data in NAD83 datum and the ! * .fgd file incorrectly specifying NAD27 datum. There are also ! * some USGS geotiff maps created with WGS84 datum. ! */ ! ! ! /* convert_to_xastir_coordinates( x,y,longitude,latitude ); */ ! if (have_fgd) /* Could be a USGS file */ ! { ! int temp_ok1, temp_ok2; ! ! if (debug_level & 16) { ! fprintf(stderr,"FGD: W:%f E:%f N:%f S:%f\n", ! f_west_bounding, ! f_east_bounding, ! f_north_bounding, ! f_south_bounding); ! } ! ! crop_it = 1; /* The map collar needs to be cropped */ ! ! temp_ok1 = convert_to_xastir_coordinates( &west_bounding, ! &north_bounding, ! f_west_bounding, ! f_north_bounding ); ! ! ! temp_ok2 = convert_to_xastir_coordinates( &east_bounding, ! &south_bounding, ! f_east_bounding, ! f_south_bounding ); ! ! if (!temp_ok1 || !temp_ok2) { ! fprintf(stderr,"draw_geotiff_image_map: problem converting from lat/lon\n"); ! return; ! } ! ! ! /* ! * Check whether map is inside our current view. It'd be ! * good to do a datum conversion first, but we don't know ! * what the datum is by this point in the code. I'm just ! * doing this check here for speed, so that I can eliminate ! * maps that aren't even close to our viewport area, without ! * having to open those map files. All other maps that pass ! * this test (at the next go-around later in the code) must ! * have their corner points datum-shifted so that we can ! * REALLY tell whether a map fits within the viewport. ! * ! * Perhaps add a bit to the corners (the max datum shift?) ! * to do our quick check? I decided to add about 10 seconds ! * to the map edges, which equates to 1000 in the Xastir ! * coordinate system. That should be greater than any datum ! * shift in North America for USGS topos. I'm artificially ! * inflating the size of the map just for this quick ! * elimination check. ! * ! * bottom top left right ! */ ! ! // Check whether we're indexing or drawing the map ! if ( (destination_pixmap != INDEX_CHECK_TIMESTAMPS) ! && (destination_pixmap != INDEX_NO_TIMESTAMPS) ) { ! ! // We're drawing. ! if (!map_visible( south_bounding + 1000, ! north_bounding - 1000, ! west_bounding - 1000, ! east_bounding + 1000 ) ) { ! if (debug_level & 16) { ! fprintf(stderr,"Map not within current view.\n"); ! fprintf(stderr,"Skipping map: %s\n", file); ! } ! ! // Map isn't inside our current view. We're done. ! // Free any memory used and return. ! // ! return; // Skip this map ! } ! } ! } ! ! ! /* ! * At this point the map MAY BE in our current view. ! * We don't know for sure until we do a datum translation ! * on the bounding coordinates and check again. Note that ! * if there's not an accompanying .fgd file, we don't have ! * the bounding coordinates yet by this point. ! */ ! ! ! /* Open TIFF descriptor to read GeoTIFF tags */ ! tif = XTIFFOpen (file, "r"); ! if (!tif) ! return; ! ! ! /* Open GTIF Key parser. Keys will be read at this time */ ! gtif = GTIFNew (tif); ! if (!gtif) ! { ! /* Close the TIFF file descriptor */ ! XTIFFClose (tif); ! return; ! } ! ! ! /* ! * Get the GeoTIFF directory info. Need this for ! * some of the operations further down in the code. ! */ ! GTIFDirectoryInfo (gtif, versions, 0); ! ! /* ! if (versions[MAJOR] > 1) ! { ! fprintf(stderr,"This file is too new for me\n"); ! GTIFFree (gtif); ! XTIFFClose (tif); ! return; ! } ! */ ! ! ! /* I might want to attempt to avoid the GTIFGetDefn ! * call, as it takes a bit of time per file. It ! * normalizes the info. Try getting just the tags ! * or keys that I need individually instead. I ! * need "defn" for the GTIFProj4ToLatLong calls though. ! */ ! if (GTIFGetDefn (gtif, &defn)) ! { ! if (debug_level & 16) ! GTIFPrintDefn (&defn, stdout); ! } ! ! ! /* Fetch a few TIFF fields for this image */ ! if ( !TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &width) ) { ! width = 5493; ! fprintf(stderr,"No width tag found in file, setting it to 5493\n"); ! } ! ! if ( !TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &height) ) { ! height = 6840; ! fprintf(stderr,"No height tag found in file, setting it to 6840\n"); ! } ! ! ! /* ! * If we don't have an associated .fgd file for this map, ! * check for corner points in the ImageDescription ! * tag (proposed new USGS DRG standard). Boundary ! * coordinates will be the outside corners of the image ! * unless I can find some other proof. ! * Currently I assume that the map has no ! * map collar to chop off and set the neat-line corners ! * to be the outside corners of the image. ! * ! * NOTE: For the USGS files (with a map collar), the ! * image must be cropped and rotated and is slightly ! * narrower at one end (top for northern hemisphere, bottom ! * for southern hemisphere). For other files with no map ! * collar, the image is rectangular but the lat/lon ! * coordinates may be rotated. ! */ ! if (!have_fgd) // Not a USGS map or perhaps a newer spec ! { ! crop_it = 0; /* Do NOT crop this map image */ ! ! /* ! * Snag and parse ImageDescription tag here. ! */ ! ! /* Code goes here for getting ImageDescription tag... */ ! ! ! /* Figure out the bounding coordinates for this map */ ! if (debug_level & 16) ! fprintf(stderr,"\nCorner Coordinates:\n"); ! ! /* Find lat/lon for NW corner of image */ ! xxx = 0.0; ! yyy = 0.0; ! if ( GTIFImageToPCS( gtif, &xxx, &yyy ) ) // Do all 4 of these in one call? ! { ! if (debug_level & 16) { ! fprintf(stderr,"%-13s ", "Upper Left" ); ! fprintf(stderr,"(%11.3f,%11.3f)\n", xxx, yyy ); ! } ! } ! if ( GTIFProj4ToLatLong( &defn, 1, &xxx, &yyy ) ) // Do all 4 of these in one call? ! { ! if (debug_level & 16) { ! fprintf(stderr," (%s,", GTIFDecToDMS( xxx, "Long", 2 ) ); ! fprintf(stderr,"%s)\n", GTIFDecToDMS( yyy, "Lat", 2 ) ); ! fprintf(stderr,"%f %f\n", xxx, yyy); ! } ! } ! f_NW_x_bounding = (float)xxx; ! f_NW_y_bounding = (float)yyy; ! ! ! /* Find lat/lon for NE corner of image */ ! xxx = width - 1; ! yyy = 0.0; ! if ( GTIFImageToPCS( gtif, &xxx, &yyy ) ) ! { ! if (debug_level & 16) { ! fprintf(stderr,"%-13s ", "Lower Right" ); ! fprintf(stderr,"(%11.3f,%11.3f)\n", xxx, yyy ); ! } ! } ! if ( GTIFProj4ToLatLong( &defn, 1, &xxx, &yyy ) ) ! { ! if (debug_level & 16) { ! fprintf(stderr," (%s,", GTIFDecToDMS( xxx, "Long", 2 ) ); ! fprintf(stderr,"%s)\n", GTIFDecToDMS( yyy, "Lat", 2 ) ); ! fprintf(stderr,"%f %f\n", xxx, yyy); ! } ! } ! f_NE_x_bounding = (float)xxx; ! f_NE_y_bounding = (float)yyy; ! ! /* Find lat/lon for SW corner of image */ ! xxx = 0.0; ! yyy = height - 1; ! if ( GTIFImageToPCS( gtif, &xxx, &yyy ) ) ! { ! if (debug_level & 16) { ! fprintf(stderr,"%-13s ", "Lower Right" ); ! fprintf(stderr,"(%11.3f,%11.3f)\n", xxx, yyy ); ! } ! } ! if ( GTIFProj4ToLatLong( &defn, 1, &xxx, &yyy ) ) ! { ! if (debug_level & 16) { ! fprintf(stderr," (%s,", GTIFDecToDMS( xxx, "Long", 2 ) ); ! fprintf(stderr,"%s)\n", GTIFDecToDMS( yyy, "Lat", 2 ) ); ! fprintf(stderr,"%f %f\n", xxx, yyy); ! } ! } ! f_SW_x_bounding = (float)xxx; ! f_SW_y_bounding = (float)yyy; ! ! /* Find lat/lon for SE corner of image */ ! xxx = width - 1; ! yyy = height - 1; ! if ( GTIFImageToPCS( gtif, &xxx, &yyy ) ) ! { ! if (debug_level & 16) { ! fprintf(stderr,"%-13s ", "Lower Right" ); ! fprintf(stderr,"(%11.3f,%11.3f)\n", xxx, yyy ); ! } ! } ! if ( GTIFProj4ToLatLong( &defn, 1, &xxx, &yyy ) ) ! { ! if (debug_level & 16) { ! fprintf(stderr," (%s,", GTIFDecToDMS( xxx, "Long", 2 ) ); ! fprintf(stderr,"%s)\n", GTIFDecToDMS( yyy, "Lat", 2 ) ); ! fprintf(stderr,"%f %f\n", xxx, yyy); ! } ! } ! f_SE_x_bounding = (float)xxx; ! f_SE_y_bounding = (float)yyy; ! } ! ! // Handle special USGS geoTIFF case here. We only have ! // four boundaries because the edges are aligned with ! // lat/long. ! else // have_fgd ! { ! f_NW_x_bounding = f_west_bounding; ! f_NW_y_bounding = f_north_bounding; ! ! f_SW_x_bounding = f_west_bounding; ! f_SW_y_bounding = f_south_bounding; ! ! f_NE_x_bounding = f_east_bounding; ! f_NE_y_bounding = f_north_bounding; ! ! f_SE_x_bounding = f_east_bounding; ! f_SE_y_bounding = f_south_bounding; ! } ! ! ! // Fill in the wgs84 variables so we can do a datum ! // conversion but keep our original values also. ! f_NW_x_bounding_wgs84 = f_NW_x_bounding; ! f_NW_y_bounding_wgs84 = f_NW_y_bounding; ! ! f_SW_x_bounding_wgs84 = f_SW_x_bounding; ! f_SW_y_bounding_wgs84 = f_SW_y_bounding; ! ! f_NE_x_bounding_wgs84 = f_NE_x_bounding; ! f_NE_y_bounding_wgs84 = f_NE_y_bounding; ! ! f_SE_x_bounding_wgs84 = f_SE_x_bounding; ! f_SE_y_bounding_wgs84 = f_SE_y_bounding; ! ! ! /* Get the datum */ ! // GTIFKeyGet( gtif, GeogGeodeticDatumGeoKey, &datum, 0, 1 ); ! // if (debug_level & 16) ! // fprintf(stderr,"GeogGeodeticDatumGeoKey: %d\n", datum ); ! ! ! /* Get the tiepoints (in UTM coordinates always?) ! * In our case they look like: ! * ! * 0.000000 Y ! * 0.000000 X ! * 0.000000 Z ! * 572983.025771 Y in UTM (longitude for some maps?) ! * 5331394.085064 X in UTM (latitude for some maps?) ! * 0.000000 Z ! * ! */ ! /* ! if (debug_level & 16) { ! fprintf(stderr,"Tiepoints:\n"); ! if ( TIFFGetField( tif, TIFFTAG_GEOTIEPOINTS, &qty, &GeoTie ) ) { ! for ( i = 0; i < qty; i++ ) { ! fprintf(stderr,"%f\n", *(GeoTie + i) ); ! } ! } ! } ! */ ! ! ! /* Get the geotiff horizontal datum name */ ! if ( defn.Datum != 32767 ) { ! GTIFGetDatumInfo( defn.Datum, &datum_name, NULL ); ! if (debug_level & 16) ! fprintf(stderr,"Datum: %d/%s\n", defn.Datum, datum_name ); ! } ! ! ! /* ! * Perform a datum shift on the bounding coordinates before we ! * check whether the map is inside our viewport. At the moment ! * this is still hard-coded to NAD27 datum. If the map is already ! * in WGS84 or NAD83 datum, skip the datum conversion code. ! */ ! if ( (defn.Datum != 6030) /* DatumE_WGS84 */ ! && (defn.Datum != 6326) /* Datum_WGS84 */ ! && (defn.Datum != 6269) ) /* Datum_North_American_Datum_1983 */ { ! ! if (debug_level & 16) ! fprintf(stderr,"***** Attempting Datum Conversions\n"); ! ! ! // This code uses datum.h/datum.c to do the conversion ! // instead of the proj.4 library as we had before. ! // Here we assume that if it's not one of the three datums ! // listed above, it's NAD27. ! ! // Convert NW corner to WGS84 ! wgs84_datum_shift(TO_WGS_84, ! &f_NW_y_bounding_wgs84, ! &f_NW_x_bounding_wgs84, ! D_NAD_27_CONUS); // NAD27 CONUS ! ! // Convert NE corner to WGS84 ! wgs84_datum_shift(TO_WGS_84, ! &f_NE_y_bounding_wgs84, ! &f_NE_x_bounding_wgs84, ! D_NAD_27_CONUS); // NAD27 CONUS ! ! // Convert SW corner to WGS84 ! wgs84_datum_shift(TO_WGS_84, ! &f_SW_y_bounding_wgs84, ! &f_SW_x_bounding_wgs84, ! D_NAD_27_CONUS); // NAD27 CONUS ! ! // Convert SE corner to WGS84 ! wgs84_datum_shift(TO_WGS_84, ! &f_SE_y_bounding_wgs84, ! &f_SE_x_bounding_wgs84, ! D_NAD_27_CONUS); // NAD27 CONUS (131) ! } ! else ! if (debug_level & 16) ! fprintf(stderr,"***** Skipping Datum Conversion\n"); ! ! ! /* ! * Convert new datum-translated bounding coordinates to the ! * Xastir coordinate system. ! * convert_to_xastir_coordinates( x,y,longitude,latitude ) ! */ ! // NW corner ! if (!convert_to_xastir_coordinates( &NW_x_bounding_wgs84, ! &NW_y_bounding_wgs84, ! (float)f_NW_x_bounding_wgs84, ! (float)f_NW_y_bounding_wgs84 ) ) { ! fprintf(stderr,"draw_geotiff_image_map: Problem converting from lat/lon\n"); ! fprintf(stderr,"Did you follow the instructions for installing PROJ?\n"); ! return; ! } ! ! // NE corner ! if (!convert_to_xastir_coordinates( &NE_x_bounding_wgs84, ! &NE_y_bounding_wgs84, ! (float)f_NE_x_bounding_wgs84, ! (float)f_NE_y_bounding_wgs84 ) ) { ! fprintf(stderr,"draw_geotiff_image_map: Problem converting from lat/lon\n"); ! fprintf(stderr,"Did you follow the instructions for installing PROJ?\n"); ! ! return; ! } ! ! // SW corner ! if (!convert_to_xastir_coordinates( &SW_x_bounding_wgs84, ! &SW_y_bounding_wgs84, ! (float)f_SW_x_bounding_wgs84, ! (float)f_SW_y_bounding_wgs84 ) ) { ! fprintf(stderr,"draw_geotiff_image_map: Problem converting from lat/lon\n"); ! fprintf(stderr,"Did you follow the instructions for installing PROJ?\n"); ! ! return; ! } ! ! // SE corner ! if (!convert_to_xastir_coordinates( &SE_x_bounding_wgs84, ! &SE_y_bounding_wgs84, ! (float)f_SE_x_bounding_wgs84, ! (float)f_SE_y_bounding_wgs84 ) ) { ! fprintf(stderr,"draw_geotiff_image_map: Problem converting from lat/lon\n"); ! fprintf(stderr,"Did you follow the instructions for installing PROJ?\n"); ! ! return; ! } ! ! ! /* ! * Check whether map is inside our current view. These ! * are the real datum-shifted bounding coordinates now, ! * so this is the final decision as to whether the map ! * should be loaded. ! */ ! ! // Find the largest dimensions ! if (NW_y_bounding_wgs84 <= NE_y_bounding_wgs84) ! north_bounding_wgs84 = NW_y_bounding_wgs84; ! else ! north_bounding_wgs84 = NE_y_bounding_wgs84; ! ! if (NW_x_bounding_wgs84 <= SW_x_bounding_wgs84) ! west_bounding_wgs84 = NW_x_bounding_wgs84; ! else ! west_bounding_wgs84 = SW_x_bounding_wgs84; ! ! if (SW_y_bounding_wgs84 >= SE_y_bounding_wgs84) ! south_bounding_wgs84 = SW_y_bounding_wgs84; ! else ! south_bounding_wgs84 = SE_y_bounding_wgs84; ! ! if (NE_x_bounding_wgs84 >= SE_x_bounding_wgs84) ! east_bounding_wgs84 = NE_x_bounding_wgs84; ! else ! east_bounding_wgs84 = SE_x_bounding_wgs84; ! ! ! // Check whether we're indexing or drawing the map ! if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS) ! || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) { ! ! xastir_snprintf(map_it, sizeof(map_it), langcode ("BBARSTA039"), filenm); ! statusline(map_it,0); // Indexing ... ! ! // We're indexing only. Save the extents in the index. ! index_update_xastir(filenm, // Filename only ! south_bounding_wgs84, // Bottom ! north_bounding_wgs84, // Top ! west_bounding_wgs84, // Left ! east_bounding_wgs84); // Right ! ! //Free any memory used and return ! /* We're finished with the geoTIFF key parser, so get rid of it */ ! GTIFFree (gtif); ! ! /* Close the TIFF file descriptor */ ! XTIFFClose (tif); ! ! return; // Done indexing this file ! } ! else { ! xastir_snprintf(map_it, sizeof(map_it), langcode ("BBARSTA028"), filenm); ! statusline(map_it,0); // Loading ... ! } ! ! ! ! ! // bottom top left right ! if (!map_visible( south_bounding_wgs84, ! north_bounding_wgs84, ! west_bounding_wgs84, ! east_bounding_wgs84 ) ) ! { ! if (debug_level & 16) { ! fprintf(stderr,"Map not within current view.\n"); ! fprintf(stderr,"Skipping map: %s\n", file); ! } ! ! /* ! * Map isn't inside our current view. We're done. ! * Free any memory used and return ! */ ! ! /* We're finished with the geoTIFF key parser, so get rid of it */ ! GTIFFree (gtif); ! ! /* Close the TIFF file descriptor */ ! XTIFFClose (tif); ! ! return; /* Skip this map */ ! } ! ! /* ! From running in debug mode: ! Width: 5493 ! Height: 6840 ! Rows Per Strip: 1 ! Bits Per Sample: 8 ! Samples Per Pixel: 1 ! Planar Config: 1 ! */ ! ! ! /* Fetch a few TIFF fields for this image */ ! if ( !TIFFGetField (tif, TIFFTAG_PHOTOMETRIC, &photometric) ) { ! photometric = PHOTOMETRIC_RGB; ! fprintf(stderr,"No photometric tag found in file, setting it to RGB\n"); ! } ! if ( !TIFFGetField (tif, TIFFTAG_ROWSPERSTRIP, &rowsPerStrip) ) { ! rowsPerStrip = 1; ! fprintf(stderr,"No rowsPerStrip tag found in file, setting it to 1\n"); ! } ! ! if ( !TIFFGetField (tif, TIFFTAG_BITSPERSAMPLE, &bitsPerSample) ) { ! bitsPerSample = 8; ! fprintf(stderr,"No bitsPerSample tag found in file, setting it to 8\n"); ! } ! ! if ( !TIFFGetField (tif, TIFFTAG_SAMPLESPERPIXEL, &samplesPerPixel) ) { ! samplesPerPixel = 1; ! fprintf(stderr,"No samplesPerPixel tag found in file, setting it to 1\n"); ! } ! ! if ( !TIFFGetField (tif, TIFFTAG_PLANARCONFIG, &planarConfig) ) { ! planarConfig = 1; ! fprintf(stderr,"No planarConfig tag found in file, setting it to 1\n"); ! } ! ! ! if (debug_level & 16) { ! fprintf(stderr," Width: %ld\n", width); ! fprintf(stderr," Height: %ld\n", height); ! fprintf(stderr," Photometric: %d\n", photometric); ! fprintf(stderr," Rows Per