Title: WebBased Open Source GIS:
1 Web-Based Open Source GIS Decision Support
Tools Explaining the Software Stack Presented
by Aaron Racicot GIS Programmer aaronr_at_ecotrust
.org April 19th, 2006
A Citizen of Salmon Nation
2Outline
- Introduction Personal and Ecotrust
- Software Stack Desktop, Web, DST
- Workflow Dataflow
- Raster Tools Mapserver-gtGRASS
- Vector Tools Mapserver-gtPostGIS
- Glue AJAX, OGR/GDAL,
- Installation and tool selection
- Where is it all going?
3Who am I
B.S. Computer Science
M.S. Environmental Science
Open Source User/Developer GIS Programmer
Split Personality
4Ecotrust - Salmon Nation
5Software Stacks Desktop
Desktop Software Stack
6Software Stacks... Server
Server Software Stack
7Software Stack... DSTs (Ecotrust)
DST Software Stack
8Work Flow What OSGIS is good at
Real-Time Web Decision Support Tools
Web User Request
Web Services
Data Gathering
Data Formatting
Data Processing
Static Data Storage
Map Formatting
Map Production
The Problem Is The Arrows! Connecting a web
request to server side GIS analysis is tricky
Web User Response
9Data Flow... DSTs (Ecotrust)
10General PHP Mapscript
dl('php_mapscript.so') dl('php_proj.so') oMa
p ms_newMapObj(MAPFILE) // Set the data
directory oMap-gtset("shapepath",
session_tmp_dir."data") // Now we need to set
the save path and image URL to a session based
directory... oWeb oMap-gtweb oWeb-gtset("image
path",session_tmp_dir) oWeb-gtset("imageurl",se
ssion_tmp_dir) // Explode the x,y
extents box_coords explode(" ",
http_form_vars"imgbox") point_coords
explode(" ", http_form_vars"imgxy")
11PHP Mapscript - Zooming
// Check if the box is to small and we should
just use the x,y if ((abs(box_coords0 -
box_coords2) lt 5) (abs(box_coords1 -
box_coords3) lt 5)) zoomPoint( oMap,
ZOOMOUT_FACTOR, point_coords0,poi
nt_coords1 ) else zoomRectangle( oMap,
box_coords0, box_coords1,
box_coords2, box_coords3 )
12PHP Mapscript - Rendering
img oMap-gtdraw() url img-gtsaveWebImage()
oMap-gtscalebar-gtset("transparent",
MS_TRUE) img_scale oMap-gtdrawScaleBar() url
_scale img_scale-gtsaveWebImage() oMap-gtlegen
d-gtset( "template",
APP_PATH."legend_template.html" ) params
array() html_legend oMap-gtprocessLegendTempla
te(params) img_ref oMap-gtdrawReferenceMap()
url_ref img_ref-gtsaveWebImage() oMap-gtsav
e(session_tmp_dir."map_tmp.map")
13PHP Mapscript - Integration
ltapplet codebase"/java/jBox" archive"jBox.jar" c
ode"jBox.class" width"800" height"600" name"jB
ox" MAYSCRIPTgt ltparam name"image" value"lt?php
echo HOST_URL.url?gt"gt ltparam name"verbose"
value"true"gt lt/appletgt ltbrgt ltimg src"lt?php
echo HOST_URL.url_ref?gt" ALT"Ref"gt ltbrgt lttablegt
lt?php echo html_legend ?gt lt/tablegt
14Raster based DST
Siuslaw Watershed Restoration Initiative
Data Gathering
Data Formatting
Data Processing
PHP Mapscript
GRASS
15Raster based DST
PostgreSQL Type Interface for GRASS GIS
string host db_str usr_str connection
pg_connect(string) if (!connection)
pg_close(connection) echo "ErrorCannot
connect to databaseltbrgt" else echo
"Connected to the SCA database ltbrgt\n" res_pg
_exec pg_exec(connection,exec_str)
16Raster based DST GRASS Class
class Grass_GIS var data_dir // Where the
GRASS data dir is var rc_dir // Where the
GRASS rc dir is var bin_dir // Where the
GRASS bin dir is var location var mapset
function Grass_GIS(data_dir, rc_dir, bin_dir,
location, mapset) this-gtdata_dir
data_dir this-gtrc_dir rc_dir
this-gtbin_dir bin_dir this-gtlocation
location this-gtmapset mapset
function Grass_GIS_copy(grass_gis)
this-gtdata_dir grass_gis-gtdata_dir
this-gtrc_dir grass_gis-gtrc_dir
this-gtbin_dir grass_gis-gtbin_dir
this-gtlocation grass_gis-gtlocation
this-gtmapset grass_gis-gtmapset
function set_location(location)
this-gtlocation location function
set_mapset(mapset) this-gtmapset mapset
function set_data_dir(data_dir)
this-gtdata_dir data_dir function
set_rc_dir(rc_dir) this-gtrc_dir rc_dir
function set_bin_dir(bin_dir) this-gtbin_dir
bin_dir
function run_command(cmd) std_output
"" grass_exec "" // Check that all
the required info is available.. if
(this-gtdata_dir ! NULL this-gtrc_dir ! NULL
this-gtbin_dir ! NULL this-gtlocation !
NULL this-gtmapset ! NULL) // Here we will
write out the script to run... fp_data
fopen(this-gtdata_dir."/grass_run.sh","w") //
write out text header fwrite(fp_data,"export
GISBASE".this-gtbin_dir." \n") fwrite(fp_data,
"export GISDBASE".this-gtdata_dir."
\n") fwrite(fp_data,"export GISRC".this-gtrc_d
ir."/.grassrc6 \n") fwrite(fp_data,"export
ETC".this-gtbin_dir."/etc \n") fwrite(fp_data,
"export PATH".this-gtbin_dir."/bin".this-gtbin_d
ir."/scripts".this-gtbin_dir.
"/garden/bin\PATH/usr/bin/usr/local/bin/
\n") fwrite(fp_data,"export LOCATION_NAME".th
is-gtlocation." \n") fwrite(fp_data,"export
MAPSET".this-gtmapset." \n") fwrite(fp_data,"e
xport LOCATION".this-gtdata_dir."/".this-gtlocati
on."/".mapset." \n") fwrite(fp_data,"\n") fw
rite(fp_data,cmd."\n") fflush(fp_data) fclo
se(fp_data) fp_data fopen(this-gtrc_dir."/.g
rassrc6","w") fwrite(fp_data,"GISDBASE
".this-gtdata_dir."\n") fwrite(fp_data,"LOCATIO
N_NAME ".this-gtlocation."\n") fwrite(fp_data,
"MAPSET ".this-gtmapset."\n") fwrite(fp_data,"
PAINTER ppm\n") fwrite(fp_data,"MAPLP
stuff.ppm\n") fflush(fp_data) fclose(fp_data
) grass_exec sprintf("chmod ux
".this-gtdata_dir."/grass_run.sh") exec(grass_e
xec,std_output,std_error)
grass_exec sprintf(this-gtdata_dir."/grass_run.
sh") exec(grass_exec,std_output,std_error)
17Raster based DST PHP GRASS
define("GRASSDATA_DIR", "/var/www/html/apps/siusla
w_target/data/GRASSDATA/") location_name
"OR_siuslaw mapset_name "land_targets sess
ion_grass_dir session_tmp_dir."/GRASSDATA" //
Make a Dir to work in echo " Make a directory to
work in inside this sessionltbrgt" dir_exec
sprintf("mkdir ".session_grass_dir) exec(dir_ex
ec,arr,err1) dir_exec sprintf("mkdir
".session_grass_dir."/rc") exec(dir_exec,arr,
err1) template_path GRASSDATA_DIR."siuslaw_
epa_template" echo " Copying over new GRASS GIS
templateltbrgt" dir_exec sprintf("cp -R
".template_path." ".session_grass_dir."/".locat
ion_name) exec(dir_exec,arr,err1) // Make a
MAPSET echo " Setting up the siuslaw specific
arealtbrgt" dir_exec sprintf("mkdir ".
session_grass_dir."/".location_name."/".mapset_n
ame) exec(dir_exec,arr,err1) // Copy
over the projection info from the PERMANENT
area echo " Setting projectionsltbrgt" dir_exec
sprintf("cp ".template_path."/PERMANENT/PROJ
". session_grass_dir."/".location_name."/".maps
et_name."/") exec(dir_exec,arr,err1)
grass_session new Grass_GIS(session_grass_dir
, session_grass_dir."/rc",
"/usr/local/grass-6.0.0", location_name,
mapset_name) grass_session-gtrun_command("g.list
typerast")
18Raster based DST AMLlt-gtGRASS
arr grass_session-gtrun_command("g.region
rastowng_grass_at_PERMANENT") echo "ltbgtStarting
to process the Siuslaw datalt/bgtltbrgt\n" //AML
step //AH2 (ah_idx 1) 10 echo " Creating
ah2_idx_grass... anchor habitat priorities
ltbrgt\n" arr grass_session-gtrun_command("r.m
apcalc ah2_idx_grass \(\(ah_idx_grass_at_PERMANENT
1\)10\)") //AML step //own_idx con(owng eq
31, 40,con(owng eq 83,30,con(owng eq 95,10,20)))
echo " Creating own_idx_grass... ownership
prioritiesltbrgt\n" arr grass_session-gtrun_co
mmand("r.mapcalc own_idx_grass
if\(owng_grass_at_PERMANENT31,40,".
"if\(owng_grass_at_PERMANENT8
3,30,if\(owng_grass_at_PERMANENT95,10,20\)\)\)") /
/AML step //reclass tpa (use slice) and setnull
trees younger than 15 years //veg_idx
setnull(age_g lt 15, slice(tpa_g,eqarea,40))
echo " Reclasification of tpa_g... to
0-40ltbrgt\n" arr grass_session-gtrun_command(
"r.rescale.eq inputtpa_g_grass_at_PERMANENT ".
"outputtpa_rescale to0,40") echo " Creating
the veg_idx... trees over ".tpa_age." years of
ageltbrgt\n" arr grass_session-gtrun_command("
r.mapcalc veg_idx_grass ".
"if\(age_g_grass_at_PERMANENT\gt".tp
a_age.",tpa_rescale,null\(\)\)") //AML
step //FING setnull(rip_stab eq 0, (ah2
veg_idx own_idx ..\infra\rd_d_inv)) echo "
Creating FING... the sum of ah2_idx_grassown_idx_
grassveg_idx_grassrd_d_inv_grassltbrgt\n" arr
grass_session-gtrun_command("r.mapcalc
fing_grass ".
"if\(rip_stab_grass_at_PERMANENT0,null\(\),".
"\(ah2_idx_grassown_idx_grassveg_idx_grassrd_d_
inv_grass_at_PERMANENT\)\)")\
19Raster Example TREESystem
Mapserver on the front end
GRASS on the back end
Web-based Query
20Raster based DST - Mapfile
LAYER NAME "Fishery Rev" STATUS
DEFAULT DATA "./GRASSDATA/CAL_ocean2/FISHERY/c
ellhd/fishery_rast_rev_zone_8bit" TYPE
RASTER PROJECTION "projaea"
"datumNAD27" "ellpsclrk66"
"lat_134" "lat_240.5"
"lat_00" "lon_0-120" "x_00"
"y_0-4000000" "unitsm" END
END
21Vector based DST
PHP -gt PHPMapscript -gt PostGIS
PostGIS
Mapserver
22Vector based DST - Database
// Now connect to the db host_str
"hostlocalhost" db_str "dbnameshelf_closure_
db" usr_str "userweb_user" string
host_str." ".db_str." ".usr_str connection
pg_connect(string) if (!connection)
pg_close(connection) echo "Error Cannot
connect to the database ltbrgt\n" else echo
"Connected to the SCA database ltbrgt\n" //
Create a dynamic VIEW in PostGIS echo "ltbgt
Create postgresql VIEW lt/bgtltBRgt\n" exec_str
sprintf("CREATE VIEW ". previous_session_name.
"_".previous_session_id." AS ". "SELECT
bk.the_geom, sum(tr.total_lbstb.percent) as
total_lbs ". "FROM tow02d_3kblk_intersect as
tb, trawl02d". " as tr, cablk3km as bk, port
as pt ". "where tb.blk_gidbk.gid
".species_sql." ".port_sql." ".gear_sql. "
and tb.tow02d_idtr.tow_id2 ". "GROUP BY
bk.the_geom HAVING count(tr.tow_id2)gt2",
start_year_short,start_year_short,start_year_sh
ort) result_pg_exec pg_exec(connection,
exec_str) if (!result_pg_exec)
printf("ltBgtslt/BgtltBRgt\n", pg_errormessage())
23Vector based DST Dump results
// Execute the pgsql2shp to create the
output echo "ltBgt Execute pgsql2shp create the
shapefile in session directory lt/Bgtltbrgt" dir_ex
ec sprintf("/usr/local/pgsql/bin/pgsql2shp -u
web_user -f ". session_tmp_dir."data/target_ar
eas/test_output.shp shelf_closure_db ".
"\"SELECT from ".previous_session_name."_".pre
vious_session_id."\"") exec(dir_exec,arr,err1)
for (ii0iiltcount(arr)ii) echo
arrii."ltbrgt\n" // Drop the dynamic
table echo "ltbgt DROP the postgresql VIEW
lt/bgtltBRgt\n" result_pg_exec pg_exec(connection
, "DROP VIEW ". previous_session_name."_".pr
evious_session_id) if (!result_pg_exec)
printf("ltBgtslt/BgtltBRgt\n", pg_errormessage())
24Vector Example - OCEANSystem
Shelf Closure mid-2002
Rockfish SFA - 2001
Rockfish SFA - 2003
25AJAX - Prototype
- function gotVariable(varName, varVal, showWait)
-
- // URL to send the AJAX request to
- var url 'http//boris.ecotrust.org/gulf_projec
t/core/SCA_Model/contents.php' - // Push the variable onto the array of parms
- var newVars new Array(varName,varVal)
- varStack.push(newVars)
- // Build the params for the URL request
- var pars ""
- for (var i0 iltvarStack.lengthi)
-
- if (i 0)
- pars pars varStacki0 ''
varStacki1 - else
- pars pars '' varStacki0 ''
varStacki1 -
- // Debug text
- var boldText document.createElement('b')
- var actionText document.createTextNode(varName
' ')
26AJAX - Prototype
- action_array array("0" gt "init_action",
- "Revenue by Species" gt
"process_rev_by_species", - "Revenue by Gear Type" gt
"process_rev_by_gear", - "Revenue Total" gt
"process_rev_by_total", - "Num Vessel Landings" gt
"process_num_vessel_landings", - "Distinct Vesseles" gt
"process_distinct_vessels", - "Average Rev Per Vessel" gt
"process_average_rev_per_vessel", - "Distinct Fishermen" gt
"process_distinct_fishermen", - "Distinct Species" gt
"process_distinct_species") - if (isset(http_form_vars"Action"))
-
- function_ret action_arrayhttp_form_vars"Act
ion"(connection, http_form_vars) -
- else
-
- // deal with the initial request
- echo "ltdiv id\"placeholder_select\"gt\n"
27AJAX - Prototype
- fwrite(fp_data, "palette(rainbow(".count(y_strin
g)."))\n") - fwrite(fp_data, "bitmap(\"species_revenue_".rand
_number.".png\", type \"png256\", height 2,
width 4, res 300)\n") - fwrite(fp_data,"plot(x,seq(min(".y_s."),max(".y
_s.")1.4,lengthlength(x)),type\"n\",xl
b\"Year\",ylab\"Revenue\")\n") - for (i1 iltcount(y_string) i)
-
- fwrite(fp_data,"lines(x,y_".i.",col".i."
)\n") - if (i1)
-
- fill_col i
-
- else
-
- fill_col fill_col.",".i
-
-
- fwrite(fp_data,"legend(xmin(x),ymax(".y_s.")1
.4,c(".species_s."),fillc(".fill_col."),
bg\"white\", ncol4)\n") - fwrite(fp_data,"title(\"Revenue plot for Species
Groups at Port Group ".port."\")\n") - fwrite(fp_data,"dev.off()\n")
- fflush(fp_data)
28GDAL/OGR Shapefile validity
- function check_valid_shapefile(shape_file_name)
-
- //echo "Checking that shapefile
".shape_file_name." is valid...ltbrgt\n" - valid TRUE
- duplicate FALSE
- importance_present FALSE
- name_temp array()
- // Here we need to check for the validity of
the shapefile - dir_exec sprintf("/usr/local/bin/ogrinfo -al
".shape_file_name) - exec(dir_exec,arr1,err1)
- for (iicount(arr1)-1 iigt0 ii--)
-
- if ((substr_count(arr1ii," Integer") gt
0) - (substr_count(arr1ii," Real") gt 0)
- (substr_count(arr1ii," String") gt
0)) -
- // Push them all onto an array
29GDAL/OGR Cont.
- for (ii0 ii lt count(name_temp) ii)
-
- for (iiiii1 iii lt count(name_temp)
iii) -
- if (name_tempiii
name_tempii) -
- // we have a duplicate
- duplicate TRUE
- duplicate_name name_tempii
-
- if (name_tempii "IMPORTANCE")
-
- importance_present TRUE
-
-
-
- if (duplicate TRUE)
-
3010 Step Tool Install
1) First install Fedora Core4 with updates 2)
Proj.4 tar -xzvf proj-4.4.9.tar.gz cd
proj-4.4.9 cd nad/ cp ../../proj-nad27-1.2.tar.gz
. tar -xzvf proj-nad27-1.2.tar.gz cd
.. ./configure make make install
3) GDAL Installed the ECW SDK (do a config, make
and install) Installed the MrSid SDK (moved to
/usr/local) wget http//gdal.org/dl/gdal-1.3.1.tar
.gz tar -xzvf gdal-1.3.1.tar.gz cd
gdal-1.3.1 ./configure --with-ecw --with
mrsid/usr/local/GeoExpressSDK/ make ogr-all make
install which gdalinfo 4) GEOS wget
http//geos.refractions.net/geos-2.2.1.tar.bz2 tar
-xjvf geos-2.2.1.tar.bz2 cd geos-2.2.1 ./configur
e make make install
3110 Step Tool Install
5) POSTGRESQL tar -xzvf postgresql-8.1.2.tar.gz cd
postgresql-8.1.2 NOTE the LDFLAGS here... this
is to support GEOS for postGIS LDFLAGS-lstdc
./configure --with-perl --prefix/usr/local/pgsql_
8_1_2 gmake gmake install Add the shared library
path to /etc/ld.so.conf /usr/local/pgsql_8_1_2/l
ib Run /sbin/ldconfig Finally add the following
to the profile file to make paths
available PATHPATH/usr/local/pgsql/bin MANPATH
MANPATH/usr/local/pgsql/man export MANPATH Add
the postgis user useradd postgis passwd postgis_at_l
ocalhost pgsql postmaster -D ./data/ gt
./data/logfile.txt 2gt1
6) POSTGIS Just make sure that the Postgresql is
configured with the LDFLAGS variable set and that
the GEOS software is downloaded and installed
from Refractions. ./configure --with-proj
--with-geos --with-pgsql make make install Now we
can create the database createdb -O aaronr
test_db createlang -U aaronr plpgsql test_db psql
-f /usr/local/pgsql_8_1_2/share/postgresql/
contrib/lwpostgis.sql -d test_db
3210 Step Tool Install
7) PHP ./configure --prefix/usr/local/php4
--program-suffix4 --enable-force-cgi-redirect
--with-config-file-path/etc/httpd/
--with-gd/usr/local/ --with-jpeg --with-png
--with-tiff --with-zlib --with-freetype-dir
--without-ttf --with-mysql --with-regexsystem
--enable-dbase --enable-dbx --enable-versioning
--with-pgsql/usr/local/pgsql_8_1_2/ make make
install strip sapi/cgi/php cp sapi/cgi/php
/var/www/cgi-bin/php4 cp php.ini-dist
/etc/httpd/php.ini Made the following mod to
/etc/httpd/php.ini Directory in which the
loadable extensions reside. extension_dir
"./" extension_dir "/etc/httpd/php_mods" mkdir
/etc/httpd/php_mods Added the following to
/etc/httpd/conf/httpd.conf For PHP scripts as
CGI-BIN AddType application/x-httpd-php-cgi .php4
.phtml Action application/x-httpd-php-cgi
/cgi-bin/php4 Now re-start the server /etc/rc.d/i
nit.d/httpd restart Stopping httpd
OK Starting
httpd
OK
8) MAPSERVER ./configure --with-jpeg --with-gd
--with-freetype --with-zlib --with-png --with-pdf
--without-tiff --with-proj --with-threads
--with-ogr --with-gdal --with-postgis --with-wfs
--with-wmsclient --with-wfsclient --enable-debug
--with-php/src/php/php-4.4.2 make cp legend
mapserv scalebar /var/www/cgi-bin/ cp
mapscript/php3/php_mapscript.so
/etc/httpd/php_mods/ 9) GRASS CFLAGS"-g -Wall"
./configure --with-gdal/usr/local/bin/gdal-confi
g --with-postgres-includes/usr/local/pgsql/includ
e/ --with-postgres-libs/usr/local/pgsql/lib/ make
make install 10) R-Statistics tar -xzvf
R-2.1.1.tar.gz cd R-2.1.1 ./configure make make
install
33Where to go for more info
- OSGIS
- Maptools - http//www.maptools.org
- FreeGIS - http//freegis.org/
- Open Source GIS - http//opensourcegis.org/
- Standards
- OGC - http//www.opengeospatial.org/
- Desktop
- GRASS - http//grass.itc.it/
- QGIS - http//qgis.org/
- UDIG - http//udig.refractions.net/confluence/disp
lay/UDIG/Home - JUMP http//jump-project.org/
- OpenEV - http//openev.sourceforge.net/
- Server/Web
- Mapserver - http//mapserver.gis.umn.edu/
- GRASS - http//grass.itc.it/
- PostGIS - http//postgis.refractions.net/
- Tools
- Remote Sensing - http//remotesensing.org/tiki-ind
ex.php - GDAL/OGR - http//gdal.maptools.org/index.html
34The End Tool Screen Shots Follow
35Backup - GRASS
36Backup R-Statistics
37Backup PostGIS
Geometry
WKT Geometry
38Backup - QGIS