Pascal Dynamic Libraries: More Than You Want To Know
Part 3: Pascal for GIS
Contents
Introduction
What's Included
Setting Up
Testing the GDAL unit
SwiftCast: Using a Pascal library and Bing Maps in a Swift app
AspCast: Using a Pascal library in a DotSpatial ASP.NET Web app
PyCast: Using a Pascal module with a Python plugin for QGIS
PasCast: Using a Pascal library with Lazarus GIS controls
QxCast: Using a Pascal library and OpenStreetMap in a qooxdoo Mobile Web app
BoxCast: Using a Pascal library and Mapbox GL in a Web app
Future topics and to-do list
Introduction
These notes describe the current status of the Pascal for GIS toolkit. They
assume that you know something about GIS. If you're just starting out with GIS,
you may find that browsing an online resource like this will be helpful:
GIS (geographic information system)
Pascal has never been relevant in the world of GIS; nor is that situation likely
to change. Historically the primary language of GIS has been
C++ for the low-level libraries and the GIS application itself, supplemented
by Python for writing scripts that utilize the libraries and for developing
plugins that extend the GIS app. In recent years, C# has emerged as a language
for doing both the low- and high-level stuff with the same language.
Nevertheless, that doesn't mean you can't use Pascal with GIS. Here are a few
examples of where Pascal might make sense:
- A Pascal console app that uses a geoprocessing library. Or add this
capability to an existing Pascal app.
- A Pascal library that can be called from a .NET/Mono GIS.
- A Pascal module that can be called from a Python plugin for a GIS.
- A Swift app that uses Apple's Map Kit framework and a Pascal
library on OS X.
- An Objective Pascal app that displays a map in a WebView
browser control on OS X.
Typically you would use Pascal for parts of these tasks to take advantage of existing
Pascal code that you don't want to rewrite in one or more other languages. Note that if you
put your Pascal code into a compiled library, you can use it with code written
in virtually any language (C, C#, Python, even Swift), meaning you only have
to write it once to use with multiple GIS tools.
What's Included
The Pascal for GIS toolkit includes units and example code for working
with several of the GIS tools listed below. The examples range from do-it-yourself
without mapping (testgdal), to a simple map with basic pan and zoom (SwiftCast
and QxCast), to a clickable but read-only map (AspCast), to a clickable
read-write map (PyCast and PasCast). The primary focus is Mac OS X, but several
of the examples can be tested on Windows and Linux too. The Free Pascal compiler
is assumed throughout, but Delphi can generally be used as well on Windows.
GIS library, app or service |
URL |
Description |
Version tested |
Pros |
Cons |
GDAL |
www.gdal.org |
Geospatial Data Abstraction Library; reads and writes virtually any format
raster or vector file. |
1.11 |
Windows, OS X, Linux; well-documented; includes many useful command-line
utilities; most open-source GISs include or depend on this library; X/MIT license. |
Might be a bit bulky to include with your own app; stable version is
out-of-date with some Linux releases. |
SAGA GIS |
sourceforge.net/projects/saga-gis |
Great number-crunching GIS with some highly specialized modules. |
|
Windows, OS X, Linux; script or shell to SAGA's command-line program to do
just about anything the UI can do; uses its own raster file format that can
be directly read and written by Pascal; includes GDAL; LGPL license for libraries. |
Includes clumsy desktop GIS based on wxWidgets; requires wxWidgets even
for command-line program; poorly documented. |
DotSpatial |
dotspatial.codeplex.com |
.NET assemblies for building a Windows.Forms-based desktop GIS or an ASP.NET Web app. |
1.7 trunk |
Windows, OS X, Linux; full download includes
GDAL binaries for Windows; has start of Cocoa map controls using MonoMac;
LGPL license. |
Windows.Forms-based UI works best only on Windows; although 100% C#, some
plugins depend on native libraries (eg, GDAL). |
QGIS |
qgis.org |
Popular GIS that's great for ad hoc use. |
2.8 |
Windows, OS X, Linux; easily extended with Python plugins; Qt-based
GIS interface looks good on all platforms; includes Qt, GDAL, SAGA and,
on Windows, Python. |
GPL license for libraries, meaning any QGIS plugin you write must also be GPL;
enormous installation footprint; documentation not always up-to-date. |
Map Kit framework |
References for OS X
and iOS |
Apple's embeddable mapping interface for OS X and iOS. |
|
Provides same look and feel as Apple's Maps app; now a standard framework
on both iOS and OS X; no longer depends on Google map services; well-documented. |
Only available on Apple platforms; requires enrollment in
Mac Developer Program; not really a GIS per se. |
Google Maps, Bing Maps, Apple Maps, OpenStreetMap |
https://www.google.com/maps
http://www.bing.com/maps
http://www.openstreetmap.org |
Services for supplying aerial imagery and other GIS layers for Web pages
and Internet-aware GIS apps. |
Bing 6.2, OpenLayers 2.13 |
Can be used with any Web browser app or control; good way of eliminating need
for local copies of aerial photos for a GIS; handy for simple mapping. |
Unless imagery cached, requires Internet connection; may be some
restrictions on use in an app; not really a GIS per se. |
Setting Up
- Free Pascal compiler
Install the latest stable version.
freepascal.org
- Pascal for GIS source code
All example code mentioned in this article is available here:
p4g.zip
Change log is here: p4g-changelog.txt
If you haven't already done so, you'll probably want to review
Part 1 and Part 2
of the Pascal Dynamic Libraries articles, which explain the library-related code.
- GIS libraries and apps
Install the GIS libraries and apps listed in the table above that you're interested in.
Tip: If you install QGIS, you also get the GDAL library,
the SAGA command-line program and libraries, and Python (the latter Windows-only;
OS X and Linux already have Python installed).
- Sample data
This toolkit does not include sample data except for what's included with the
examples. If you need more, download the classic Spearfish dataset from here:
grass.osgeo.org/download/sample-data
Tip: Use this Web site to zoom in on any location in the USA and
clip out and download GIS layers for up to 10,000 acres. Included in the
downloaded zip file will be soil and watershed shapefiles (vector data)
as well as an elevation data file, aerial photo and topographic map (raster data):
clipper.missouri.edu/index.asp
Testing the GDAL unit
The GDAL library has a C interface, so you'll need to parse GDAL's
header files (.h) before you can use GDAL with Pascal. Some of this has already
been done for you and is included as the GDAL unit in the Pascal for GIS
source.
Obtaining the GDAL library
To obtain the GDAL library on Windows, just install SAGA GIS, DotSpatial or
QGIS as these all include GDAL. You can also download GDAL from here:
http://www.gisinternals.com
To obtain the GDAL library on OS X, there are two options:
- Download the "GDAL Complete" .dmg from here:
http://www.kyngchaos.com/software/frameworks
This .dmg installs GDAL and several other frameworks (PROJ, GEOS, etc.)
into /Library/Frameworks.
Note that these frameworks are required for QGIS on OS X and can also be used
with SAGA GIS and DotSpatial on OS X. Note that the frameworks
are all universal, meaning they can be used with both 32- and 64-bit apps.
- Build GDAL yourself.
- Download the GDAL .tar.gz file from here:
http://www.gdal.org
- Unzip in its own directory, then in that directory enter:
./configure
make
This creates a 64-bit libgdal.1.dylib (and libgdal.dylib symlink) in .libs
subdir, ready for installing (optional) in /usr/local/lib with:
make install
- However, since Mono is currently 32-bit only on Mac, you can do this instead:
./configure CFLAGS="-Os -arch i386 -arch x86_64" CXXFLAGS="-Os -arch i386 -arch x86_64" LDFLAGS="-arch i386 -arch x86_64"
make clean
make
This creates a universal library. If you need only a 32-bit library,
just omit the x86_64 switches.
Build the PROJ library too (if you need to reproject spatial data).
Testing the GDAL library
To test the GDAL unit with the GDAL library, change to the directory where
the GDAL unit source files and testgdal.pas are located. This simple
console app can be used to display a few bits of information about virtually
any vector or raster data file.
Note that depending on what version of the GDAL library you want to test,
you may need to edit GDAL.pas and specify the library name
to use with Windows if it's different from the default (gdal111.dll).
To test the app with the GDAL library on OS X, do one of the following:
- If you built and installed GDAL to /usr/local/lib as described above,
you don't need to do anything.
- If you built GDAL above, but did not install it, copy libgdal.1.dylib
to where testgdal.pas is located, then enter this:
mv libgdal.1.dylib libgdal.dylib
install_name_tool libgdal.dylib -id ./libgdal.dylib
- If you installed the GDAL framework and want to use it instead of the library,
compile with the -dGDAL_FRAMEWORK switch to link against the GDAL framework
instead of the library.
Now compile the testgdal app:
ppc386 testgdal
Note that if you have only the 64-bit GDAL library, you'll need
to compile testgdal.pas with ppcx64 (OS X) or ppcrossx64 (Windows).
On OS X, you can see what the executable is linked against as follows:
otool -L testgdal
To test the app with the GDAL library on Windows, you'll need a path to the GDAL
library. For example, to use QGIS's GDAL library with the test app, enter this
in a batch file:
setlocal
set PATH=C:\Program Files (x86)\QGIS\bin;%PATH%
testgdal %1%
Run the app and specify a vector or raster file to examine. Examples:
On OS X: ./testgdal someshapefile.shp
On Windows: testgdal.bat somegridfile.asc
Testing the GDAL and PROJ libraries
If the GDAL library can find the PROJ library, you can also use the GDAL
transformation (projection) functions. The testshapes.pas console app is
supplied for testing these functions.
On OS X, compile the testshapes app like this:
ppc386 -Fu../ndfd testshapes
To use the GDAL and PROJ frameworks instead of the libraries, include the
-dGDAL_FRAMEWORK switch.
On Windows, compile the testshapes app like this:
ppc386 -Fu..\ndfd testshapes
When run, testshapes will create the locations shapefile used in the PasCast
example below.
SwiftCast: Using a Pascal library and Bing Maps in a Swift app
SwiftCast is an example app for OS X that shows how to:
- Use a Pascal library in a Swift app. Specifically it uses the ndfd library
and its Swift wrapper class from Part 2
of Pascal Dynamic Libraries to retrieve weather forecast data.
- Use a WebView control in a Swift app as an embedded Web browser.
- Load a local HTML file containing a bit of JavaScript
that displays a map of forecast data using Bing Maps.
A screenshot of SwiftCast is here: SwiftCast.jpg
To try out SwiftCast, you have two options:
- Open SwiftCast.xcodeproj in Xcode and choose Product | Run. Make sure
you've compiled the ndfd library beforehand.
- Download SwiftCast.dmg from here: SwiftCast.dmg
Double-click SwiftCast.dmg. Or control-click it and choose Open.
A screenshot of the SwiftCast project in Xcode is here:
SwiftCast-Xcode.jpg
Notes on SwiftCast:
- SwiftCast loads file viewForecast.bing.6.2.html into its WebView
control. This file's JavaScript code uses version 6.2 of Bing Maps.
One drawback to version 6.2 is
that it doesn't appear to have a way to label points on the map directly.
Instead, you position the mouse over a location's pushpin and its label
will pop up. Bing 7.0 has a way to label
points directly, but 7.0 requires signing up for a developer account
to use it. Google Maps could also be used. To use a different mapping
service, just replace JavaScript functions showMap and showLocation,
which look like this for Bing 6.2:
function showMap(lat, lon) {
map = new VEMap('map');
map.LoadMap(new VELatLong(lat, lon), 10, VEMapStyle.Road, false);
}
function showLocation(lat, lon, location, forecast) {
var point = new VELatLong(lat, lon);
var pin = new VEShape(VEShapeType.Pushpin, point);
pin.SetTitle(location);
pin.SetDescription(forecast);
map.AddShape(pin);
}
- SwiftCast loads a local copy of an HTML file into its WebView control,
looking for it in its Resources folder using this bit of code:
let htmlPath = Bundle.main.resourcePath! + "/viewForecast.bing.6.2.html"
But there's no reason why this file couldn't be loaded by specifying an
https:// location. That would allow you to update the HTML that's loaded
without needing to update the app itself.
- Several of the default menus that Xcode's template adds to a new app
are not relevant to a simple app like SwiftCast. However, these menus
have been left alone in case someone wants to extend SwiftCast,
for example, to support loading a file containing locations and lat/lon
coordinates rather than just using the app's hard-wired locations.
Adding the ndfd library to an Xcode Swift project is fairly straightforward:
AspCast: Using a Pascal library in a DotSpatial ASP.NET Web app
AspCast is an example app for .NET and Mono that shows how to:
- Use a Pascal library in an ASP.NET Web app. Specifically it uses the
ndfd library and its C# wrapper class from Part 2
of Pascal Dynamic Libraries to retrieve weather forecast data.
- Use the DotSpatial assemblies to add GIS functionality to the Web app.
- Display a clickable map using Bing Maps; clicking on the map displays
the forecast for that point; pan and zoom to any place in the U.S.
A screenshot of AspCast is here: AspCast.jpg
To try out AspCast, you have several options. Be sure to copy the required
DotSpatial assemblies, the ndfd native library and its interop assembly
as described below.
- Open AspCast.sln in Xamarin Studio on Mac or Windows and choose
Run | Run With | Mono Soft Debugger for ASP.NET.
- If you have Visual Studio, you can also open and run AspCast.sln there.
- The MonoDevelop IDE should also work (eg, on Linux), but this
has not been tested.
- If you don't have any of these IDEs installed, just compile AspCast from
the command line (enter this one level up from the refs subfolder):
xbuild
(With .NET on Windows, use msbuild.)
- Note that once you've compiled AspCast, you can also start it from the
command line with Mono's XSP server (enter this one level up from the
refs subfolder):
xsp4
Then enter this in a browser:
http://localhost:8080
A screenshot of the AspCast project in Xamarin Studio is here:
AspCast-XamarinStudio.jpg
Notes on AspCast:
- ASP.NET apps sometimes get shut down immediately when run with
Xamarin Studio's Mono Web server on Windows. If this happens,
try running AspCast with a different Web server, such as IIS Express.
- AspCast works fairly well in Safari on an iPad too, with the
exception of panning the map, which conflicts with normal scrolling
within the browser.
Creating a DotSpatial ASP.NET app is fairly straightforward:
- In Xamarin Studio, choose File | New | Solution, then under C#, select
ASP.NET and ASP.NET Project.
- You can immediately test this simple app by choosing Run | Run With |
Mono Soft Debugger for ASP.NET. This will start the app and launch a
Web browser. When done, choose Run | Stop.
- Now choose File | New | File and, under Misc, select Assembly Information.
This will create a file where you can enter version and copyright info.
- If you'll be adding any custom buttons to the app's eventual toolbar,
create a subfolder named Images (or something similar).
- If you'll be displaying any shapefiles in the app, create a subfolder
named Layers (or something similar).
- Create a subfolder named refs (or something similar). Copy the DotSpatial
assemblies to the refs subfolder. Where to get these assemblies?
For convenience so you don't have to build them yourself, you can
download pre-built assemblies from here:
DotSpatial_p4g.zip
- If you'll be using any "unmanaged" native libraries, copy them into the
main folder (where Default.aspx is) on OS X or into the bin subfolder
on Windows. For example, copy the ndfd library (previously compiled elsewhere).
- Copy any native libraries' interop assemblies into the refs folder.
For example, copy Ndfd.Interop.dll (previously compiled elsewhere).
- Create ImageHandler.ashx and ImageHandler.ashx.cs files for the app.
These are simple files; look at AspCast's for examples. Be sure to
include them in the project by right-clicking on the Solution panel
and choosing Add | Add Files.
- Add legend, toolbar and map controls to Default.aspx and corresponding
code to Default.aspx.cs. See AspCast for example code.
PyCast: Using a Pascal module with a Python plugin for QGIS
PyCast is an example plugin for QGIS that shows how to:
- Use a Pascal library with Python. Specifically it uses the ndfd library
and its compiled module and Python wrapper class from Part 2 of
Pascal Dynamic Libraries to retrieve weather forecast data.
- Display forecasts for points in a layer in the supplied PyCast.qgs project;
pan and zoom to any place in the U.S. and add points to this layer.
- Display a background map with the QGIS OpenLayers plugin; the PyCast.qgs
project uses Apple Maps.
A screenshot of PyCast is here: PyCast.jpg
To try out the PyCast plugin, follow these steps to add it to QGIS:
- Install the OpenLayers plugin. In QGIS, choose Plugins | Manage and
Install Plugins.
- Copy the PyCast folder to QGIS's plugins folder. On OS X, plugins are
installed under:
~/.qgis2/python/plugins
On Windows, QGIS plugins are installed under:
\Users\yourname\.qgis2\python\plugins
- Compile the ndfd library and its Pascal module, then copy these two
binary files into the PyCast folder (that you created under plugins).
QGIS uses Python 2.7.x, so don't use the Python 3 module; also, be sure
to copy the 32-bit library and module with 32-bit QGIS or the 64-bit
library and module with 64-bit QGIS (on Mac, QGIS is only 64-bit, so
both the 64-bit and "fat" binaries will work).
- On OS X, fix up the library and module so the module can find and load
the library:
install_name_tool libndfd.dylib -id @loader_path/libndfd.dylib
install_name_tool ndfdmod.so -change ./libndfd.dylib @loader_path/libndfd.dylib
- In QGIS, choose Plugins | Manage and Install Plugins, then
check the PyCast plugin to enable it.
- Choose Web | PyCast to see the PyCast commands; there's also a
PyCast button on the toolbar.
- Finally, in QGIS, choose Project | Open and select the PyCast.qgs project
in the PyCast_Example folder. Now follow the PyCast help.
A screenshot of a PyCast source file in TextWrangler is here:
PyCast-TextWrangler.jpg
Notes on PyCast:
- Typically QGIS plugins are installed in a submenu under one of the standard
program menus, so the PyCast plugin is installed under the Web menu
along with the OpenLayers plugin.
- QGIS plugins are usually downloaded and installed automatically via
the plugin manager, but since PyCast requires two binary files that
you need to build, it isn't currently distributed that way.
- Sometimes OpenLayers maps don't fully download and a few tiles may be
blank. You can usually remedy this by choosing View | Refresh or
panning the map a little bit to force the tiles to be reloaded.
Creating a Python plugin for QGIS involves several tools. Since the Python
source for all plugins is included, you might find it easier just to adapt
an existing plugin or learn how to write a plugin by reviewing the code of
PyCast or other plugins. However, you can also follow these steps to create
a simple plugin that will be installed under the Plugins menu:
- Install the Plugin Builder plugin in QGIS and use it to create the
rudiments of a new plugin.
- Use Qt Designer to design a dialog box for your plugin.
- Convert the .ui file created by Qt Designer to Python code with the
pyuic4 utility included with QGIS. See the example comp-ui.sh script
included with PyCast.
- Convert icons and other resources to Python code with the pyrcc4 utility
included with QGIS. See the example comp-qrc.sh script included with PyCast.
- Use a text editor or Python IDE to add code to your plugin and edit
the plugin's metadata.txt file.
QGIS API documentation is here: http://www.qgis.org/en/docs/index.html
PasCast: Using a Pascal library with Lazarus GIS controls
PasCast is a cross-platform example app for Lazarus that shows how to:
- Use a Pascal library in a Lazarus LCL app. Specifically it uses the
ndfd library and its Pascal wrapper class from Part 2 of Pascal Dynamic
Libraries to retrieve weather forecast data.
- Use the P4G_Ctrls GIS controls for Lazarus.
- Display a clickable map of image and vector layers.
A screenshot of PasCast is here: PasCast.jpg
To try out PasCast, you have two options:
- Open pascast.lpi in Lazarus and compile it. Make sure you've first followed
the steps in the PasCast folder's ReadMe.txt file to set up PasCast's
dependencies in Lazarus.
- With OS X, you can download PasCast.dmg from here: PasCast.dmg
Double-click SwiftCast.dmg. Or control-click it and choose Open.
A screenshot of the PasCast project in Lazarus is here:
PasCast-Lazarus.jpg
Notes on PasCast:
- The downloadable PasCast.dmg's app bundle includes all of the layer files
PasCast needs, as well as its own copies of the GDAL, PROJ and ndfd
libraries, so you don't need to install anything else to run it.
- After compiling PasCast, Lazarus will attempt to run the fixlazbundle.sh
script to fix up the PasCast.app bundle on OS X. This script is not
needed on other platforms and will fail with an error message in the
build log. You can ignore this message on other platforms.
- PasCast displays a map of an area of southwestern Colorado. While the
area is not large geographically as weather forecasts go, it does have
dramatic changes in elevation (>1000m). When you click around on the map
to get a forecast, you would expect the forecast to change, but it
mostly doesn't, suggesting that the NDFD forecast model does not fully
account for local elevation differences.
Using the P4G_Ctrls GIS controls with Lazarus is fairly straightforward:
Lazarus documentation is here: http://www.lazarus-ide.org
QxCast: Using a Pascal library and OpenStreetMap in a qooxdoo Mobile Web app
QxCast is a mobile Web app that shows how to:
- Use a Pascal library with a Pascal CGI server app. Specifically it uses the
ndfd library and its Pascal wrapper class from Part 2 of Pascal Dynamic
Libraries to retrieve weather forecast data.
- Use the qooxdoo JavaScript framework
for the client app.
- Develop both the client and server app projects with Lazarus and the
qxotica tools.
- Use the OpenLayers
JavaScript mapping library to display a map of forecast data.
A screenshot of QxCast is here: QxCast.jpg
To try out QxCast locally, first set up the getforecast server app.
The getforecast server app has no dependencies outside of Free Pascal and the
ndfd library's Pascal wrapper class, so just compile it and copy getforecast.cgi
and the ndfd library (previously compiled elsewhere) to the server app's folder
With IIS, you also copy getforecast's web.config file.
On Mac, the server app files go under /Library/WebServer/CGI-Executables.
On Windows, they go under C:\inetpub\wwwroot.
Now follow the steps for running the client app for the Unicodum demo app
here.
A screenshot of the QxCast client project in Lazarus is here:
QxCast-Lazarus.jpg
Notes on QxCast:
- See Part 4 for tips on deploying a
CGI app on an actual server (not just locally).
BoxCast: Using a Pascal library and Mapbox GL in a Web app
BoxCast is a Web app that shows how to:
- Use a Pascal library with a Pascal CGI server app. Specifically it uses the
ndfd library and its Pascal wrapper class from Part 2 of Pascal Dynamic
Libraries to retrieve weather forecast data.
- Use the Mapbox GL
Javascript library for the client app.
- Use the corslite
Javascript library to make AJAX calls to the server app.
A screenshot of BoxCast is here: BoxCast.jpg
To try out BoxCast locally, first set up QxCast's getforecast server app
(see notes above). Then open BoxCast's index.html file in a browser.
A screenshot of the boxcast.js client file is here:
BoxCast-TextWrangler.jpg
Notes on BoxCast:
- See Part 4 for tips on deploying a
CGI app on an actual server (not just locally).
- The qooxdoo framework used by QxCast above uses JSONP to work around
browser restrictions on cross-domain calls. Mapbox uses a newer
approach called CORS. With Apache,
this requires a small change to its httpd.conf file (in /etc/apache2).
With IIS, the web.config file deployed with getforecast.cgi
takes care of enabling CORS for the server app.
- To deploy the BoxCast client files, copy and place index.html,
boxcast.js and boxcast-config.js together. By default, boxcast-config.js
assumes the server app will be running locally
(http://localhost/cgi-bin/getforecast.cgi).
Edit the URL in this config file to call the server app on a remote server.
Mapbox GL is a powerful Javascript mapping library, but it can also be used
with Mapbox Studio, a Web-based tool for creating your own custom maps (called
styles).
In addition, you can create and use your own
vector tilesets
in Mapbox Studio by uploading zipped shapefiles and then associating the
resulting tilesets with layers in your custom map. You can also host your own
styles and tilesets on Mapbox and reference them in your Web apps.
You can try out Mapbox Studio for free by creating a Mapbox account.
Note that BoxCast uses a standard Mapbox style and does not use any tilesets
outside of what the standard map style uses (roads, satellite imagery, etc.).
Future topics and to-do list
- Create iSwiftCast example for iPad?
- Investigate GIS options for iOS?
Copyright 2015 by Phil Hess.
macpgmr (at) icloud (dot) com
First posted March 19, 2015; last edited June 10, 2017.