FE 'tkGooies'

'MAPtools' group

Tk GUI script
'tkReadOutlineFile_ WriteFilteredFile'

(Code for a GUI to read an outline data file
--- for example, longitude-latitude data ---
and create an outline file with fewer points.)
(FE = Freedom Environment)

FE Home Page > FE Downloads Page >

FE 'tkGooies' Description Page >

FE 'tkGooies' 'MAPtools' MENU Page >

This
'tkReadOutlineFile_WriteFilteredFile'
Code Page

INTRODUCTION to Tcl-Tk script
'tkReadOutlineFile_ WriteFilteredFile'

For several years (circa 2014-2016), I had been planning to make various 'map making' Tk GUI's that

  • provide 'vector' (outline) maps
    (drawn with line-segments)

    and

  • image-pixels maps
    (assembled from 'tiles')

And, eventually, I want to provide additional map utility GUI's that allow for reading a 'marker-locations' file and then apply markers to a previously created map image (vector-map or tiles-map).

On the page 'tkReadOutlineFile_drawOutlineOnCanvas', I presented my first map-making 'tkGooie' script --- to make 'vector' maps from outline-data files in a simple format.

Each line of the input outline-file is to contain x,y coordinates (which may be a longitude-latitude pair, in decimal degrees).

    Note that the outline data in the file does not have to be longitude-latitude map data.

    It could be pairs of coordinates that provide an outline of almost any object --- for example, a silouette of a person or an animal or an insect or a fish.

    OR, the data file could provide an outline of a logo --- or a group of alphanumeric characters in one or more font styles.

    OR, the data file could provide vertex coordinates of a geometric figure like a pentagon or hexagon or octagon.

    OR, a more complicated geometric figure could be defined by the points in the file --- such as a fractal-like geometric figure, like the 3rd or 4th level of a 'Koch Snowlake'.

    In fact, the outline data could depict a snowflake --- or flower petals --- or the outline of a leaf --- or the outline of tree branches.

    Use your imagination.


SOURCES OF OUTLINE DATA :
(for maps)

The x,y data in the input file (which MAY be longitude,latitude data) is assumed to be in human-readable ASCII format, NOT binary ('ones-and-zeros', 'machine-readable') format.

There are many outline (boundary) data files on the internet --- in *ASCII* (non-binary) format --- for continents, countries, regions, states, counties, provinces, etc.

Examples:

There is a lot of XML-like markup language in '.geojson' and '.kml' files (uncompressed '.kmz' files).

For input to this utility, the user can take those files and 'clean them up' so that there are only a pair of space-separated (or comma-separated) decimal numbers at the start of each line.

The input file can contain a few comment lines indicated by '#' in column one of each comment line --- typically one (or a few) comment lines at the top of the file that describe the contents of the file --- and that, optionally, document the source of the data.

    NOTE:
    Generally, in 2016, there are several times more '.kml' and '.kmz' files than '.geojson' files to be found on the internet by searching for files with those suffixes.

In '.kml' files, the x,y data is between <coordinates> and </coordinates> markers.

This 'tkReadOutlineFile_ WriteFiltered File' utility is written to read input files in very simple, minimal format --- x,y ASCII decimal number pairs on each data line --- without any XML-like markup language in the input file.

There will be shell scripts in the 'FE Nautilus Scripts' subsystem that extract and re-format (to one x,y point per data line) the x,y coordinate pairs from KML and GeoJSON files --- with very few 'left-overs' (XML tags).

    NOTE:
    Coordinate-pair data in files for drawing maps is usually provided with LONGITUDE BEFORE LATITUDE.

    You can think of the LONGITUDE value as providing the X-distance along the equator of a planet, and the LATITUDE value as providing the Y-distance from the equator to a north or south pole.

    The LONGITUDE angle is usually specified between -180 and +180 degrees --- from a zero longitude (like the longitude line through Greenwich, England on Earth).

    The LATITUDE angle is usually specified between -90 and +90 degrees, measured from the equator.

If you want more information on KML or GeoJSON files, you can do a WEB SEARCH on keywords like


A Motivation for this Tk Script:
(huge outline data files)

A major motivation for this Tk script is that sometimes one can find an outline data file that contains thousands of data points, but one typically only needs a few hundred data points to create nice-looking maps.

For example, the site 'gadm.org' contains files for about 250 countries (gadm = 'geographic administrative areas') --- essentially all the countries/administrative-areas on Earth.

But many of these files contain tens of thousands of points --- available in KML files.

Those country files may be 'streamlined' into the simple format (no markup language tags) that are used in these 'tkGooie' outline file utilities.

About 150 of those 'streamlined' files are being made available on this site --- via a Map Data SOURCES-of-Outline-Files page.

This 'tkReadOutlineFile_ WriteFilteredFile' utility will be used to make some smaller versions of the huge simple-format files.

Small, medium, and large outline files may be presented on that data-file-samples page.


Basic Goals of the Tk Script:

My purpose for this Tk GUI script is/was to read the x,y points in an outline-data-file and create a smaller outline-data-file.

The GUI is/was to allow multiple filter options to the user:

  • An entry field for a point-distance 'filter precision' (or 'decimal tolerance') number --- to allow for skipping the selection (writing) of any point that is very close to the previous point.

  • Four entry fields in which to, optionally, specify the limits of a rectangular-area --- Xmin, Xmax, Ymin, Ymax --- in 'world coordinate' units.

    The selected points will be within these limits.


PLANNED LAYOUT OF THE GUI:

As I have done with other Tk scripts that I have written in the past year or so, I laid out a 'text image' of the GUI --- to aid me as I coded the frames and widgets.

I used the following conventions to make the sketch, with a text editor.


  SQUARE-BRACKETS indicate a comment (not to be placed on the GUI).
  BRACES          indicate a Tk 'button' widget.
  A COLON         indicates that the text before the colon is on a 'label' widget.
  <---O--->       indicates a Tk 'scale' widget (if any).
  CAPITAL-X       indicates a Tk 'checkbutton' widget (if any).
  CAPITAL-O       indicates a Tk 'radiobutton' widget (if any).
  UNDERSCORES     indicate a Tk 'entry' widget (if any).

According to those conventions, I created the following 'text sketch'.


 FrameNames
 VVVVVVVVVV
             ------------------------------------------------------------------------------------------
             Read an Outline File (e.g. Longitudes-Latitudes) - and Write a 'Filtered' Outline File
             [window title]
             ------------------------------------------------------------------------------------------

 .fRbuttons   {Exit} {Help} {Read-Write}

 .fRfile      Enter outline-data filename: ______________________________________________ {Browse...}

 .fRmsg       [ ..........  Messages go here, in a label widget .................................... ]

 .fRparms     Filter Distance: 0.01___ (to filter out any point close to a previous point ; larger filters more)
                                        [a label here contains the text above]

 .fRlimits    X  Filter by     Min-X: -45.0___  Max-X: 45.0___  Min-Y: -45.0___  Max-Y: 45.0___
                 X-Y limits


From the diagram above, I could see that this GUI will contain about:

  • 4 button widgets
  • 8 label widgets
  • 6 entry widgets
  • 1 checkbutton widget
  • 0 radiobutton widgets
  • 0 canvas widgets
  • 0 scale widgets
  • 0 listbox widgets
  • 0 text widgets

Assembling the pieces   (The GUI)

Now it was a matter of putting the pieces together.

I took 'code-pieces' from some of my other Tk scripts that read from one file and write to another --- in particular, I took most of the GUI widgets from my

'tkReadOutlineFile_ drawOutlineOnCanvas' script.

I ended up with the following GUI as an initial display, when the GUI is started up.

The message line just below the filename entry field indicates that the first step for the user is to choose an outline-data-file to process.

The following image shows that a filename has been selected.

It is in the filename entry field, but the data has not been read yet.

The message line indicates that the user can cause the data to be read --- and the output file to be written --- by a mouse-click on the 'Read-Write' button.

Allowing for a reload of the data from the filename that is still in the entry field can be useful if one needs to edit the file to change some data and then quickly re-create the output file from the same input file.

---

The image below shows that after the data is loaded, the message area shows some statistics about

  • total number of lines read
    (including comment lines and null/empty lines)

  • number of data lines that passed the filter-tests, out of the

  • total number of data-lines read.

Note that the Xmin,Xmax,Ymin,Ymax entry fields contained limits like -45.0 and 45.0 until the data was read from the chosen file.

The min-max values are determined from the data in the file.

Ordinarily, the user will simply click on the 'Read-Write' button without changing the min-max values.

But the user can 'tighten up' these values in order to plot a subset of the data points.

Click on the 'Filter on X-Y Limits' checkbutton widget to activate filtering by the min-max limits.

---

The 'Point Filter Precision' value can be raised to use fewer points in creating the output file --- or reduced to include more points in the output file.

The script skips writing points whose x-value AND y-value is closer than (less than) the 'filter precision' to the previous x,y values.

---

Below is a GUI screenshot that was taken after the 'filter precision' was changed from 0.01 to 0.1 --- and after a mouse-click on the 'Read-Write' button.

Note that out of 1496 data points in the input file, 569 were written to the output file.

---

After the output file is created, it is shown in a GUI text editor.

Below is a GUI screenshot that shows the output file in a text editor --- namely 'scite' (SCIntilla Text Editor).

The Tk script can use almost any GUI text editor.

You can edit the Tk script to change the 'set TEXTeditor' command near the bottom of the Tk script, to use a different editor.

---

In addition, one can edit the script to change the name of the output file and the directory in which it is created.

This Tk script is released with the output directory set to '/tmp' in a 'set DIRtemp' statement near the bottom of the Tk script.

Edit that statement if you want to change the output directory.

---

The output filename is set to

$env(USER)_filtered_outline.txt

in the 'read-file_write-file' proc --- where $env(USER) provides the userid, to avoid filename 'collisions' on a multi-user machine.

If you do not like that name, you can simply edit the Tk script to change it.


Execution time:
(and outline quality)

It turns out that most countries --- even countries with a 'ragged' boundary, like Australia or Brazil or the island of Malta --- will have a pretty nice outline with about 200 to 500 data points.

It is gratifying that the creation of such small data files --- by this 'filter outline file' utility --- is done almost instantly --- even from an input file that contains ten or twenty thousand data lines --- thanks to the efficiency of the wonderful 'byte-code' implementation of the 'wish' Tcl-Tk interpreter.

---

'Loops' in the data:

Note that even separate 'loops' like continents (in a Continents input file like the test file used in the screenshots above) are handled by this 'tkGooie' script.

The 'loops' are simply indicated in the input and output data files by a comment line (or empty line) separating one 'loop' from a previous 'loop'.

Note that the output file (shown in the 'scite' text editor screenshot above) includes a 'LoopCount:' indicator --- after the x,y data numbers in each data line.

In that Continents output file, there are loops 1 through 7 seen in the data.

The extra text in each data line does not bother the outline plotting done with the

'tkReadOutlineFile_ drawOutlineOnCanvas' script.

That script only reads the 2 space-separated (or comma-separated) numbers at the start of each data line.

The strings like 'LoopCount: 2' --- on the end of the data lines --- are ignored by the outline-drawing 'tkGooie'.


DESCRIPTION OF THE CODE

Below, I provide the Tk script code for this 'tkReadOutlineFile_WriteFilteredFile' 'app'.

I follow my usual 'canonical' structure for Tk code, for this Tk script:



  0) Set general window & widget parms (win-name, win-position,
     win-color-scheme, fonts, widget-geometry-parms, win-size-control).

  1a) Define ALL frames (and sub-frames, if any).
  1b) Pack   ALL frames and sub-frames.

  2) Define & pack all widgets in the frames, frame by frame.
              Within each frame, define ALL the widgets.
              Then pack the widgets.

  3) Define keyboard and mouse/touchpad/touch-sensitive-screen action
     BINDINGS, if needed.

  4) Define PROCS, if needed.

  5) Additional GUI initialization (typically with one or more of
     the procs), if needed.


This Tk coding structure is discussed in more detail on the page A Canonical Structure for Tk Code --- and variations.

This Tk coding structure makes it easy for me to find code sections --- while generating and testing this script, and when looking for code snippets to include in other scripts (code re-use).


Experimenting with the GUI

As in all my scripts that use the 'pack' geometry manager (which is all of my 100-plus Tk scripts, so far), I provide the four main 'pack' parameters

  • '-side'
  • '-anchor'
  • '-fill'
  • '-expand'

on all the 'pack' commands for the frames and widgets.

I think I have found a good setting of the '-side', '-anchor', '-fill', and '-expand' parameters on the 'pack' commands for the various widgets of this GUI.

In particular ...

The filename 'entry' widget will expand/contract appropriately when the GUI window size is changed --- and button, checkbutton, and label widgets stay fixed in size and relative-location as the window size changes.

If anyone wants to change the way the GUI configures itself as the main (top-level) window size is changed, they can experiment with the '-side', '-anchor', '-fill', and '-expand' parameters on the 'pack' commands for the various widgets --- to get the widget behavior that they want.

---

Additional experimentation with the GUI:

You could change the fonts used for the various GUI widgets.

For example, you could change '-weight' from 'bold' to 'normal' --- or '-slant' from 'roman' to 'italic'.

Or change font families.

In fact, you may NEED to change the font families, because the families I used may not be available on your computer --- and the default font that the 'wish' interpreter chooses may not be very pleasing.

Furthermore, there are variables used to set geometry parameters of widgets --- parameters such as border-widths and padding.

And you could change the '-relief' values for frames and widgets.

Feel free to experiment with those 'appearance' parameters as well.


Some features of the code

There are plenty of comments in the code to describe what most of the code-sections are doing.

See the top of the 'PROCS' section of the script for a list of the procs used in this Tk script.

See comments in the procs for details on the purpose of each proc and for details on the methods by which each proc was implemented.

Here is a quick overview of the procs --- to give an idea of the 'guts' of this utility:



   - 'get_filename'             - called by the 'Browse...' button

   - 'read-file_write-file'     - called by the 'Read-Write' button

   - 'advise_user'              - called by the 'get_filename' and 'read-file_write-file'
                                  procs and in the 'Additional GUI Initialization'
                                  section at the bottom of this script

   - 'edit_inputs'              - called by the 'read-file_write-file' proc

   - 'decimal_check'            - called by 'edit_inputs' proc

   - 'numeric_check_string_double' - called by proc 'read-file_write-file'

   - 'popup_msgVarWithScroll'   - called by the 'Help' button.


A fervent hope

It is my hope that the copious comments in the code might help Tcl-Tk coding 'newbies' get started in making GUI's like this.

Without the comments --- especially in the 'read-file_write-file' proc and in the various 'check' procs --- the code might look much more cryptic.

Without the comments, potential young Tcler's might be tempted to return to their iPhones and iPads and iPods --- to look for videos of TV news organizations interviewing politicians and their 'surrogates' and their 'experts' --- and asking them questions for which we all know the (useless) answers.

Examples:

  1. TV Interviewer Question:
    Don't you think your man is a mysoginist for doing yada-yada-yada?

    Surrogate #1's Answer:
    Why not at all, Anderson. Our man is a broad-shouldered champion of women's rights. Yada, yada yada.

    Surrogate #2's Answer:
    (ignoring the question completely and launching into a well-rehearsed attack on the opponent)
    Anderson, our man's opponent is a criminal who should be in jail. After all, she has yada-yada-yada.

  2. TV Interviewer Question:
    Don't you think your woman has endangered national security by doing yada-yada-yada?

    Surrogate #1's Answer:
    Why not at all, Anderson. Our woman has stone-walled ... I mean answered ... such questions in multiple hearings before Congress. Yada, yada yada.

    Surrogate #2's Answer:
    (ignoring the question completely and launching into a well-rehearsed attack on the opponent)
    Anderson, our woman's opponent is a criminal who should be in jail. After all, he has yada-yada-yada.

Potential Tclers:

When you get tired of looking at devoid-of-common-sense-TV-interviews with-politicians-and-the-like, try installing-using-changing-enhancing the following Tk GUI script.

To help out in making scripts like this, here is a page that provides sources of Tcl-Tk code snippets by providing links to various 'tkGooies' scripts that can make it relatively quick work to compose

  • widget definitions,
  • bind statements, and
  • procedure code.

And when you get to the testing-and-debugging phase of development of a script, here is a page that describes the wonderfulness of the 'wish' 'stack trace' facility, which can make the testing-and-debugging go relatively quickly and painlessly.


The Tk Script CODE

Here is a link to CODE for the Tk script

'tkReadOutlineFile_ WriteFilteredFile.tk'.

With your web browser, you can 'right-click' on this link --- and in the menu that pops up, select an item like 'Save Link Target As ...' --- to save this file to your local computer.

Then you can rename the file to remove the '.txt' suffix.

Make sure that you have execute permission set on the file --- in order to execute the script.

Some possible FUTURE ENHANCEMENTS

There are some enhancements that could be considered for this script, such as:

  1. Allow for specifying the text-editor to use --- on the GUI :

    An entry field could be added to the GUI, to allow the user to enter a command-name --- to use a text-editor of the user's choice --- and to allow for switching to another text-editor.

  2. Allow for specifying an output filename --- on the GUI :

    An entry field could be added to the GUI, to allow the user to enter a (fully-qualified) filename to use for the output file.

Speaking of enhancements, I may make some changes to the way that the Xmin, Xmax, Ymin, Ymax entry fields are initialized and used --- as I use this outline-file-reducing 'tkGooie' to create sample outline-data-files (from bigger outline data files) that I generate and post on the Outline Data Sources page.

You can check back, on occasion, to see whether I have changed the code for this 'tkGooie' (at the code-link above).

I usually document changes, in 'Changed by:' lines at the bottom of the top (big) comments section at the top of the Tk script.

That is a quick way to see if I have changed the script.

---

The bottom line here is that there are almost always enhancements that could be made to (or 'forks' that could be made from) a Tk GUI 'app' like this.

One advantage of this Tk script is that it is 'open' code --- available to anyone for enhancement.

So if you would like to take a different approach to implementing this script, you are welcome to take this code and build on it (or reconstruct it).


IN CONCLUSION

As I have said on other code-donation pages on this site ...

There's a lot to like about a utility that is 'free freedom' --- that is, no-cost and open-source so that you can modify/enhance/fix it without having to wait for someone else to do it for you (which may be never).

A BIG THANK YOU to Ousterhout for starting Tcl-Tk, and a BIG THANK YOU to the Tcl-Tk developers and maintainers who have kept the simply MAH-velous 'wish' interpreter going.

Bottom of this web page that
presents Code for
'tkReadOutlineFile_ WriteFilteredFile'

--- a Tk script 'app'
in the FE 'tkGooies' system,
in the 'MAPtools' group.

To return to a previously visited web page location, click on the Back button of your web browser a sufficient number of times. OR, use the History-list option of your web browser.
OR ...

< Go to Top of Page, above. >

Page history:

This FE web page was created 2016 Nov 29.

Page was changed 2019 Feb 22.
(Added css and javascript to try to handle text-size for smartphones, esp. in portrait orientation.)

Page was changed 2019 Jun 26.
(Specified image widths in percents to size the images according to width of the browser window.)


This code may someday be posted in a page on the Tcler's Wiki ---
wiki.tcl.tk. If I do that, I will put a link to the page here.